import { _decorator, Node, Label, Vec3, Prefab, find, UITransform, resources, RigidBody2D, instantiate } from 'cc'; import { sp } from 'cc'; import { ConfigManager, EnemyConfig } from '../Core/ConfigManager'; import { EnemyComponent } from '../CombatSystem/EnemyComponent'; import { EnemyInstance } from './EnemyInstance'; import { BaseSingleton } from '../Core/BaseSingleton'; import { SaveDataManager } from '../LevelSystem/SaveDataManager'; import { LevelConfigManager } from '../LevelSystem/LevelConfigManager'; import EventBus, { GameEvents } from '../Core/EventBus'; import { EnemyAttackStateManager } from './EnemyAttackStateManager'; import { Wall } from './Wall'; import { BurnEffect } from './BulletEffects/BurnEffect'; import { Audio } from '../AudioManager/AudioManager'; import { BundleLoader } from '../Core/BundleLoader'; import { ResourcePreloader } from '../Core/ResourcePreloader'; const { ccclass, property } = _decorator; @ccclass('EnemyController') export class EnemyController extends BaseSingleton { // 仅类型声明,实例由 BaseSingleton 维护 public static _instance: EnemyController; // 敌人预制体 @property({ type: Prefab, tooltip: '拖拽Enemy预制体到这里' }) public enemyPrefab: Prefab = null; // 敌人容器节点 @property({ type: Node, tooltip: '拖拽enemyContainer节点到这里(Canvas/GameLevelUI/enemyContainer)' }) public enemyContainer: Node = null; // 金币预制体 @property({ type: Prefab, tooltip: '金币预制体 CoinDrop' }) public coinPrefab: Prefab = null; // 移除Toast预制体属性,改用事件机制 // @property({ // type: Prefab, // tooltip: 'Toast预制体,用于显示波次提示' // }) // public toastPrefab: Prefab = null; // === 生成 & 属性参数(保留需要可在内部自行设定,Inspector 不再显示) === private spawnInterval: number = 3; // === 默认数值(当配置文件尚未加载时使用) === private defaultEnemySpeed: number = 50; private defaultAttackPower: number = 20; // 对应combat.attackDamage private defaultHealth: number = 10; // 对应stats.health @property({ type: Node, tooltip: '拖拽 TopFence 节点到这里' }) public topFenceNode: Node = null; @property({ type: Node, tooltip: '拖拽 BottomFence 节点到这里' }) public bottomFenceNode: Node = null; @property({ type: Node, tooltip: '拖拽 Line5 节点到这里 (Canvas/GameLevelUI/enemyContainer/Line5)' }) public line5Node: Node = null; @property({ type: Node, tooltip: '拖拽 Line6 节点到这里 (Canvas/GameLevelUI/enemyContainer/Line6)' }) public line6Node: Node = null; // 关卡配置管理器节点 @property({ type: Node, tooltip: '拖拽Canvas/LevelConfigManager节点到这里,用于获取LevelConfigManager组件' }) public levelConfigManagerNode: Node = null; // 主墙体组件 private wallComponent: Wall = null; // 游戏区域边界 - 改为public,让敌人实例可以访问 public gameBounds = { left: 0, right: 0, top: 0, bottom: 0 }; // 活跃的敌人列表 private activeEnemies: Node[] = []; // 游戏是否已开始 private gameStarted: boolean = false; // 墙体节点 private wallNodes: Node[] = []; // 是否正在清理敌人(用于阻止清理时触发游戏胜利判断) private isClearing: boolean = false; // 配置管理器 private configManager: ConfigManager = null; // 关卡配置管理器 private levelConfigManager: LevelConfigManager = null; // 资源预加载管理器 private resourcePreloader: ResourcePreloader = null; // 当前关卡血量倍率 private currentHealthMultiplier: number = 1.0; private currentWaveHealthMultiplier: number = 1.0; // 当前波次的血量系数 @property({ type: Node, tooltip: '敌人数量显示节点 (EnemyNumber)' }) public enemyCountLabelNode: Node = null; @property({ type: Node, tooltip: '当前波数显示Label (WaveNumber-前)' }) public currentWaveNumberLabelNode: Node = null; @property({ type: Node, tooltip: '总波数显示Label (WaveNumber-后)' }) public totalWaveNumberLabelNode: Node = null; // 当前波次敌人数据 private totalWaves: number = 1; private currentWave: number = 1; private currentWaveTotalEnemies: number = 0; private currentWaveEnemiesKilled: number = 0; private currentWaveEnemiesSpawned: number = 0; // 当前波次已生成的敌人数量 private currentWaveEnemyConfigs: any[] = []; // 当前波次的敌人配置列表 // 暂停前保存的敌人状态 private pausedEnemyStates: Map = new Map(); /** * BaseSingleton 首次实例化回调 */ protected init() { // 获取配置管理器实例 this.configManager = ConfigManager.getInstance(); // 获取资源预加载管理器实例 this.resourcePreloader = ResourcePreloader.getInstance(); // 获取关卡配置管理器实例 if (this.levelConfigManagerNode) { this.levelConfigManager = this.levelConfigManagerNode.getComponent(LevelConfigManager) || null; if (!this.levelConfigManager) { // LevelConfigManager节点上未找到LevelConfigManager组件 } } else { // levelConfigManagerNode未通过装饰器绑定,请在编辑器中拖拽Canvas/LevelConfigManager节点 this.levelConfigManager = null; } // 如果没有指定enemyContainer,尝试找到它 if (!this.enemyContainer) { this.enemyContainer = find('Canvas/GameLevelUI/enemyContainer'); if (!this.enemyContainer) { // 找不到enemyContainer节点,将尝试创建 } } // 获取游戏区域边界 this.calculateGameBounds(); // 查找墙体节点和组件 this.findWallNodes(); // 直接通过拖拽节点获取 Wall 组件 if (this.topFenceNode && this.topFenceNode.getComponent(Wall)) { this.wallComponent = this.topFenceNode.getComponent(Wall); } else if (this.bottomFenceNode && this.bottomFenceNode.getComponent(Wall)) { this.wallComponent = this.bottomFenceNode.getComponent(Wall); } else { // 未找到墙体组件,将无法处理墙体伤害 } // 确保enemyContainer节点存在 this.ensureEnemyContainer(); // UI节点已通过装饰器拖拽绑定,无需find查找 if (!this.enemyCountLabelNode) { // enemyCountLabelNode 未通过装饰器绑定,请在编辑器中拖拽 Canvas-001/TopArea/EnemyNode/EnemyNumber 节点 } if (!this.currentWaveNumberLabelNode) { // currentWaveNumberLabelNode 未通过装饰器绑定,请在编辑器中拖拽 Canvas-001/TopArea/WaveInfo/WaveNumber-前 节点 } if (!this.totalWaveNumberLabelNode) { // totalWaveNumberLabelNode 未通过装饰器绑定,请在编辑器中拖拽 Canvas-001/TopArea/WaveInfo/WaveNumber-后 节点 } // 初始化敌人数量显示 this.updateEnemyCountLabel(); // 延迟验证Line节点绑定(解决微信平台初始化时序问题) this.scheduleOnce(() => { this.validateLineNodes(); }, 0.1); // 监听游戏事件 this.setupEventListeners(); } /** * 验证Line节点绑定(解决微信平台初始化时序问题) */ private validateLineNodes() { // 验证Line5节点 if (!this.line5Node && this.enemyContainer) { this.line5Node = this.enemyContainer.getChildByName('Line5'); if (this.line5Node) { console.log('[EnemyController] Line5节点重新绑定成功'); } else { console.warn('[EnemyController] Line5节点未找到'); } } // 验证Line6节点 if (!this.line6Node && this.enemyContainer) { this.line6Node = this.enemyContainer.getChildByName('Line6'); if (this.line6Node) { console.log('[EnemyController] Line6节点重新绑定成功'); } else { console.warn('[EnemyController] Line6节点未找到'); } } // 输出当前Line节点状态 console.log('[EnemyController] Line5节点状态:', this.line5Node ? '已绑定' : '未绑定'); console.log('[EnemyController] Line6节点状态:', this.line6Node ? '已绑定' : '未绑定'); } /** * 设置事件监听器 */ private setupEventListeners() { const eventBus = EventBus.getInstance(); // 监听暂停事件 eventBus.on(GameEvents.GAME_PAUSE, this.onGamePauseEvent, this); eventBus.on(GameEvents.GAME_PAUSE_SKILL_SELECTION, this.onGamePauseEvent, this); eventBus.on(GameEvents.GAME_PAUSE_BLOCK_SELECTION, this.onGamePauseEvent, this); // 监听游戏恢复事件 eventBus.on(GameEvents.GAME_RESUME, this.onGameResumeEvent, this); eventBus.on(GameEvents.GAME_RESUME_SKILL_SELECTION, this.onGameResumeSkillSelectionEvent, this); eventBus.on(GameEvents.GAME_RESUME_BLOCK_SELECTION, this.onGameResumeBlockSelectionEvent, this); // 监听游戏成功/失败事件 eventBus.on(GameEvents.GAME_SUCCESS, this.onGameEndEvent, this); eventBus.on(GameEvents.GAME_DEFEAT, this.onGameDefeatEvent, this); // 监听敌人相关事件 eventBus.on(GameEvents.ENEMY_UPDATE_COUNT, this.onUpdateEnemyCountEvent, this); eventBus.on(GameEvents.ENEMY_START_WAVE, this.onStartWaveEvent, this); eventBus.on(GameEvents.ENEMY_START_GAME, this.onStartGameEvent, this); eventBus.on(GameEvents.ENEMY_SHOW_START_WAVE_PROMPT, this.onShowStartWavePromptEvent, this); // 监听子弹发射检查事件 eventBus.on(GameEvents.BALL_FIRE_BULLET, this.onBallFireBulletEvent, this); // 监听获取最近敌人事件 eventBus.on(GameEvents.ENEMY_GET_NEAREST, this.onGetNearestEnemyEvent, this); // 监听重置敌人控制器事件 eventBus.on(GameEvents.RESET_ENEMY_CONTROLLER, this.onResetEnemyControllerEvent, this); // 监听重置相关事件 eventBus.on(GameEvents.CLEAR_ALL_GAME_OBJECTS, this.onClearAllGameObjectsEvent, this); eventBus.on(GameEvents.CLEAR_ALL_ENEMIES, this.onClearAllEnemiesEvent, this); eventBus.on(GameEvents.RESET_ENEMY_CONTROLLER, this.onResetEnemyControllerEvent, this); // 监听伤害事件 eventBus.on(GameEvents.APPLY_DAMAGE_TO_ENEMY, this.onApplyDamageToEnemyEvent, this); // 监听子弹击中敌人事件 eventBus.on(GameEvents.BULLET_HIT_ENEMY, this.onBulletHitEnemyEvent, this); } /** * 获取当前关卡的血量倍率 */ private async getCurrentHealthMultiplier(): Promise { // 优先使用当前波次的血量系数 if (this.currentWaveHealthMultiplier > 0) { return this.currentWaveHealthMultiplier; } if (!this.levelConfigManager) { return 1.0; } try { const saveDataManager = SaveDataManager.getInstance(); const currentLevel = saveDataManager ? saveDataManager.getCurrentLevel() : 1; const levelConfig = await this.levelConfigManager.getLevelConfig(currentLevel); if (levelConfig && levelConfig.levelSettings && levelConfig.levelSettings.healthMultiplier) { return levelConfig.levelSettings.healthMultiplier; } } catch (error) { console.warn('[EnemyController] 获取关卡血量倍率失败:', error); } return 1.0; } /** * 获取当前波次的血量倍率(从关卡配置中读取) */ private async getWaveHealthMultiplier(): Promise { if (!this.levelConfigManager) { return 1.0; } try { const saveDataManager = SaveDataManager.getInstance(); const currentLevel = saveDataManager ? saveDataManager.getCurrentLevel() : 1; const levelConfig = await this.levelConfigManager.getLevelConfig(currentLevel); if (levelConfig && levelConfig.waves && levelConfig.waves.length > 0) { // 查找当前波次的配置 const currentWaveConfig = levelConfig.waves.find(wave => wave.waveId === this.currentWave); if (currentWaveConfig && typeof currentWaveConfig.healthMultiplier === 'number') { console.log(`[EnemyController] 从关卡配置获取波次 ${this.currentWave} 血量倍率: ${currentWaveConfig.healthMultiplier}`); return currentWaveConfig.healthMultiplier; } } } catch (error) { console.warn('[EnemyController] 获取波次血量倍率失败:', error); } return 1.0; } /** * 计算最终的敌人血量倍率 * 综合考虑:关卡基础倍率 × 波次倍率 × 敌人个体倍率 */ /** * 计算最终血量倍率(关卡 × 波次) */ private async calculateFinalHealthMultiplier(): Promise { try { // 1. 获取关卡基础血量倍率 let levelMultiplier = 1.0; if (this.levelConfigManager) { const saveDataManager = SaveDataManager.getInstance(); const currentLevel = saveDataManager ? saveDataManager.getCurrentLevel() : 1; const levelConfig = await this.levelConfigManager.getLevelConfig(currentLevel); if (levelConfig && typeof levelConfig.levelSettings.healthMultiplier === 'number') { levelMultiplier = levelConfig.levelSettings.healthMultiplier; } } // 2. 获取当前波次血量倍率 const waveMultiplier = await this.getWaveHealthMultiplier(); // 3. 计算最终倍率:关卡倍率 × 波次倍率 const finalMultiplier = levelMultiplier * waveMultiplier; console.log(`[EnemyController] 血量倍率计算 - 关卡: ${levelMultiplier}, 波次: ${waveMultiplier}, 最终: ${finalMultiplier}`); return finalMultiplier; } catch (error) { console.warn('[EnemyController] 计算最终血量倍率失败:', error); return 1.0; // 返回默认倍率 } } /** * 处理游戏暂停事件 */ private onGamePauseEvent() { console.log('[EnemyController] 接收到游戏暂停事件,暂停所有敌人'); this.pauseAllEnemies(); this.pauseSpawning(); } /** * 处理游戏恢复事件 */ private onGameResumeEvent() { console.log('[EnemyController] 接收到游戏恢复事件,恢复所有敌人'); this.resumeAllEnemies(); // 通过事件检查游戏状态,决定是否恢复敌人生成 this.resumeSpawning(); } /** * 处理技能选择恢复事件 */ private onGameResumeSkillSelectionEvent() { console.log('[EnemyController] 接收到技能选择恢复事件,恢复所有敌人'); this.resumeAllEnemies(); this.resumeSpawning(); } /** * 处理底板选择恢复事件 */ private onGameResumeBlockSelectionEvent() { console.log('[EnemyController] 接收到底板选择恢复事件,恢复所有敌人'); this.resumeAllEnemies(); this.resumeSpawning(); } /** * 处理游戏结束事件 */ private onGameEndEvent() { this.stopGame(false); // 停止游戏但不清除敌人 } /** * 处理游戏失败事件 */ private onGameDefeatEvent() { this.stopGame(true); // 停止游戏并清除所有敌人 //是否是应该此时调用onGameDefeat()方法? } /** * 处理清除所有游戏对象事件 */ private onClearAllGameObjectsEvent() { this.clearAllEnemies(false); // 清除敌人但不触发事件 } /** * 处理清除所有敌人事件 * 专门响应CLEAR_ALL_ENEMIES事件,用于游戏结束时的敌人清理 */ private onClearAllEnemiesEvent() { console.log('[EnemyController] 接收到CLEAR_ALL_ENEMIES事件,开始清理所有敌人'); this.clearAllEnemies(false); // 清除敌人但不触发事件,避免循环 } /** * 处理重置敌人控制器事件 */ private onResetEnemyControllerEvent() { this.resetToInitialState(); } /** * 处理子弹发射检查事件 */ private onBallFireBulletEvent(data: { canFire: (value: boolean) => void }) { // 检查是否有活跃敌人 const hasActiveEnemies = this.hasActiveEnemies(); data.canFire(hasActiveEnemies); } /** * 处理获取最近敌人事件 */ private onGetNearestEnemyEvent(data: { position: Vec3, callback: (enemy: Node | null) => void }) { const { position, callback } = data; if (callback && typeof callback === 'function') { const nearestEnemy = this.getNearestEnemy(position); callback(nearestEnemy); } } /** * 处理对敌人造成伤害事件 */ private onApplyDamageToEnemyEvent(data: { enemyNode: Node, damage: number, isCritical: boolean, source: string }) { console.log(`[EnemyController] 接收到伤害事件 - 敌人: ${data.enemyNode.name}, 伤害: ${data.damage}, 暴击: ${data.isCritical}, 来源: ${data.source}`); if (!data.enemyNode || !data.enemyNode.isValid) { console.log(`[EnemyController] 敌人节点无效,跳过伤害处理`); return; } // 调用现有的damageEnemy方法 this.damageEnemy(data.enemyNode, data.damage, data.isCritical); } /** * 处理子弹击中敌人事件 */ private onBulletHitEnemyEvent(data: { enemyNode: Node, damage: number, isCritical: boolean, source: string }) { console.log(`[EnemyController] 接收到子弹击中敌人事件 - 敌人: ${data.enemyNode.name}, 伤害: ${data.damage}, 暴击: ${data.isCritical}, 来源: ${data.source}`); if (!data.enemyNode || !data.enemyNode.isValid) { console.log(`[EnemyController] 敌人节点无效,跳过伤害处理`); return; } // 调用现有的damageEnemy方法 this.damageEnemy(data.enemyNode, data.damage, data.isCritical); } /** * 暂停所有敌人 */ private pauseAllEnemies(): void { const activeEnemies = this.getActiveEnemies(); console.log(`[EnemyController] 暂停 ${activeEnemies.length} 个敌人`); for (const enemy of activeEnemies) { if (!enemy || !enemy.isValid) continue; // 保存敌人状态 - 从EnemySprite子节点获取RigidBody2D const enemySprite = enemy.getChildByName('EnemySprite'); if (!enemySprite) { console.error('[EnemyController] pauseAllEnemies: 未找到EnemySprite子节点'); continue; } const rigidBody = enemySprite.getComponent(RigidBody2D); if (rigidBody) { this.pausedEnemyStates.set(enemy, { velocity: rigidBody.linearVelocity.clone(), angularVelocity: rigidBody.angularVelocity, isMoving: true, attackTimer: 0 // 可以扩展保存攻击计时器 }); // 停止敌人运动 - 使用更温和的方式 rigidBody.linearVelocity.set(0, 0); rigidBody.angularVelocity = 0; // 不强制让刚体休眠,避免物理系统状态异常 // rigidBody.sleep(); } // 暂停EnemyInstance组件 const enemyInstance = enemy.getComponent('EnemyInstance'); if (enemyInstance && typeof (enemyInstance as any).pause === 'function') { (enemyInstance as any).pause(); } // 暂停敌人AI组件(如果有的话) const enemyAI = enemy.getComponent('EnemyAI'); if (enemyAI && typeof (enemyAI as any).pause === 'function') { (enemyAI as any).pause(); } // 暂停敌人动画(如果有的话) const animation = enemy.getComponent('Animation'); if (animation && typeof (animation as any).pause === 'function') { (animation as any).pause(); } } } /** * 恢复所有敌人 */ private resumeAllEnemies(): void { const activeEnemies = this.getActiveEnemies(); for (const enemy of activeEnemies) { if (!enemy || !enemy.isValid) continue; const savedState = this.pausedEnemyStates.get(enemy); if (savedState) { // 从EnemySprite子节点获取RigidBody2D const enemySprite = enemy.getChildByName('EnemySprite'); if (!enemySprite) { console.error('[EnemyController] resumeAllEnemies: 未找到EnemySprite子节点'); continue; } const rigidBody = enemySprite.getComponent(RigidBody2D); if (rigidBody) { // 恢复敌人运动 rigidBody.wakeUp(); rigidBody.linearVelocity = savedState.velocity; rigidBody.angularVelocity = savedState.angularVelocity; } } // 恢复EnemyInstance组件 const enemyInstance = enemy.getComponent('EnemyInstance'); if (enemyInstance && typeof (enemyInstance as any).resume === 'function') { (enemyInstance as any).resume(); } // 恢复敌人AI组件 const enemyAI = enemy.getComponent('EnemyAI'); if (enemyAI && typeof (enemyAI as any).resume === 'function') { (enemyAI as any).resume(); } // 恢复敌人动画 const animation = enemy.getComponent('Animation'); if (animation && typeof (animation as any).resume === 'function') { (animation as any).resume(); } } // 清空保存的状态 this.pausedEnemyStates.clear(); } // 计算游戏区域边界 private calculateGameBounds() { const gameArea = find('Canvas/GameLevelUI/GameArea'); if (!gameArea) { return; } const uiTransform = gameArea.getComponent(UITransform); if (!uiTransform) { return; } const worldPos = gameArea.worldPosition; const width = uiTransform.width; const height = uiTransform.height; this.gameBounds = { left: worldPos.x - width / 2, right: worldPos.x + width / 2, top: worldPos.y + height / 2, bottom: worldPos.y - height / 2 }; } // 查找墙体节点 private findWallNodes() { const gameArea = find('Canvas/GameLevelUI/GameArea'); if (gameArea) { this.wallNodes = []; for (let i = 0; i < gameArea.children.length; i++) { const child = gameArea.children[i]; if (child.name.includes('Wall') || child.name.includes('wall') || child.name.includes('墙')) { this.wallNodes.push(child); } } } } /** * 查找墙体组件 */ private findWallComponent() { // 查找墙体节点上的Wall组件 for (const wallNode of this.wallNodes) { this.wallComponent = wallNode.getComponent(Wall); if (this.wallComponent) { break; } } } // 移除 initWallHealthDisplay 和 updateWallHealthDisplay 方法,这些现在由Wall组件处理 // 确保enemyContainer节点存在 ensureEnemyContainer() { // 如果已经通过拖拽设置了节点,直接使用 if (this.enemyContainer && this.enemyContainer.isValid) { return; } // 尝试查找节点 this.enemyContainer = find('Canvas/GameLevelUI/enemyContainer'); if (this.enemyContainer) { return; } // 如果找不到,创建新节点 const gameLevelUI = find('Canvas/GameLevelUI'); if (!gameLevelUI) { console.error('找不到GameLevelUI节点,无法创建enemyContainer'); return; } this.enemyContainer = new Node('enemyContainer'); gameLevelUI.addChild(this.enemyContainer); if (!this.enemyContainer.getComponent(UITransform)) { this.enemyContainer.addComponent(UITransform); } } // 游戏开始 startGame() { // 游戏状态检查现在通过事件系统处理 this.gameStarted = true; // 确保enemyContainer节点存在 this.ensureEnemyContainer(); // 确保先取消之前的定时器,避免重复调度 this.unschedule(this.spawnEnemy); // 播放游戏开始音效 Audio.playUISound('data/弹球音效/start zombie'); // 立即生成第一个敌人,与音效同步 this.spawnEnemy(); // 然后按间隔生成后续敌人 this.schedule(this.spawnEnemy, this.spawnInterval); // 触发敌人生成开始事件 const eventBus = EventBus.getInstance(); eventBus.emit(GameEvents.ENEMY_SPAWNING_STARTED); } // 游戏结束 stopGame(clearEnemies: boolean = true) { this.gameStarted = false; // 停止生成敌人 this.unschedule(this.spawnEnemy); // 触发敌人生成停止事件 const eventBus = EventBus.getInstance(); eventBus.emit(GameEvents.ENEMY_SPAWNING_STOPPED); // 只有在指定时才清除所有敌人 if (clearEnemies) { // 清除敌人,在重置状态时不触发事件,避免错误的游戏成功判定 this.clearAllEnemies(false); } } // 生成敌人 async spawnEnemy() { if (!this.gameStarted || !this.enemyPrefab) { return; } // 游戏状态检查现在通过事件系统处理 // 检查是否已达到当前波次的敌人生成上限 if (this.currentWaveEnemiesSpawned >= this.currentWaveTotalEnemies) { this.unschedule(this.spawnEnemy); // 停止定时生成 return; } // 随机选择从Line1或Line2生成 const fromTop = Math.random() > 0.5; // 实例化敌人 const enemy = instantiate(this.enemyPrefab) as Node; enemy.name = 'Enemy'; // 确保敌人节点名称为Enemy // 添加到场景中 const enemyContainer = find('Canvas/GameLevelUI/enemyContainer'); if (!enemyContainer) { return; } enemyContainer.addChild(enemy); // 根据随机选择生成在对应线上的随机位置 const lineName = fromTop ? 'Line1' : 'Line2'; const lineNode = enemyContainer.getChildByName(lineName); if (!lineNode) { console.warn(`[EnemyController] 未找到 ${lineName} 节点,取消本次敌人生成`); enemy.destroy(); return; } // 在对应线上随机 X 坐标 const spawnWorldX = this.gameBounds.left + Math.random() * (this.gameBounds.right - this.gameBounds.left); const spawnWorldY = lineNode.worldPosition.y; // 根据生成位置计算漂移目标位置 let driftWorldX = spawnWorldX; let driftWorldY = spawnWorldY; // 获取漂移目标线节点 let targetLineNode: Node = null; if (fromTop) { // 从Line1生成,漂移到Line5 targetLineNode = this.line5Node || enemyContainer.getChildByName('Line5'); console.log(`[EnemyController] 从Line1生成敌人,查找Line5节点: this.line5Node=${!!this.line5Node}, 通过名称查找=${!!enemyContainer.getChildByName('Line5')}`); } else { // 从Line2生成,漂移到Line6 targetLineNode = this.line6Node || enemyContainer.getChildByName('Line6'); console.log(`[EnemyController] 从Line2生成敌人,查找Line6节点: this.line6Node=${!!this.line6Node}, 通过名称查找=${!!enemyContainer.getChildByName('Line6')}`); } if (targetLineNode && targetLineNode.isValid) { // 使用目标线的Y坐标作为漂移目标 driftWorldY = targetLineNode.worldPosition.y; console.log(`[EnemyController] 使用新逻辑:目标线节点找到`); console.log(`[EnemyController] 节点名称: ${targetLineNode.name}`); console.log(`[EnemyController] 本地坐标Y: ${targetLineNode.position.y}`); console.log(`[EnemyController] 世界坐标Y: ${targetLineNode.worldPosition.y}`); console.log(`[EnemyController] 漂移目标Y坐标: ${driftWorldY}`); } else { console.log(`[EnemyController] 目标线节点未找到或无效,使用旧逻辑(屏幕边界)`); // 如果找不到目标线节点,回退到原来的屏幕边界逻辑 const canvas = find('Canvas'); if (canvas) { const canvasUI = canvas.getComponent(UITransform); if (canvasUI) { const screenHeight = canvasUI.height; const canvasWorldPos = canvas.worldPosition; if (fromTop) { // 从Line1生成,漂移到屏幕上边界位置-30px const screenTop = canvasWorldPos.y + screenHeight / 2; driftWorldY = screenTop - 30; console.log(`[EnemyController] 旧逻辑:从Line1漂移到屏幕上边界,Y坐标: ${driftWorldY}`); } else { // 从Line2生成,漂移到屏幕下边界位置+30px const screenBottom = canvasWorldPos.y - screenHeight / 2; driftWorldY = screenBottom + 30; console.log(`[EnemyController] 旧逻辑:从Line2漂移到屏幕下边界,Y坐标: ${driftWorldY}`); } } } } // 设置初始位置(线上的位置) const initialWorldPos = new Vec3(spawnWorldX, spawnWorldY, 0); const initialLocalPos = enemyContainer.getComponent(UITransform).convertToNodeSpaceAR(initialWorldPos); enemy.position = initialLocalPos; // 记录漂移目标位置(墙体附近的位置) const driftWorldPos = new Vec3(driftWorldX, driftWorldY, 0); // === 根据配置设置敌人 === // 检查是否已经存在EnemyInstance组件,避免重复添加 let enemyComp = enemy.getComponent(EnemyInstance); if (!enemyComp) { enemyComp = enemy.addComponent(EnemyInstance); } // 确保敌人数据库已加载 await EnemyInstance.loadEnemyDatabase(); let enemyConfig: EnemyConfig = null; let enemyId: string = null; if (this.configManager && this.configManager.isConfigLoaded()) { // 优先使用当前波次配置中的敌人类型 if (this.currentWaveEnemyConfigs.length > 0) { // 修复:根据每种敌人的count配置来选择敌人类型,而不是简单的循环选择 let selectedEnemyType = null; let cumulativeCount = 0; for (const enemyTypeConfig of this.currentWaveEnemyConfigs) { cumulativeCount += enemyTypeConfig.count || 1; if (this.currentWaveEnemiesSpawned < cumulativeCount) { selectedEnemyType = enemyTypeConfig; break; } } if (selectedEnemyType) { const enemyType = selectedEnemyType.enemyType || selectedEnemyType; enemyId = enemyType; console.log(`[EnemyController] 使用敌人类型: ${enemyType} 作为敌人ID (已生成: ${this.currentWaveEnemiesSpawned})`); enemyConfig = this.configManager.getEnemyById(enemyId) || this.configManager.getRandomEnemy(); } else { // 如果超出了配置的敌人数量,使用随机敌人 enemyConfig = this.configManager.getRandomEnemy(); enemyId = enemyConfig?.id || 'normal_zombie'; console.warn(`[EnemyController] 超出配置的敌人数量,使用随机敌人: ${enemyId}`); } } else { enemyConfig = this.configManager.getRandomEnemy(); enemyId = enemyConfig?.id || 'normal_zombie'; } } // 计算最终血量倍率(关卡 × 波次) const finalHealthMultiplier = await this.calculateFinalHealthMultiplier(); if (enemyConfig && enemyId) { try { const cfgComp = enemy.addComponent(EnemyComponent); cfgComp.enemyConfig = enemyConfig; cfgComp.spawner = this; } catch (error) { console.error(`[EnemyController] 添加EnemyComponent失败:`, error); } // 使用EnemyInstance的新配置系统 try { // 设置敌人配置 enemyComp.setEnemyConfig(enemyId); // 应用血量倍率 const baseHealth = enemyComp.health || this.defaultHealth; const finalHealth = Math.round(baseHealth * finalHealthMultiplier); enemyComp.health = finalHealth; enemyComp.maxHealth = finalHealth; console.log(`[EnemyController] 敌人 ${enemyId} 配置已应用,血量: ${finalHealth} (最终倍率: ${finalHealthMultiplier})`); } catch (error) { console.error(`[EnemyController] 应用敌人配置时出错:`, error); // 使用默认值 const finalHealth = Math.round(this.defaultHealth * finalHealthMultiplier); enemyComp.health = finalHealth; enemyComp.maxHealth = finalHealth; enemyComp.speed = this.defaultEnemySpeed; enemyComp.attackPower = this.defaultAttackPower; } // 加载动画 this.loadEnemyAnimation(enemy, enemyConfig); } else { // 使用默认配置 try { enemyComp.setEnemyConfig('normal_zombie'); // 默认敌人类型 const baseHealth = enemyComp.health || this.defaultHealth; const finalHealth = Math.round(baseHealth * finalHealthMultiplier); enemyComp.health = finalHealth; enemyComp.maxHealth = finalHealth; } catch (error) { console.error(`[EnemyController] 应用默认敌人配置时出错:`, error); // 使用硬编码默认值 const finalHealth = Math.round(this.defaultHealth * finalHealthMultiplier); enemyComp.health = finalHealth; enemyComp.maxHealth = finalHealth; enemyComp.speed = this.defaultEnemySpeed; enemyComp.attackPower = this.defaultAttackPower; } } // 额外的属性设置 enemyComp.spawnFromTop = fromTop; enemyComp.targetFence = fromTop ? find('Canvas/GameLevelUI/GameArea/TopFence') : find('Canvas/GameLevelUI/GameArea/BottomFence'); // 设置漂移目标位置(墙体附近的位置) enemyComp.driftTargetPosition = driftWorldPos.clone(); // 计算墙体上的随机目标位置 if (enemyComp.targetFence && enemyComp.targetFence.isValid) { const fenceWorldPos = enemyComp.targetFence.worldPosition.clone(); const fenceTransform = enemyComp.targetFence.getComponent(UITransform); if (fenceTransform) { // 在墙体宽度范围内随机选择X坐标 const fenceWidth = fenceTransform.width; const randomX = fenceWorldPos.x + (Math.random() - 0.5) * fenceWidth * 0.8; // 0.8是为了避免太靠近边缘 enemyComp.targetPosition = new Vec3(randomX, fenceWorldPos.y, fenceWorldPos.z); } else { // 如果无法获取墙体尺寸,使用墙体中心位置 enemyComp.targetPosition = fenceWorldPos; } } enemyComp.movingDirection = Math.random() > 0.5 ? 1 : -1; enemyComp.targetY = fromTop ? this.gameBounds.top - 50 : this.gameBounds.bottom + 50; enemyComp.changeDirectionTime = 0; enemyComp.controller = this; // 更新敌人血量显示 enemyComp.updateHealthDisplay(); // 添加到活跃敌人列表 this.activeEnemies.push(enemy); // 增加已生成敌人计数 this.currentWaveEnemiesSpawned++; // 生成敌人时不更新敌人数量显示,避免重置计数 } // 清除所有敌人 clearAllEnemies(triggerEvents: boolean = true) { // 设置清理标志,阻止清理过程中触发游戏胜利判断 if (!triggerEvents) { this.isClearing = true; } // 如果不触发事件,先暂时禁用 notifyEnemyDead 方法 const originalNotifyMethod = this.notifyEnemyDead; if (!triggerEvents) { // 临时替换为空函数 this.notifyEnemyDead = () => {}; } for (const enemy of this.activeEnemies) { if (enemy && enemy.isValid) { enemy.destroy(); } } // 恢复原来的方法 if (!triggerEvents) { this.notifyEnemyDead = originalNotifyMethod; } this.activeEnemies = []; // 重置清理标志 if (!triggerEvents) { this.isClearing = false; } // 清除敌人时不更新敌人数量显示,避免重置计数 } // 获取所有活跃的敌人 getActiveEnemies(): Node[] { // 过滤掉已经无效的敌人 this.activeEnemies = this.activeEnemies.filter(enemy => enemy && enemy.isValid); return this.activeEnemies; } // 获取当前敌人数量 getCurrentEnemyCount(): number { return this.getActiveEnemies().length; } // 获取最近的敌人节点(排除漂移状态的敌人) public getNearestEnemy(fromPosition: Vec3): Node | null { const enemies = this.getActiveEnemies(); if (enemies.length === 0) return null; // 过滤掉漂移状态和不可攻击(隐身等状态)的敌人 const attackStateManager = EnemyAttackStateManager.getInstance(); const nonDriftingEnemies = enemies.filter(enemy => { const enemyInstance = enemy.getComponent('EnemyInstance') as any; const notDrifting = !enemyInstance || !enemyInstance.isDrifting(); const attackable = attackStateManager ? attackStateManager.isEnemyAttackable(enemy) : true; return notDrifting && attackable; }); if (nonDriftingEnemies.length === 0) return null; let nearestEnemy: Node = null; let nearestDistance = Infinity; for (const enemy of nonDriftingEnemies) { const distance = Vec3.distance(fromPosition, enemy.worldPosition); if (distance < nearestDistance) { nearestDistance = distance; nearestEnemy = enemy; } } return nearestEnemy; } // 检查是否有活跃敌人(排除漂移状态的敌人) public hasActiveEnemies(): boolean { const activeEnemies = this.getActiveEnemies(); // 过滤掉漂移状态的敌人 const nonDriftingEnemies = activeEnemies.filter(enemy => { const enemyInstance = enemy.getComponent('EnemyInstance') as any; return !enemyInstance || !enemyInstance.isDrifting(); }); return nonDriftingEnemies.length > 0; } // 调试方法:检查enemyContainer中的实际敌人节点 private debugEnemyContainer() { const enemyContainer = find('Canvas/GameLevelUI/enemyContainer'); if (!enemyContainer) { return; } let enemyNodeCount = 0; enemyContainer.children.forEach((child, index) => { if (child.name === 'Enemy' || child.name.includes('Enemy')) { enemyNodeCount++; } }); } // 调试方法:强制清理无效敌人引用 public debugCleanupEnemies() { const beforeCount = this.activeEnemies.length; this.activeEnemies = this.activeEnemies.filter(enemy => enemy && enemy.isValid); const afterCount = this.activeEnemies.length; return afterCount; } // 获取游戏是否已开始状态 public isGameStarted(): boolean { return this.gameStarted; } // 暂停生成敌人 public pauseSpawning(): void { if (this.gameStarted) { this.unschedule(this.spawnEnemy); // 触发敌人生成停止事件 const eventBus = EventBus.getInstance(); eventBus.emit(GameEvents.ENEMY_SPAWNING_STOPPED); } } // 恢复生成敌人 public resumeSpawning(): void { // 游戏状态检查现在通过事件系统处理 if (!this.gameStarted) { return; } // 检查是否已达到当前波次的敌人生成上限 if (this.currentWaveEnemiesSpawned >= this.currentWaveTotalEnemies) { return; } // 确保先取消之前的定时器,避免重复调度 this.unschedule(this.spawnEnemy); this.schedule(this.spawnEnemy, this.spawnInterval); // 触发敌人生成开始事件 const eventBus = EventBus.getInstance(); eventBus.emit(GameEvents.ENEMY_SPAWNING_STARTED); } // 敌人受到伤害 damageEnemy(enemy: Node, damage: number, isCritical: boolean = false) { if (!enemy || !enemy.isValid) return; // 游戏状态检查现在通过事件系统处理 // 获取敌人组件 const enemyComp = enemy.getComponent(EnemyInstance); if (!enemyComp) return; // 检查是否可攻击(隐身等状态不可被攻击) const attackStateManager = EnemyAttackStateManager.getInstance(); if (attackStateManager && !attackStateManager.isEnemyAttackable(enemy)) { console.log(`[EnemyController] 敌人不可攻击,跳过伤害: ${enemy.name}`); return; } // 减少敌人血量 enemyComp.takeDamage(damage, isCritical); // 检查敌人是否死亡 if (enemyComp.health <= 0) { // 从活跃敌人列表中移除 const index = this.activeEnemies.indexOf(enemy); if (index !== -1) { this.activeEnemies.splice(index, 1); } // 清理敌人身上的所有灼烧效果,防止定时器继续运行 try { const burnEffect = enemy.getComponent(BurnEffect); if (burnEffect) { console.log(`[EnemyController] 清理敌人身上的灼烧效果`); // 先停止灼烧效果,再移除组件 burnEffect.stopBurnEffect(); enemy.removeComponent(BurnEffect); } } catch (error) { console.warn(`[EnemyController] 清理灼烧效果时出错:`, error); } // 敌人死亡时不在这里更新数量显示,由GameManager统一管理 // 延迟销毁敌人,避免在物理碰撞监听器中直接销毁导致的刚体激活错误 this.scheduleOnce(() => { if (enemy && enemy.isValid) { enemy.destroy(); } }, 0); } } // 墙体受到伤害 - 现在委托给Wall组件 damageWall(damage: number) { if (this.wallComponent) { this.wallComponent.takeDamage(damage); } else { console.warn('[EnemyController] 墙体组件未找到,无法处理伤害'); } } // 游戏结束 gameOver() { // 停止游戏,但不清除敌人 this.stopGame(false); // 通过事件系统触发游戏失败 const eventBus = EventBus.getInstance(); eventBus.emit(GameEvents.GAME_DEFEAT); } update(dt: number) { if (!this.gameStarted) return; // 更新所有敌人 for (let i = this.activeEnemies.length - 1; i >= 0; i--) { const enemy = this.activeEnemies[i]; if (!enemy || !enemy.isValid) { this.activeEnemies.splice(i, 1); continue; } // 敌人更新由各自的组件处理 // 不再需要检查敌人是否到达墙体,因为敌人到达游戏区域后会自动攻击 // 敌人的攻击逻辑已经在EnemyInstance中处理 } } public getCurrentWallHealth(): number { return this.wallComponent ? this.wallComponent.getCurrentHealth() : 0; } public forceEnemyAttack() { const activeEnemies = this.getActiveEnemies(); for (const enemy of activeEnemies) { const enemyComp = enemy.getComponent(EnemyInstance); if (enemyComp) { // 直接调用damageWall方法进行测试 this.damageWall(enemyComp.attackPower); } } } /** 供 EnemyInstance 在 onDestroy 中调用 */ public notifyEnemyDead(enemyNode?: Node) { // 如果正在清理敌人,不触发任何游戏事件 if (this.isClearing) { if (enemyNode) { const idx = this.activeEnemies.indexOf(enemyNode); if (idx !== -1) { this.activeEnemies.splice(idx, 1); } } return; } if (enemyNode) { const idx = this.activeEnemies.indexOf(enemyNode); if (idx !== -1) { this.activeEnemies.splice(idx, 1); } else { console.log(`[EnemyController] 警告:尝试移除的敌人不在activeEnemies数组中!`); } // 移除EnemyController内部的击杀计数,统一由GameManager管理 // this.currentWaveEnemiesKilled++; // 敌人死亡通知时不更新数量显示,由GameManager统一管理 } // 直接通过事件总线发送ENEMY_KILLED事件,避免通过GamePause的双重调用 const eventBus = EventBus.getInstance(); eventBus.emit('ENEMY_KILLED'); } /** * 加载敌人骨骼动画 */ private loadEnemyAnimation(enemyNode: Node, enemyConfig: EnemyConfig) { console.log(`[EnemyController] 开始加载敌人动画,敌人ID: ${enemyConfig?.id}, 敌人名称: ${enemyConfig?.name}`); if (!enemyConfig || !enemyConfig.visualConfig) { console.warn('[EnemyController] 敌人配置或视觉配置缺失,使用默认动画'); return; } let spinePath: string | undefined = enemyConfig.visualConfig?.spritePath; console.log(`[EnemyController] 敌人 ${enemyConfig.id} 的spritePath: ${spinePath}`); if (!spinePath) { console.warn('[EnemyController] 敌人精灵路径缺失'); return; } if (spinePath.startsWith('@EnemyAni')) { spinePath = spinePath.replace('@EnemyAni', 'Animation/EnemyAni'); } if (spinePath.startsWith('@')) { spinePath = spinePath.substring(1); } // 对于Animation/EnemyAni路径,需要添加子目录和文件名 // 例如:Animation/EnemyAni/007 -> Animation/EnemyAni/007/007 if (spinePath.startsWith('Animation/EnemyAni/')) { const parts = spinePath.split('/'); if (parts.length === 3) { const animId = parts[2]; spinePath = `${spinePath}/${animId}`; } } // 移除Animation/前缀,因为BundleLoader会从Bundle中加载 if (spinePath.startsWith('Animation/')) { spinePath = spinePath.replace('Animation/', ''); } console.log(`[EnemyController] 最终加载路径: ${spinePath}`); // 优先使用预加载的资源 let skeletonData = this.resourcePreloader.getPreloadedEnemyAnimation(spinePath); if (skeletonData) { console.log(`[EnemyController] 使用预加载的敌人动画: ${spinePath}`); this.applySkeletonData(enemyNode, enemyConfig, skeletonData); } else { console.log(`[EnemyController] 预加载资源未找到,动态加载: ${spinePath}`); BundleLoader.loadSkeletonData(spinePath).then((dynamicSkeletonData) => { if (!dynamicSkeletonData) { console.warn(`加载敌人Spine动画失败: ${spinePath}`); return; } this.applySkeletonData(enemyNode, enemyConfig, dynamicSkeletonData); }); } } /** * 应用骨骼动画数据到敌人节点 */ private applySkeletonData(enemyNode: Node, enemyConfig: EnemyConfig, skeletonData: any) { // 获取EnemySprite子节点 const enemySprite = enemyNode.getChildByName('EnemySprite'); if (!enemySprite) { console.error('[EnemyController] 未找到EnemySprite子节点,无法设置骨骼动画'); return; } let skeleton = enemySprite.getComponent(sp.Skeleton); if (!skeleton) { skeleton = enemySprite.addComponent(sp.Skeleton); } skeleton.skeletonData = skeletonData; const anims = enemyConfig.visualConfig.animations; const walkName = anims?.walk ?? 'walk'; const idleName = anims?.idle ?? 'idle'; if (skeleton.findAnimation(walkName)) { skeleton.setAnimation(0, walkName, true); } else if (skeleton.findAnimation(idleName)) { skeleton.setAnimation(0, idleName, true); } else { console.warn(`[EnemyController] 未找到合适的动画,walk: ${walkName}, idle: ${idleName}`); } } // 更新敌人数量显示 public updateEnemyCountLabel(killedCount?: number) { if (!this.enemyCountLabelNode) { console.warn('[EnemyController] enemyCountLabelNode 未找到,无法更新敌人数量显示'); return; } const label = this.enemyCountLabelNode.getComponent(Label); if (label) { // 计算剩余敌人数量:总数 - 击杀数量 let remaining: number; if (killedCount !== undefined) { // 使用传入的击杀数量计算剩余数量 remaining = Math.max(0, this.currentWaveTotalEnemies - killedCount); } else { // 如果没有传入击杀数量,则显示当前波次总敌人数(初始状态) remaining = this.currentWaveTotalEnemies; } label.string = remaining.toString(); } else { console.warn('[EnemyController] enemyCountLabelNode 上未找到 Label 组件'); } } public startWave(waveNum: number, totalWaves: number, totalEnemies: number, waveEnemyConfigs?: any[], waveHealthMultiplier?: number) { this.currentWave = waveNum; this.totalWaves = totalWaves; this.currentWaveTotalEnemies = totalEnemies; this.currentWaveEnemiesSpawned = 0; // 重置已生成敌人计数器 this.currentWaveEnemyConfigs = waveEnemyConfigs || []; // 存储当前波次的敌人配置 this.currentWaveHealthMultiplier = waveHealthMultiplier || 1.0; // 设置当前波次的血量系数 // 移除EnemyController内部的击杀计数重置,统一由GameManager管理 // this.currentWaveEnemiesKilled = 0; // 修复问题1:根据波次配置设置生成间隔 if (this.currentWaveEnemyConfigs.length > 0) { // 使用第一个敌人配置的spawnInterval,如果有多个配置可以取平均值或最小值 const firstEnemyConfig = this.currentWaveEnemyConfigs[0]; if (firstEnemyConfig && typeof firstEnemyConfig.spawnInterval === 'number') { this.spawnInterval = firstEnemyConfig.spawnInterval; console.log(`[EnemyController] 设置生成间隔为: ${this.spawnInterval}`); } } console.log(`[EnemyController] 开始波次 ${waveNum}/${totalWaves},需要生成 ${totalEnemies} 个敌人`); console.log(`[EnemyController] 波次敌人配置:`, this.currentWaveEnemyConfigs); console.log(`[EnemyController] 当前生成间隔: ${this.spawnInterval}`); this.updateWaveLabel(); this.updateEnemyCountLabel(); // 移除startWaveUI的隐藏,因为现在使用Toast预制体 // if (this.startWaveUI) this.startWaveUI.active = false; } private updateWaveLabel() { // 更新当前波数显示 if (this.currentWaveNumberLabelNode) { const currentLabel = this.currentWaveNumberLabelNode.getComponent(Label); if (currentLabel) { currentLabel.string = this.currentWave.toString(); } else { console.warn('[EnemyController] currentWaveNumberLabelNode 上未找到 Label 组件'); } } else { console.warn('[EnemyController] currentWaveNumberLabelNode 未找到,无法更新当前波次标签'); } // 更新总波数显示 if (this.totalWaveNumberLabelNode) { const totalLabel = this.totalWaveNumberLabelNode.getComponent(Label); if (totalLabel) { totalLabel.string = this.totalWaves.toString(); } else { console.warn('[EnemyController] totalWaveNumberLabelNode 上未找到 Label 组件'); } } else { console.warn('[EnemyController] totalWaveNumberLabelNode 未找到,无法更新总波次标签'); } } /** 显示每波开始提示,随后开启敌人生成 */ public showStartWavePromptUI(duration: number = 2) { // 通过事件系统检查游戏是否已经结束 let gameOver = false; EventBus.getInstance().emit(GameEvents.GAME_CHECK_OVER, (isOver: boolean) => { gameOver = isOver; }); if (gameOver) { return; } // 暂停敌人生成,确保在Toast显示期间不会生成敌人 this.pauseSpawning(); // 使用事件机制显示Toast const toastText = `第${this.currentWave}波敌人来袭!`; EventBus.getInstance().emit(GameEvents.SHOW_TOAST, { message: toastText, duration: duration }); // 等待Toast消息播放结束后再开始生成敌人 if (duration > 0) { this.scheduleOnce(() => { // 再次检查游戏状态,确保游戏未结束 let gameOverCheck = false; EventBus.getInstance().emit(GameEvents.GAME_CHECK_OVER, (isOver: boolean) => { gameOverCheck = isOver; }); if (gameOverCheck) { return; } // Toast播放完毕,开始生成敌人 this.startGame(); }, duration); } else { // 如果duration为0,立即开始游戏 this.startGame(); } } /** * 重置到初始状态 * 用于游戏重新开始时重置所有敌人相关状态 */ public resetToInitialState(): void { // 停止游戏并清理所有敌人 this.stopGame(true); // 重置波次信息 this.currentWave = 1; this.totalWaves = 1; this.currentWaveTotalEnemies = 0; this.currentWaveEnemiesKilled = 0; this.currentWaveEnemiesSpawned = 0; this.currentWaveEnemyConfigs = []; // 重置血量倍率 this.currentHealthMultiplier = 1.0; this.currentWaveHealthMultiplier = 1.0; // 清空暂停状态 this.pausedEnemyStates.clear(); // 重置UI显示 this.updateEnemyCountLabel(); this.updateWaveLabel(); } /** * 处理更新敌人计数事件 */ private onUpdateEnemyCountEvent(killedCount: number) { this.updateEnemyCountLabel(killedCount); } /** * 处理启动波次事件 */ private onStartWaveEvent(data: { wave: number; totalWaves: number; enemyCount: number; waveEnemyConfigs: any[]; healthMultiplier?: number }) { this.startWave(data.wave, data.totalWaves, data.enemyCount, data.waveEnemyConfigs, data.healthMultiplier); } /** * 处理启动游戏事件 */ private onStartGameEvent() { this.startGame(); } /** * 处理显示波次提示事件 */ private onShowStartWavePromptEvent() { this.showStartWavePromptUI(); } onDestroy() { // 清理事件监听 const eventBus = EventBus.getInstance(); eventBus.off(GameEvents.GAME_PAUSE, this.onGamePauseEvent, this); eventBus.off(GameEvents.GAME_PAUSE_SKILL_SELECTION, this.onGamePauseEvent, this); eventBus.off(GameEvents.GAME_PAUSE_BLOCK_SELECTION, this.onGamePauseEvent, this); eventBus.off(GameEvents.GAME_RESUME, this.onGameResumeEvent, this); eventBus.off(GameEvents.GAME_RESUME_SKILL_SELECTION, this.onGameResumeSkillSelectionEvent, this); eventBus.off(GameEvents.GAME_RESUME_BLOCK_SELECTION, this.onGameResumeBlockSelectionEvent, this); eventBus.off(GameEvents.GAME_SUCCESS, this.onGameEndEvent, this); eventBus.off(GameEvents.GAME_DEFEAT, this.onGameEndEvent, this); eventBus.off(GameEvents.CLEAR_ALL_GAME_OBJECTS, this.onClearAllGameObjectsEvent, this); eventBus.off(GameEvents.CLEAR_ALL_ENEMIES, this.onClearAllEnemiesEvent, this); eventBus.off(GameEvents.RESET_ENEMY_CONTROLLER, this.onResetEnemyControllerEvent, this); // 清理新增的事件监听 eventBus.off(GameEvents.ENEMY_UPDATE_COUNT, this.onUpdateEnemyCountEvent, this); eventBus.off(GameEvents.ENEMY_START_WAVE, this.onStartWaveEvent, this); eventBus.off(GameEvents.ENEMY_START_GAME, this.onStartGameEvent, this); eventBus.off(GameEvents.ENEMY_SHOW_START_WAVE_PROMPT, this.onShowStartWavePromptEvent, this); // 清空状态 this.pausedEnemyStates.clear(); } }