Bullet.ts 5.2 KB

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