EnemyComponent.ts 4.8 KB

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