Bullet.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import { _decorator, Animation, AnimationClip, Component, Node, Rect, SpriteFrame, UITransform, Vec3 } from 'cc';
  2. import { LifeBar } from './LifeBar';
  3. import { BulletPool } from './BulletPool';
  4. const { ccclass, property } = _decorator;
  5. export enum BulletState {
  6. Normal,
  7. Explode,
  8. }
  9. @ccclass('Bullet')
  10. export class Bullet extends Component {
  11. //对象池
  12. private _pool: BulletPool = null!;
  13. private _isEnemyBullet: boolean = false;
  14. private _animation: Animation = null;
  15. private _animations: Map<BulletState, string> = new Map();
  16. private _explodeframes: SpriteFrame[] = [];
  17. private _bulletFrames: SpriteFrame[] = [];
  18. //是否爆炸 true -> 爆炸
  19. isExplode: boolean = false;
  20. //子弹速度
  21. bulletSpeed: number = 100;
  22. //子弹方向
  23. direction: number = 1;
  24. //攻击力
  25. atk: number = null;
  26. //被攻击的节点
  27. targetNode: Node = null;
  28. //是否碰撞
  29. private _hasCollided: boolean = false;
  30. private _initPos: Vec3 = null;
  31. protected onLoad(): void {
  32. this._animation = this.node.addComponent(Animation);
  33. this._createClip(BulletState.Normal, [], 10);
  34. this._createClip(BulletState.Explode, [], 10);
  35. }
  36. start() {
  37. this._initPos = this.node.position.clone();
  38. this._collectAni();
  39. this._playAnimation(BulletState.Normal);
  40. }
  41. public reset(config: {
  42. pool: BulletPool,
  43. isEnemy: boolean,
  44. direction: number,
  45. bulletFrames: SpriteFrame[],
  46. explodeFrames: SpriteFrame[],
  47. targetNode: Node,
  48. atk: number,
  49. }) {
  50. //重置状态
  51. this._pool = config.pool;
  52. this._isEnemyBullet = config.isEnemy;
  53. this.direction = config.direction;
  54. this._bulletFrames = config.bulletFrames;
  55. this._explodeframes = config.explodeFrames;
  56. this.targetNode = config.targetNode;
  57. this.atk = config.atk;
  58. this._hasCollided = false;
  59. this.isExplode = false;
  60. this.bulletSpeed = this._isEnemyBullet ? 100 : 90;
  61. this._initPos = this.node.position.clone();
  62. this._collectAni();
  63. this._playAnimation(BulletState.Normal);
  64. //重置位置和动画
  65. this.node.active = true;
  66. }
  67. private _recycle() {
  68. if (this._pool) {
  69. //停止所有动画和事件
  70. this._animation.stop();
  71. this._animation.off(Animation.EventType.FINISHED);
  72. this.unscheduleAllCallbacks();
  73. this.node.active = false;
  74. //回收到对象池
  75. this._pool.recycle(this.node, this._isEnemyBullet);
  76. } else {
  77. console.log("destroy");
  78. this.node.destroy();
  79. }
  80. }
  81. update(deltaTime: number) {
  82. this.move(deltaTime);
  83. this.onBulletCollision(this.targetNode);
  84. this._checkDistance();
  85. }
  86. // 处理子弹碰撞
  87. private onBulletCollision(targetNode: Node) {
  88. if (this._hasCollided || !targetNode.isValid) return;
  89. const boxBullet = this.node.getComponent(UITransform).getBoundingBoxToWorld();
  90. let boxTarget: Rect = null;
  91. if(this.targetNode.getChildByName("Rect")){
  92. boxTarget = this.targetNode.getChildByName("Rect").getComponent(UITransform).getBoundingBoxToWorld();
  93. } else {
  94. boxTarget = this.targetNode.getComponent(UITransform).getBoundingBoxToWorld();
  95. }
  96. if (boxTarget.intersects(boxBullet)) {
  97. const targetLifeBar = targetNode.getComponent(LifeBar);
  98. const curHp: number = targetLifeBar._curHp - this.atk;
  99. targetLifeBar.updateProgressBar(curHp);
  100. if (curHp <= 0) {
  101. this._recycle();
  102. }
  103. this._hasCollided = true;
  104. this._playAnimation(BulletState.Explode);
  105. }
  106. }
  107. move(dt: number) {
  108. let x = this.node.getWorldPosition().x;
  109. let y = this.node.getWorldPosition().y;
  110. let z = this.node.getWorldPosition().z;
  111. x = x + this.bulletSpeed * this.direction * dt;
  112. this.node.setWorldPosition(x, y, z)
  113. }
  114. private _checkDistance() {
  115. const currentPos: Vec3 = this.node.position;
  116. const distance: number = Vec3.distance(currentPos, this._initPos);
  117. if (distance >= 250) {
  118. this._recycle();
  119. }
  120. }
  121. private _collectAni() {
  122. this._createClip(BulletState.Explode, this._explodeframes, 10);
  123. this._createClip(BulletState.Normal, this._bulletFrames, 10);
  124. }
  125. private _createClip(state: BulletState, frames: SpriteFrame[], fps: number) {
  126. const clip: AnimationClip = AnimationClip.createWithSpriteFrames(frames, fps);
  127. clip.name = BulletState[state];
  128. clip.wrapMode = state === BulletState.Explode ?
  129. AnimationClip.WrapMode.Normal :
  130. AnimationClip.WrapMode.Loop;
  131. this._animation.addClip(clip, clip.name);
  132. this._animations.set(state, clip.name);
  133. }
  134. private _playAnimation(state: BulletState) {
  135. if (!this._animation) return;
  136. const clipName = this._animations.get(state);
  137. if (!clipName) return;
  138. this._animation.stop();
  139. this._animation.play(clipName);
  140. if (state === BulletState.Explode) {
  141. this.bulletSpeed = 0;
  142. this._animation.once(Animation.EventType.FINISHED, () => {
  143. this._recycle();
  144. })
  145. }
  146. }
  147. }