EnemyComponent.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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. body: Node = null!;
  19. @property(Node)
  20. leftHand: Node = null!;
  21. @property(Node)
  22. rightHand: Node = null!;
  23. @property(Node)
  24. leftFoot: Node = null!;
  25. @property(Node)
  26. rightFoot: Node = null!;
  27. @property(Node)
  28. leftHandGuge: Node = null!;
  29. @property(Node)
  30. rightHandGuge: Node = null!;
  31. @property(Node)
  32. leftFootGuge: Node = null!;
  33. @property(Node)
  34. rightFootGuge: Node = null!;
  35. @property(Material)
  36. hitMaterial: Material = null!;
  37. currentHp: number = 0;
  38. status: EnemyStatus = EnemyStatus.LIFE;
  39. speed: number = 50;
  40. headshot: boolean = false;
  41. tigger: Collider = null!;
  42. protected onLoad(): void {
  43. this.tigger = this.node.getComponent(Collider)!;
  44. }
  45. start() {
  46. this.status = EnemyStatus.LIFE;
  47. this.tigger = this.node.getComponent(Collider)!;
  48. this.rigidBody.isKinematic = true;
  49. this.registerEvent();
  50. }
  51. private registerEvent() {
  52. this.tigger.on('onTriggerEnter', this.onTriggerEnter, this);
  53. EventDispatcher.instance.on(GameEvent.EVENT_CAMERA_SHOOT_ENEMY, this.onShootEnemy, this);
  54. }
  55. private unRegisterEvent() {
  56. this.tigger.off('onTriggerEnter', this.onTriggerEnter, this);
  57. }
  58. protected onTriggerEnter(event: ITriggerEvent): void {
  59. }
  60. private async onShootEnemy(hitNode: Node) {
  61. // 检查是否是当前怪物节点被击中
  62. if (this.node === hitNode && this.status === EnemyStatus.LIFE) {
  63. this.status = EnemyStatus.DIE;
  64. // 修改所有部位材质为击中材质
  65. this.changeMaterial(this.head);
  66. this.changeMaterial(this.body);
  67. this.changeMaterial(this.leftHand);
  68. this.changeMaterial(this.rightHand);
  69. this.changeMaterial(this.leftFoot);
  70. this.changeMaterial(this.rightFoot);
  71. this.playHitTwitch();
  72. await GameUtil.delay(0.5);
  73. this.rigidBody.isKinematic = false;
  74. this.rigidBody.isDynamic = true;
  75. await GameUtil.delay(0.3);
  76. this.node.destroy();
  77. }
  78. }
  79. private changeMaterial(node: Node) {
  80. if (!node || !this.hitMaterial) return;
  81. const renderer = node.getComponent(MeshRenderer);
  82. if (renderer) {
  83. renderer.material = this.hitMaterial;
  84. }
  85. }
  86. // 中枪抽搐效果
  87. playHitTwitch() {
  88. // 抖动参数配置
  89. const shakeConfig = {
  90. head: { times: 5, duration: 0.12, axis: 'x' },
  91. leftHand: { times: 6, duration: 0.1, axis: 'y' },
  92. rightHand: { times: 6, duration: 0.15, axis: 'y' },
  93. leftFoot: { times: 4, duration: 0.1, axis: 'y' },
  94. rightFoot: { times: 4, duration: 0.1, axis: 'y' }
  95. };
  96. // 生成随机抖动值
  97. const getRandomShake = () => (10 + Math.random() * 10) * (Math.random() > 0.5 ? 1 : -1);
  98. // 创建抖动动画函数
  99. const createShakeTween = (node: Node, config: { times: number, duration: number, axis: string }) => {
  100. const rotation = node.rotation.clone();
  101. const t = tween(node);
  102. for (let i = 0; i < config.times; i++) {
  103. const shakeValue = getRandomShake();
  104. let newRotation = rotation.clone();
  105. if (config.axis === 'x') {
  106. newRotation = Quat.fromEuler(new Quat(), -90 + getRandomShake(), rotation.y, rotation.z);
  107. } else {
  108. newRotation = Quat.fromEuler(new Quat(), 90, rotation.y + shakeValue, rotation.z);
  109. }
  110. t.to(config.duration, { rotation: newRotation });
  111. }
  112. return t;
  113. };
  114. // 头部抖动
  115. createShakeTween(this.head, shakeConfig.head).start();
  116. // 左手抖动
  117. createShakeTween(this.leftHandGuge, shakeConfig.leftHand).start();
  118. // 右手抖动
  119. createShakeTween(this.rightHandGuge, shakeConfig.rightHand).start();
  120. // 左腿抖动
  121. createShakeTween(this.leftFootGuge, shakeConfig.leftFoot).start();
  122. // 右腿抖动
  123. createShakeTween(this.rightFootGuge, shakeConfig.rightFoot).start();
  124. }
  125. protected onDestroy(): void {
  126. Tween.stopAllByTarget(this.node);
  127. this.unRegisterEvent();
  128. }
  129. }