BulletController.ts 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. import { _decorator, Component, Node, Vec2, Vec3, find, RigidBody2D, Collider2D, Contact2DType, IPhysics2DContact } from 'cc';
  2. const { ccclass, property } = _decorator;
  3. @ccclass('BulletController')
  4. export class BulletController extends Component {
  5. @property
  6. public speed: number = 300;
  7. @property
  8. public damage: number = 10;
  9. @property
  10. public lifetime: number = 5;
  11. private targetEnemy: Node = null;
  12. private rigidBody: RigidBody2D = null;
  13. private lifeTimer: number = 0;
  14. private initialDirection: Vec2 = null; // 存储初始方向
  15. start() {
  16. // 获取刚体组件
  17. this.rigidBody = this.node.getChildByName('Icon').getComponent(RigidBody2D);
  18. // 设置子弹生命周期
  19. this.lifeTimer = this.lifetime;
  20. // 查找最近的敌人
  21. this.findNearestEnemy();
  22. // 如果没有找到敌人,设置随机方向
  23. if (!this.initialDirection) {
  24. const angle = Math.random() * Math.PI * 2;
  25. this.initialDirection = new Vec2(
  26. Math.cos(angle),
  27. Math.sin(angle)
  28. );
  29. console.log('未找到敌人目标,设置随机方向');
  30. }
  31. // 设置初始速度
  32. this.updateVelocity();
  33. // 注册碰撞事件
  34. const collider = this.node.getChildByName('Icon').getComponent(Collider2D);
  35. if (collider) {
  36. collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
  37. }
  38. }
  39. // 查找最近的敌人
  40. findNearestEnemy() {
  41. // 直接查找enemyContainer节点
  42. const enemyContainer = find('Canvas/GameLevelUI/enemyContainer');
  43. if (!enemyContainer) {
  44. console.warn('找不到enemyContainer节点');
  45. return;
  46. }
  47. // 获取enemyContainer下的所有子节点(敌人)
  48. const enemies = enemyContainer.children;
  49. if (!enemies || enemies.length === 0) {
  50. console.log('没有可用的敌人目标');
  51. return;
  52. }
  53. console.log(`在enemyContainer中找到 ${enemies.length} 个敌人`);
  54. // 找到最近的敌人
  55. let nearestEnemy = null;
  56. let minDistance = Number.MAX_VALUE;
  57. for (const enemy of enemies) {
  58. if (!enemy || !enemy.isValid) continue;
  59. const distance = Vec3.distance(this.node.worldPosition, enemy.worldPosition);
  60. if (distance < minDistance) {
  61. minDistance = distance;
  62. nearestEnemy = enemy;
  63. }
  64. }
  65. if (nearestEnemy) {
  66. this.targetEnemy = nearestEnemy;
  67. // 计算朝向敌人的方向,并保存为初始方向
  68. const bulletPos = this.node.worldPosition;
  69. const enemyPos = this.targetEnemy.worldPosition;
  70. this.initialDirection = new Vec2(
  71. enemyPos.x - bulletPos.x,
  72. enemyPos.y - bulletPos.y
  73. );
  74. this.initialDirection.normalize();
  75. console.log('子弹锁定敌人目标,设置初始方向');
  76. }
  77. }
  78. // 更新子弹速度方向
  79. updateVelocity() {
  80. if (!this.rigidBody) return;
  81. // 使用初始方向,不追踪敌人
  82. if (this.initialDirection) {
  83. // 设置速度
  84. this.rigidBody.linearVelocity = new Vec2(
  85. this.initialDirection.x * this.speed,
  86. this.initialDirection.y * this.speed
  87. );
  88. }
  89. }
  90. // 碰撞检测
  91. onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
  92. // 检查是否碰到敌人
  93. if (otherCollider.node.name === 'Enemy') {
  94. console.log('子弹击中敌人');
  95. // 获取EnemyController
  96. const enemyController = find('Canvas/GameLevelUI/EnemyController');
  97. if (enemyController) {
  98. const enemyControllerComp = enemyController.getComponent('EnemyController');
  99. if (enemyControllerComp) {
  100. // 对敌人造成伤害
  101. (enemyControllerComp as any).damageEnemy(otherCollider.node, this.damage);
  102. }
  103. }
  104. // 销毁子弹
  105. this.destroyBullet();
  106. }
  107. // 检查是否碰到墙体或其他物体
  108. else if (otherCollider.node.name !== 'Ball') { // 不与小球碰撞
  109. this.destroyBullet();
  110. }
  111. }
  112. // 销毁子弹
  113. destroyBullet() {
  114. if (this.node && this.node.isValid) {
  115. this.node.destroy();
  116. }
  117. }
  118. update(dt: number) {
  119. // 更新生命周期
  120. this.lifeTimer -= dt;
  121. if (this.lifeTimer <= 0) {
  122. this.destroyBullet();
  123. return;
  124. }
  125. // 注意:不再每帧更新速度方向,子弹将沿初始方向直线移动
  126. }
  127. }