BulletCount.ts 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. import { _decorator, Component, Node, Vec3, instantiate } from 'cc';
  2. const { ccclass, property } = _decorator;
  3. /**
  4. * 子弹数量控制器
  5. * 负责根据配置生成不同数量和模式的子弹
  6. */
  7. export interface BulletCountConfig {
  8. type: 'single' | 'spread' | 'burst'; // 发射模式
  9. amount: number; // 子弹数量
  10. spreadAngle: number; // 散射角度(度)
  11. burstCount: number; // 连发数量
  12. burstDelay: number; // 连发间隔(秒)
  13. }
  14. export interface BulletSpawnInfo {
  15. position: Vec3; // 发射位置
  16. direction: Vec3; // 发射方向
  17. delay: number; // 延迟时间
  18. index: number; // 子弹索引
  19. }
  20. @ccclass('BulletCount')
  21. export class BulletCount extends Component {
  22. /**
  23. * 根据配置计算所有子弹的生成信息
  24. * @param config 子弹数量配置
  25. * @param firePosition 发射位置
  26. * @param baseDirection 基础方向
  27. * @returns 子弹生成信息数组
  28. */
  29. public static calculateBulletSpawns(
  30. config: BulletCountConfig,
  31. firePosition: Vec3,
  32. baseDirection: Vec3
  33. ): BulletSpawnInfo[] {
  34. const spawns: BulletSpawnInfo[] = [];
  35. switch (config.type) {
  36. case 'single':
  37. spawns.push(...this.createSingleShot(config, firePosition, baseDirection));
  38. break;
  39. case 'spread':
  40. spawns.push(...this.createSpreadShot(config, firePosition, baseDirection));
  41. break;
  42. case 'burst':
  43. spawns.push(...this.createBurstShot(config, firePosition, baseDirection));
  44. break;
  45. }
  46. return spawns;
  47. }
  48. /**
  49. * 单发模式
  50. */
  51. private static createSingleShot(
  52. config: BulletCountConfig,
  53. firePosition: Vec3,
  54. baseDirection: Vec3
  55. ): BulletSpawnInfo[] {
  56. return [{
  57. position: firePosition.clone(),
  58. direction: baseDirection.clone().normalize(),
  59. delay: 0,
  60. index: 0
  61. }];
  62. }
  63. /**
  64. * 散射模式 - 同时发射多颗子弹,呈扇形分布
  65. */
  66. private static createSpreadShot(
  67. config: BulletCountConfig,
  68. firePosition: Vec3,
  69. baseDirection: Vec3
  70. ): BulletSpawnInfo[] {
  71. const spawns: BulletSpawnInfo[] = [];
  72. const bulletCount = config.amount;
  73. const spreadAngleRad = config.spreadAngle * Math.PI / 180;
  74. if (bulletCount === 1) {
  75. // 只有一颗子弹时,直接使用基础方向
  76. return this.createSingleShot(config, firePosition, baseDirection);
  77. }
  78. // 计算每颗子弹的角度偏移
  79. const angleStep = spreadAngleRad / (bulletCount - 1);
  80. const startAngle = -spreadAngleRad / 2;
  81. for (let i = 0; i < bulletCount; i++) {
  82. const angle = startAngle + angleStep * i;
  83. const direction = this.rotateVector(baseDirection, angle);
  84. spawns.push({
  85. position: firePosition.clone(),
  86. direction: direction.normalize(),
  87. delay: 0,
  88. index: i
  89. });
  90. }
  91. return spawns;
  92. }
  93. /**
  94. * 连发模式 - 按时间间隔依次发射子弹
  95. */
  96. private static createBurstShot(
  97. config: BulletCountConfig,
  98. firePosition: Vec3,
  99. baseDirection: Vec3
  100. ): BulletSpawnInfo[] {
  101. const spawns: BulletSpawnInfo[] = [];
  102. const burstCount = config.burstCount || config.amount;
  103. for (let i = 0; i < burstCount; i++) {
  104. spawns.push({
  105. position: firePosition.clone(),
  106. direction: baseDirection.clone().normalize(),
  107. delay: i * config.burstDelay,
  108. index: i
  109. });
  110. }
  111. return spawns;
  112. }
  113. /**
  114. * 旋转向量
  115. */
  116. private static rotateVector(vector: Vec3, angleRad: number): Vec3 {
  117. const cos = Math.cos(angleRad);
  118. const sin = Math.sin(angleRad);
  119. return new Vec3(
  120. vector.x * cos - vector.y * sin,
  121. vector.x * sin + vector.y * cos,
  122. vector.z
  123. );
  124. }
  125. /**
  126. * 创建散射位置偏移(可选功能,用于霰弹枪等)
  127. */
  128. public static createSpreadPositions(
  129. basePosition: Vec3,
  130. spreadRadius: number,
  131. count: number
  132. ): Vec3[] {
  133. const positions: Vec3[] = [];
  134. if (count === 1) {
  135. positions.push(basePosition.clone());
  136. return positions;
  137. }
  138. const angleStep = (Math.PI * 2) / count;
  139. for (let i = 0; i < count; i++) {
  140. const angle = angleStep * i;
  141. const offset = new Vec3(
  142. Math.cos(angle) * spreadRadius,
  143. Math.sin(angle) * spreadRadius,
  144. 0
  145. );
  146. positions.push(basePosition.clone().add(offset));
  147. }
  148. return positions;
  149. }
  150. /**
  151. * 验证配置有效性
  152. */
  153. public static validateConfig(config: BulletCountConfig): boolean {
  154. if (!config) return false;
  155. // 检查基本参数
  156. if (config.amount <= 0) return false;
  157. if (config.spreadAngle < 0 || config.spreadAngle > 360) return false;
  158. if (config.burstDelay < 0) return false;
  159. // 检查类型特定参数
  160. switch (config.type) {
  161. case 'spread':
  162. if (config.amount > 20) {
  163. console.warn('散射子弹数量过多,可能影响性能');
  164. return false;
  165. }
  166. break;
  167. case 'burst':
  168. if (config.burstCount <= 0) return false;
  169. if (config.burstDelay <= 0.01) {
  170. console.warn('连发间隔过短,可能影响性能');
  171. }
  172. break;
  173. }
  174. return true;
  175. }
  176. }