Browse Source

血量倍率实现

181404010226 2 months ago
parent
commit
0cc8d56dd5

+ 29 - 32
assets/Scenes/GameLevel.scene

@@ -165,7 +165,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 360,
-      "y": 667,
+      "y": 666.9999999999999,
       "z": 0
     },
     "_lrot": {
@@ -335,7 +335,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 0,
-      "y": -820,
+      "y": -819.9999999999999,
       "z": 0
     },
     "_lrot": {
@@ -493,7 +493,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 0,
-      "y": -762.28,
+      "y": -762.2799999999999,
       "z": 0
     },
     "_lrot": {
@@ -738,7 +738,7 @@
     "_contentSize": {
       "__type__": "cc.Size",
       "width": 720,
-      "height": 1334
+      "height": 1333.9999999999998
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
@@ -853,7 +853,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 0,
-      "y": 0,
+      "y": -1.1368683772161603e-13,
       "z": 0
     },
     "_lrot": {
@@ -1270,7 +1270,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 18.132,
-      "y": -457.699,
+      "y": -457.6989999999999,
       "z": 0
     },
     "_lrot": {
@@ -9783,7 +9783,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 0,
-      "y": 0,
+      "y": -1.1368683772161603e-13,
       "z": 0
     },
     "_lrot": {
@@ -10049,7 +10049,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 0,
-      "y": 452.76,
+      "y": 495.422,
       "z": 0
     },
     "_lrot": {
@@ -10158,7 +10158,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 0,
-      "y": -606.727,
+      "y": -604.787,
       "z": 0
     },
     "_lrot": {
@@ -10226,10 +10226,7 @@
       "b": 11,
       "a": 0
     },
-    "_spriteFrame": {
-      "__uuid__": "7d8f9b89-4fd1-4c9f-a3ab-38ec7cded7ca@f9941",
-      "__expectedType__": "cc.SpriteFrame"
-    },
+    "_spriteFrame": null,
     "_type": 0,
     "_fillType": 0,
     "_sizeMode": 0,
@@ -13714,7 +13711,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 360,
-      "y": 667,
+      "y": 666.9999999999999,
       "z": 0
     },
     "_lrot": {
@@ -13844,7 +13841,7 @@
     "_contentSize": {
       "__type__": "cc.Size",
       "width": 720,
-      "height": 1334
+      "height": 1333.9999999999998
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
@@ -18596,7 +18593,7 @@
     "_contentSize": {
       "__type__": "cc.Size",
       "width": 720,
-      "height": 1334
+      "height": 1333.9999999999998
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
@@ -18699,7 +18696,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 0,
-      "y": 317.85,
+      "y": 317.84999999999997,
       "z": 0
     },
     "_lrot": {
@@ -18864,7 +18861,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 0,
-      "y": 199.969,
+      "y": 199.96899999999994,
       "z": 0
     },
     "_lrot": {
@@ -19036,7 +19033,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 0,
-      "y": 97.5,
+      "y": 97.49999999999994,
       "z": 0
     },
     "_lrot": {
@@ -21120,7 +21117,7 @@
     "_contentSize": {
       "__type__": "cc.Size",
       "width": 720,
-      "height": 1334
+      "height": 1333.9999999999998
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
@@ -21254,7 +21251,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 0.14999999999997726,
-      "y": -588.66,
+      "y": -588.6599999999999,
       "z": 0
     },
     "_lrot": {
@@ -25336,7 +25333,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 0,
-      "y": 629.5,
+      "y": 629.4999999999999,
       "z": 0
     },
     "_lrot": {
@@ -31232,7 +31229,7 @@
       "__id__": 926
     },
     "_children": [],
-    "_active": true,
+    "_active": false,
     "_components": [
       {
         "__id__": 932
@@ -32429,7 +32426,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 0,
-      "y": 0,
+      "y": 2.28,
       "z": 0
     },
     "_lrot": {
@@ -32556,7 +32553,7 @@
     "_top": 4.062999999999998,
     "_bottom": 0.37195384615384625,
     "_horizontalCenter": 0,
-    "_verticalCenter": 0,
+    "_verticalCenter": 0.039999999999999994,
     "_isAbsLeft": true,
     "_isAbsRight": true,
     "_isAbsTop": true,
@@ -32578,7 +32575,7 @@
       "__id__": 962
     },
     "_children": [],
-    "_active": true,
+    "_active": false,
     "_components": [
       {
         "__id__": 968
@@ -35826,7 +35823,7 @@
     "_contentSize": {
       "__type__": "cc.Size",
       "width": 720,
-      "height": 1334
+      "height": 1333.9999999999998
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
@@ -35878,7 +35875,7 @@
     "_contentSize": {
       "__type__": "cc.Size",
       "width": 720,
-      "height": 1334
+      "height": 1333.9999999999998
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
@@ -39092,7 +39089,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 0,
-      "y": -667.155,
+      "y": -667.1549999999999,
       "z": 0
     },
     "_lrot": {
@@ -43718,7 +43715,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 281.9,
-      "y": 553.12,
+      "y": 553.1199999999999,
       "z": 0
     },
     "_lrot": {
@@ -43915,7 +43912,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 281.5,
-      "y": 485.124,
+      "y": 485.1239999999999,
       "z": 0
     },
     "_lrot": {
@@ -45034,7 +45031,7 @@
     "_contentSize": {
       "__type__": "cc.Size",
       "width": 720,
-      "height": 1334
+      "height": 1333.9999999999998
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",

+ 156 - 48
assets/scripts/CombatSystem/EnemyController.ts

@@ -11,6 +11,7 @@ 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;
 
 
@@ -106,6 +107,9 @@ export class EnemyController extends BaseSingleton {
     // 关卡配置管理器
     private levelConfigManager: LevelConfigManager = null;
     
+    // 资源预加载管理器
+    private resourcePreloader: ResourcePreloader = null;
+    
     // 当前关卡血量倍率
     private currentHealthMultiplier: number = 1.0;
     private currentWaveHealthMultiplier: number = 1.0; // 当前波次的血量系数
@@ -150,6 +154,9 @@ export class EnemyController extends BaseSingleton {
         // 获取配置管理器实例
         this.configManager = ConfigManager.getInstance();
         
+        // 获取资源预加载管理器实例
+        this.resourcePreloader = ResourcePreloader.getInstance();
+        
         // 获取关卡配置管理器实例
         if (this.levelConfigManagerNode) {
             this.levelConfigManager = this.levelConfigManagerNode.getComponent(LevelConfigManager) || null;
@@ -200,10 +207,44 @@ export class EnemyController extends BaseSingleton {
         // 初始化敌人数量显示
         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 ? '已绑定' : '未绑定');
+    }
+
     /**
      * 设置事件监听器
      */
@@ -279,6 +320,70 @@ export class EnemyController extends BaseSingleton {
         return 1.0;
     }
 
+    /**
+     * 获取当前波次的血量倍率(从关卡配置中读取)
+     */
+    private async getWaveHealthMultiplier(): Promise<number> {
+        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<number> {
+        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; // 返回默认倍率
+        }
+    }
+
     /**
      * 处理游戏暂停事件
      */
@@ -759,20 +864,8 @@ export class EnemyController extends BaseSingleton {
             }
         }
 
-        // 获取当前敌人的血量倍率
-        let healthMultiplier = 1.0;
-        if (this.currentWaveEnemyConfigs.length > 0) {
-            const configIndex = this.currentWaveEnemiesSpawned % this.currentWaveEnemyConfigs.length;
-            const enemyTypeConfig = this.currentWaveEnemyConfigs[configIndex];
-            if (enemyTypeConfig && typeof enemyTypeConfig.healthMultiplier === 'number') {
-                healthMultiplier = enemyTypeConfig.healthMultiplier;
-            }
-        }
-        
-        // 如果没有找到敌人配置中的血量系数,则使用波次级别的血量系数作为备用
-        if (healthMultiplier === 1.0) {
-            healthMultiplier = await this.getCurrentHealthMultiplier();
-        }
+        // 计算最终血量倍率(关卡 × 波次)
+        const finalHealthMultiplier = await this.calculateFinalHealthMultiplier();
         
         if (enemyConfig && enemyId) {
             try {
@@ -790,15 +883,15 @@ export class EnemyController extends BaseSingleton {
                 
                 // 应用血量倍率
                 const baseHealth = enemyComp.health || this.defaultHealth;
-                const finalHealth = Math.round(baseHealth * healthMultiplier);
+                const finalHealth = Math.round(baseHealth * finalHealthMultiplier);
                 enemyComp.health = finalHealth;
                 enemyComp.maxHealth = finalHealth;
                 
-                console.log(`[EnemyController] 敌人 ${enemyId} 配置已应用,血量: ${finalHealth} (系数: ${healthMultiplier})`);
+                console.log(`[EnemyController] 敌人 ${enemyId} 配置已应用,血量: ${finalHealth} (最终倍率: ${finalHealthMultiplier})`);
             } catch (error) {
                 console.error(`[EnemyController] 应用敌人配置时出错:`, error);
                 // 使用默认值
-                const finalHealth = Math.round(this.defaultHealth * healthMultiplier);
+                const finalHealth = Math.round(this.defaultHealth * finalHealthMultiplier);
                 enemyComp.health = finalHealth;
                 enemyComp.maxHealth = finalHealth;
                 enemyComp.speed = this.defaultEnemySpeed;
@@ -812,13 +905,13 @@ export class EnemyController extends BaseSingleton {
             try {
                 enemyComp.setEnemyConfig('normal_zombie'); // 默认敌人类型
                 const baseHealth = enemyComp.health || this.defaultHealth;
-                const finalHealth = Math.round(baseHealth * healthMultiplier);
+                const finalHealth = Math.round(baseHealth * finalHealthMultiplier);
                 enemyComp.health = finalHealth;
                 enemyComp.maxHealth = finalHealth;
             } catch (error) {
                 console.error(`[EnemyController] 应用默认敌人配置时出错:`, error);
                 // 使用硬编码默认值
-                const finalHealth = Math.round(this.defaultHealth * healthMultiplier);
+                const finalHealth = Math.round(this.defaultHealth * finalHealthMultiplier);
                 enemyComp.health = finalHealth;
                 enemyComp.maxHealth = finalHealth;
                 enemyComp.speed = this.defaultEnemySpeed;
@@ -1187,38 +1280,52 @@ export class EnemyController extends BaseSingleton {
         
         console.log(`[EnemyController] 最终加载路径: ${spinePath}`);
 
-        BundleLoader.loadSkeletonData(spinePath).then((skeletonData) => {
-            if (!skeletonData) {
-                console.warn(`加载敌人Spine动画失败: ${spinePath}`);
-                return;
-            }
-
-            // 获取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;
+        // 优先使用预加载的资源
+        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);
+            });
+        }
+    }
 
-            const anims = enemyConfig.visualConfig.animations;
-            const walkName = anims?.walk ?? 'walk';
-            const idleName = anims?.idle ?? 'idle';
+    /**
+     * 应用骨骼动画数据到敌人节点
+     */
+    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}`);
-            }
-        });
+        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}`);
+        }
     }
 
     // 更新敌人数量显示
@@ -1362,6 +1469,7 @@ export class EnemyController extends BaseSingleton {
         
         // 重置血量倍率
         this.currentHealthMultiplier = 1.0;
+        this.currentWaveHealthMultiplier = 1.0;
         
         // 清空暂停状态
         this.pausedEnemyStates.clear();

+ 28 - 12
assets/scripts/Core/ConfigManager.ts

@@ -1,6 +1,7 @@
 import { _decorator, resources, JsonAsset } from 'cc';
 import { BaseSingleton } from './BaseSingleton';
 import { JsonConfigLoader } from './JsonConfigLoader';
+import { BundleLoader } from './BundleLoader';
 const { ccclass, property } = _decorator;
 
 // 局内金币花费配置接口
@@ -283,17 +284,19 @@ export class ConfigManager extends BaseSingleton {
         }
     }
 
-    // 确保resources bundle已经准备好
-    private ensureResourcesBundle(): Promise<void> {
-        return new Promise((resolve) => {
-            console.log('[ConfigManager] 检查resources bundle状态...');
-            
-            // 增加延迟时间,确保Cocos Creator资源系统完全初始化
-            setTimeout(() => {
-                console.log('[ConfigManager] resources bundle初始化等待完成');
-                resolve();
-            }, 2000); // 增加到2秒
-        });
+    // 确保data bundle已经准备好
+    private async ensureResourcesBundle(): Promise<void> {
+        console.log('[ConfigManager] 检查data bundle状态...');
+        
+        try {
+            // 确保BundleLoader已经加载了data bundle
+            const bundleLoader = BundleLoader.getInstance();
+            await bundleLoader.loadBundle('data');
+            console.log('[ConfigManager] data bundle加载完成');
+        } catch (error) {
+            console.error('[ConfigManager] data bundle加载失败:', error);
+            throw error;
+        }
     }
 
     // 加载武器配置
@@ -332,7 +335,20 @@ export class ConfigManager extends BaseSingleton {
         
         try {
             this.enemiesConfig = await JsonConfigLoader.getInstance().loadConfig('enemies');
-            console.log('[ConfigManager] ✅ 敌人配置加载成功');
+            
+            // 验证配置完整性
+            console.log('[ConfigManager] 验证敌人配置完整性...');
+            if (!Array.isArray(this.enemiesConfig)) {
+                throw new Error('敌人配置格式错误:应该是数组结构');
+            }
+            
+            console.log(`[ConfigManager] ✅ 敌人配置加载成功,共${this.enemiesConfig.length}个敌人`);
+            
+            // 打印前几个敌人的ID用于调试
+            if (this.enemiesConfig.length > 0) {
+                const enemyIds = this.enemiesConfig.slice(0, 5).map(enemy => enemy.id);
+                console.log(`[ConfigManager] 敌人ID示例: ${enemyIds.join(', ')}${this.enemiesConfig.length > 5 ? '...' : ''}`);
+            }
         } catch (error) {
             console.error('[ConfigManager] 敌人配置文件加载失败:', error);
             throw error;

+ 8 - 3
assets/scripts/Core/EventBus.ts

@@ -94,13 +94,18 @@ export enum GameEvents {
     BLOCK_DRAG_START = 'BLOCK_DRAG_START',
     BLOCK_DRAG_END = 'BLOCK_DRAG_END',
     
-    // Toast提示事件
+    // Toast提示事件// Toast提示事件
     SHOW_TOAST = 'SHOW_TOAST',
     HIDE_TOAST = 'HIDE_TOAST',
     
-    // 资源不足Toast事件
     SHOW_RESOURCE_TOAST = 'SHOW_RESOURCE_TOAST',
-    HIDE_RESOURCE_TOAST = 'HIDE_RESOURCE_TOAST'
+    HIDE_RESOURCE_TOAST = 'HIDE_RESOURCE_TOAST',
+    
+    // 资源预加载事件
+    RESOURCE_PRELOAD_START = 'RESOURCE_PRELOAD_START',
+    RESOURCE_PRELOAD_PROGRESS = 'RESOURCE_PRELOAD_PROGRESS',
+    RESOURCE_PRELOAD_COMPLETE = 'RESOURCE_PRELOAD_COMPLETE',
+    RESOURCE_PRELOAD_ERROR = 'RESOURCE_PRELOAD_ERROR'
 }
 
 export default class EventBus extends EventTarget {

+ 338 - 0
assets/scripts/Core/ResourcePreloader.ts

@@ -0,0 +1,338 @@
+import { _decorator, Component, SpriteFrame, sp } from 'cc';
+import { BundleLoader } from './BundleLoader';
+import { LevelConfigManager } from '../LevelSystem/LevelConfigManager';
+import { SaveDataManager } from '../LevelSystem/SaveDataManager';
+import { ConfigManager } from './ConfigManager';
+import EventBus, { GameEvents } from './EventBus';
+
+const { ccclass } = _decorator;
+
+/**
+ * 资源预加载管理器
+ * 解决微信开发者平台动态加载资源不及时的问题
+ * 在进入战斗前预加载当前关卡的背景图片和敌人资源
+ */
+@ccclass('ResourcePreloader')
+export class ResourcePreloader {
+    private static instance: ResourcePreloader = null;
+    private bundleLoader: BundleLoader;
+    private levelConfigManager: LevelConfigManager;
+    private saveDataManager: SaveDataManager;
+    private configManager: ConfigManager;
+    
+    // 预加载缓存
+    private preloadedBackgrounds: Map<string, SpriteFrame> = new Map();
+    private preloadedEnemyAnimations: Map<string, sp.SkeletonData> = new Map();
+    
+    // 预加载状态
+    private isPreloading: boolean = false;
+    private preloadProgress: number = 0;
+    private preloadErrors: string[] = [];
+    
+    public static getInstance(): ResourcePreloader {
+        if (!ResourcePreloader.instance) {
+            ResourcePreloader.instance = new ResourcePreloader();
+        }
+        return ResourcePreloader.instance;
+    }
+    
+    constructor() {
+        this.bundleLoader = BundleLoader.getInstance();
+        this.levelConfigManager = LevelConfigManager.getInstance();
+        this.saveDataManager = SaveDataManager.getInstance();
+        this.configManager = ConfigManager.getInstance();
+    }
+    
+    /**
+     * 预加载指定关卡的资源
+     * @param levelId 关卡ID
+     */
+    public async preloadLevelResources(levelId: number): Promise<boolean> {
+        try {
+            console.log(`[ResourcePreloader] 开始预加载关卡 ${levelId} 的资源`);
+            EventBus.getInstance().emit(GameEvents.RESOURCE_PRELOAD_START);
+            
+            const levelConfig = await this.levelConfigManager.getLevelConfig(levelId);
+            if (!levelConfig) {
+                console.warn(`[ResourcePreloader] 找不到关卡 ${levelId} 的配置`);
+                EventBus.getInstance().emit(GameEvents.RESOURCE_PRELOAD_ERROR, { error: `找不到关卡 ${levelId} 的配置` });
+                return false;
+            }
+            
+            let totalResources = 0;
+            let loadedResources = 0;
+            
+            // 计算总资源数
+            if (levelConfig.backgroundImage) {
+                totalResources++;
+            }
+            
+            const enemyTypes = new Set<string>();
+            if (levelConfig.waves) {
+                levelConfig.waves.forEach(wave => {
+                    if (wave.enemies && Array.isArray(wave.enemies)) {
+                        wave.enemies.forEach(enemy => {
+                            if (enemy.enemyType) {
+                                enemyTypes.add(enemy.enemyType);
+                            }
+                        });
+                    }
+                });
+            }
+            totalResources += enemyTypes.size;
+            
+            console.log(`[ResourcePreloader] 关卡 ${levelId} 需要预加载 ${totalResources} 个资源`);
+            
+            // 预加载背景图片
+            if (levelConfig.backgroundImage) {
+                try {
+                    EventBus.getInstance().emit(GameEvents.RESOURCE_PRELOAD_PROGRESS, {
+                        progress: (loadedResources / totalResources) * 100,
+                        message: `正在加载背景图片: ${levelConfig.backgroundImage}`
+                    });
+                    
+                    await this.preloadBackground(levelConfig.backgroundImage);
+                    loadedResources++;
+                    
+                    EventBus.getInstance().emit(GameEvents.RESOURCE_PRELOAD_PROGRESS, {
+                        progress: (loadedResources / totalResources) * 100,
+                        message: `背景图片加载完成: ${levelConfig.backgroundImage}`
+                    });
+                    
+                    console.log(`[ResourcePreloader] 背景图片预加载完成: ${levelConfig.backgroundImage}`);
+                } catch (error) {
+                    console.warn(`[ResourcePreloader] 背景图片预加载失败: ${levelConfig.backgroundImage}`, error);
+                }
+            }
+            
+            // 预加载敌人动画
+            for (const enemyType of enemyTypes) {
+                try {
+                    EventBus.getInstance().emit(GameEvents.RESOURCE_PRELOAD_PROGRESS, {
+                        progress: (loadedResources / totalResources) * 100,
+                        message: `正在加载敌人动画: ${enemyType}`
+                    });
+                    
+                    await this.preloadEnemyAnimation(enemyType);
+                    loadedResources++;
+                    
+                    EventBus.getInstance().emit(GameEvents.RESOURCE_PRELOAD_PROGRESS, {
+                        progress: (loadedResources / totalResources) * 100,
+                        message: `敌人动画加载完成: ${enemyType}`
+                    });
+                    
+                    console.log(`[ResourcePreloader] 敌人动画预加载完成: ${enemyType}`);
+                } catch (error) {
+                    console.warn(`[ResourcePreloader] 敌人动画预加载失败: ${enemyType}`, error);
+                }
+            }
+            
+            console.log(`[ResourcePreloader] 关卡 ${levelId} 资源预加载完成,成功加载 ${loadedResources}/${totalResources} 个资源`);
+            EventBus.getInstance().emit(GameEvents.RESOURCE_PRELOAD_COMPLETE);
+            return true;
+            
+        } catch (error) {
+            console.error(`[ResourcePreloader] 关卡 ${levelId} 资源预加载失败:`, error);
+            EventBus.getInstance().emit(GameEvents.RESOURCE_PRELOAD_ERROR, { error: error.toString() });
+            return false;
+        }
+    }
+    
+    /**
+     * 预加载当前关卡的所有资源
+     */
+    public async preloadCurrentLevelResources(): Promise<void> {
+        const currentLevel = this.saveDataManager.getCurrentLevel();
+        const success = await this.preloadLevelResources(currentLevel);
+        
+        if (!success) {
+            throw new Error('资源预加载失败');
+        }
+    }
+    
+    /**
+     * 预加载背景图片
+     * @param backgroundPath 背景图片路径
+     */
+    private async preloadBackground(backgroundPath: string): Promise<void> {
+        // 如果已经预加载过,直接返回
+        if (this.preloadedBackgrounds.has(backgroundPath)) {
+            return;
+        }
+        
+        // 转换路径格式:从 "images/LevelBackground/BG1" 转换为 "LevelBackground/BG1"
+        const bundlePath = backgroundPath.replace('images/', '');
+        const spriteFramePath = `${bundlePath}/spriteFrame`;
+        
+        try {
+            const spriteFrame = await this.bundleLoader.loadSpriteFrame(spriteFramePath);
+            this.preloadedBackgrounds.set(backgroundPath, spriteFrame);
+            console.log(`[ResourcePreloader] 背景图片缓存成功: ${backgroundPath}`);
+        } catch (error) {
+            console.error(`[ResourcePreloader] 背景图片预加载失败: ${backgroundPath}`, error);
+            throw error;
+        }
+    }
+    
+    /**
+     * 预加载敌人动画资源
+     * @param enemyType 敌人类型
+     */
+    private async preloadEnemyAnimation(enemyType: string): Promise<void> {
+        // 如果已经预加载过,直接返回
+        if (this.preloadedEnemyAnimations.has(enemyType)) {
+            return;
+        }
+        
+        try {
+            // 获取敌人配置
+            const enemiesConfig = this.configManager.getAllEnemies();
+            if (!enemiesConfig || enemiesConfig.length === 0) {
+                throw new Error('敌人配置未加载');
+            }
+            
+            const enemyConfig = enemiesConfig.find((enemy: any) => enemy.id === enemyType);
+            if (!enemyConfig) {
+                throw new Error(`未找到敌人类型: ${enemyType}`);
+            }
+            
+            // 获取敌人动画路径
+            let spinePath = enemyConfig.visualConfig?.spritePath || enemyConfig.visual?.sprite_path;
+            if (!spinePath) {
+                throw new Error(`敌人 ${enemyType} 没有配置动画路径`);
+            }
+            
+            // 路径转换逻辑(与EnemyController保持一致)
+            if (spinePath.startsWith('@EnemyAni')) {
+                spinePath = spinePath.replace('@EnemyAni', 'Animation/EnemyAni');
+            }
+            if (spinePath.startsWith('@')) {
+                spinePath = spinePath.substring(1);
+            }
+            
+            // 对于Animation/EnemyAni路径,需要添加子目录和文件名
+            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/', '');
+            }
+            
+            // 预加载骨骼动画数据
+            const skeletonData = await BundleLoader.loadSkeletonData(spinePath);
+            this.preloadedEnemyAnimations.set(enemyType, skeletonData);
+            console.log(`[ResourcePreloader] 敌人动画缓存成功: ${enemyType} -> ${spinePath}`);
+            
+        } catch (error) {
+            console.error(`[ResourcePreloader] 敌人动画预加载失败: ${enemyType}`, error);
+            throw error;
+        }
+    }
+    
+    /**
+     * 计算需要预加载的资源总数
+     * @param levelConfig 关卡配置
+     * @returns 资源总数
+     */
+    private calculateTotalResources(levelConfig: any): number {
+        let total = 0;
+        
+        // 背景图片
+        if (levelConfig.backgroundImage) {
+            total += 1;
+        }
+        
+        // 敌人动画
+        const enemyTypes = this.extractEnemyTypes(levelConfig);
+        total += enemyTypes.length;
+        
+        return total;
+    }
+    
+    /**
+     * 从关卡配置中提取所有敌人类型
+     * @param levelConfig 关卡配置
+     * @returns 敌人类型数组
+     */
+    private extractEnemyTypes(levelConfig: any): string[] {
+        const enemyTypes = new Set<string>();
+        
+        if (levelConfig.waves && Array.isArray(levelConfig.waves)) {
+            for (const wave of levelConfig.waves) {
+                if (wave.enemies && Array.isArray(wave.enemies)) {
+                    for (const enemy of wave.enemies) {
+                        if (enemy.enemyType) {
+                            enemyTypes.add(enemy.enemyType);
+                        }
+                    }
+                }
+            }
+        }
+        
+        return Array.from(enemyTypes);
+    }
+    
+    /**
+     * 更新预加载进度
+     * @param loaded 已加载数量
+     * @param total 总数量
+     */
+    private updateProgress(loaded: number, total: number): void {
+        this.preloadProgress = total > 0 ? (loaded / total) * 100 : 100;
+        
+        // 发送进度更新事件
+        EventBus.getInstance().emit(GameEvents.RESOURCE_PRELOAD_PROGRESS, {
+            progress: this.preloadProgress,
+            loaded: loaded,
+            total: total
+        });
+    }
+    
+    /**
+     * 获取预加载的背景图片
+     * @param backgroundPath 背景图片路径
+     * @returns SpriteFrame或null
+     */
+    public getPreloadedBackground(backgroundPath: string): SpriteFrame | null {
+        return this.preloadedBackgrounds.get(backgroundPath) || null;
+    }
+    
+    /**
+     * 获取预加载的敌人动画
+     * @param enemyType 敌人类型
+     * @returns SkeletonData或null
+     */
+    public getPreloadedEnemyAnimation(enemyType: string): sp.SkeletonData | null {
+        return this.preloadedEnemyAnimations.get(enemyType) || null;
+    }
+    
+    /**
+     * 清理预加载缓存
+     */
+    public clearCache(): void {
+        this.preloadedBackgrounds.clear();
+        this.preloadedEnemyAnimations.clear();
+        console.log('[ResourcePreloader] 预加载缓存已清理');
+    }
+    
+    /**
+     * 获取预加载状态
+     */
+    public getPreloadStatus(): {
+        isPreloading: boolean;
+        progress: number;
+        errors: string[];
+    } {
+        return {
+            isPreloading: this.isPreloading,
+            progress: this.preloadProgress,
+            errors: [...this.preloadErrors]
+        };
+    }
+}

+ 9 - 0
assets/scripts/Core/ResourcePreloader.ts.meta

@@ -0,0 +1,9 @@
+{
+  "ver": "4.0.24",
+  "importer": "typescript",
+  "imported": true,
+  "uuid": "5118b173-b7e9-4122-895c-0c2826943719",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

+ 66 - 0
assets/scripts/Debug/ConfigManagerInitTest.ts

@@ -0,0 +1,66 @@
+import { _decorator, Component, Node } from 'cc';
+import { ConfigManager } from '../Core/ConfigManager';
+
+const { ccclass, property } = _decorator;
+
+@ccclass('ConfigManagerInitTest')
+export class ConfigManagerInitTest extends Component {
+
+    start() {
+        // 延迟3秒后开始测试,确保ConfigManager有足够时间初始化
+        this.scheduleOnce(() => {
+            this.testConfigManagerInit();
+        }, 3);
+    }
+
+    private testConfigManagerInit() {
+        console.log('=== 开始测试ConfigManager初始化 ===');
+        
+        try {
+            // 获取ConfigManager实例
+            const configManager = ConfigManager.getInstance();
+            console.log('✓ ConfigManager实例获取成功');
+            
+            // 检查配置是否已加载
+            const isLoaded = configManager.isConfigLoaded();
+            console.log('配置加载状态:', isLoaded);
+            
+            if (isLoaded) {
+                console.log('✓ 配置已加载');
+                
+                // 测试获取敌人配置
+                const enemies = configManager.getAllEnemies();
+                console.log('敌人配置数量:', enemies.length);
+                
+                if (enemies.length > 0) {
+                    console.log('✓ 成功获取敌人配置');
+                    console.log('前3个敌人:', enemies.slice(0, 3).map(e => ({ id: e.id, name: e.name })));
+                } else {
+                    console.error('✗ 敌人配置为空');
+                }
+                
+                // 测试获取武器配置
+                const weapons = configManager.getAllWeapons();
+                console.log('武器配置数量:', weapons.length);
+                
+                if (weapons.length > 0) {
+                    console.log('✓ 成功获取武器配置');
+                } else {
+                    console.error('✗ 武器配置为空');
+                }
+                
+            } else {
+                console.error('✗ 配置尚未加载完成');
+                // 延迟再次检查
+                this.scheduleOnce(() => {
+                    this.testConfigManagerInit();
+                }, 2);
+            }
+            
+        } catch (error) {
+            console.error('测试过程中发生错误:', error);
+        }
+        
+        console.log('=== ConfigManager初始化测试完成 ===');
+    }
+}

+ 9 - 0
assets/scripts/Debug/ConfigManagerInitTest.ts.meta

@@ -0,0 +1,9 @@
+{
+  "ver": "4.0.24",
+  "importer": "typescript",
+  "imported": true,
+  "uuid": "7d24b525-87de-44c6-8fea-0e63512df073",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

+ 67 - 0
assets/scripts/Debug/EnemyConfigTest.ts

@@ -0,0 +1,67 @@
+import { _decorator, Component, log } from 'cc';
+import { ConfigManager } from '../Core/ConfigManager';
+const { ccclass, property } = _decorator;
+
+/**
+ * 敌人配置测试组件
+ * 用于验证敌人配置加载功能
+ */
+@ccclass('EnemyConfigTest')
+export class EnemyConfigTest extends Component {
+
+    async start() {
+        // 等待一段时间确保ConfigManager初始化完成
+        setTimeout(() => {
+            this.testEnemyConfig();
+        }, 3000);
+    }
+
+    private testEnemyConfig() {
+        console.log('=== 敌人配置测试开始 ===');
+        
+        const configManager = ConfigManager.getInstance();
+        
+        // 检查配置是否已加载
+        if (!configManager.isConfigLoaded()) {
+            console.error('❌ ConfigManager配置尚未加载完成');
+            return;
+        }
+        
+        // 获取所有敌人配置
+        const enemies = configManager.getAllEnemies();
+        
+        if (enemies && enemies.length > 0) {
+            console.log(`✅ 敌人配置加载成功,共 ${enemies.length} 个敌人`);
+            
+            // 测试特定敌人ID
+            const testEnemyIds = ['normal_zombie', 'roadblock_zombie', 'mage_zombie', 'boss1_gatekeeper'];
+            
+            testEnemyIds.forEach(enemyId => {
+                const enemy = configManager.getEnemyById(enemyId);
+                if (enemy) {
+                    console.log(`✅ 找到敌人: ${enemyId} - ${enemy.name}`);
+                } else {
+                    console.error(`❌ 未找到敌人: ${enemyId}`);
+                }
+            });
+            
+            // 打印前5个敌人的基本信息
+            console.log('前5个敌人信息:');
+            enemies.slice(0, 5).forEach((enemy, index) => {
+                console.log(`${index + 1}. ID: ${enemy.id}, 名称: ${enemy.name}, 类型: ${enemy.type}`);
+            });
+            
+        } else {
+            console.error('❌ 敌人配置为空或加载失败');
+        }
+        
+        console.log('=== 敌人配置测试结束 ===');
+    }
+    
+    /**
+     * 手动测试方法,可以在Inspector中调用
+     */
+    public manualTest() {
+        this.testEnemyConfig();
+    }
+}

+ 9 - 0
assets/scripts/Debug/EnemyConfigTest.ts.meta

@@ -0,0 +1,9 @@
+{
+  "ver": "4.0.24",
+  "importer": "typescript",
+  "imported": true,
+  "uuid": "556143d8-f79e-4a1e-b430-b950cfbc9a03",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

+ 67 - 0
assets/scripts/Debug/EnemyLoadTest.ts

@@ -0,0 +1,67 @@
+import { _decorator, Component, Node } from 'cc';
+import { ConfigManager } from '../Core/ConfigManager';
+import { JsonConfigLoader } from '../Core/JsonConfigLoader';
+import { BundleLoader } from '../Core/BundleLoader';
+
+const { ccclass, property } = _decorator;
+
+@ccclass('EnemyLoadTest')
+export class EnemyLoadTest extends Component {
+
+    start() {
+        // 延迟5秒后开始测试,确保所有系统都已初始化
+        this.scheduleOnce(() => {
+            this.testEnemyLoading();
+        }, 5);
+    }
+
+    private async testEnemyLoading() {
+        console.log('=== 开始测试敌人配置加载 ===');
+        
+        try {
+            // 测试1: 直接使用BundleLoader加载data bundle
+            console.log('测试1: 加载data bundle');
+            const bundleLoader = BundleLoader.getInstance();
+            await bundleLoader.loadBundle('data');
+            console.log('✓ data bundle加载成功');
+            
+            // 测试2: 使用JsonConfigLoader加载enemies配置
+            console.log('测试2: 使用JsonConfigLoader加载enemies配置');
+            const jsonLoader = JsonConfigLoader.getInstance();
+            const enemiesConfig = await jsonLoader.loadConfig('enemies');
+            
+            if (enemiesConfig) {
+                console.log('✓ enemies配置加载成功');
+                console.log('enemies配置类型:', typeof enemiesConfig);
+                console.log('是否为数组:', Array.isArray(enemiesConfig));
+                
+                if (Array.isArray(enemiesConfig)) {
+                    console.log('敌人数量:', enemiesConfig.length);
+                    console.log('前3个敌人ID:', enemiesConfig.slice(0, 3).map(e => e.id));
+                } else {
+                    console.log('enemies配置结构:', Object.keys(enemiesConfig));
+                }
+            } else {
+                console.error('✗ enemies配置加载失败');
+            }
+            
+            // 测试3: 检查ConfigManager的状态
+            console.log('测试3: 检查ConfigManager状态');
+            const configManager = ConfigManager.getInstance();
+            const allEnemies = configManager.getAllEnemies();
+            
+            console.log('ConfigManager中的敌人数量:', allEnemies.length);
+            if (allEnemies.length > 0) {
+                console.log('✓ ConfigManager成功获取敌人配置');
+                console.log('前3个敌人ID:', allEnemies.slice(0, 3).map(e => e.id));
+            } else {
+                console.error('✗ ConfigManager未能获取敌人配置');
+            }
+            
+        } catch (error) {
+            console.error('测试过程中发生错误:', error);
+        }
+        
+        console.log('=== 敌人配置加载测试完成 ===');
+    }
+}

+ 9 - 0
assets/scripts/Debug/EnemyLoadTest.ts.meta

@@ -0,0 +1,9 @@
+{
+  "ver": "4.0.24",
+  "importer": "typescript",
+  "imported": true,
+  "uuid": "a2918278-9a76-4269-bd1c-35ea72e4f5a5",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

+ 72 - 0
assets/scripts/Debug/ResourcePreloaderTest.ts

@@ -0,0 +1,72 @@
+import { _decorator, Component, log } from 'cc';
+import { ResourcePreloader } from '../Core/ResourcePreloader';
+import { ConfigManager } from '../Core/ConfigManager';
+const { ccclass, property } = _decorator;
+
+/**
+ * 资源预加载器测试组件
+ * 用于验证敌人动画预加载功能
+ */
+@ccclass('ResourcePreloaderTest')
+export class ResourcePreloaderTest extends Component {
+
+    async start() {
+        // 等待一段时间确保ConfigManager初始化完成
+        setTimeout(() => {
+            this.testResourcePreloader();
+        }, 5000);
+    }
+
+    private async testResourcePreloader() {
+        console.log('=== 资源预加载器测试开始 ===');
+        
+        const configManager = ConfigManager.getInstance();
+        const resourcePreloader = ResourcePreloader.getInstance();
+        
+        // 检查配置是否已加载
+        if (!configManager.isConfigLoaded()) {
+            console.error('❌ ConfigManager配置尚未加载完成');
+            return;
+        }
+        
+        // 获取所有敌人配置
+        const enemies = configManager.getAllEnemies();
+        
+        if (!enemies || enemies.length === 0) {
+            console.error('❌ 敌人配置为空');
+            return;
+        }
+        
+        console.log(`✅ 敌人配置已加载,共 ${enemies.length} 个敌人`);
+        
+        // 测试预加载特定敌人动画
+        const testEnemyIds = ['normal_zombie', 'roadblock_zombie', 'mage_zombie', 'boss1_gatekeeper'];
+        
+        for (const enemyId of testEnemyIds) {
+            try {
+                console.log(`开始预加载敌人动画: ${enemyId}`);
+                
+                // 直接调用私有方法进行测试(通过反射)
+                const preloader = resourcePreloader as any;
+                if (preloader.preloadEnemyAnimation) {
+                    await preloader.preloadEnemyAnimation(enemyId);
+                    console.log(`✅ 敌人动画预加载成功: ${enemyId}`);
+                } else {
+                    console.error(`❌ preloadEnemyAnimation方法不存在`);
+                }
+                
+            } catch (error) {
+                console.error(`❌ 敌人动画预加载失败: ${enemyId}`, error);
+            }
+        }
+        
+        console.log('=== 资源预加载器测试结束 ===');
+    }
+    
+    /**
+     * 手动测试方法,可以在Inspector中调用
+     */
+    public async manualTest() {
+        await this.testResourcePreloader();
+    }
+}

+ 9 - 0
assets/scripts/Debug/ResourcePreloaderTest.ts.meta

@@ -0,0 +1,9 @@
+{
+  "ver": "4.0.24",
+  "importer": "typescript",
+  "imported": true,
+  "uuid": "09176db6-bded-4c23-b257-0abb7d2e96e1",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

+ 43 - 0
assets/scripts/FourUI/MainSystem/MainUIControlller.ts

@@ -9,6 +9,7 @@ import { MoneyAni } from '../../Animations/MoneyAni';
 import EventBus, { GameEvents } from '../../Core/EventBus';
 import { Audio } from '../../AudioManager/AudioManager';
 import { BundleLoader } from '../../Core/BundleLoader';
+import { ResourcePreloader } from '../../Core/ResourcePreloader';
 const { ccclass, property } = _decorator;
 
 @ccclass('MainUIController')
@@ -64,6 +65,9 @@ export class MainUIController extends Component {
     // 播放主界面背景音乐(等待bundle加载完成)
     await this.playMainUIBGM();
     
+    // 预加载当前关卡和下一关的资源
+    this.preloadLevelResources();
+    
     console.log('[MainUIController] onLoad 执行完成');
   }
 
@@ -415,6 +419,9 @@ export class MainUIController extends Component {
     // 通过事件系统通知UI更新
     EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);
     
+    // 返回主界面时重新预加载资源,确保下次进入游戏时资源已准备就绪
+    this.preloadLevelResources();
+    
     console.log('MainUIController.onReturnToMainUI 执行完成');
   }
   
@@ -506,6 +513,42 @@ export class MainUIController extends Component {
     }
   }
 
+  /**
+   * 预加载当前关卡和下一关的资源
+   * 在MainUI场景加载时提前预加载,避免进入游戏时的资源加载延迟
+   */
+  private async preloadLevelResources(): Promise<void> {
+    console.log('[MainUIController] 开始预加载关卡资源');
+    
+    try {
+      const resourcePreloader = ResourcePreloader.getInstance();
+      const currentLevel = this.sdm.getCurrentLevel();
+      
+      // 预加载当前关卡资源
+      console.log(`[MainUIController] 预加载当前关卡 ${currentLevel} 的资源`);
+      try {
+        await resourcePreloader.preloadLevelResources(currentLevel);
+        console.log(`[MainUIController] 当前关卡 ${currentLevel} 资源预加载完成`);
+      } catch (error) {
+        console.warn(`[MainUIController] 当前关卡 ${currentLevel} 资源预加载失败:`, error);
+      }
+      
+      // 预加载下一关资源(如果存在)
+      const nextLevel = currentLevel + 1;
+      console.log(`[MainUIController] 预加载下一关卡 ${nextLevel} 的资源`);
+      try {
+        await resourcePreloader.preloadLevelResources(nextLevel);
+        console.log(`[MainUIController] 下一关卡 ${nextLevel} 资源预加载完成`);
+      } catch (error) {
+        console.warn(`[MainUIController] 下一关卡 ${nextLevel} 资源预加载失败(可能不存在该关卡):`, error);
+      }
+      
+      console.log('[MainUIController] 关卡资源预加载流程完成');
+    } catch (error) {
+      console.error('[MainUIController] 预加载关卡资源时发生错误:', error);
+    }
+  }
+
   /* =============== Util =============== */
   private format(n:number){ return n>=1000000? (n/1e6).toFixed(1)+'M' : n>=1000? (n/1e3).toFixed(1)+'K' : n.toString(); }
 }

+ 25 - 13
assets/scripts/FourUI/ShopSystem/ShopController.ts

@@ -87,15 +87,21 @@ export class ShopController extends Component {
         return num.toString().split('').join(' ');
     }
     
+
+    
     async onLoad() {
         this.saveDataManager = SaveDataManager.getInstance();
-        await this.loadShopConfig();
+        
+        // 用户已手动隐藏图标,代码只在非免费时显示图标
+        
         this.loadDailyRewardData();
+        await this.loadShopConfig();
         this.setupEventListeners();
+        this.updateUI();
     }
     
     start() {
-        this.updateUI();
+        // start方法保留为空,所有初始化逻辑已在onLoad中完成
     }
     
     private async loadShopConfig() {
@@ -209,7 +215,15 @@ export class ShopController extends Component {
     }
     
     private updateUI() {
-        if (!this.shopConfig || !this.dailyRewardData) return;
+        if (!this.shopConfig || !this.dailyRewardData) {
+            console.log('[ShopController] 配置或数据未准备好,跳过UI更新');
+            return;
+        }
+        
+        console.log('[ShopController] 开始更新UI,数据状态:', {
+            moneyFreeUsed: this.dailyRewardData.moneyFreeUsed,
+            diamondFreeUsed: this.dailyRewardData.diamondFreeUsed
+        });
         
         // 更新钞票奖励UI
         this.updateMoneyRewardUI();
@@ -258,16 +272,15 @@ export class ShopController extends Component {
             if (this.moneyCountLabel) {
                 if (!freeUsed) {
                     this.moneyCountLabel.string = "免  费";
-                    // 免费时隐藏图标
-                    if (this.moneyIconNode) {
-                        this.moneyIconNode.active = false;
-                    }
+                    // 免费时保持图标隐藏(用户已手动隐藏)
+                    console.log('[ShopController] 钞票免费状态:保持图标隐藏,显示"免费"');
                 } else {
                     const remainingCount = maxCount - totalCount;
                     this.moneyCountLabel.string = `${remainingCount}/${maxCount}`;
-                    // 观看广告时显示图标
+                    // 非免费时显示图标
                     if (this.moneyIconNode) {
                         this.moneyIconNode.active = true;
+                        console.log(`[ShopController] 钞票广告状态:显示图标,剩余次数 ${remainingCount}/${maxCount}`);
                     }
                 }
             }
@@ -314,16 +327,15 @@ export class ShopController extends Component {
             if (this.diamondCountLabel) {
                 if (!freeUsed) {
                     this.diamondCountLabel.string = "免  费";
-                    // 免费时隐藏图标
-                    if (this.diamondIconNode) {
-                        this.diamondIconNode.active = false;
-                    }
+                    // 免费时保持图标隐藏(用户已手动隐藏)
+                    console.log('[ShopController] 钻石免费状态:保持图标隐藏,显示"免费"');
                 } else {
                     const remainingCount = maxCount - totalCount;
                     this.diamondCountLabel.string = `${remainingCount}/${maxCount}`;
-                    // 观看广告时显示图标
+                    // 非免费时显示图标
                     if (this.diamondIconNode) {
                         this.diamondIconNode.active = true;
+                        console.log(`[ShopController] 钻石广告状态:显示图标,剩余次数 ${remainingCount}/${maxCount}`);
                     }
                 }
             }

+ 16 - 4
assets/scripts/LevelSystem/BackgroundManager.ts

@@ -3,6 +3,7 @@ import { LevelConfigManager } from './LevelConfigManager';
 import { SaveDataManager } from './SaveDataManager';
 import EventBus, { GameEvents } from '../Core/EventBus';
 import { BundleLoader } from '../Core/BundleLoader';
+import { ResourcePreloader } from '../Core/ResourcePreloader';
 
 const { ccclass, property } = _decorator;
 
@@ -18,6 +19,7 @@ export class BackgroundManager extends Component {
     private levelConfigManager: LevelConfigManager = null;
     private saveDataManager: SaveDataManager = null;
     private bundleLoader: BundleLoader = null;
+    private resourcePreloader: ResourcePreloader = null;
 
     onLoad() {
         // 获取关卡配置管理器
@@ -26,6 +28,8 @@ export class BackgroundManager extends Component {
         this.saveDataManager = SaveDataManager.getInstance();
         // 获取BundleLoader实例
         this.bundleLoader = BundleLoader.getInstance();
+        // 获取ResourcePreloader实例
+        this.resourcePreloader = ResourcePreloader.getInstance();
         // 监听关卡开始事件
         EventBus.getInstance().on(GameEvents.GAME_START, this.onGameStart, this);
     }
@@ -110,15 +114,23 @@ export class BackgroundManager extends Component {
             return;
         }
 
-        console.log(`[BackgroundManager] 开始从images Bundle加载背景图片: ${imagePath}`);
+        console.log(`[BackgroundManager] 开始设置背景图片: ${imagePath}`);
         
         try {
-            // 从images Bundle加载SpriteFrame
-            const spriteFrame = await this.bundleLoader.loadSpriteFrame(`${imagePath}/spriteFrame`);
+            // 优先使用预加载的资源
+            let spriteFrame = this.resourcePreloader.getPreloadedBackground(imagePath);
+            
+            if (!spriteFrame) {
+                console.log(`[BackgroundManager] 预加载资源未找到,动态加载 ${imagePath}`);
+                // 如果预加载资源不存在,则动态加载
+                spriteFrame = await this.bundleLoader.loadSpriteFrame(`${imagePath}/spriteFrame`);
+            } else {
+                console.log(`[BackgroundManager] 使用预加载的背景图片 ${imagePath}`);
+            }
             
             if (spriteFrame && this.backgroundSprite && this.backgroundSprite.isValid) {
                 this.backgroundSprite.spriteFrame = spriteFrame;
-                console.log(`[BackgroundManager] 背景图片加载成功: ${imagePath}`);
+                console.log(`[BackgroundManager] 背景图片设置成功: ${imagePath}`);
             }
         } catch (error) {
             console.error(`[BackgroundManager] 背景图片加载失败: ${imagePath}`, error);

+ 3 - 1
assets/scripts/LevelSystem/LevelConfigManager.ts

@@ -27,6 +27,7 @@ interface LevelConfig {
 interface WaveConfig {
     waveId: number;
     enemies: EnemyWaveConfig[];
+    healthMultiplier?: number;
 }
 
 /**
@@ -207,7 +208,8 @@ export class LevelConfigManager extends Component {
                 for (const waveData of jsonData.waves) {
                     const wave: WaveConfig = {
                         waveId: waveData.waveId || 0,
-                        enemies: []
+                        enemies: [],
+                        healthMultiplier: waveData.healthMultiplier
                     };
 
                     if (Array.isArray(waveData.enemies)) {

+ 153 - 0
assets/scripts/UI/PreloadProgressUI.ts

@@ -0,0 +1,153 @@
+import { _decorator, Component, Node, Label, ProgressBar } from 'cc';
+import EventBus, { GameEvents } from '../Core/EventBus';
+
+const { ccclass, property } = _decorator;
+
+/**
+ * 资源预加载进度显示UI组件
+ * 用于在游戏启动时显示资源加载进度
+ */
+@ccclass('PreloadProgressUI')
+export class PreloadProgressUI extends Component {
+    
+    @property({ type: Node, tooltip: '预加载进度UI根节点' })
+    public progressUINode: Node = null;
+    
+    @property({ type: ProgressBar, tooltip: '进度条组件' })
+    public progressBar: ProgressBar = null;
+    
+    @property({ type: Label, tooltip: '进度文本标签' })
+    public progressLabel: Label = null;
+    
+    @property({ type: Label, tooltip: '状态文本标签' })
+    public statusLabel: Label = null;
+    
+    private eventBus: EventBus = null;
+    
+    onLoad() {
+        this.eventBus = EventBus.getInstance();
+        
+        // 监听预加载事件
+        this.eventBus.on(GameEvents.RESOURCE_PRELOAD_START, this.onPreloadStart, this);
+        this.eventBus.on(GameEvents.RESOURCE_PRELOAD_PROGRESS, this.onPreloadProgress, this);
+        this.eventBus.on(GameEvents.RESOURCE_PRELOAD_COMPLETE, this.onPreloadComplete, this);
+        this.eventBus.on(GameEvents.RESOURCE_PRELOAD_ERROR, this.onPreloadError, this);
+        
+        // 初始状态隐藏UI
+        this.hideProgressUI();
+    }
+    
+    onDestroy() {
+        if (this.eventBus) {
+            this.eventBus.off(GameEvents.RESOURCE_PRELOAD_START, this.onPreloadStart, this);
+            this.eventBus.off(GameEvents.RESOURCE_PRELOAD_PROGRESS, this.onPreloadProgress, this);
+            this.eventBus.off(GameEvents.RESOURCE_PRELOAD_COMPLETE, this.onPreloadComplete, this);
+            this.eventBus.off(GameEvents.RESOURCE_PRELOAD_ERROR, this.onPreloadError, this);
+        }
+    }
+    
+    /**
+     * 预加载开始事件处理
+     */
+    private onPreloadStart() {
+        console.log('[PreloadProgressUI] 预加载开始');
+        this.showProgressUI();
+        this.updateProgress(0, '开始加载资源...');
+        this.updateStatus('正在预加载关卡资源');
+    }
+    
+    /**
+     * 预加载进度更新事件处理
+     */
+    private onPreloadProgress(data: { progress: number; message: string }) {
+        console.log(`[PreloadProgressUI] 预加载进度: ${data.progress}% - ${data.message}`);
+        this.updateProgress(data.progress, data.message);
+    }
+    
+    /**
+     * 预加载完成事件处理
+     */
+    private onPreloadComplete() {
+        console.log('[PreloadProgressUI] 预加载完成');
+        this.updateProgress(100, '资源加载完成');
+        this.updateStatus('预加载完成,准备开始游戏');
+        
+        // 延迟隐藏UI,让用户看到完成状态
+        this.scheduleOnce(() => {
+            this.hideProgressUI();
+        }, 0.5);
+    }
+    
+    /**
+     * 预加载错误事件处理
+     */
+    private onPreloadError(data: { error: string }) {
+        console.warn(`[PreloadProgressUI] 预加载错误: ${data.error}`);
+        this.updateStatus(`预加载失败: ${data.error}`);
+        
+        // 延迟隐藏UI
+        this.scheduleOnce(() => {
+            this.hideProgressUI();
+        }, 2.0);
+    }
+    
+    /**
+     * 显示进度UI
+     */
+    private showProgressUI() {
+        if (this.progressUINode) {
+            this.progressUINode.active = true;
+        }
+    }
+    
+    /**
+     * 隐藏进度UI
+     */
+    private hideProgressUI() {
+        if (this.progressUINode) {
+            this.progressUINode.active = false;
+        }
+    }
+    
+    /**
+     * 更新进度条和进度文本
+     */
+    private updateProgress(progress: number, message: string) {
+        if (this.progressBar) {
+            this.progressBar.progress = progress / 100;
+        }
+        
+        if (this.progressLabel) {
+            this.progressLabel.string = `${Math.round(progress)}%`;
+        }
+        
+        if (message && this.statusLabel) {
+            this.updateStatus(message);
+        }
+    }
+    
+    /**
+     * 更新状态文本
+     */
+    private updateStatus(status: string) {
+        if (this.statusLabel) {
+            this.statusLabel.string = status;
+        }
+    }
+    
+    /**
+     * 手动显示预加载进度(用于测试)
+     */
+    public showPreloadProgress() {
+        this.showProgressUI();
+        this.updateProgress(0, '手动测试预加载进度');
+        this.updateStatus('测试模式');
+    }
+    
+    /**
+     * 手动隐藏预加载进度(用于测试)
+     */
+    public hidePreloadProgress() {
+        this.hideProgressUI();
+    }
+}

+ 9 - 0
assets/scripts/UI/PreloadProgressUI.ts.meta

@@ -0,0 +1,9 @@
+{
+  "ver": "4.0.24",
+  "importer": "typescript",
+  "imported": true,
+  "uuid": "b7dc679d-fb32-4f7d-8cdc-062f6b5952a0",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}