EnemyComponent.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import { _decorator, CCBoolean, CCFloat, Collider, Component, isValid, ITriggerEvent, Material, MeshRenderer, Node, PhysicsSystem, Quat, RigidBody, tween, Tween, Vec3 } from 'cc';
  2. import { EventDispatcher } from 'db://assets/core_tgx/easy_ui_framework/EventDispatcher';
  3. import { GameEvent } from '../Enum/GameEvent';
  4. import { GameUtil } from '../GameUtil';
  5. const { ccclass, property, executeInEditMode } = _decorator;
  6. export enum EnemyStatus {
  7. LIFE,
  8. DIE
  9. }
  10. @ccclass('EnemyComponent')
  11. @executeInEditMode
  12. export class EnemyComponent extends Component {
  13. @property(RigidBody)
  14. rigidBody: RigidBody = null!;
  15. @property(Node)
  16. head: Node = null!;
  17. @property(Node)
  18. leftHand: Node = null!;
  19. @property(Node)
  20. rightHand: Node = null!;
  21. @property(Node)
  22. leftFoot: Node = null!;
  23. @property(Node)
  24. rightFoot: Node = null!;
  25. @property(Node)
  26. eyeRender: Node = null!;
  27. @property(Node)
  28. bodyRender: Node = null!;
  29. @property(Material)
  30. hitEyeMaterial: Material = null!; // 击中眼睛的材质
  31. @property(Material)
  32. hitMaterial: Material = null!; // 击中时身体的材质
  33. currentHp: number = 0;
  34. status: EnemyStatus = EnemyStatus.LIFE;
  35. speed: number = 50;
  36. headshot: boolean = false;
  37. tigger: Collider = null!;
  38. protected onLoad(): void {
  39. this.tigger = this.node.getComponent(Collider)!;
  40. }
  41. start() {
  42. this.status = EnemyStatus.LIFE;
  43. this.tigger = this.node.getComponent(Collider)!;
  44. this.rigidBody.isKinematic = true;
  45. this.registerEvent();
  46. }
  47. private registerEvent() {
  48. this.tigger.on('onTriggerEnter', this.onTriggerEnter, this);
  49. EventDispatcher.instance.on(GameEvent.EVENT_CAMERA_SHOOT_ENEMY, this.onShootEnemy, this);
  50. }
  51. private unRegisterEvent() {
  52. this.tigger.off('onTriggerEnter', this.onTriggerEnter, this);
  53. }
  54. protected onTriggerEnter(event: ITriggerEvent): void {
  55. }
  56. private async onShootEnemy(hitNode: Node) {
  57. // 检查是否是当前怪物节点被击中
  58. if (this.node === hitNode && this.status === EnemyStatus.LIFE) {
  59. this.status = EnemyStatus.DIE;
  60. // 修改所有部位材质为击中材质
  61. this.changeMaterial();
  62. this.playHitTwitch();
  63. await GameUtil.delay(0.7);
  64. this.rigidBody.isKinematic = false;
  65. this.rigidBody.isDynamic = true;
  66. await GameUtil.delay(0.3);
  67. this.node.destroy();
  68. }
  69. }
  70. private changeMaterial() {
  71. if (!this.bodyRender || !this.hitMaterial) return;
  72. const renderer = this.bodyRender.getComponent(MeshRenderer);
  73. const eyeRenderer = this.eyeRender.getComponent(MeshRenderer);
  74. if (renderer) {
  75. renderer.material = this.hitMaterial;
  76. }
  77. if (eyeRenderer) {
  78. eyeRenderer.material = this.hitEyeMaterial;
  79. }
  80. }
  81. // 中枪抽搐效果
  82. playHitTwitch() {
  83. // 抖动参数配置
  84. const shakeConfig = {
  85. head: { times: 5, duration: 0.12 },
  86. leftHand: { times: 6, duration: 0.1 },
  87. rightHand: { times: 6, duration: 0.15 },
  88. leftFoot: { times: 5, duration: 0.13 },
  89. rightFoot: { times: 5, duration: 0.13 }
  90. };
  91. // 生成随机抖动值
  92. const getRandomShake = () => (10 + Math.random() * 10) * (Math.random() > 0.5 ? 1 : -1);
  93. // 创建抖动动画函数
  94. const createShakeTween = (node: Node, config: { times: number, duration: number }) => {
  95. const t = tween(node);
  96. for (let i = 0; i < config.times; i++) {
  97. const euler = new Vec3();
  98. node.rotation.getEulerAngles(euler);
  99. const shakeValue = getRandomShake();
  100. const newEuler = new Vec3(euler.x + shakeValue, euler.y + shakeValue, euler.z);
  101. const newRotation = new Quat();
  102. Quat.fromEuler(newRotation, newEuler.x, newEuler.y, newEuler.z);
  103. t.to(config.duration, { rotation: newRotation });
  104. }
  105. return t;
  106. };
  107. // 头部抖动
  108. createShakeTween(this.head, shakeConfig.head).start();
  109. // 左手抖动
  110. createShakeTween(this.leftHand, shakeConfig.leftHand).start();
  111. // 右手抖动
  112. createShakeTween(this.rightHand, shakeConfig.rightHand).start();
  113. // 左腿抖动
  114. createShakeTween(this.leftFoot, shakeConfig.leftFoot).start();
  115. // 右腿抖动
  116. createShakeTween(this.rightFoot, shakeConfig.rightFoot).start();
  117. }
  118. protected onDestroy(): void {
  119. Tween.stopAllByTarget(this.node);
  120. this.unRegisterEvent();
  121. }
  122. }