Bladeren bron

能量条重置优化

181404010226 5 maanden geleden
bovenliggende
commit
dde38ad48a

+ 166 - 0
EventBus事件使用分析报告.md

@@ -0,0 +1,166 @@
+# EventBus事件使用分析报告
+
+## 概述
+根据`游戏管理.txt`文档要求和EventBus事件定义,本报告分析了当前事件系统的使用情况,并提出改进建议。
+
+## 事件使用情况分析
+
+### 1. 已正确使用的事件
+
+#### 游戏状态事件
+- ✅ `GAME_START` - 在GameBlockSelection、IN_game、GameManager中正确触发和监听
+- ✅ `GAME_PAUSE` - 在GamePause、IN_game中正确使用
+- ✅ `GAME_RESUME` - 在GameBlockSelection、GamePause中正确使用
+- ✅ `GAME_SUCCESS` - 在GamePause、IN_game中触发,在GameManager、UIStateManager中监听
+- ✅ `GAME_DEFEAT` - 在GamePause、IN_game中触发,在GameManager、UIStateManager中监听
+
+#### 重置事件(完整实现)
+- ✅ `GAME_RESTART` - 在GameManager中触发,在StartGame中监听
+- ✅ `RESET_GAME_MANAGER` - 在StartGame、GameManager中触发和监听
+- ✅ `RESET_ENEMY_CONTROLLER` - 在StartGame中触发,在EnemyController中监听
+- ✅ `RESET_BALL_CONTROLLER` - 在IN_game、StartGame中触发,在BallController中监听
+- ✅ `RESET_BLOCK_MANAGER` - 在IN_game、StartGame中触发,在BlockManager中监听
+- ✅ `RESET_BLOCK_SELECTION` - 在IN_game、StartGame中触发,在GameBlockSelection中监听
+- ✅ `RESET_WALL_HEALTH` - 在IN_game、StartGame中触发,在Wall中监听
+- ✅ `RESET_GAME_PAUSE` - 在StartGame中触发,在GamePause中监听
+- ✅ `RESET_ENERGY_SYSTEM` - 在StartGame、IN_game中触发和监听
+
+#### 清理事件
+- ✅ `CLEAR_ALL_ENEMIES` - 在IN_game中触发
+- ✅ `CLEAR_ALL_BULLETS` - 在IN_game中触发
+- ✅ `CLEAR_ALL_GAME_OBJECTS` - 在StartGame、IN_game中触发,在EnemyController中监听
+
+#### 球控制事件
+- ✅ `BALL_START` - 在IN_game、GameManager中触发,在BallController中监听
+- ✅ `BALL_CREATE` - 在BallController中监听
+- ✅ `BALL_FIRE_BULLET` - 在WeaponBullet中触发,在GamePause、EnemyController中监听
+
+#### 敌人控制事件
+- ✅ `ENEMY_START_GAME` - 在IN_game中触发,在EnemyController中监听
+- ✅ `ENEMY_START_WAVE` - 在IN_game中触发,在EnemyController中监听
+- ✅ `ENEMY_SHOW_START_WAVE_PROMPT` - 在IN_game、GameManager中触发,在EnemyController中监听
+- ✅ `ENEMY_UPDATE_COUNT` - 在IN_game中触发,在EnemyController中监听
+- ✅ `ENEMY_CHECK_ACTIVE` - 在IN_game中触发,在EnemyController中监听
+- ✅ `ENEMY_CHECK_GAME_STARTED` - 在IN_game中触发,在EnemyController中监听
+- ✅ `ENEMY_GET_COUNT` - 在IN_game中触发,在EnemyController中监听
+- ✅ `GAME_CHECK_OVER` - 在EnemyController、IN_game中触发,在GamePause中监听
+
+#### 方块选择事件
+- ✅ `BLOCK_SELECTION_OPEN` - 在GameBlockSelection中触发
+- ✅ `BLOCK_SELECTION_CLOSE` - 在GameBlockSelection中触发
+- ✅ `SHOW_BLOCK_SELECTION` - 在StartGame中触发,在GamePause中监听
+
+### 2. 定义但未使用的事件
+
+#### 游戏重置事件
+- ❌ `GAME_RESET_REQUEST` - 仅在StartGame中触发,无监听器
+- ❌ `GAME_RESET_COMPLETE` - 仅在StartGame中触发,无监听器
+
+#### UI事件
+- ❌ `SHOP_UPDATED` - 完全未使用
+- ❌ `SHOW_GAME_BLOCK_SELECTION` - 完全未使用
+- ⚠️ `RESET_UI_STATES` - 在StartGame中触发,但UIStateManager中被注释掉
+
+#### 墙体事件
+- ❌ `WALL_HEALTH_CHANGED` - 完全未使用
+- ❌ `WALL_DESTROYED` - 完全未使用
+- ❌ `WALL_TAKE_DAMAGE` - 完全未使用
+
+#### 敌人事件
+- ❌ `ENEMY_SPAWN_START` - 完全未使用
+- ❌ `ENEMY_SPAWN_STOP` - 完全未使用
+- ❌ `ENEMY_ALL_PAUSE` - 完全未使用
+- ❌ `ENEMY_ALL_RESUME` - 完全未使用
+- ❌ `ENEMY_TAKE_DAMAGE` - 完全未使用
+- ❌ `ENEMY_SPAWN_REQUEST` - 完全未使用
+- ❌ `ENEMY_GET_NEAREST` - 在EnemyController中监听,但无触发
+
+#### 球事件
+- ❌ `BALL_CREATE_ADDITIONAL` - 在BallController中监听,但无触发
+
+#### 方块选择事件
+- ❌ `BLOCK_SELECTION_HIDE` - 完全未使用
+- ❌ `BLOCK_SELECTION_SHOW` - 完全未使用
+
+#### 子弹事件
+- ❌ `BULLET_CREATE_REQUEST` - 完全未使用
+- ❌ `BULLET_HIT_ENEMY` - 完全未使用
+
+## 根据游戏管理文档的改进建议
+
+### ✅ 已完成的改进
+
+#### 1. UI状态管理改进
+根据文档要求,已实现以下UI状态切换:
+
+- ✅ 修复 `RESET_UI_STATES` 事件监听(UIStateManager.ts中取消注释)
+- ✅ 添加 `RETURN_TO_MAIN_MENU` 事件在GameManager.onMainMenuClick中触发
+- ✅ 根据游戏管理文档添加UI状态切换事件:
+  - ✅ `ENTER_BATTLE_PREPARATION` - 进入备战状态(在GameBlockSelection.showBlockSelection中触发)
+  - ✅ `ENTER_PLAYING_STATE` - 进入游玩状态(在IN_game.ts的startGame中触发)
+  - ✅ `ENTER_GAME_END_STATE` - 进入游戏结束状态(在IN_game.ts的onGameSuccess/onGameDefeat中触发)
+- ✅ **修复重新开始游戏UI状态切换问题**:
+  - 在 `GameBlockSelection.ts` 中添加了对 `SHOW_BLOCK_SELECTION` 事件的监听
+  - 修正了 `GamePause.ts` 中对 `SHOW_BLOCK_SELECTION` 事件的处理逻辑
+  - 确保重新开始游戏时正确显示方块选择界面并触发相应的UI状态切换事件
+- ✅ **修复重新开始游戏时GameEnd UI残留问题**:
+  - 在 `GameManager.ts` 的 `onResetGameManagerEvent` 方法中添加了对 `gameEndUI` 的隐藏逻辑
+  - 确保重新开始游戏时游戏结束界面被正确清理
+
+#### 2. 墙体事件系统完善
+已在Wall组件中添加事件触发:
+
+- ✅ 在Wall.ts的takeDamage方法中触发 `WALL_TAKE_DAMAGE` 和 `WALL_HEALTH_CHANGED`
+- ✅ 在墙体被摧毁时触发 `WALL_DESTROYED`
+- ✅ 在setHealth和heal方法中触发 `WALL_HEALTH_CHANGED`
+
+#### 3. 子弹系统事件
+已在子弹相关组件中实现:
+
+- ✅ 在WeaponBullet.createBullets中触发 `BULLET_CREATE_REQUEST` 事件
+- ✅ 在WeaponBullet.onHit中触发 `BULLET_HIT_ENEMY` 事件
+
+### 🔄 待实现的改进
+
+#### 4. 商店系统事件
+建议在商店相关操作中使用:
+```typescript
+// 商店数据更新时
+EventBus.getInstance().emit(GameEvents.SHOP_UPDATED);
+```
+
+#### 5. 敌人控制事件完善
+建议在EnemyController中添加:
+```typescript
+// 开始生成敌人
+EventBus.getInstance().emit(GameEvents.ENEMY_SPAWN_START);
+
+// 停止生成敌人
+EventBus.getInstance().emit(GameEvents.ENEMY_SPAWN_STOP);
+
+// 暂停所有敌人
+EventBus.getInstance().emit(GameEvents.ENEMY_ALL_PAUSE);
+
+// 恢复所有敌人
+EventBus.getInstance().emit(GameEvents.ENEMY_ALL_RESUME);
+```
+
+## 实现优先级
+
+### 高优先级(立即实现)
+1. 修复`RESET_UI_STATES`事件监听
+2. 实现墙体事件系统
+3. 完善UI状态切换事件
+
+### 中优先级(后续实现)
+1. 实现商店更新事件
+2. 完善敌人控制事件
+3. 实现子弹系统事件
+
+### 低优先级(可选实现)
+1. 清理未使用的事件定义
+2. 添加事件文档说明
+
+## 总结
+
+当前EventBus系统已经实现了核心的游戏状态管理和重置功能,但在UI状态管理、墙体事件、商店系统等方面还有改进空间。建议按照优先级逐步完善事件系统,以更好地支持游戏管理文档中描述的功能需求。

File diff suppressed because it is too large
+ 225 - 137
assets/Scenes/GameLevel.scene


+ 9 - 0
assets/Scenes/游戏管理.txt

@@ -0,0 +1,9 @@
+游戏中各种资源数据的管理:
+一、实体型数据例如小球、方块、敌人等。应当随着关卡结束销毁。
+二、战斗数据:例如敌人波数、敌人数量、子弹伤害、武器类型等级伤害、墙体血量等。当关卡重置时应该从本地json中读取数据,结合脚本计算数值进行更新。
+三、UI:现在的ui分为游戏内的Canvas/GameLevelUI为游戏游玩界面ui、Canvas/GameLevelUI/BlockSelectionUI方块选择ui、Canvas/SelectSkillUI技能选择ui、Canvas/GameEnd游戏结束ui
+游戏外的:Canvas/MainUI主界面ui、Canvas/ShopUI商店ui、Canvas/SkillUpUI游戏外的技能升级ui(和游戏内的技能不同!)、Canvas/UpgradeUI(暂未设计)
+当关卡重置时,应该按要求显示ui:1.备战阶段block_selection:进入关卡游戏开始动画(只要是触发onBattle方法),都应该先显示Canvas/GameLevelUI为游戏游玩界面ui和Canvas/GameLevelUI/BlockSelectionUI方块选择ui即备战阶段,其它ui都是关闭的。
+2.playing游玩状态,是正式开始游戏,方块选择ui隐藏,游戏开始动画结束。敌人和小球都开始运动,子弹开始发射。若能量满弹出Canvas/SelectSkillUI技能选择ui,若每波结束弹出BlockSelectionUI方块选择ui。
+3.游戏结束:胜利或者失败,游戏进程都暂停,敌人、小球都停止运动,正在发射的子弹可以发射出去。
+游戏结束后点击继续触发onMainMenuClick()方法返回游戏外主界面ui。

+ 1 - 1
assets/scripts/test/Skill.txt.meta → assets/Scenes/游戏管理.txt.meta

@@ -2,7 +2,7 @@
   "ver": "1.0.1",
   "importer": "text",
   "imported": true,
-  "uuid": "d9e31eb4-0041-4c1d-95cd-637d8583355f",
+  "uuid": "b35c354b-1532-4ab5-ade2-05a9d3e417b2",
   "files": [
     ".json"
   ],

+ 4 - 4
assets/scripts/Animations/GameStartMove.ts

@@ -152,8 +152,8 @@ export class GameStartMove extends Component {
             return;
         }
 
-        // 确保BlockSelectionUI可见
-        this.blockSelectionUI.active = true;
+        // BlockSelectionUI现在默认就是可见状态,无需手动设置
+        // this.blockSelectionUI.active = true; // 已移除,因为UI默认激活
 
         // 使用存储的原始位置作为目标位置
         let targetPos: Vec3;
@@ -211,10 +211,10 @@ export class GameStartMove extends Component {
         console.log('GameStartMove.enterBlockSelectionMode 开始执行进入方块选择模式动画');
         
         // 摄像机瞬间下移
-        this.moveDownInstant();
+        //this.moveDownInstant();
         
         // 方块选择UI从底部上滑入场
-        this.slideUpFromBottom(distance, duration);
+        //this.slideUpFromBottom(distance, duration);
         
         console.log('GameStartMove.enterBlockSelectionMode 动画已启动');
     }

+ 91 - 18
assets/scripts/CombatSystem/BlockManager.ts

@@ -138,6 +138,15 @@ export class BlockManager extends Component {
         
         // 监听重置方块管理器事件
         eventBus.on(GameEvents.RESET_BLOCK_MANAGER, this.onResetBlockManagerEvent, this);
+        
+        // 监听方块生成事件
+        eventBus.on(GameEvents.GENERATE_BLOCKS, this.onGenerateBlocksEvent, this);
+        
+        // 移除GAME_START事件监听,避免与GameBlockSelection重复生成方块
+        // eventBus.on(GameEvents.GAME_START, this.onGameStartEvent, this);
+        
+        // 监听波次完成事件(每波结束后生成新方块)
+        eventBus.on(GameEvents.WAVE_COMPLETED, this.onWaveCompletedEvent, this);
     }
     
     // 处理重置方块管理器事件
@@ -146,6 +155,24 @@ export class BlockManager extends Component {
         this.onGameReset();
     }
     
+    // 处理方块生成事件
+    private onGenerateBlocksEvent() {
+        console.log('[BlockManager] 接收到方块生成事件');
+        this.generateRandomBlocksInKuang();
+    }
+    
+    // 处理游戏开始事件 - 已废弃,避免与GameBlockSelection重复生成方块
+    // private onGameStartEvent() {
+    //     console.log('[BlockManager] 接收到游戏开始事件,生成初始方块');
+    //     this.generateRandomBlocksInKuang();
+    // }
+    
+    // 处理波次完成事件
+    private onWaveCompletedEvent() {
+        console.log('[BlockManager] 接收到波次完成事件,生成新方块');
+        this.generateRandomBlocksInKuang();
+    }
+    
     start() {
         // 获取配置管理器
         this.configManager = ConfigManager.getInstance();
@@ -210,10 +237,11 @@ export class BlockManager extends Component {
         // 设置事件监听器
         this.setupEventListeners();
         
-        // 等待配置加载完成后生成方块
-        this.scheduleOnce(() => {
-            this.generateRandomBlocksInKuang();
-        }, 0.5);
+        // 移除自动生成方块逻辑,改为事件触发
+        // 方块生成现在通过以下事件触发:
+        // - GAME_START: 游戏开始时
+        // - WAVE_COMPLETED: 每波敌人消灭后
+        // - GENERATE_BLOCKS: 手动触发生成
     }
     
     // 确保有PlacedBlocks节点
@@ -331,8 +359,6 @@ export class BlockManager extends Component {
         // 获取当前关卡的武器配置列表
         const levelWeapons = await this.getCurrentLevelWeapons();
         
-        console.log('开始在kuang容器中生成武器方块,关卡武器配置:', levelWeapons);
-        
         for (let i = 0; i < 3; i++) {
             let weaponConfig: WeaponConfig | null = null;
             
@@ -400,6 +426,7 @@ export class BlockManager extends Component {
             
             // 为新生成的方块添加标签
             BlockTag.addTag(block);
+            console.log(`[BlockManager] 为方块 ${block.name} 添加标签,UUID: ${block.uuid}`);
         }
         
         this.updateCoinDisplay();
@@ -572,6 +599,10 @@ export class BlockManager extends Component {
         } else if (this.tryPlaceBlockToGrid(this.currentDragBlock)) {
             this.handleSuccessfulPlacement(startLocation);
         } else {
+            console.log(`[BlockManager] 方块 ${this.currentDragBlock.name} 放置到网格失败`);
+            console.log(`[BlockManager] 方块标签状态:`, BlockTag.hasTag(this.currentDragBlock));
+            console.log(`[BlockManager] 方块UUID:`, this.currentDragBlock.uuid);
+            
             // 放置失败,尝试直接与重叠方块合成
             if (this.tryMergeOnOverlap(this.currentDragBlock)) {
                 // 合成成功时,若来自 kuang 则扣费
@@ -581,6 +612,7 @@ export class BlockManager extends Component {
                 }
                 // 当前拖拽块已被销毁(合并时),无需复位
             } else {
+                console.log(`[BlockManager] 方块 ${this.currentDragBlock.name} 合成也失败,返回原位置`);
                 this.returnBlockToOriginalPosition();
             }
         }
@@ -762,12 +794,18 @@ export class BlockManager extends Component {
     
     // 尝试将方块放置到网格中
     tryPlaceBlockToGrid(block: Node): boolean {
-        if (!this.gridContainer || !this.gridInitialized) return false;
+        console.log(`[BlockManager] 尝试放置方块 ${block.name} 到网格`);
+        
+        if (!this.gridContainer || !this.gridInitialized) {
+            console.log(`[BlockManager] 网格容器或网格未初始化`);
+            return false;
+        }
         
         let b1Node = block;
         if (block.name !== 'B1') {
             b1Node = block.getChildByName('B1');
             if (!b1Node) {
+                console.log(`[BlockManager] 方块 ${block.name} 没有B1子节点`);
                 return false;
             }
         }
@@ -775,6 +813,9 @@ export class BlockManager extends Component {
         const b1WorldPos = b1Node.parent.getComponent(UITransform).convertToWorldSpaceAR(b1Node.position);
         const gridPos = this.gridContainer.getComponent(UITransform).convertToNodeSpaceAR(b1WorldPos);
         
+        console.log(`[BlockManager] B1世界坐标:`, b1WorldPos);
+        console.log(`[BlockManager] 网格本地坐标:`, gridPos);
+        
         const gridSize = this.gridContainer.getComponent(UITransform).contentSize;
         const halfWidth = gridSize.width / 2;
         const halfHeight = gridSize.height / 2;
@@ -782,14 +823,17 @@ export class BlockManager extends Component {
         const tolerance = this.gridSpacing * 0.5;
         if (gridPos.x < -halfWidth - tolerance || gridPos.x > halfWidth + tolerance || 
             gridPos.y < -halfHeight - tolerance || gridPos.y > halfHeight + tolerance) {
+            console.log(`[BlockManager] 方块超出网格边界`);
             return false;
         }
         
         const nearestGrid = this.findNearestGridNode(gridPos);
         if (!nearestGrid) {
+            console.log(`[BlockManager] 找不到最近的网格节点`);
             return false;
         }
         
+        console.log(`[BlockManager] 找到最近的网格节点: ${nearestGrid.name}`);
         return this.tryPlaceBlockToSpecificGrid(block, nearestGrid);
     }
     
@@ -860,22 +904,33 @@ export class BlockManager extends Component {
     
     // 检查方块是否可以放置在指定位置
     canPlaceBlockAt(block: Node, targetGrid: Node): boolean {
-        if (!this.gridInitialized) return false;
         
-        const targetRowCol = this.getGridRowCol(targetGrid);
-        if (!targetRowCol) return false;
+        if (!this.gridInitialized) {
+            console.log(`[BlockManager] 网格未初始化`);
+            return false;
+        }
         
+        const targetRowCol = this.getGridRowCol(targetGrid);
+        if (!targetRowCol) {
+            console.log(`[BlockManager] 无法获取目标网格的行列信息`);
+            return false;
+        }
+                
         const parts = this.getBlockParts(block);
         
-        for (const part of parts) {
+        for (let i = 0; i < parts.length; i++) {
+            const part = parts[i];
             const row = targetRowCol.row - part.y;
             const col = targetRowCol.col + part.x;
             
+            
             if (row < 0 || row >= this.GRID_ROWS || col < 0 || col >= this.GRID_COLS) {
+                console.log(`[BlockManager] 部件${i} 超出网格边界: row=${row}, col=${col}, 网格大小=${this.GRID_ROWS}x${this.GRID_COLS}`);
                 return false;
             }
             
             if (this.gridOccupationMap[row][col] === 1) {
+                console.log(`[BlockManager] 部件${i} 位置已被占用: row=${row}, col=${col}`);
                 return false;
             }
         }
@@ -976,6 +1031,7 @@ export class BlockManager extends Component {
     
     // 清除方块
     clearBlocks() {
+        console.log('[BlockManager] clearBlocks开始,当前方块总数:', this.blocks.length);
         const blocksToRemove = [];
         
         for (const block of this.blocks) {
@@ -987,6 +1043,8 @@ export class BlockManager extends Component {
             }
         }
         
+        console.log('[BlockManager] 找到需要清理的kuang区域方块数量:', blocksToRemove.length);
+        
         for (const block of blocksToRemove) {
             const dbNode = block['dbNode'];
             if (dbNode && dbNode.isValid) {
@@ -1012,8 +1070,11 @@ export class BlockManager extends Component {
             // 清理武器配置映射
             this.blockWeaponConfigs.delete(block);
             
+            console.log('[BlockManager] 销毁kuang区域方块:', block.name);
             block.destroy();
         }
+        
+        console.log('[BlockManager] clearBlocks完成,剩余方块总数:', this.blocks.length);
     }
     
     // 游戏开始时调用
@@ -1045,23 +1106,31 @@ export class BlockManager extends Component {
     // 游戏重置时调用
     onGameReset() {
         console.log('[BlockManager] 游戏重置,清理所有状态');
+        console.log('[BlockManager] 重置前方块总数:', this.blocks.length);
         
         this.gameStarted = false;
         this.clearAllCooldowns();
         
         // 清理已放置的方块
+        console.log('[BlockManager] 开始清理已放置的方块');
         this.clearPlacedBlocks();
         
         // 重置网格占用状态
+        console.log('[BlockManager] 开始重置网格占用状态');
         this.resetGridOccupation();
         
         // 清理kuang区域的方块
+        console.log('[BlockManager] 开始清理kuang区域的方块');
         this.clearBlocks();
         
         // 清理所有方块标签
+        console.log('[BlockManager] 开始清理所有方块标签');
         BlockTag.clearAllTags();
         
+        console.log('[BlockManager] 清理后方块总数:', this.blocks.length);
+        
         // 重新生成方块
+        console.log('[BlockManager] 开始重新生成方块');
         this.generateRandomBlocksInKuang();
         
         console.log('[BlockManager] 游戏重置完成');
@@ -1070,6 +1139,7 @@ export class BlockManager extends Component {
     // 清理已放置的方块
     private clearPlacedBlocks() {
         if (!this.placedBlocksContainer || !this.placedBlocksContainer.isValid) {
+            console.log('[BlockManager] PlacedBlocks容器无效,跳过清理');
             return;
         }
         
@@ -1077,6 +1147,8 @@ export class BlockManager extends Component {
         
         // 清理PlacedBlocks容器中的所有方块
         const placedBlocks = [...this.placedBlocksContainer.children];
+        let clearedCount = 0;
+        
         for (const block of placedBlocks) {
             if (block && block.isValid) {
                 // 从blocks数组中移除
@@ -1091,10 +1163,14 @@ export class BlockManager extends Component {
                 this.blockPriceMap.delete(block);
                 this.blockWeaponConfigs.delete(block);
                 
+                console.log('[BlockManager] 销毁已放置方块:', block.name);
                 // 销毁方块
                 block.destroy();
+                clearedCount++;
             }
         }
+        
+        console.log(`[BlockManager] 已清理 ${clearedCount} 个已放置方块`);
     }
     
     // 重置网格占用状态
@@ -1404,18 +1480,11 @@ export class BlockManager extends Component {
         // 创建临时实例来检查形状
         const tempBlock = instantiate(prefab);
         const parts = this.getBlockParts(tempBlock);
-        console.log(`${prefab.name} 的部件坐标:`, parts.map(p => `(${p.x},${p.y})`));
         const actualShape = this.extractShapeFromBlock(tempBlock);
         tempBlock.destroy();
         
-        // 添加调试日志
-        console.log(`检查预制体 ${prefab.name} 是否匹配形状 ${targetShape.name}`);
-        console.log('预制体实际形状:', actualShape);
-        console.log('目标形状:', targetShape.shape);
-        
         // 比较形状矩阵
         const matches = this.compareShapeMatrices(actualShape, targetShape.shape);
-        console.log('匹配结果:', matches);
         return matches;
     }
     
@@ -1663,5 +1732,9 @@ export class BlockManager extends Component {
         // 清理事件监听
         const eventBus = EventBus.getInstance();
         eventBus.off(GameEvents.RESET_BLOCK_MANAGER, this.onResetBlockManagerEvent, this);
+        eventBus.off(GameEvents.GENERATE_BLOCKS, this.onGenerateBlocksEvent, this);
+        // 移除GAME_START事件清理,因为已不再监听该事件
+        // eventBus.off(GameEvents.GAME_START, this.onGameStartEvent, this);
+        eventBus.off(GameEvents.WAVE_COMPLETED, this.onWaveCompletedEvent, this);
     }
 }

+ 124 - 18
assets/scripts/CombatSystem/BlockSelection/GameBlockSelection.ts

@@ -97,13 +97,53 @@ export class GameBlockSelection extends Component {
 
     // 回调函数,用于通知GameManager
     public onConfirmCallback: () => void = null;
+    
+    // 标记是否已初始化
+    private isInitialized: boolean = false;
+    
+    // 标记是否应该生成方块(只有在onBattle触发后才为true)
+    private shouldGenerateBlocks: boolean = false;
+
+    onEnable() {
+        console.log('[GameBlockSelection] onEnable() 节点被激活');
+        // 如果还未初始化,则进行初始化
+        if (!this.isInitialized) {
+            this.initializeComponent();
+        }
+    }
 
     start() {
-        console.log('GameBlockSelection.start() 开始初始化');
+        console.log('[GameBlockSelection] start() 被调用');
+        // 如果还未初始化,则进行初始化
+        if (!this.isInitialized) {
+            this.initializeComponent();
+        }
+    }
+    
+    private initializeComponent() {
+        console.log('[GameBlockSelection] initializeComponent() 开始初始化');
+        console.log('[GameBlockSelection] 组件节点名称:', this.node.name);
+        console.log('[GameBlockSelection] 组件节点激活状态:', this.node.active);
         
         // 获取管理器实例
         this.session = LevelSessionManager.inst;
         
+        // 如果组件挂载在BlockSelectionUI节点上,则将该节点设为blockSelectionUINode
+        if (!this.blockSelectionUINode && this.node.name === 'BlockSelectionUI') {
+            this.blockSelectionUINode = this.node;
+            console.log('[GameBlockSelection] 组件挂载在BlockSelectionUI节点上,设置为blockSelectionUINode:', this.blockSelectionUINode.name);
+        }
+        
+        // 如果dibanNode未绑定,尝试在当前节点下查找
+        if (!this.dibanNode && this.blockSelectionUINode) {
+            this.dibanNode = this.blockSelectionUINode.getChildByName('diban');
+            if (this.dibanNode) {
+                console.log('[GameBlockSelection] 找到diban节点:', this.dibanNode.name);
+            } else {
+                console.error('[GameBlockSelection] 无法找到diban节点');
+            }
+        }
+        
         // 获取BallController
         if (this.ballControllerNode) {
             this.ballController = this.ballControllerNode.getComponent(BallController);
@@ -151,21 +191,41 @@ export class GameBlockSelection extends Component {
             this.coinLabelNode = find('Canvas-001/TopArea/CoinNode/CoinLabel');
         }
 
+        // 初始化金币显示
+        this.updateCoinDisplay();
+
         // 绑定按钮事件
         this.bindButtonEvents();
         
         // 设置事件监听器
         this.setupEventListeners();
         
-        console.log('GameBlockSelection.start() 初始化完成');
+        // 标记为已初始化
+        this.isInitialized = true;
+        
+        console.log('GameBlockSelection.initializeComponent() 初始化完成');
     }
 
     // 设置事件监听器
     private setupEventListeners() {
+        console.log('[GameBlockSelection] 开始设置事件监听器');
         const eventBus = EventBus.getInstance();
+        console.log('[GameBlockSelection] EventBus实例获取结果:', !!eventBus);
         
         // 监听重置方块选择事件
         eventBus.on(GameEvents.RESET_BLOCK_SELECTION, this.onResetBlockSelectionEvent, this);
+        console.log('[GameBlockSelection] RESET_BLOCK_SELECTION事件监听器已设置');
+        
+        // 监听显示方块选择事件
+        eventBus.on(GameEvents.SHOW_BLOCK_SELECTION, this.onShowBlockSelectionEvent, this);
+        console.log('[GameBlockSelection] SHOW_BLOCK_SELECTION事件监听器已设置');
+        
+        // 监听游戏开始事件,用于标记可以开始生成方块
+        eventBus.on(GameEvents.GAME_START, this.onGameStartEvent, this);
+        console.log('[GameBlockSelection] GAME_START事件监听器已设置');
+        
+        console.log('[GameBlockSelection] 事件监听器设置完成,组件节点:', this.node.name);
+        console.log('[GameBlockSelection] 当前节点状态:', this.node.active);
     }
     
     // 处理重置方块选择事件
@@ -174,6 +234,21 @@ export class GameBlockSelection extends Component {
         this.resetSelection();
     }
     
+    // 处理显示方块选择事件
+    private onShowBlockSelectionEvent() {
+        console.log('[GameBlockSelection] ===== 接收到显示方块选择事件 =====');
+        console.log('[GameBlockSelection] 当前组件节点:', this.node.name, '状态:', this.node.active);
+        console.log('[GameBlockSelection] blockSelectionUINode:', this.blockSelectionUINode?.name, '状态:', this.blockSelectionUINode?.active);
+        this.showBlockSelection(true); // false表示不是下一波,而是游戏开始
+        console.log('[GameBlockSelection] ===== 显示方块选择事件处理完成 =====');
+    }
+    
+    // 处理游戏开始事件
+    private onGameStartEvent() {
+        console.log('[GameBlockSelection] 接收到游戏开始事件,允许生成方块');
+        this.shouldGenerateBlocks = true;
+    }
+    
     // 绑定按钮事件
     private bindButtonEvents() {
         // 绑定新增小球按钮
@@ -344,8 +419,14 @@ export class GameBlockSelection extends Component {
         if (this.coinLabelNode) {
             const label = this.coinLabelNode.getComponent(Label);
             if (label) {
-                label.string = this.session.getCoins().toString();
+                const coins = this.session.getCoins();
+                label.string = coins.toString();
+                console.log(`[GameBlockSelection] 更新金币显示: ${coins}`);
+            } else {
+                console.warn('[GameBlockSelection] coinLabelNode缺少Label组件');
             }
+        } else {
+            console.warn('[GameBlockSelection] coinLabelNode未找到');
         }
     }
 
@@ -388,38 +469,59 @@ export class GameBlockSelection extends Component {
 
     // 显示方块选择UI(用于游戏开始或下一波)
     public showBlockSelection(isNextWave: boolean = false) {
+        console.log('[GameBlockSelection] showBlockSelection开始执行');
+        console.log('[GameBlockSelection] 节点状态检查:', {
+            node: !!this.node,
+            nodeActive: this.node?.active,
+            nodeName: this.node?.name,
+            gridContainer: !!this.gridContainer,
+            gridContainerActive: this.gridContainer?.active,
+            blockSelectionUINode: !!this.blockSelectionUINode,
+            blockSelectionUINodeActive: this.blockSelectionUINode?.active,
+            blockSelectionUINodeName: this.blockSelectionUINode?.name
+        });
+        
         // 通过事件系统暂停游戏
         const eventBus = EventBus.getInstance();
         eventBus.emit(GameEvents.GAME_PAUSE);
         console.log('[GameBlockSelection] 显示方块选择UI,确保游戏暂停');
         
-        // 首先显示UI节点
-        this.node.active = true;
+        // BlockSelectionUI节点现在默认就是激活状态,无需手动设置
+        // 只需要确认节点状态用于调试
+        if (this.blockSelectionUINode) {
+            console.log('[GameBlockSelection] BlockSelectionUI节点状态:', this.blockSelectionUINode.active, this.blockSelectionUINode.name);
+        } else {
+            console.log('[GameBlockSelection] 组件节点状态:', this.node.active, this.node.name);
+        }
         
         if (this.gridContainer) {
             this.gridContainer.active = true;
+            console.log('[GameBlockSelection] gridContainer已激活:', this.gridContainer.active);
+        } else {
+            console.warn('[GameBlockSelection] gridContainer未找到');
         }
 
-        // 如果有BlockSelectionUI节点,确保它可见
-        if (this.blockSelectionUINode) {
-            this.blockSelectionUINode.active = true;
-        }
-
-        // 每次显示方块选择UI时,生成新的随机方块
-        if (this.blockManager) {
+        // 只有在onBattle触发后才生成方块
+        if (this.shouldGenerateBlocks && this.blockManager) {
             this.blockManager.refreshBlocks();
             console.log('[GameBlockSelection] 生成新的随机方块');
+        } else if (!this.shouldGenerateBlocks) {
+            console.log('[GameBlockSelection] 等待onBattle触发后才生成方块');
         } else {
             console.warn('[GameBlockSelection] BlockManager未找到,无法生成随机方块');
         }
 
         // 播放BlockSelectionUI出现动画
+        console.log('[GameBlockSelection] 准备播放显示动画');
         this.playShowAnimation();
 
+        // 触发进入备战状态事件
+        EventBus.getInstance().emit(GameEvents.ENTER_BATTLE_PREPARATION);
+
         // 派发事件
         EventBus.getInstance().emit(GameEvents.BLOCK_SELECTION_OPEN);
 
-        console.log(`[GameBlockSelection] ${isNextWave ? '显示下一波方块选择UI' : '显示游戏开始方块选择UI'}`);
+        console.log(`[GameBlockSelection] ${isNextWave ? '显示下一波方块选择UI' : '显示游戏开始方块选择UI'} 完成`);
     }
 
     // 隐藏方块选择UI
@@ -511,11 +613,13 @@ export class GameBlockSelection extends Component {
     public resetSelection() {
         console.log('[GameBlockSelection] 重置方块选择状态');
         
-        // 重置BlockManager状态
-        if (this.blockManager) {
-            this.blockManager.onGameReset();
-            console.log('[GameBlockSelection] BlockManager状态已重置');
-        }
+        // 重置方块生成标志,等待下次onBattle触发
+        this.shouldGenerateBlocks = false;
+        console.log('[GameBlockSelection] 重置方块生成标志');
+        
+        // 注意:不再直接调用blockManager.onGameReset(),因为StartGame.clearGameStates()
+        // 已经通过RESET_BLOCK_MANAGER事件触发了BlockManager的重置,避免重复生成方块
+        console.log('[GameBlockSelection] BlockManager将通过事件系统自动重置');
         
         // 清理所有方块标签
         BlockTag.clearAllTags();
@@ -597,5 +701,7 @@ export class GameBlockSelection extends Component {
         // 清理事件监听
         const eventBus = EventBus.getInstance();
         eventBus.off(GameEvents.RESET_BLOCK_SELECTION, this.onResetBlockSelectionEvent, this);
+        eventBus.off(GameEvents.SHOW_BLOCK_SELECTION, this.onShowBlockSelectionEvent, this);
+        eventBus.off(GameEvents.GAME_START, this.onGameStartEvent, this);
     }
 }

+ 10 - 2
assets/scripts/CombatSystem/GamePause.ts

@@ -40,7 +40,7 @@ export class GamePause extends Component {
         
         // 监听游戏开始和结束事件来更新游戏模式状态
         eventBus.on(GameEvents.GAME_START, this.onGameStartEvent, this);
-        eventBus.on(GameEvents.SHOW_BLOCK_SELECTION, this.onGameEndEvent, this);
+        eventBus.on(GameEvents.SHOW_BLOCK_SELECTION, this.onShowBlockSelectionEvent, this);
         
         // 监听子弹发射检查事件
         eventBus.on(GameEvents.BALL_FIRE_BULLET, this.onBallFireBulletEvent, this);
@@ -76,6 +76,14 @@ export class GamePause extends Component {
         this.isInGameMode = false;
     }
     
+    /**
+     * 处理显示方块选择事件
+     */
+    private onShowBlockSelectionEvent() {
+        console.log('[GamePause] 接收到显示方块选择事件,进入方块选择模式');
+        this.isInGameMode = false; // 方块选择时不在游戏模式中
+    }
+    
     /**
      * 处理子弹发射检查事件
      */
@@ -278,7 +286,7 @@ export class GamePause extends Component {
         eventBus.off(GameEvents.RESET_GAME_PAUSE, this.onResetGamePauseEvent, this);
         eventBus.off(GameEvents.GAME_START, this.onGameStartEvent, this);
         eventBus.off(GameEvents.GAME_CHECK_OVER, this.onGameCheckOverEvent, this);
-        eventBus.off(GameEvents.SHOW_BLOCK_SELECTION, this.onGameEndEvent, this);
+        eventBus.off(GameEvents.SHOW_BLOCK_SELECTION, this.onShowBlockSelectionEvent, this);
         
         GamePause._instance = null;
     }

+ 48 - 1
assets/scripts/CombatSystem/Wall.ts

@@ -102,8 +102,24 @@ export class Wall extends Component {
     public takeDamage(damage: number) {
         if (damage <= 0) return;
 
+        const previousHealth = this.currentHealth;
         this.currentHealth = Math.max(0, this.currentHealth - damage);
         
+        // 触发受到伤害事件
+        const eventBus = EventBus.getInstance();
+        eventBus.emit(GameEvents.WALL_TAKE_DAMAGE, {
+            damage: damage,
+            previousHealth: previousHealth,
+            currentHealth: this.currentHealth
+        });
+        
+        // 触发血量变化事件
+        eventBus.emit(GameEvents.WALL_HEALTH_CHANGED, {
+            previousHealth: previousHealth,
+            currentHealth: this.currentHealth,
+            maxHealth: this.getMaxHealth()
+        });
+        
         // 更新血量显示
         this.updateHealthDisplay();
         
@@ -121,8 +137,14 @@ export class Wall extends Component {
     private onWallDestroyed() {
         console.log('[Wall] 墙体被摧毁,触发游戏失败');
         
-        // 通过事件系统触发游戏失败
+        // 通过事件系统触发墙体被摧毁事件
         const eventBus = EventBus.getInstance();
+        eventBus.emit(GameEvents.WALL_DESTROYED, {
+            finalHealth: this.currentHealth,
+            maxHealth: this.getMaxHealth()
+        });
+        
+        // 触发游戏失败
         eventBus.emit(GameEvents.GAME_DEFEAT);
     }
 
@@ -139,7 +161,19 @@ export class Wall extends Component {
      * 设置墙体血量
      */
     public setHealth(health: number) {
+        const previousHealth = this.currentHealth;
         this.currentHealth = Math.max(0, health);
+        
+        // 如果血量发生变化,触发血量变化事件
+        if (previousHealth !== this.currentHealth) {
+            const eventBus = EventBus.getInstance();
+            eventBus.emit(GameEvents.WALL_HEALTH_CHANGED, {
+                previousHealth: previousHealth,
+                currentHealth: this.currentHealth,
+                maxHealth: this.getMaxHealth()
+            });
+        }
+        
         this.updateHealthDisplay();
     }
 
@@ -219,8 +253,21 @@ export class Wall extends Component {
      * 恢复墙体血量
      */
     public heal(amount: number) {
+        const previousHealth = this.currentHealth;
         const maxHealth = this.getMaxHealth();
         this.currentHealth = Math.min(maxHealth, this.currentHealth + amount);
+        
+        // 如果血量发生变化,触发血量变化事件
+        if (previousHealth !== this.currentHealth) {
+            const eventBus = EventBus.getInstance();
+            eventBus.emit(GameEvents.WALL_HEALTH_CHANGED, {
+                previousHealth: previousHealth,
+                currentHealth: this.currentHealth,
+                maxHealth: maxHealth,
+                healAmount: this.currentHealth - previousHealth
+            });
+        }
+        
         this.updateHealthDisplay();
     }
 

+ 19 - 1
assets/scripts/CombatSystem/WeaponBullet.ts

@@ -130,9 +130,12 @@ export class WeaponBullet extends Component {
         // 关卡备战或其他情况下可关闭生成
         if (!WeaponBullet.shootingEnabled) return [];
 
+        // 触发子弹创建请求事件
+        const eventBus = EventBus.getInstance();
+        eventBus.emit(GameEvents.BULLET_CREATE_REQUEST, { weaponId: initData.weaponId, position: initData.firePosition });
+
         // 通过事件系统检查是否可以发射子弹
         let canFire = true;
-        const eventBus = EventBus.getInstance();
         eventBus.emit(GameEvents.BALL_FIRE_BULLET, { canFire: (result: boolean) => { canFire = result; } });
         
         if (!canFire) {
@@ -400,6 +403,21 @@ export class WeaponBullet extends Component {
             return; // Skip further processing if the collider is another bullet
         }
         
+        // 检查是否命中敌人并触发事件
+        const isEnemy = otherNode.name.toLowerCase().includes('enemy') || 
+                       otherNode.name.toLowerCase().includes('敌人') || 
+                       otherNode.getComponent('EnemyInstance');
+        
+        if (isEnemy) {
+            // 触发子弹命中敌人事件
+            EventBus.getInstance().emit(GameEvents.BULLET_HIT_ENEMY, {
+                bullet: this.node,
+                enemy: otherNode,
+                damage: this.getFinalDamage(),
+                weaponId: this.weaponConfig?.id
+            });
+        }
+        
         // 获取碰撞世界坐标
         let contactWorldPos: Vec3 = null;
         if (contact && (contact as any).getWorldManifold) {

+ 10 - 0
assets/scripts/Core/EventBus.ts

@@ -38,6 +38,12 @@ export enum GameEvents {
     BLOCK_SELECTION_CLOSE = 'BLOCK_SELECTION_CLOSE',
     SHOW_GAME_BLOCK_SELECTION = 'SHOW_GAME_BLOCK_SELECTION',
     SHOW_BLOCK_SELECTION = 'SHOW_BLOCK_SELECTION',
+    RETURN_TO_MAIN_MENU = 'RETURN_TO_MAIN_MENU',
+    
+    // UI状态切换事件(根据游戏管理文档)
+    ENTER_BATTLE_PREPARATION = 'ENTER_BATTLE_PREPARATION',  // 进入备战阶段
+    ENTER_PLAYING_STATE = 'ENTER_PLAYING_STATE',            // 进入游玩状态
+    ENTER_GAME_END_STATE = 'ENTER_GAME_END_STATE',          // 进入游戏结束状态
     
     // 敌人控制事件
     ENEMY_SPAWN_START = 'ENEMY_SPAWN_START',
@@ -75,6 +81,10 @@ export enum GameEvents {
     BLOCK_SELECTION_HIDE = 'BLOCK_SELECTION_HIDE',
     BLOCK_SELECTION_SHOW = 'BLOCK_SELECTION_SHOW',
     
+    // 方块生成事件
+    GENERATE_BLOCKS = 'GENERATE_BLOCKS',
+    WAVE_COMPLETED = 'WAVE_COMPLETED',
+    
     // 子弹事件
     BULLET_CREATE_REQUEST = 'BULLET_CREATE_REQUEST',
     BULLET_HIT_ENEMY = 'BULLET_HIT_ENEMY'

+ 6 - 1
assets/scripts/Core/LevelSessionManager.ts

@@ -28,6 +28,7 @@ export class LevelSessionManager {
       startTime: Date.now(),
       sessionCoins: 45
     };
+    console.log(`[LevelSessionManager] 初始化完成,sessionCoins设置为: ${this.data.sessionCoins}`);
   }
 
   public get runtime() { return this.data; }
@@ -36,7 +37,11 @@ export class LevelSessionManager {
   public clear() { this.data = null; }
 
   // ======== 本局金币接口 ========
-  public getCoins(): number { return this.data?.sessionCoins ?? 0; }
+  public getCoins(): number { 
+    const coins = this.data?.sessionCoins ?? 0;
+    console.log(`[LevelSessionManager] getCoins() 返回: ${coins}, data存在: ${!!this.data}`);
+    return coins;
+  }
   public addCoins(amt:number){ if(this.data) this.data.sessionCoins += amt; }
   /** 成功返回true */
   public spendCoins(amt:number):boolean{ if(!this.data || amt<=0) return false; if(this.data.sessionCoins<amt) return false; this.data.sessionCoins-=amt; return true; }

+ 8 - 1
assets/scripts/FourUI/MainSystem/MainUIControlller.ts

@@ -6,6 +6,7 @@ import { GameState } from '../../LevelSystem/IN_game';
 import { GameStartMove } from '../../Animations/GameStartMove';
 import { TopBarController } from '../TopBarController';
 import { MoneyAni } from '../../Animations/MoneyAni';
+import EventBus, { GameEvents } from '../../Core/EventBus';
 const { ccclass, property } = _decorator;
 
 @ccclass('MainUIController')
@@ -105,7 +106,11 @@ export class MainUIController extends Component {
     const gm = this.gameManagerNode?.getComponent(GameManager);
     // 设置应用状态为游戏中(会自动隐藏TopBar和NavBar)
     gm?.setAppState(AppState.IN_GAME);
-    gm?.restartGame();
+    
+    // 统一使用StartGame启动游戏流程
+    const eventBus = EventBus.getInstance();
+    eventBus.emit(GameEvents.GAME_START);
+    
     gm?.loadCurrentLevelConfig();
 
     // Camera move down instantly for battle prep
@@ -113,6 +118,8 @@ export class MainUIController extends Component {
     gsm?.moveDownInstant();
   }
 
+
+
   /* ================= 刷新 ================= */
   private refreshLevelNumber(){
     if (this.levelNumberLabel) this.levelNumberLabel.string = `第 ${this.sdm.getCurrentLevel()} 关`;

+ 216 - 110
assets/scripts/LevelSystem/GameManager.ts

@@ -11,7 +11,7 @@ import { GameBlockSelection } from '../CombatSystem/BlockSelection/GameBlockSele
 // GamePause已通过事件系统解耦,不再需要直接导入
 import { Wall } from '../CombatSystem/Wall';
 import { GameStartMove } from '../Animations/GameStartMove';
-import { ReStartGame } from './ReStartGame';
+import { StartGame } from './StartGame';
 import { InGameManager, GameState } from './IN_game';
 const { ccclass, property } = _decorator;
 
@@ -109,6 +109,13 @@ export class GameManager extends Component {
     
     // 游戏内管理器引用
     private inGameManager: InGameManager = null;
+    
+
+    
+    // BlockSelection UI状态监听
+    private blockSelectionUIWasActive: boolean = false;  // 记录BlockSelection UI的上一次状态
+    private blockSelectionUIInitialized: boolean = false;  // 标记是否已初始化
+    private blockSelectionUIMonitoringEnabled: boolean = false;  // 标记是否启用监听
 
     // 游戏区域的边界
     private gameBounds = {
@@ -157,6 +164,9 @@ export class GameManager extends Component {
     }
 
     start() {
+        // 初始化StartGame的静态事件监听器
+        StartGame.initializeEventListeners();
+        
         // 初始化物理系统
         this.initPhysicsSystem();
         
@@ -177,7 +187,18 @@ export class GameManager extends Component {
         // 初始化游戏状态
         this.initializeGameState();
         
-        // 初始化UI节点
+        // 设置应用状态为游戏中
+        this.currentAppState = AppState.IN_GAME;
+        console.log('[GameManager] 设置应用状态为IN_GAME');
+        
+        // 先初始化UI状态监听(记录真实的初始状态)
+        this.initializeBlockSelectionUIListener();
+        
+        // 启用BlockSelection UI状态监听
+        this.blockSelectionUIMonitoringEnabled = true;
+        console.log('[GameManager] 游戏启动,启用BlockSelection UI状态监听');
+        
+        // 再初始化UI节点(可能会改变UI状态)
         this.initUINodes();
         
         // 敌人控制器已通过事件系统解耦,不再需要直接查找和设置
@@ -189,14 +210,19 @@ export class GameManager extends Component {
         this.initGameBlockSelection();
         this.initGameStartMove();
         
-        // 加载当前关卡配置
-        this.loadCurrentLevelConfig();
-
+        // 关卡配置加载已移至StartGame.initializeGameData()中,确保正确的时序
+        
         // 监听GamePause状态变化事件
         this.setupGamePauseEventListeners();
         
         // 初始化游戏计时器
         this.gameStartTime = Date.now();
+        
+        // 触发游戏启动流程(显示方块选择UI)
+        console.log('[GameManager] 触发游戏启动流程');
+        StartGame.startGameFlow().catch(error => {
+            console.error('[GameManager] 游戏启动流程出错:', error);
+        });
     }
 
     /**
@@ -220,6 +246,9 @@ export class GameManager extends Component {
         // 监听重置游戏管理器事件
         eventBus.on(GameEvents.RESET_GAME_MANAGER, this.onResetGameManagerEvent, this);
         
+        // 监听主菜单按钮点击事件(由UIStateManager转发)
+        eventBus.on('CONTINUE_CLICK', this.onMainMenuClick, this);
+        
         // 敌人击杀事件监听已迁移到 InGameManager
     }
 
@@ -230,15 +259,10 @@ export class GameManager extends Component {
         console.log('[GameManager] 接收到游戏成功事件,执行成功处理');
         
         // 游戏状态管理已迁移到 InGameManager
+        // UI显示控制已迁移到 UIStateManager
         
         // 注意:不在这里切换到MAIN_MENU状态,保持IN_GAME状态
         // 只有用户点击成功界面的按钮时才切换到主界面
-        
-        // 显示游戏结束UI并设置成功文本
-        if (this.gameEndUI) {
-            this.gameEndUI.active = true;
-            this.setEndLabelText('SUCCESS');
-        }
 
         // 执行游戏成功逻辑
         this.onGameSuccess();
@@ -251,15 +275,10 @@ export class GameManager extends Component {
         console.log('[GameManager] 接收到游戏失败事件,执行失败处理');
         
         // 游戏状态管理已迁移到 InGameManager
+        // UI显示控制已迁移到 UIStateManager
         
         // 注意:不在这里切换到MAIN_MENU状态,保持IN_GAME状态
         // 只有用户点击失败界面的按钮时才切换到主界面
-        
-        // 显示游戏结束UI并设置失败文本
-        if (this.gameEndUI) {
-            this.gameEndUI.active = true;
-            this.setEndLabelText('DEFEAT');
-        }
 
         // 执行游戏失败逻辑
         this.onGameDefeat().catch(error => {
@@ -280,8 +299,25 @@ export class GameManager extends Component {
      * 处理游戏重启事件
      */
     private onGameRestartEvent() {
-        console.log('[GameManager] 接收到游戏重启事件');
-        this.restartGame();
+        console.log('[GameManager] 接收到游戏重启事件,重置GameManager状态');
+        
+        // 设置应用状态为游戏中
+        this.currentAppState = AppState.IN_GAME;
+        this.gameStarted = false;
+        this.gameStartTime = 0;
+        this.gameEndTime = 0;
+        
+        // 启用BlockSelection UI状态监听
+        this.blockSelectionUIMonitoringEnabled = true;
+        console.log('[GameManager] 游戏重启,启用BlockSelection UI状态监听');
+        
+        console.log('[GameManager] GameManager状态重置完成');
+        
+        // 直接调用StartGame的启动方法,统一使用游戏启动流程
+        console.log('[GameManager] 直接调用StartGame.startGameFlow');
+        StartGame.startGameFlow().catch(error => {
+            console.error('[GameManager] 游戏重启流程出错:', error);
+        });
     }
     
     /**
@@ -294,7 +330,88 @@ export class GameManager extends Component {
         this.gameStarted = false;
         this.gameStartTime = 0;
         this.gameEndTime = 0;
-        console.log('[GameManager] 游戏管理器状态已重置');
+        
+        // 禁用UI状态监听
+        this.blockSelectionUIMonitoringEnabled = false;
+        
+        console.log('[GameManager] 游戏管理器状态已重置,UI监听已禁用');
+    }
+    
+
+    
+    /**
+     * 初始化BlockSelection UI状态监听
+     */
+    private initializeBlockSelectionUIListener() {
+        if (!this.gameBlockSelection) {
+            console.warn('[GameManager] BlockSelection UI节点未找到,无法初始化状态监听');
+            return;
+        }
+        
+        // 获取GameBlockSelection组件,检查是否有blockSelectionUINode引用
+        const blockSelectionComponent = this.gameBlockSelection.getComponent(GameBlockSelection);
+        let targetNode = this.gameBlockSelection; // 默认监听gameBlockSelection节点
+        
+        if (blockSelectionComponent && blockSelectionComponent.blockSelectionUINode) {
+            // 如果组件有blockSelectionUINode引用,监听该节点
+            targetNode = blockSelectionComponent.blockSelectionUINode;
+            console.log('[GameManager] 将监听blockSelectionUINode:', targetNode.name);
+        } else {
+            console.log('[GameManager] 将监听gameBlockSelection节点:', targetNode.name);
+        }
+        
+        // 记录初始状态
+        this.blockSelectionUIWasActive = targetNode.active;
+        this.blockSelectionUIInitialized = true;
+        
+        console.log(`[GameManager] BlockSelection UI状态监听已初始化,目标节点: ${targetNode.name},初始状态: ${this.blockSelectionUIWasActive}`);
+    }
+    
+
+    
+    /**
+     * 检查BlockSelection UI状态变化并处理清理逻辑
+     */
+    private checkBlockSelectionUIStateChange() {
+        if (!this.blockSelectionUIInitialized || !this.gameBlockSelection || !this.blockSelectionUIMonitoringEnabled) {
+            return;
+        }
+        
+        // 获取要监听的目标节点
+        const blockSelectionComponent = this.gameBlockSelection.getComponent(GameBlockSelection);
+        let targetNode = this.gameBlockSelection;
+        
+        if (blockSelectionComponent && blockSelectionComponent.blockSelectionUINode) {
+            targetNode = blockSelectionComponent.blockSelectionUINode;
+        }
+        
+        const currentActive = targetNode.active;
+        
+        // 检测从非激活状态变为激活状态(UI显示)
+        if (!this.blockSelectionUIWasActive && currentActive) {
+            console.log(`[GameManager] 检测到BlockSelection UI显示 (${targetNode.name}),触发方块清理`);
+            this.onBlockSelectionUIShow();
+        }
+        
+        // 更新状态记录
+        this.blockSelectionUIWasActive = currentActive;
+    }
+    
+
+    
+
+    
+    /**
+     * 处理BlockSelection UI显示事件
+     */
+    private onBlockSelectionUIShow() {
+        console.log('[GameManager] BlockSelection UI显示,触发方块清理');
+        
+        // 触发方块清理事件
+        const eventBus = EventBus.getInstance();
+        eventBus.emit(GameEvents.RESET_BLOCK_MANAGER);
+        
+        console.log('[GameManager] 方块清理事件已发送');
     }
     
     // 敌人击杀事件处理已迁移到 InGameManager
@@ -314,9 +431,6 @@ export class GameManager extends Component {
         const eventBus = EventBus.getInstance();
         eventBus.emit(GameEvents.GAME_RESUME);
 
-        if (this.gameEndUI) {
-            this.gameEndUI.active = false;
-        }
         // === 新增:恢复时弹出下一波提示Toast ===
         if (this.shouldShowNextWavePrompt) {
             this.shouldShowNextWavePrompt = false;
@@ -326,6 +440,9 @@ export class GameManager extends Component {
     }
 
     update(deltaTime: number) {
+        // 检查UI状态变化(无论在什么状态下都要检查)
+        this.checkBlockSelectionUIStateChange();
+        
         // 只有在游戏中时才进行游戏逻辑更新
         if (this.currentAppState !== AppState.IN_GAME) {
             return;
@@ -357,9 +474,8 @@ export class GameManager extends Component {
         this.levelConfigManager = LevelConfigManager.getInstance();
         // enemyController已通过事件系统解耦,不再需要直接初始化
         
-        // 初始化存档管理器
+        // 存档管理器初始化已迁移到StartGame
         this.saveDataManager = SaveDataManager.getInstance();
-        this.saveDataManager.initialize();
     }
 
     // === 游戏状态初始化 ===
@@ -372,6 +488,7 @@ export class GameManager extends Component {
     }
 
     // === 计算游戏区域边界 ===
+    // 已迁移到StartGame,这里保留方法以兼容现有调用
     private calculateGameBounds() {
         const canvas = find('Canvas');
         if (!canvas) {
@@ -395,11 +512,6 @@ export class GameManager extends Component {
 
     // === 初始化UI节点 ===
     private initUINodes() {
-        // 初始化游戏结束UI
-        if (this.gameEndUI) {
-            this.gameEndUI.active = false;
-        }
-        
         // 初始化游戏内管理器
         if (this.inGameManagerNode) {
             this.inGameManager = this.inGameManagerNode.getComponent(InGameManager);
@@ -466,11 +578,33 @@ export class GameManager extends Component {
         // 更新统计数据
         this.saveDataManager.updateStatistic('totalTimePlayed', gameTime);
         this.saveDataManager.updateStatistic('totalEnemiesDefeated', this.totalEnemiesSpawned);
+    }
+    
+    /**
+     * 清除上一关的成功或失败记录
+     */
+    private clearPreviousGameRecord() {
+        console.log('[GameManager] 清除上一关的游戏记录');
+        
+        // 重置游戏时间记录
+        this.gameStartTime = 0;
+        this.gameEndTime = 0;
         
-        // 兼容原有的LevelManager
-        if (this.levelManager) {
-            this.levelManager.completeLevel(currentLevel, 0);
+        // 重置敌人击杀统计
+        this.totalEnemiesSpawned = 0;
+        
+        // 通过InGameManager重置游戏状态记录
+        const inGameManager = this.getInGameManager();
+        if (inGameManager) {
+            // 重置InGameManager中的游戏状态
+            inGameManager.resetGameRecord();
+            console.log('[GameManager] InGameManager游戏记录已重置');
         }
+        
+        console.log('[GameManager] 上一关游戏记录清除完成');
+        
+        // 兼容原有的LevelManager(已移除错误的currentLevel引用)
+        // 注意:LevelManager的相关逻辑已迁移到SaveDataManager
     }
     
     // === 计算游戏时长 ===
@@ -489,82 +623,48 @@ export class GameManager extends Component {
         this.setupEndUIButtons();
     }
 
-    /**
-     * 设置游戏结束UI的EndLabel文本
-     * @param text 要显示的文本 ('SUCCESS' 或 'DEFEAT')
-     */
-    private setEndLabelText(text: string) {
-        if (!this.gameEndUI) return;
-        
-        const endLabel = this.gameEndUI.getChildByPath('Sprite/EndLabel');
-        if (endLabel) {
-            const labelComponent = endLabel.getComponent(Label);
-            if (labelComponent) {
-                labelComponent.string = text;
-                console.log(`[GameManager] 设置EndLabel文本为: ${text}`);
-            } else {
-                console.warn('[GameManager] 未找到EndLabel的Label组件');
-            }
-        } else {
-            console.warn('[GameManager] 未找到EndLabel节点路径: Sprite/EndLabel');
-        }
-    }
+
 
     // === 设置游戏结束界面按钮 ===
     private setupEndUIButtons() {
-        if (this.gameEndUI) {
-            const restartBtn = this.gameEndUI.getChildByName('RestartBtn');
-            const mainMenuBtn = this.gameEndUI.getChildByName('MainMenuBtn');
-            const shopBtn = this.gameEndUI.getChildByName('ShopBtn');
-            const reviveBtn = this.gameEndUI.getChildByName('ReviveBtn');
-
-            if (restartBtn) {
-                const button = restartBtn.getComponent(Button);
-                if (button) {
-                    button.node.on(Button.EventType.CLICK, this.onRestartClick, this);
-                }
-            }
-
-            if (mainMenuBtn) {
-                const button = mainMenuBtn.getComponent(Button);
-                if (button) {
-                    button.node.on(Button.EventType.CLICK, this.onMainMenuClick, this);
-                }
-            }
-
-            if (shopBtn) {
-                const button = shopBtn.getComponent(Button);
-                if (button) {
-                    button.node.on(Button.EventType.CLICK, this.onShopClick, this);
-                }
-            }
-
-            if (reviveBtn) {
-                const button = reviveBtn.getComponent(Button);
-                if (button) {
-                    button.node.on(Button.EventType.CLICK, this.onReviveClick, this);
-                }
-            }
-        }
+        // UI按钮事件处理已迁移到 UIStateManager
+        // 通过事件系统处理按钮点击事件
     }
 
     // === 按钮点击事件处理 ===
-    private onRestartClick() {
-        console.log('[GameManager] 重新开始游戏');
-        // 通过事件系统触发游戏重启
-        const eventBus = EventBus.getInstance();
-        eventBus.emit(GameEvents.GAME_RESTART);
-    }
     
     private onMainMenuClick() {
         console.log('[GameManager] 返回主菜单');
         
-        // 首先清理游戏数据
-        if (this.inGameManager) {
+        // 1. 通过InGameManager清理游戏数据(敌人清除、能量条重置、方块清除、敌人波数和数量重置)
+        const inGameManager = this.getInGameManager();
+        if (inGameManager) {
             console.log('[GameManager] 触发游戏数据清理');
-            this.inGameManager.triggerGameDataCleanup();
+            inGameManager.triggerGameDataCleanup();
+        } else {
+            console.warn('[GameManager] 未找到InGameManager,跳过游戏数据清理');
+        }
+        
+        // 2. 发送重置UI状态事件,让UIStateManager统一关闭所有相关面板
+        const eventBus = EventBus.getInstance();
+        eventBus.emit(GameEvents.RESET_UI_STATES);
+        
+        // 3. 清除上一关的成功或失败记录
+        this.clearPreviousGameRecord();
+        
+        // 4. 重置关卡到第1关(解决能量条未重置和下次战斗变成下一关的问题)
+        if (this.saveDataManager) {
+            this.saveDataManager.setCurrentLevel(1);
+            console.log('[GameManager] 关卡已重置为第1关');
         }
         
+        // 5. 重置应用状态为主菜单
+        this.currentAppState = AppState.MAIN_MENU;
+        console.log('[GameManager] 应用状态已重置为MAIN_MENU');
+        
+        // 6. 触发返回主菜单事件
+        eventBus.emit(GameEvents.RETURN_TO_MAIN_MENU);
+        
         // 使用装饰器属性获取MainUI,避免使用find
         if (!this.mainUI) {
             console.error('[GameManager] MainUI节点未在编辑器中设置,请拖拽Canvas/MainUI到GameManager的mainUI属性');
@@ -645,6 +745,10 @@ export class GameManager extends Component {
         this.gameStartTime = Date.now();
         // 游戏状态管理已迁移到 InGameManager
         
+        // 启用BlockSelection UI状态监听
+        this.blockSelectionUIMonitoringEnabled = true;
+        console.log('[GameManager] 游戏开始,启用BlockSelection UI状态监听');
+        
         // 发送游戏开始事件,通知其他组件
         const eventBus = EventBus.getInstance();
         eventBus.emit(GameEvents.GAME_START);
@@ -665,10 +769,7 @@ export class GameManager extends Component {
         // 通过事件系统开始敌人生成
         eventBus.emit(GameEvents.ENEMY_START_GAME);
 
-        LevelSessionManager.inst.initialize(
-            SaveDataManager.getInstance().getCurrentLevel(),
-            this.getWallHealth()
-        );
+        // 注意:LevelSessionManager已在StartGame.startGameFlow()中正确初始化,无需重复初始化
     }
     
     private spawnBall() {
@@ -800,11 +901,11 @@ export class GameManager extends Component {
         this.gameStartTime = 0;
         this.gameEndTime = 0;
 
-        // 通过事件系统重置游戏状态
+        // 通过事件系统触发游戏重启,让StartGame组件处理完整的重置流程
         const eventBus = EventBus.getInstance();
-        eventBus.emit(GameEvents.RESET_GAME_MANAGER);
+        eventBus.emit(GameEvents.GAME_RESTART);
         
-        console.log('[GameManager] 游戏状态重置完成');
+        console.log('[GameManager] 游戏重启事件已发送');
     }
 
     public forceGameSuccess() {
@@ -842,15 +943,10 @@ export class GameManager extends Component {
         eventBus.off(GameEvents.GAME_DEFEAT, this.onGameDefeatEvent, this);
         eventBus.off(GameEvents.GAME_RESTART, this.onGameRestartEvent, this);
         eventBus.off(GameEvents.RESET_GAME_MANAGER, this.onResetGameManagerEvent, this);
+        eventBus.off('CONTINUE_CLICK', this.onMainMenuClick, this);
         // ENEMY_KILLED事件监听已迁移到 InGameManager
 
-        // 清理按钮事件监听
-        if (this.gameEndUI) {
-            const buttons = this.gameEndUI.getComponentsInChildren(Button);
-            buttons.forEach(button => {
-                button.node.off(Button.EventType.CLICK);
-            });
-        }
+        // 按钮事件监听已迁移到 UIStateManager
 
         // 清理单例实例
         if (GameManager._instance === this) {
@@ -998,14 +1094,24 @@ export class GameManager extends Component {
 
     // 初始化GameBlockSelection组件
     private initGameBlockSelection() {
+        console.log('[GameManager] 初始化GameBlockSelection组件');
+        console.log('[GameManager] gameBlockSelection节点:', !!this.gameBlockSelection, this.gameBlockSelection?.name);
+        
         if (this.gameBlockSelection) {
             this.blockSelectionComponent = this.gameBlockSelection.getComponent(GameBlockSelection);
+            console.log('[GameManager] GameBlockSelection组件获取结果:', !!this.blockSelectionComponent);
+            
             if (this.blockSelectionComponent) {
                 // 设置确认回调
                 this.blockSelectionComponent.setConfirmCallback(() => {
                     this.handleConfirmAction();
                 });
+                console.log('[GameManager] GameBlockSelection组件初始化成功,确认回调已设置');
+            } else {
+                console.error('[GameManager] 无法获取GameBlockSelection组件,请检查节点是否正确挂载了该组件');
             }
+        } else {
+            console.error('[GameManager] gameBlockSelection节点未设置,请在Inspector中拖拽正确的节点');
         }
     }
 

+ 56 - 6
assets/scripts/LevelSystem/IN_game.ts

@@ -6,7 +6,7 @@ import { GameStartMove } from '../Animations/GameStartMove';
 import { LevelSessionManager } from '../Core/LevelSessionManager';
 import { SaveDataManager } from './SaveDataManager';
 import { SkillManager } from '../CombatSystem/SkillSelection/SkillManager';
-import { ReStartGame } from './ReStartGame';
+import { StartGame } from './StartGame';
 
 const { ccclass, property } = _decorator;
 
@@ -508,6 +508,11 @@ export class InGameManager extends Component {
     private triggerGameDefeat() {
         // 立即设置游戏状态为失败,防止后续敌人击杀事件被处理
         this.currentState = GameState.DEFEAT;
+        this.gameEndTime = Date.now();
+        
+        // 触发游戏结束状态事件
+        EventBus.getInstance().emit(GameEvents.ENTER_GAME_END_STATE, { result: 'defeat' });
+        
         console.log('[InGameManager] 设置游戏状态为失败,发送GAME_DEFEAT事件');
         EventBus.getInstance().emit(GameEvents.GAME_DEFEAT);
     }
@@ -518,6 +523,11 @@ export class InGameManager extends Component {
     private triggerGameSuccess() {
         // 立即设置游戏状态为成功,防止后续敌人击杀事件被处理
         this.currentState = GameState.SUCCESS;
+        this.gameEndTime = Date.now();
+        
+        // 触发游戏结束状态事件
+        EventBus.getInstance().emit(GameEvents.ENTER_GAME_END_STATE, { result: 'success' });
+        
         console.log('[InGameManager] 设置游戏状态为成功,发送GAME_SUCCESS事件');
         EventBus.getInstance().emit(GameEvents.GAME_SUCCESS);
     }
@@ -601,7 +611,7 @@ export class InGameManager extends Component {
             this.selectSkillUI.active = true;
             this.pauseGame();
             // 重置能量
-            ReStartGame.resetEnergy();
+            StartGame.resetEnergy();
         }
     }
     
@@ -808,6 +818,9 @@ export class InGameManager extends Component {
             this.currentState = GameState.PLAYING;
         }
         
+        // 触发进入游玩状态事件
+        EventBus.getInstance().emit(GameEvents.ENTER_PLAYING_STATE);
+        
         // 发送游戏开始事件,确保GamePause正确设置状态
         EventBus.getInstance().emit(GameEvents.GAME_START);
         console.log('[InGameManager] 发送GAME_START事件');
@@ -823,7 +836,7 @@ export class InGameManager extends Component {
     }
     
     /**
-     * 重置能量值(供ReStartGame调用)
+     * 重置能量值(供StartGame调用)
      */
     public resetEnergyValue() {
         this.energyPoints = 0;
@@ -832,7 +845,7 @@ export class InGameManager extends Component {
     }
     
     /**
-     * 重置波次信息(供ReStartGame调用)
+     * 重置波次信息(供StartGame调用)
      */
     public resetWaveInfo() {
         this.currentWave = 1;
@@ -845,7 +858,7 @@ export class InGameManager extends Component {
     }
     
     /**
-     * 重置能量系统(供ReStartGame调用)
+     * 重置能量系统(供StartGame调用)
      */
     public resetEnergySystem() {
         this.energyPoints = 0;
@@ -925,7 +938,7 @@ export class InGameManager extends Component {
     }
     
     /**
-     * 重置游戏状态(供ReStartGame调用)
+     * 重置游戏状态(供StartGame调用)
      */
     public resetGameStates() {
         this.currentState = GameState.PLAYING;
@@ -940,6 +953,43 @@ export class InGameManager extends Component {
         this.checkTimer = 0;
         console.log('[InGameManager] 游戏状态重置完成');
     }
+    
+    /**
+     * 重置游戏记录(供GameManager调用)
+     * 清除上一关的成功或失败记录
+     */
+    public resetGameRecord() {
+        console.log('[InGameManager] 重置游戏记录');
+        
+        // 重置游戏状态为初始状态
+        this.currentState = GameState.PLAYING;
+        
+        // 重置时间记录
+        this.gameStartTime = 0;
+        this.gameEndTime = 0;
+        
+        // 重置波次和敌人统计
+        this.currentWave = 1;
+        this.currentWaveEnemyCount = 0;
+        this.currentWaveTotalEnemies = 0;
+        this.enemiesKilled = 0;
+        this.totalEnemiesSpawned = 0;
+        this.levelTotalEnemies = 0;
+        
+        // 重置游戏标志
+        this.gameStarted = false;
+        this.enemySpawningStarted = false;
+        this.preparingNextWave = false;
+        this.pendingSkillSelection = false;
+        this.pendingBlockSelection = false;
+        this.shouldShowNextWavePrompt = false;
+        
+        // 重置能量系统
+        this.energyPoints = 0;
+        this.updateEnergyBar();
+        
+        console.log('[InGameManager] 游戏记录重置完成');
+    }
 
     /**
      * 手动触发游戏数据清理(供外部调用)

+ 0 - 108
assets/scripts/LevelSystem/ReStartGame.ts

@@ -1,108 +0,0 @@
-import { _decorator, Component,  find } from 'cc';
-import { LevelSessionManager } from '../Core/LevelSessionManager';
-import EventBus, { GameEvents } from '../Core/EventBus';
-const { ccclass } = _decorator;
-
-/**
- * 游戏重置管理器
- * 负责协调各个组件的重置操作,使用事件系统解耦
- */
-@ccclass('ReStartGame')
-export class ReStartGame extends Component {
-    
-    start() {
-        // 监听游戏重启事件
-        const eventBus = EventBus.getInstance();
-        eventBus.on(GameEvents.GAME_RESTART, this.onGameRestartEvent, this);
-    }
-    
-    onDestroy() {
-        // 移除事件监听
-        const eventBus = EventBus.getInstance();
-        eventBus.off(GameEvents.GAME_RESTART, this.onGameRestartEvent, this);
-    }
-    
-    /**
-     * 处理游戏重启事件
-     */
-    private onGameRestartEvent() {
-        console.log('[ReStartGame] 接收到游戏重启事件,开始重置游戏状态');
-        ReStartGame.resetAllGameStates();
-    }
-    
-    /**
-     * 完整重置游戏状态
-     * 在关闭成功/失败界面时调用
-     */
-    public static resetAllGameStates() {
-        console.log('[ReStartGame] 开始完整重置游戏状态');
-        
-        const eventBus = EventBus.getInstance();
-        
-        // 发送游戏重置请求事件
-        eventBus.emit(GameEvents.GAME_RESET_REQUEST);
-        
-        // 按顺序发送各个组件的重置事件
-        setTimeout(() => {
-            // 1. 清理所有游戏对象
-            eventBus.emit(GameEvents.CLEAR_ALL_GAME_OBJECTS);
-            
-            // 2. 重置各个组件状态
-            eventBus.emit(GameEvents.RESET_GAME_MANAGER);
-            eventBus.emit(GameEvents.RESET_ENEMY_CONTROLLER);
-            eventBus.emit(GameEvents.RESET_BALL_CONTROLLER);
-            eventBus.emit(GameEvents.RESET_BLOCK_MANAGER);
-            eventBus.emit(GameEvents.RESET_BLOCK_SELECTION);
-            eventBus.emit(GameEvents.RESET_WALL_HEALTH);
-            eventBus.emit(GameEvents.RESET_GAME_PAUSE);
-            eventBus.emit(GameEvents.RESET_ENERGY_SYSTEM);
-            
-            // 3. 重置UI状态
-            eventBus.emit(GameEvents.RESET_UI_STATES);
-            
-            // 4. 重新初始化游戏
-            setTimeout(() => {
-                ReStartGame.reinitializeGame();
-                eventBus.emit(GameEvents.GAME_RESET_COMPLETE);
-                console.log('[ReStartGame] 游戏状态重置完成');
-            }, 100);
-        }, 50);
-    }
-    
-
-    
-    /**
-     * 重新初始化游戏
-     */
-    private static reinitializeGame() {
-        console.log('[ReStartGame] 开始重新初始化游戏');
-        
-        // 清理并重新初始化关卡会话数据
-        LevelSessionManager.inst.clear();
-        
-        // 通过事件系统显示方块选择界面
-        const eventBus = EventBus.getInstance();
-        eventBus.emit(GameEvents.SHOW_BLOCK_SELECTION);
-        
-        console.log('[ReStartGame] 游戏重新初始化完成');
-    }
-    
-    /**
-     * 快速重启游戏(用于重新开始按钮)
-     */
-    public static quickRestart() {
-        console.log('[ReStartGame] 快速重启游戏');
-        
-        // 执行完整重置
-        ReStartGame.resetAllGameStates();
-    }
-    
-    /**
-     * 通过事件系统重置能量值
-     */
-    public static resetEnergy() {
-        const eventBus = EventBus.getInstance();
-        eventBus.emit(GameEvents.RESET_ENERGY_SYSTEM);
-        console.log('[ReStartGame] 发送能量重置事件');
-    }
-}

+ 0 - 9
assets/scripts/LevelSystem/ReStartGame.ts.meta

@@ -1,9 +0,0 @@
-{
-  "ver": "4.0.24",
-  "importer": "typescript",
-  "imported": true,
-  "uuid": "3e27e721-ad15-41cd-9d1b-17793f5e84e1",
-  "files": [],
-  "subMetas": {},
-  "userData": {}
-}

+ 18 - 2
assets/scripts/LevelSystem/SaveDataManager.ts

@@ -219,7 +219,7 @@ export class SaveDataManager {
             lastPlayTime: Date.now(),
             totalPlayTime: 0,
             
-            coins: 0,        // 初始金币
+            coins: 45,       // 初始金币
             diamonds: 0,       // 初始钻石
             gems: 0,
             
@@ -297,7 +297,7 @@ export class SaveDataManager {
             createTime: Date.now(),
             lastPlayTime: Date.now(),
             totalPlayTime: 0,
-            coins: 1000,
+            coins: 45,
             diamonds: 50,
             gems: 0,
             wallLevel: 1,        // 初始墙体等级
@@ -400,6 +400,22 @@ export class SaveDataManager {
         return this.playerData?.currentLevel || 1;
     }
     
+    /**
+     * 设置当前关卡
+     */
+    public setCurrentLevel(level: number): void {
+        if (!this.playerData) return;
+        
+        // 确保关卡在有效范围内
+        if (level >= 1 && level <= this.playerData.maxUnlockedLevel) {
+            this.playerData.currentLevel = level;
+            this.savePlayerData();
+            console.log(`[SaveDataManager] 当前关卡设置为: ${level}`);
+        } else {
+            console.warn(`[SaveDataManager] 无效的关卡设置: ${level},当前最大解锁关卡: ${this.playerData.maxUnlockedLevel}`);
+        }
+    }
+    
     public getMaxUnlockedLevel(): number {
         return this.playerData?.maxUnlockedLevel || 1;
     }

+ 164 - 0
assets/scripts/LevelSystem/StartGame.ts

@@ -0,0 +1,164 @@
+import { _decorator, Component, find, UITransform } from 'cc';
+import { LevelSessionManager } from '../Core/LevelSessionManager';
+import { SaveDataManager } from './SaveDataManager';
+import EventBus, { GameEvents } from '../Core/EventBus';
+import { GameManager } from './GameManager';
+const { ccclass } = _decorator;
+
+/**
+ * 游戏启动管理器
+ * 负责统一处理游戏启动流程:显示方块选择UI → 玩家选择方块 → 确认开始游戏,并加载游戏状态
+ * 不区分首次游戏和重启游戏,统一按照流程进行
+ * 
+ * 注意:这个类主要提供静态方法,不需要挂载到场景节点上
+ */
+@ccclass('StartGame')
+export class StartGame extends Component {
+    
+    private static eventListenersInitialized = false;
+    
+    start() {
+        // 初始化静态事件监听器(只初始化一次)
+        StartGame.initializeEventListeners();
+    }
+    
+    onDestroy() {
+        // 组件销毁时不移除静态事件监听,因为其他地方可能还需要使用
+    }
+    
+    /**
+     * 初始化静态事件监听器
+     * 可以被外部调用以确保事件监听器已设置
+     */
+    public static initializeEventListeners() {
+        if (StartGame.eventListenersInitialized) {
+            return;
+        }
+        
+        const eventBus = EventBus.getInstance();
+        eventBus.on(GameEvents.GAME_START, StartGame.onGameStartEvent);
+        eventBus.on(GameEvents.GAME_RESTART, StartGame.onGameStartEvent);
+        
+        StartGame.eventListenersInitialized = true;
+        console.log('[StartGame] 静态事件监听器初始化完成');
+    }
+    
+    /**
+     * 处理游戏启动事件(统一处理首次启动和重启)
+     */
+    private static onGameStartEvent() {
+        console.log('[StartGame] 接收到游戏启动事件,开始游戏启动流程');
+        StartGame.startGameFlow();
+    }
+    
+    /**
+     * 统一的游戏启动流程
+     * 无论是首次启动还是重启,都按照相同流程进行
+     * 注意:不在此处清理游戏状态,清理由GameEnd UI状态监听机制负责
+     */
+    public static async startGameFlow() {
+        console.log('[StartGame] 开始游戏启动流程');
+        
+        // 确保事件监听器已初始化
+        StartGame.initializeEventListeners();
+        
+        const eventBus = EventBus.getInstance();
+        
+        // 1. 初始化游戏数据
+        console.log('[StartGame] 初始化游戏数据');
+        await StartGame.initializeGameData();
+        
+        // 2. 显示方块选择UI
+        console.log('[StartGame] 显示方块选择UI');
+        setTimeout(() => {
+            console.log('[StartGame] 准备发送SHOW_BLOCK_SELECTION事件');
+            eventBus.emit(GameEvents.SHOW_BLOCK_SELECTION);
+            console.log('[StartGame] SHOW_BLOCK_SELECTION事件已发送');
+            console.log('[StartGame] 游戏启动流程完成');
+        }, 600);
+    }
+    
+
+    
+    /**
+     * 初始化游戏数据
+     */
+    private static async initializeGameData() {
+        // 清理并重新初始化关卡会话数据
+        LevelSessionManager.inst.clear();
+        
+        // 初始化存档管理器
+        const saveDataManager = SaveDataManager.getInstance();
+        saveDataManager.initialize();
+        
+        // 重新初始化LevelSessionManager,设置sessionCoins为45
+        LevelSessionManager.inst.initialize(
+            saveDataManager.getCurrentLevel(),
+            100 // 默认墙血量,可以根据需要调整
+        );
+        
+        // 计算游戏区域边界
+        StartGame.calculateGameBounds();
+        
+        console.log('[StartGame] 游戏数据初始化完成,sessionCoins已设置为45');
+        
+        // 先重置能量为0
+        const eventBus = EventBus.getInstance();
+        eventBus.emit(GameEvents.RESET_ENERGY_SYSTEM);
+        console.log('[StartGame] 发送能量重置事件');
+        
+        // 延迟加载关卡配置,确保能量重置先执行
+        setTimeout(async () => {
+            // 获取GameManager实例并加载关卡配置
+            const gameManagerNode = find('GameManager');
+            if (gameManagerNode) {
+                const gameManager = gameManagerNode.getComponent(GameManager);
+                if (gameManager && gameManager.loadCurrentLevelConfig) {
+                    await gameManager.loadCurrentLevelConfig();
+                    console.log('[StartGame] 关卡配置加载完成');
+                }
+            }
+        }, 100);
+    }
+    
+    /**
+     * 计算游戏区域边界
+     */
+    private static calculateGameBounds() {
+        const canvas = find('Canvas');
+        if (!canvas) {
+            console.warn('[StartGame] 未找到Canvas节点');
+            return;
+        }
+
+        const canvasUI = canvas.getComponent(UITransform);
+        if (!canvasUI) {
+            console.warn('[StartGame] Canvas节点缺少UITransform组件');
+            return;
+        }
+
+        const screenWidth = canvasUI.width;
+        const screenHeight = canvasUI.height;
+        const worldPos = canvas.worldPosition;
+
+        const gameBounds = {
+            left: worldPos.x - screenWidth / 2,
+            right: worldPos.x + screenWidth / 2,
+            bottom: worldPos.y - screenHeight / 2,
+            top: worldPos.y + screenHeight / 2
+        };
+        
+        console.log('[StartGame] 游戏区域边界计算完成:', gameBounds);
+    }
+    
+
+    
+    /**
+     * 通过事件系统重置能量值
+     */
+    public static resetEnergy() {
+        const eventBus = EventBus.getInstance();
+        eventBus.emit(GameEvents.RESET_ENERGY_SYSTEM);
+        console.log('[StartGame] 发送能量重置事件');
+    }
+}

+ 1 - 1
assets/scripts/test/GamePauseTest.ts.meta → assets/scripts/LevelSystem/StartGame.ts.meta

@@ -2,7 +2,7 @@
   "ver": "4.0.24",
   "importer": "typescript",
   "imported": true,
-  "uuid": "23b4b2e9-aa3d-4998-ad31-d10645592dab",
+  "uuid": "7ee1087a-505c-45fc-8f45-99f9ca4ecac3",
   "files": [],
   "subMetas": {},
   "userData": {}

+ 57 - 2
assets/scripts/LevelSystem/UIStateManager.ts

@@ -14,6 +14,9 @@ export class UIStateManager extends BaseSingleton {
 
     @property({ type: Node, tooltip: '游戏结束面板 (Canvas/GameEnd)' })
     public endPanel: Node = null;
+    
+    // 控制是否响应游戏结束事件的标志
+    private shouldRespondToGameEvents: boolean = true;
 
     protected init() {
         // 自动查找面板
@@ -30,7 +33,7 @@ export class UIStateManager extends BaseSingleton {
         // 监听事件
         EventBus.getInstance().on(GameEvents.GAME_SUCCESS, this.onGameSuccess, this);
         EventBus.getInstance().on(GameEvents.GAME_DEFEAT, this.onGameDefeat, this);
-        // EventBus.getInstance().on(GameEvents.RESET_UI_STATES, this.closeAllPanels, this);
+        EventBus.getInstance().on(GameEvents.RESET_UI_STATES, this.closeAllPanels, this);
     }
 
     private bindPanelButtons() {
@@ -69,6 +72,12 @@ export class UIStateManager extends BaseSingleton {
     }
 
     private onGameSuccess() {
+        // 如果被禁用响应游戏事件,则跳过
+        if (!this.shouldRespondToGameEvents) {
+            console.log('[UIStateManager] 已禁用游戏事件响应,跳过GAME_SUCCESS处理');
+            return;
+        }
+        
         if (this.endPanel) {
             this.endPanel.active = true;
             this.setEndLabelText('SUCCESS');
@@ -76,6 +85,12 @@ export class UIStateManager extends BaseSingleton {
     }
 
     private onGameDefeat() {
+        // 如果被禁用响应游戏事件,则跳过
+        if (!this.shouldRespondToGameEvents) {
+            console.log('[UIStateManager] 已禁用游戏事件响应,跳过GAME_DEFEAT处理');
+            return;
+        }
+        
         if (this.endPanel) {
             this.endPanel.active = true;
             this.setEndLabelText('DEFEAT');
@@ -84,6 +99,46 @@ export class UIStateManager extends BaseSingleton {
 
     /** 对外接口 */
     public closeAllPanels() {
-        if (this.endPanel) this.endPanel.active = false;
+        console.log('[UIStateManager] 重置UI状态,关闭所有面板');
+        
+        // 关闭游戏结束面板
+        if (this.endPanel) {
+            this.endPanel.active = false;
+            console.log('[UIStateManager] 已关闭GameEnd面板');
+        }
+        
+        // 关闭技能选择面板
+        const selectSkillUI = find('Canvas/SelectSkillUI');
+        if (selectSkillUI && selectSkillUI.active) {
+            selectSkillUI.active = false;
+            console.log('[UIStateManager] 已关闭SelectSkillUI面板');
+        }
+        
+        // 关闭其他可能的游戏UI面板
+        const gameBlockSelection = find('Canvas/GameBlockSelection');
+        if (gameBlockSelection && gameBlockSelection.active) {
+            gameBlockSelection.active = false;
+            console.log('[UIStateManager] 已关闭GameBlockSelection面板');
+        }
+        
+        // 暂时禁用游戏事件响应,避免与GameManager冲突
+        this.shouldRespondToGameEvents = false;
+        console.log('[UIStateManager] 已禁用游戏事件响应');
+        
+        // 延迟重新启用,给GameManager足够时间处理
+        this.scheduleOnce(() => {
+            this.shouldRespondToGameEvents = true;
+            console.log('[UIStateManager] 已重新启用游戏事件响应');
+        }, 1.0);
+    }
+
+    protected onDestroy() {
+        // 清理事件监听
+        const eventBus = EventBus.getInstance();
+        eventBus.off(GameEvents.GAME_SUCCESS, this.onGameSuccess, this);
+        eventBus.off(GameEvents.GAME_DEFEAT, this.onGameDefeat, this);
+        eventBus.off(GameEvents.RESET_UI_STATES, this.closeAllPanels, this);
+        
+        super.onDestroy();
     }
 }

+ 0 - 9
assets/scripts/test.meta

@@ -1,9 +0,0 @@
-{
-  "ver": "1.2.0",
-  "importer": "directory",
-  "imported": true,
-  "uuid": "ed5be3dd-a9df-42a2-9eca-778104ed34b3",
-  "files": [],
-  "subMetas": {},
-  "userData": {}
-}

+ 0 - 131
assets/scripts/test/GamePauseTest.ts

@@ -1,131 +0,0 @@
-import { _decorator, Component, Node } from 'cc';
-import EventBus, { GameEvents } from '../Core/EventBus';
-
-const { ccclass, property } = _decorator;
-
-/**
- * GamePause测试脚本
- * 用于测试游戏状态管理和事件流程
- */
-@ccclass('GamePauseTest')
-export class GamePauseTest extends Component {
-
-    start() {
-        // 延迟执行测试,确保所有组件都已初始化
-        this.scheduleOnce(() => {
-            this.runTests();
-        }, 2);
-    }
-
-    private runTests() {
-        console.log('=== GamePause测试开始 ===');
-        
-        // 测试1:检查GamePause实例
-        this.testGamePauseInstance();
-        
-        // 测试2:测试游戏开始事件
-        this.testGameStartEvent();
-        
-        // 测试3:测试游戏失败触发
-        this.testGameDefeatTrigger();
-        
-        console.log('=== GamePause测试完成 ===');
-    }
-
-    private testGamePauseInstance() {
-        console.log('--- 测试1:GamePause状态检查 ---');
-        
-        // 通过事件系统检查游戏状态
-        const eventBus = EventBus.getInstance();
-        
-        // 检查游戏是否结束
-        let isGameOver = false;
-        eventBus.emit(GameEvents.GAME_CHECK_OVER, (result: boolean) => {
-            isGameOver = result;
-        });
-        
-        console.log('✓ 通过事件系统检查游戏状态');
-        console.log('是否游戏结束:', isGameOver);
-    }
-
-    private testGameStartEvent() {
-        console.log('--- 测试2:游戏开始事件测试 ---');
-        
-        // 发送游戏开始事件
-        const eventBus = EventBus.getInstance();
-        console.log('发送GAME_START事件...');
-        eventBus.emit(GameEvents.GAME_START);
-        
-        // 检查状态
-        this.scheduleOnce(() => {
-            console.log('游戏开始事件发送后的状态检查:');
-            // 通过事件系统检查游戏状态
-            let isGameOver = false;
-            eventBus.emit(GameEvents.GAME_CHECK_OVER, (result: boolean) => {
-                isGameOver = result;
-            });
-            console.log('是否游戏结束:', isGameOver);
-        }, 0.1);
-    }
-
-    private testGameDefeatTrigger() {
-        console.log('--- 测试3:游戏失败触发测试 ---');
-        
-        // 延迟执行,确保游戏开始事件已处理
-        this.scheduleOnce(() => {
-            console.log('尝试触发游戏失败...');
-            // 通过事件系统触发游戏失败
-            const eventBus = EventBus.getInstance();
-            eventBus.emit(GameEvents.GAME_DEFEAT);
-            
-            // 检查结果
-            this.scheduleOnce(() => {
-                console.log('游戏失败触发后的状态检查:');
-                // 通过事件系统检查游戏状态
-                let isGameOver = false;
-                eventBus.emit(GameEvents.GAME_CHECK_OVER, (result: boolean) => {
-                    isGameOver = result;
-                });
-                console.log('是否游戏结束:', isGameOver);
-                
-                if (isGameOver) {
-                    console.log('✓ 游戏失败触发成功');
-                } else {
-                    console.log('✗ 游戏失败触发失败');
-                }
-            }, 0.1);
-        }, 0.5);
-    }
-
-    /**
-     * 手动测试方法 - 可以在控制台调用
-     */
-    public manualTestGameStart() {
-        console.log('手动测试:发送游戏开始事件');
-        const eventBus = EventBus.getInstance();
-        eventBus.emit(GameEvents.GAME_START);
-    }
-
-    public manualTestGameDefeat() {
-        console.log('手动测试:触发游戏失败');
-        const eventBus = EventBus.getInstance();
-        eventBus.emit(GameEvents.GAME_DEFEAT);
-    }
-
-    public checkGamePauseStatus() {
-        console.log('检查GamePause状态:');
-        const eventBus = EventBus.getInstance();
-        
-        // 通过事件系统检查游戏状态
-        let isGameOver = false;
-        eventBus.emit(GameEvents.GAME_CHECK_OVER, (result: boolean) => {
-            isGameOver = result;
-        });
-        
-        let canFireBullet = true;
-        eventBus.emit(GameEvents.BALL_FIRE_BULLET, { canFire: (result: boolean) => { canFireBullet = result; } });
-        
-        console.log('是否游戏结束:', isGameOver);
-        console.log('是否允许发射子弹:', canFireBullet);
-    }
-}

+ 0 - 12
assets/scripts/test/Skill.txt

@@ -1,12 +0,0 @@
-Cheaper Units
-效果:方块价格降低 10%。能让玩家在购买单位时花费更少资源(如金币等)。
-Crit Chance
-效果:将造成暴击伤害的几率提高 10% 。触发暴击可使伤害大幅提升,有概率触发暴击伤害,计算方式:原来伤害+10%,最终伤害考虑暴击率,暴击率从玩家数据获得(初始暴击率10%)。
-Heal
-效果:使 “墙”的生命值增加 10%。
-Multi Shots
-效果:将多发子弹同时射出(多射)的几率提高 10% 。在游戏战斗场景中,触发多射可在一次攻击时发射多颗子弹(原来的单发子弹有概率多发子弹)。
-XP hunter
-效果:获取的经验值(XP)增加 10% 。在游戏进程中,更多经验值能让玩家更快升级,解锁新技能、道具或提升角色属性,从长远角度助力角色成长和游戏进度推进。
-Ball Speed
-效果:在游戏中,球的速度加快10%

+ 0 - 109
assets/scripts/test/WeaponRandomSpawner.ts

@@ -1,109 +0,0 @@
-import { _decorator, Component, Node, Sprite, SpriteFrame, resources, Prefab, instantiate, UITransform, Vec2, Vec3, RigidBody2D, macro } from 'cc';
-const { ccclass, property } = _decorator;
-
-@ccclass('WeaponRandomSpawner')
-export class WeaponRandomSpawner extends Component {
-    /**
-     * Pellet prefab used as bullet. Drag the Pellet.prefab into this slot in the editor.
-     */
-    @property({ type: Prefab })
-    public pelletPrefab: Prefab | null = null;
-
-    /**
-     * Time interval (seconds) between two shots.
-     */
-    @property
-    public fireInterval: number = 1.0;
-
-    /** Cached weapon sprite component (WeaponBlock/B1/Weapon) */
-    private _weaponSprite: Sprite | null = null;
-    /** The sprite frame chosen randomly at scene start */
-    private _selectedFrame: SpriteFrame | null = null;
-
-    onLoad() {
-        // Locate the Weapon sprite component inside the prefab hierarchy
-        const b1Node: Node | null = this.node.getChildByName('B1');
-        if (!b1Node) {
-            console.error('[WeaponRandomSpawner] Cannot find child node "B1"');
-            return;
-        }
-        const weaponNode: Node | null = b1Node.getChildByName('Weapon');
-        if (!weaponNode) {
-            console.error('[WeaponRandomSpawner] Cannot find grand-child node "Weapon" under B1');
-            return;
-        }
-        this._weaponSprite = weaponNode.getComponent(Sprite);
-        if (!this._weaponSprite) {
-            console.error('[WeaponRandomSpawner] Sprite component missing on Weapon node');
-            return;
-        }
-
-        // Load all sprite frames under resources/images/PlantsSprite at runtime
-        resources.loadDir('images/PlantsSprite', SpriteFrame, (err, assets) => {
-            if (err) {
-                console.error('[WeaponRandomSpawner] Failed to load PlantsSprite resources:', err);
-                return;
-            }
-            if (!assets || assets.length === 0) {
-                console.warn('[WeaponRandomSpawner] No sprite frames found in images/PlantsSprite');
-                return;
-            }
-
-            // Pick one sprite frame randomly and apply to weapon
-            this._selectedFrame = assets[Math.floor(Math.random() * assets.length)];
-            // Add null safety check before setting spriteFrame
-            if (this._weaponSprite && this._weaponSprite.isValid && this._weaponSprite.node && this._weaponSprite.node.isValid) {
-                this._weaponSprite.spriteFrame = this._selectedFrame;
-            }
-        });
-    }
-
-    start() {
-        // Start auto-fire schedule
-        this.schedule(this._fire.bind(this), this.fireInterval);
-    }
-
-    onDestroy() {
-        // Clear references to prevent operations on destroyed components
-        this._weaponSprite = null;
-        this._selectedFrame = null;
-    }
-
-    /**
-     * Instantiate a bullet prefab, copy the weapon sprite frame to it (scaled to half size)
-     * and give it an upward velocity.
-     */
-    private _fire() {
-        if (!this.pelletPrefab || !this._selectedFrame) {
-            return; // Not ready yet
-        }
-
-        const bullet: Node = instantiate(this.pelletPrefab);
-        // Add to the same scene, at world position of the weapon muzzle (current node)
-        this.node.scene?.addChild(bullet);
-        bullet.setWorldPosition(this.node.worldPosition);
-
-        // Set bullet sprite frame with null safety checks
-        const bulletSprite = bullet.getComponent(Sprite);
-        if (bulletSprite && bulletSprite.isValid && bullet && bullet.isValid) {
-            bulletSprite.spriteFrame = this._selectedFrame;
-        }
-
-        // Match bullet size to half of weapon sprite size
-        const weaponUi = this._weaponSprite?.node.getComponent(UITransform);
-        const bulletUi = bullet.getComponent(UITransform);
-        if (weaponUi && bulletUi) {
-            const size = weaponUi.contentSize;
-            bulletUi.setContentSize(size.width * 0.5, size.height * 0.5);
-        } else {
-            // Fallback: scale the whole node
-            bullet.setScale(this.node.scale.x * 0.5, this.node.scale.y * 0.5, 1);
-        }
-
-        // Give the bullet an upward velocity if it has a RigidBody2D component
-        const rb = bullet.getComponent(RigidBody2D);
-        if (rb) {
-            rb.linearVelocity = new Vec2(0, 600);
-        }
-    }
-} 

+ 0 - 9
assets/scripts/test/WeaponRandomSpawner.ts.meta

@@ -1,9 +0,0 @@
-{
-  "ver": "4.0.24",
-  "importer": "typescript",
-  "imported": true,
-  "uuid": "e2fb1d25-5225-4bbd-a2eb-b6d656d4a5d1",
-  "files": [],
-  "subMetas": {},
-  "userData": {}
-}

Some files were not shown because too many files changed in this diff