Bullet.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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. }
  34. start() {
  35. this._initPos = this.node.position.clone();
  36. this._collectAni();
  37. this._playAnimation(BulletState.Normal);
  38. }
  39. public reset(config: {
  40. pool: BulletPool,
  41. isEnemy: boolean,
  42. direction: number,
  43. bulletFrames: SpriteFrame[],
  44. explodeFrames: SpriteFrame[],
  45. targetNode: Node,
  46. atk: number,
  47. }) {
  48. //重置状态
  49. this._pool = config.pool;
  50. this._isEnemyBullet = config.isEnemy;
  51. this.direction = config.direction;
  52. this._bulletFrames = config.bulletFrames;
  53. this._explodeframes = config.explodeFrames;
  54. this.targetNode = config.targetNode;
  55. this.atk = config.atk;
  56. this._hasCollided = false;
  57. this.isExplode = false;
  58. this.bulletSpeed = this._isEnemyBullet ? 100 : 90;
  59. this._initPos = this.node.position.clone();
  60. this._playAnimation(BulletState.Normal);
  61. //重置位置和动画
  62. this.node.active = true;
  63. }
  64. private _recycle() {
  65. if (this._pool) {
  66. //停止所有动画和事件
  67. this._animation.stop();
  68. this._animation.off(Animation.EventType.FINISHED);
  69. this.unscheduleAllCallbacks();
  70. this.node.active = false;
  71. //回收到对象池
  72. this._pool.recycle(this.node, this._isEnemyBullet);
  73. } else {
  74. this.node.destroy();
  75. }
  76. }
  77. update(deltaTime: number) {
  78. this.move(deltaTime);
  79. this.onBulletCollision(this.targetNode);
  80. this._checkDistance();
  81. }
  82. // 处理子弹碰撞
  83. private onBulletCollision(targetNode: Node) {
  84. if (this._hasCollided || !targetNode.isValid) return;
  85. const boxBullet = this.node.getComponent(UITransform).getBoundingBoxToWorld();
  86. let boxTarget: Rect = null;
  87. if(this.targetNode.getChildByName("Rect")){
  88. boxTarget = this.targetNode.getChildByName("Rect").getComponent(UITransform).getBoundingBoxToWorld();
  89. } else {
  90. boxTarget = this.targetNode.getComponent(UITransform).getBoundingBoxToWorld();
  91. }
  92. if (boxTarget.intersects(boxBullet)) {
  93. const targetLifeBar = targetNode.getComponent(LifeBar);
  94. const curHp: number = targetLifeBar._curHp - this.atk;
  95. targetLifeBar.updateProgressBar(curHp);
  96. if (curHp <= 0) {
  97. this._recycle();
  98. }
  99. this._hasCollided = true;
  100. this._playAnimation(BulletState.Explode);
  101. }
  102. }
  103. move(dt: number) {
  104. let x = this.node.getWorldPosition().x;
  105. let y = this.node.getWorldPosition().y;
  106. let z = this.node.getWorldPosition().z;
  107. x = x + this.bulletSpeed * this.direction * dt;
  108. this.node.setWorldPosition(x, y, z)
  109. }
  110. private _checkDistance() {
  111. const currentPos: Vec3 = this.node.position;
  112. const distance: number = Vec3.distance(currentPos, this._initPos);
  113. if (distance >= 250) {
  114. this._recycle();
  115. }
  116. }
  117. private _collectAni() {
  118. this._createClip(BulletState.Explode, this._explodeframes, 10);
  119. this._createClip(BulletState.Normal, this._bulletFrames, 10);
  120. }
  121. private _createClip(state: BulletState, frames: SpriteFrame[], fps: number) {
  122. const clip: AnimationClip = AnimationClip.createWithSpriteFrames(frames, fps);
  123. clip.name = BulletState[state];
  124. clip.wrapMode = state === BulletState.Explode ?
  125. AnimationClip.WrapMode.Normal :
  126. AnimationClip.WrapMode.Loop;
  127. this._animation.addClip(clip, clip.name);
  128. this._animations.set(state, clip.name);
  129. }
  130. private _playAnimation(state: BulletState) {
  131. if (!this._animation) return;
  132. const clipName = this._animations.get(state);
  133. if (!clipName) return;
  134. this._animation.stop();
  135. this._animation.play(clipName);
  136. if (state === BulletState.Explode) {
  137. this.bulletSpeed = 0;
  138. this._animation.once(Animation.EventType.FINISHED, () => {
  139. this._recycle();
  140. })
  141. }
  142. }
  143. }