EnemySpawnerExample.ts 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. import { _decorator, Component, Node, Prefab, instantiate, Vec3, Vec2, Sprite, SpriteFrame, resources, RigidBody2D, CCFloat, CCInteger } from 'cc';
  2. import { ConfigManager, EnemyConfig } from './ConfigManager';
  3. import { EnemyComponent } from './EnemyComponent';
  4. const { ccclass, property } = _decorator;
  5. /**
  6. * 敌人生成器示例脚本
  7. * 展示如何使用ConfigManager来创建不同类型的敌人
  8. */
  9. @ccclass('EnemySpawnerExample')
  10. export class EnemySpawnerExample extends Component {
  11. @property({
  12. type: Prefab,
  13. tooltip: '基础敌人预制体'
  14. })
  15. public enemyPrefab: Prefab = null;
  16. @property({
  17. type: Node,
  18. tooltip: '敌人容器节点'
  19. })
  20. public enemyContainer: Node = null;
  21. @property({
  22. type: CCFloat,
  23. tooltip: '生成间隔(秒)'
  24. })
  25. public spawnInterval: number = 2.0;
  26. @property({
  27. type: CCInteger,
  28. tooltip: '最大敌人数量'
  29. })
  30. public maxEnemies: number = 10;
  31. private configManager: ConfigManager = null;
  32. private currentWave: number = 1;
  33. private currentEnemyCount: number = 0;
  34. private spawnTimer: number = 0;
  35. start() {
  36. // 获取配置管理器实例
  37. this.configManager = ConfigManager.getInstance();
  38. // 等待配置加载完成后开始生成
  39. this.scheduleOnce(() => {
  40. this.startSpawning();
  41. }, 1.0);
  42. }
  43. update(deltaTime: number) {
  44. if (!this.configManager || !this.configManager.isConfigLoaded()) {
  45. return;
  46. }
  47. // 更新生成计时器
  48. this.spawnTimer += deltaTime;
  49. if (this.spawnTimer >= this.spawnInterval && this.currentEnemyCount < this.maxEnemies) {
  50. this.spawnRandomEnemy();
  51. this.spawnTimer = 0;
  52. }
  53. }
  54. // 开始生成敌人
  55. private startSpawning() {
  56. if (!this.configManager || !this.configManager.isConfigLoaded()) {
  57. console.warn('配置管理器未准备好');
  58. return;
  59. }
  60. console.log('开始生成敌人');
  61. this.spawnTimer = 0;
  62. }
  63. // 生成随机敌人
  64. private spawnRandomEnemy() {
  65. // 根据当前波次获取合适的敌人
  66. const enemyConfig = this.configManager.getEnemyForWave(this.currentWave);
  67. if (!enemyConfig) {
  68. console.warn('无法获取敌人配置');
  69. return;
  70. }
  71. this.spawnEnemy(enemyConfig);
  72. }
  73. // 生成指定类型的敌人
  74. public spawnEnemyByType(enemyType: string) {
  75. const enemyConfig = this.configManager.getEnemyById(enemyType);
  76. if (!enemyConfig) {
  77. console.warn(`找不到类型为 ${enemyType} 的敌人配置`);
  78. return;
  79. }
  80. this.spawnEnemy(enemyConfig);
  81. }
  82. // 生成指定稀有度的敌人
  83. public spawnEnemyByRarity(rarity: string) {
  84. const enemyConfig = this.configManager.getRandomEnemy(rarity);
  85. if (!enemyConfig) {
  86. console.warn(`无法获取稀有度为 ${rarity} 的敌人配置`);
  87. return;
  88. }
  89. this.spawnEnemy(enemyConfig);
  90. }
  91. // 根据敌人配置生成敌人
  92. private spawnEnemy(enemyConfig: EnemyConfig) {
  93. if (!this.enemyPrefab) {
  94. console.error('敌人预制体未设置');
  95. return;
  96. }
  97. // 实例化敌人
  98. const enemyNode = instantiate(this.enemyPrefab);
  99. if (!enemyNode) {
  100. console.error('敌人实例化失败');
  101. return;
  102. }
  103. // 设置生成位置(右侧屏幕外)
  104. const spawnPosition = new Vec3(800, Math.random() * 400 - 200, 0);
  105. enemyNode.setPosition(spawnPosition);
  106. // 添加到容器
  107. if (this.enemyContainer) {
  108. this.enemyContainer.addChild(enemyNode);
  109. } else {
  110. this.node.addChild(enemyNode);
  111. }
  112. // 设置敌人配置
  113. this.setupEnemy(enemyNode, enemyConfig);
  114. this.currentEnemyCount++;
  115. console.log(`生成敌人: ${enemyConfig.name} (${enemyConfig.rarity})`);
  116. }
  117. // 设置敌人配置
  118. private setupEnemy(enemyNode: Node, enemyConfig: EnemyConfig) {
  119. // 添加敌人组件
  120. const enemyComponent = enemyNode.addComponent(EnemyComponent);
  121. if (enemyComponent) {
  122. enemyComponent.enemyConfig = enemyConfig;
  123. enemyComponent.spawner = this;
  124. }
  125. // 设置敌人外观
  126. this.setupEnemyVisual(enemyNode, enemyConfig);
  127. // 设置敌人物理
  128. this.setupEnemyPhysics(enemyNode, enemyConfig);
  129. // 设置敌人名称
  130. enemyNode.name = `Enemy_${enemyConfig.id}_${Date.now()}`;
  131. }
  132. // 设置敌人外观
  133. private setupEnemyVisual(enemyNode: Node, enemyConfig: EnemyConfig) {
  134. const spriteComponent = enemyNode.getComponent(Sprite);
  135. if (!spriteComponent) {
  136. console.warn('敌人节点没有Sprite组件');
  137. return;
  138. }
  139. // 根据稀有度设置颜色
  140. const rarityColors = {
  141. 'common': { r: 200, g: 200, b: 200, a: 255 }, // 灰色
  142. 'uncommon': { r: 255, g: 255, b: 0, a: 255 }, // 黄色
  143. 'rare': { r: 255, g: 100, b: 0, a: 255 }, // 橙色
  144. 'boss': { r: 255, g: 0, b: 0, a: 255 } // 红色
  145. };
  146. const color = rarityColors[enemyConfig.rarity] || rarityColors['common'];
  147. spriteComponent.color = spriteComponent.color.set(color.r, color.g, color.b, color.a);
  148. // 设置缩放
  149. enemyNode.setScale(enemyConfig.visualConfig.scale, enemyConfig.visualConfig.scale, 1);
  150. // 尝试加载敌人图标
  151. this.loadEnemySprite(spriteComponent, enemyConfig);
  152. }
  153. // 加载敌人图标
  154. private loadEnemySprite(spriteComponent: Sprite, enemyConfig: EnemyConfig) {
  155. const spritePath = enemyConfig.visualConfig.spritePrefab;
  156. if (!spritePath) {
  157. console.warn(`敌人 ${enemyConfig.name} 没有图标路径`);
  158. return;
  159. }
  160. // 加载图标资源
  161. resources.load(spritePath, SpriteFrame, (err, spriteFrame) => {
  162. if (err) {
  163. console.warn(`加载敌人图标失败: ${spritePath}`, err);
  164. return;
  165. }
  166. spriteComponent.spriteFrame = spriteFrame;
  167. });
  168. }
  169. // 设置敌人物理
  170. private setupEnemyPhysics(enemyNode: Node, enemyConfig: EnemyConfig) {
  171. const rigidBody = enemyNode.getComponent(RigidBody2D);
  172. if (rigidBody) {
  173. // 设置线性速度(向左移动)
  174. const speed = enemyConfig.stats.speed;
  175. rigidBody.linearVelocity = new Vec2(-speed, 0);
  176. }
  177. }
  178. // 敌人死亡回调
  179. public onEnemyDeath(enemyNode: Node) {
  180. this.currentEnemyCount--;
  181. // 移除敌人节点
  182. if (enemyNode && enemyNode.isValid) {
  183. enemyNode.destroy();
  184. }
  185. }
  186. // 设置当前波次
  187. public setCurrentWave(wave: number) {
  188. this.currentWave = wave;
  189. console.log(`设置当前波次: ${wave}`);
  190. }
  191. // 获取当前波次
  192. public getCurrentWave(): number {
  193. return this.currentWave;
  194. }
  195. // 获取当前敌人数量
  196. public getCurrentEnemyCount(): number {
  197. return this.currentEnemyCount;
  198. }
  199. // 清除所有敌人
  200. public clearAllEnemies() {
  201. if (this.enemyContainer) {
  202. this.enemyContainer.destroyAllChildren();
  203. }
  204. this.currentEnemyCount = 0;
  205. }
  206. // 暂停生成
  207. public pauseSpawning() {
  208. this.spawnInterval = Number.MAX_VALUE;
  209. }
  210. // 恢复生成
  211. public resumeSpawning(interval: number = 2.0) {
  212. this.spawnInterval = interval;
  213. this.spawnTimer = 0;
  214. }
  215. }