Parcourir la source

合成价格标签解决

181404010226 il y a 3 mois
Parent
commit
92c9500f0e
46 fichiers modifiés avec 1209 ajouts et 1798 suppressions
  1. 19 12
      assets/Scenes/GameLevel.scene
  2. 0 9
      assets/data/backups.meta
  3. 0 9
      assets/data/backups/levels.meta
  4. 0 116
      assets/data/backups/levels/Level1_20250919_113116.json
  5. 0 11
      assets/data/backups/levels/Level1_20250919_113116.json.meta
  6. 0 172
      assets/data/backups/levels/Level2_20250919_113116.json
  7. 0 11
      assets/data/backups/levels/Level2_20250919_113116.json.meta
  8. 0 234
      assets/data/backups/levels/Level3_20250919_113116.json
  9. 0 476
      assets/data/backups/levels/Level4_20250919_113116.json
  10. 0 11
      assets/data/backups/levels/Level4_20250919_113116.json.meta
  11. 0 118
      assets/data/backups/levels/Level5_20250919_113116.json
  12. 0 11
      assets/data/backups/levels/Level5_20250919_113116.json.meta
  13. 0 119
      assets/data/backups/levels/Level6_20250919_113116.json
  14. 0 11
      assets/data/backups/levels/Level6_20250919_113116.json.meta
  15. 0 57
      assets/data/backups/levels/Level7_20250919_113116.json
  16. 0 11
      assets/data/backups/levels/Level7_20250919_113116.json.meta
  17. 0 154
      assets/data/backups/levels/Level8_20250919_113116.json
  18. 0 11
      assets/data/backups/levels/Level8_20250919_113116.json.meta
  19. 0 174
      assets/data/backups/levels/Level9_20250919_113116.json
  20. 0 11
      assets/data/backups/levels/Level9_20250919_113116.json.meta
  21. 20 0
      assets/data/ball_price_config.json
  22. 1 1
      assets/data/ball_price_config.json.meta
  23. BIN
      assets/data/excel/BallController标准配置表.xlsx
  24. BIN
      assets/data/excel/小球价格配置表.xlsx
  25. 12 0
      assets/data/excel/小球价格配置表.xlsx.meta
  26. 352 0
      assets/scripts/Ads/AdManager.ts
  27. 9 0
      assets/scripts/Ads/AdManager.ts.meta
  28. 3 3
      assets/scripts/Animations/GameStartMove.ts
  29. 148 0
      assets/scripts/AudioManager/AudioCacheOptimization.md
  30. 11 0
      assets/scripts/AudioManager/AudioCacheOptimization.md.meta
  31. 61 4
      assets/scripts/AudioManager/AudioManager.ts
  32. 124 1
      assets/scripts/CombatSystem/BallController.ts
  33. 34 0
      assets/scripts/CombatSystem/BlockManager.ts
  34. 198 11
      assets/scripts/CombatSystem/BlockSelection/GameBlockSelection.ts
  35. 27 1
      assets/scripts/CombatSystem/EnemyController.ts
  36. 12 3
      assets/scripts/CombatSystem/GameEnd.ts
  37. 9 0
      assets/scripts/CombatSystem/GamePause.ts
  38. 4 0
      assets/scripts/Core/EventBus.ts
  39. 55 0
      assets/scripts/Debug/BallPauseTest.ts
  40. 9 0
      assets/scripts/Debug/BallPauseTest.ts.meta
  41. 24 12
      assets/scripts/FourUI/MainSystem/MainUIControlller.ts
  42. 25 8
      assets/scripts/FourUI/ShopSystem/ShopController.ts
  43. 29 6
      assets/scripts/FourUI/TopBarController.ts
  44. 10 0
      assets/scripts/LevelSystem/GameManager.ts
  45. 12 9
      assets/scripts/LevelSystem/IN_game.ts
  46. 1 1
      assets/scripts/LevelSystem/SaveDataManager.ts

+ 19 - 12
assets/Scenes/GameLevel.scene

@@ -496,7 +496,7 @@
     "_lpos": {
       "__type__": "cc.Vec3",
       "x": 0,
-      "y": -432.5,
+      "y": -1192.826,
       "z": 0
     },
     "_lrot": {
@@ -1515,8 +1515,8 @@
     "__prefab": null,
     "_contentSize": {
       "__type__": "cc.Size",
-      "width": 84.0859375,
-      "height": 54.4
+      "width": 172,
+      "height": 40
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
@@ -1554,8 +1554,11 @@
     "_lineHeight": 40,
     "_overflow": 0,
     "_enableWrapText": true,
-    "_font": null,
-    "_isSystemFontUsed": true,
+    "_font": {
+      "__uuid__": "f5482737-839c-4813-9511-f36bf1223968",
+      "__expectedType__": "cc.LabelAtlas"
+    },
+    "_isSystemFontUsed": false,
     "_spacingX": 0,
     "_isItalic": false,
     "_isBold": false,
@@ -31013,7 +31016,7 @@
     "_prefab": null,
     "_lpos": {
       "__type__": "cc.Vec3",
-      "x": 11.744140625000002,
+      "x": 11.744140624999998,
       "y": 0,
       "z": 0
     },
@@ -31140,7 +31143,7 @@
     "_right": 0,
     "_top": 4.062999999999998,
     "_bottom": 0.37195384615384625,
-    "_horizontalCenter": 0.0638268512228261,
+    "_horizontalCenter": 0.06382685122282608,
     "_verticalCenter": 0,
     "_isAbsLeft": true,
     "_isAbsRight": true,
@@ -32392,7 +32395,7 @@
     "_prefab": null,
     "_lpos": {
       "__type__": "cc.Vec3",
-      "x": 16.212890625,
+      "x": 8.19580078125,
       "y": 0,
       "z": 0
     },
@@ -32431,7 +32434,7 @@
     "__prefab": null,
     "_contentSize": {
       "__type__": "cc.Size",
-      "width": 80.42578125,
+      "width": 64.3916015625,
       "height": 36.76
     },
     "_anchorPoint": {
@@ -32461,7 +32464,7 @@
       "b": 255,
       "a": 255
     },
-    "_string": "35/36",
+    "_string": "1/10",
     "_horizontalAlign": 1,
     "_verticalAlign": 1,
     "_actualFontSize": 26,
@@ -32519,7 +32522,7 @@
     "_right": 0,
     "_top": 4.062999999999998,
     "_bottom": 0.37195384615384625,
-    "_horizontalCenter": 0.08811353600543478,
+    "_horizontalCenter": 0.044542395550271736,
     "_verticalCenter": 0,
     "_isAbsLeft": true,
     "_isAbsRight": true,
@@ -35815,6 +35818,10 @@
       "__uuid__": "b0dff099-9502-41f9-8678-6126d42ddd68",
       "__expectedType__": "cc.JsonAsset"
     },
+    "ballPriceConfig": {
+      "__uuid__": "2c4beb85-fa85-41dc-a32a-b614ec345d96",
+      "__expectedType__": "cc.JsonAsset"
+    },
     "debugDrawSnapRange": true,
     "_id": "ealiXZigZIgrXLo2NL22Ns"
   },
@@ -39007,7 +39014,7 @@
     "_left": 0,
     "_right": 0,
     "_top": 0,
-    "_bottom": 0,
+    "_bottom": -760.3259999999999,
     "_horizontalCenter": 0,
     "_verticalCenter": 0,
     "_isAbsLeft": true,

+ 0 - 9
assets/data/backups.meta

@@ -1,9 +0,0 @@
-{
-  "ver": "1.2.0",
-  "importer": "directory",
-  "imported": true,
-  "uuid": "e242b44c-426f-4a66-b68d-d38b97f43404",
-  "files": [],
-  "subMetas": {},
-  "userData": {}
-}

+ 0 - 9
assets/data/backups/levels.meta

@@ -1,9 +0,0 @@
-{
-  "ver": "1.2.0",
-  "importer": "directory",
-  "imported": true,
-  "uuid": "7539d626-ee80-4a10-b7eb-ab066792bdf9",
-  "files": [],
-  "subMetas": {},
-  "userData": {}
-}

+ 0 - 116
assets/data/backups/levels/Level1_20250919_113116.json

@@ -1,116 +0,0 @@
-{
-  "levelId": "Level1",
-  "name": "新手关卡(草地平原)",
-  "scene": "grassland",
-  "description": "新手引导关卡,学习基础塔防玩法",
-  "backgroundImage": "images/LevelBackground/BG1",
-  "availableWeapons": [
-    "毛豆射手"
-  ],
-  "coinReward": 300,
-  "diamondReward": 20,
-  "initialCoins": 100,
-  "timeLimit": 300,
-  "difficulty": "normal",
-  "healthMultiplier": 1.0,
-  "waves": [
-    {
-      "waveId": 1,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 10,
-          "spawnInterval": 4.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        }
-      ]
-    },
-    {
-      "waveId": 2,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 15,
-          "spawnInterval": 3.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        }
-      ]
-    },
-    {
-      "waveId": 3,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 20,
-          "spawnInterval": 2.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        }
-      ]
-    },
-    {
-      "waveId": 4,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 40,
-          "spawnInterval": 1.5,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 10,
-          "spawnInterval": 3.0,
-          "spawnDelay": 30.0,
-          "characteristics": "中速移动, 无技能"
-        }
-      ]
-    },
-    {
-      "waveId": 5,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 40,
-          "spawnInterval": 1.5,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 30,
-          "spawnInterval": 2.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        }
-      ]
-    }
-  ],
-  "levelSettings": {
-    "energyMaxUpgrades": [
-      5,
-      10,
-      15,
-      20,
-      25,
-      30,
-      40,
-      50,
-      60,
-      70,
-      80,
-      90,
-      100,
-      120,
-      150,
-      200,
-      300,
-      400,
-      500,
-      500
-    ]
-  }
-}

+ 0 - 11
assets/data/backups/levels/Level1_20250919_113116.json.meta

@@ -1,11 +0,0 @@
-{
-  "ver": "2.0.1",
-  "importer": "json",
-  "imported": true,
-  "uuid": "491b975d-25e8-4852-9ac8-9a3175a595ee",
-  "files": [
-    ".json"
-  ],
-  "subMetas": {},
-  "userData": {}
-}

+ 0 - 172
assets/data/backups/levels/Level2_20250919_113116.json

@@ -1,172 +0,0 @@
-{
-  "levelId": "Level2",
-  "name": "丛林冒险(森林场景)",
-  "scene": "forest",
-  "description": "森林场景的塔防挑战,引入新的敌人类型和武器组合",
-  "backgroundImage": "images/LevelBackground/BG2",
-  "availableWeapons": [
-    "毛豆射手",
-    "尖胡萝卜"
-  ],
-  "coinReward": 500,
-  "diamondReward": 30,
-  "initialCoins": 100,
-  "timeLimit": 300,
-  "difficulty": "normal",
-  "healthMultiplier": 1.2,
-  "waves": [
-    {
-      "waveId": 1,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 10,
-          "spawnInterval": 3.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 5,
-          "spawnInterval": 6.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        }
-      ]
-    },
-    {
-      "waveId": 2,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 15,
-          "spawnInterval": 3.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 8,
-          "spawnInterval": 6.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 3,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 30,
-          "spawnInterval": 1.5,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 10,
-          "spawnInterval": 3.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 4,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 40,
-          "spawnInterval": 1.5,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 30,
-          "spawnInterval": 2.0,
-          "spawnDelay": 10.0,
-          "characteristics": "高生命, 慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 5,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 60,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "mage_zombie",
-          "count": 10,
-          "spawnInterval": 6.0,
-          "spawnDelay": 0.0,
-          "characteristics": "远程魔法攻击, 中等生命"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 40,
-          "spawnInterval": 1.5,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 6,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 60,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 60,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "boss1_gatekeeper",
-          "count": 1,
-          "spawnInterval": 60.0,
-          "spawnDelay": 30.0,
-          "characteristics": "超高生命, 多种攻击方式, 召唤小怪"
-        }
-      ]
-    }
-  ],
-  "levelSettings": {
-    "energyMax": 5,
-    "energyMaxUpgrades": [
-      5,
-      10,
-      15,
-      20,
-      25,
-      30,
-      40,
-      50,
-      60,
-      70,
-      80,
-      90,
-      100,
-      120,
-      150,
-      200,
-      300,
-      400,
-      500,
-      500
-    ]
-  }
-}

+ 0 - 11
assets/data/backups/levels/Level2_20250919_113116.json.meta

@@ -1,11 +0,0 @@
-{
-  "ver": "2.0.1",
-  "importer": "json",
-  "imported": true,
-  "uuid": "091b3224-53c2-4c96-90ae-069aa51a1455",
-  "files": [
-    ".json"
-  ],
-  "subMetas": {},
-  "userData": {}
-}

+ 0 - 234
assets/data/backups/levels/Level3_20250919_113116.json

@@ -1,234 +0,0 @@
-{
-  "levelId": "Level3",
-  "name": "魔法废墟(魔幻场景)",
-  "scene": "magic_ruins",
-  "description": "魔幻场景的塔防挑战,引入远程攻击敌人和隐身机制",
-  "backgroundImage": "images/LevelBackground/BG3",
-  "availableWeapons": [
-    "毛豆射手",
-    "尖胡萝卜",
-    "锯齿草"
-  ],
-  "coinReward": 800,
-  "diamondReward": 50,
-  "initialCoins": 100,
-  "timeLimit": 300,
-  "difficulty": "normal",
-  "healthMultiplier": 1.4,
-  "waves": [
-    {
-      "waveId": 1,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 10,
-          "spawnInterval": 3.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 5,
-          "spawnInterval": 6.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 2,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 20,
-          "spawnInterval": 2.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 10,
-          "spawnInterval": 4.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "mage_zombie",
-          "count": 5,
-          "spawnInterval": 6.0,
-          "spawnDelay": 10.0,
-          "characteristics": "远程魔法攻击, 中等生命"
-        }
-      ]
-    },
-    {
-      "waveId": 3,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 20,
-          "spawnInterval": 2.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 20,
-          "spawnInterval": 2.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "mage_zombie",
-          "count": 20,
-          "spawnInterval": 2.0,
-          "spawnDelay": 0.0,
-          "characteristics": "远程魔法攻击, 中等生命"
-        }
-      ]
-    },
-    {
-      "waveId": 4,
-      "enemies": [
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 45,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "mage_zombie",
-          "count": 30,
-          "spawnInterval": 1.5,
-          "spawnDelay": 0.0,
-          "characteristics": "远程魔法攻击, 中等生命"
-        },
-        {
-          "enemyType": "wandering_zombie",
-          "count": 20,
-          "spawnInterval": 2.0,
-          "spawnDelay": 5.0,
-          "characteristics": "左右摇摆, 近战范围大"
-        }
-      ]
-    },
-    {
-      "waveId": 5,
-      "enemies": [
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 60,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "mage_zombie",
-          "count": 40,
-          "spawnInterval": 1.5,
-          "spawnDelay": 0.0,
-          "characteristics": "远程魔法攻击, 中等生命"
-        },
-        {
-          "enemyType": "wandering_zombie",
-          "count": 60,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "左右摇摆, 近战范围大"
-        },
-        {
-          "enemyType": "boss1_gatekeeper",
-          "count": 1,
-          "spawnInterval": 60.0,
-          "spawnDelay": 10.0,
-          "characteristics": "超高生命, 多种攻击方式, 召唤小怪"
-        }
-      ]
-    },
-    {
-      "waveId": 6,
-      "enemies": [
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 60,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "mage_zombie",
-          "count": 40,
-          "spawnInterval": 1.5,
-          "spawnDelay": 0.0,
-          "characteristics": "远程魔法攻击, 中等生命"
-        },
-        {
-          "enemyType": "stealth_zombie",
-          "count": 20,
-          "spawnInterval": 2.0,
-          "spawnDelay": 10.0,
-          "characteristics": "隐身能力, 快速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 7,
-      "enemies": [
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 80,
-          "spawnInterval": 0.7,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "mage_zombie",
-          "count": 40,
-          "spawnInterval": 1.5,
-          "spawnDelay": 0.0,
-          "characteristics": "远程魔法攻击, 中等生命"
-        },
-        {
-          "enemyType": "stealth_zombie",
-          "count": 40,
-          "spawnInterval": 1.5,
-          "spawnDelay": 0.0,
-          "characteristics": "隐身能力, 快速移动"
-        },
-        {
-          "enemyType": "boss2_gravedigger",
-          "count": 1,
-          "spawnInterval": 60.0,
-          "spawnDelay": 20.0,
-          "characteristics": "超高生命, 范围攻击, 召唤增援"
-        }
-      ]
-    }
-  ],
-  "levelSettings": {
-    "energyMax": 6,
-    "energyMaxUpgrades": [
-      5,
-      10,
-      15,
-      20,
-      25,
-      30,
-      40,
-      50,
-      60,
-      70,
-      80,
-      90,
-      100,
-      120,
-      150,
-      200,
-      300,
-      400,
-      500,
-      500
-    ]
-  }
-}

+ 0 - 476
assets/data/backups/levels/Level4_20250919_113116.json

@@ -1,476 +0,0 @@
-{
-  "levelId": "Level4",
-  "name": "钢铁堡垒(工业场景)",
-  "scene": "industrial",
-  "description": "工业场景的高难度挑战,引入BOSS战和超高防御敌人",
-  "backgroundImage": "images/LevelBackground/BG1",
-  "availableWeapons": [
-    "毛豆射手",
-    "尖胡萝卜",
-    "锯齿草",
-    "西瓜炸弹"
-  ],
-  "coinReward": 1000,
-  "diamondReward": 80,
-  "initialCoins": 100,
-  "timeLimit": 300,
-  "difficulty": "normal",
-  "healthMultiplier": 1.6,
-  "waves": [
-    {
-      "waveId": 1,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 10,
-          "spawnInterval": 3.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 10,
-          "spawnInterval": 3.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 1,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 10,
-          "spawnInterval": 3.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 10,
-          "spawnInterval": 3.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 2,
-      "enemies": [
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 10,
-          "spawnInterval": 4.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "normal_zombie",
-          "count": 10,
-          "spawnInterval": 4.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 5,
-          "spawnInterval": 4.0,
-          "spawnDelay": 20.0,
-          "characteristics": "超高生命, 极慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 2,
-      "enemies": [
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 10,
-          "spawnInterval": 4.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "normal_zombie",
-          "count": 10,
-          "spawnInterval": 4.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 5,
-          "spawnInterval": 4.0,
-          "spawnDelay": 20.0,
-          "characteristics": "超高生命, 极慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 3,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 20,
-          "spawnInterval": 2.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 20,
-          "spawnInterval": 2.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 5,
-          "spawnInterval": 8.0,
-          "spawnDelay": 0.0,
-          "characteristics": "超高生命, 极慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 3,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 20,
-          "spawnInterval": 2.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 20,
-          "spawnInterval": 2.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 5,
-          "spawnInterval": 8.0,
-          "spawnDelay": 0.0,
-          "characteristics": "超高生命, 极慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 4,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 60,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 30,
-          "spawnInterval": 2.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 10,
-          "spawnInterval": 6.0,
-          "spawnDelay": 0.0,
-          "characteristics": "超高生命, 极慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 4,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 60,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 30,
-          "spawnInterval": 2.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 10,
-          "spawnInterval": 6.0,
-          "spawnDelay": 0.0,
-          "characteristics": "超高生命, 极慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 5,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 60,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "archer_zombie",
-          "count": 10,
-          "spawnInterval": 4.0,
-          "spawnDelay": 20.0,
-          "characteristics": "远程弓箭攻击"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 30,
-          "spawnInterval": 1.0,
-          "spawnDelay": 30.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 20,
-          "spawnInterval": 2.0,
-          "spawnDelay": 20.0,
-          "characteristics": "超高生命, 极慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 5,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 60,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "archer_zombie",
-          "count": 10,
-          "spawnInterval": 4.0,
-          "spawnDelay": 20.0,
-          "characteristics": "远程弓箭攻击"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 30,
-          "spawnInterval": 1.0,
-          "spawnDelay": 30.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 20,
-          "spawnInterval": 2.0,
-          "spawnDelay": 20.0,
-          "characteristics": "超高生命, 极慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 6,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 60,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "archer_zombie",
-          "count": 20,
-          "spawnInterval": 2.5,
-          "spawnDelay": 10.0,
-          "characteristics": "远程弓箭攻击"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 60,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 30,
-          "spawnInterval": 2.0,
-          "spawnDelay": 0.0,
-          "characteristics": "超高生命, 极慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 6,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 60,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "archer_zombie",
-          "count": 20,
-          "spawnInterval": 2.5,
-          "spawnDelay": 10.0,
-          "characteristics": "远程弓箭攻击"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 60,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 30,
-          "spawnInterval": 2.0,
-          "spawnDelay": 0.0,
-          "characteristics": "超高生命, 极慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 7,
-      "enemies": [
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 60,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "archer_zombie",
-          "count": 30,
-          "spawnInterval": 2.0,
-          "spawnDelay": 0.0,
-          "characteristics": "远程弓箭攻击"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 30,
-          "spawnInterval": 2.0,
-          "spawnDelay": 0.0,
-          "characteristics": "超高生命, 极慢速移动"
-        },
-        {
-          "enemyType": "boss1_gatekeeper",
-          "count": 1,
-          "spawnInterval": 60.0,
-          "spawnDelay": 30.0,
-          "characteristics": "超高生命, 多种攻击方式, 召唤小怪"
-        }
-      ]
-    },
-    {
-      "waveId": 7,
-      "enemies": [
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 60,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "archer_zombie",
-          "count": 30,
-          "spawnInterval": 2.0,
-          "spawnDelay": 0.0,
-          "characteristics": "远程弓箭攻击"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 30,
-          "spawnInterval": 2.0,
-          "spawnDelay": 0.0,
-          "characteristics": "超高生命, 极慢速移动"
-        },
-        {
-          "enemyType": "boss1_gatekeeper",
-          "count": 1,
-          "spawnInterval": 60.0,
-          "spawnDelay": 30.0,
-          "characteristics": "超高生命, 多种攻击方式, 召唤小怪"
-        }
-      ]
-    },
-    {
-      "waveId": 8,
-      "enemies": [
-        {
-          "enemyType": "bucket_zombie",
-          "count": 60,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "超高生命, 极慢速移动"
-        },
-        {
-          "enemyType": "boss2_gravedigger",
-          "count": 1,
-          "spawnInterval": 60.0,
-          "spawnDelay": 30.0,
-          "characteristics": "超高生命, 范围攻击, 召唤增援"
-        }
-      ]
-    },
-    {
-      "waveId": 8,
-      "enemies": [
-        {
-          "enemyType": "bucket_zombie",
-          "count": 60,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "超高生命, 极慢速移动"
-        },
-        {
-          "enemyType": "boss2_gravedigger",
-          "count": 1,
-          "spawnInterval": 60.0,
-          "spawnDelay": 30.0,
-          "characteristics": "超高生命, 范围攻击, 召唤增援"
-        }
-      ]
-    }
-  ],
-  "levelSettings": {
-    "energyMax": 6,
-    "energyMaxUpgrades": [
-      5,
-      10,
-      15,
-      20,
-      25,
-      30,
-      40,
-      50,
-      60,
-      70,
-      80,
-      90,
-      100,
-      120,
-      150,
-      200,
-      300,
-      400,
-      500,
-      500
-    ]
-  }
-}

+ 0 - 11
assets/data/backups/levels/Level4_20250919_113116.json.meta

@@ -1,11 +0,0 @@
-{
-  "ver": "2.0.1",
-  "importer": "json",
-  "imported": true,
-  "uuid": "9ac2d0a7-71ef-4088-ae59-b804d408645c",
-  "files": [
-    ".json"
-  ],
-  "subMetas": {},
-  "userData": {}
-}

+ 0 - 118
assets/data/backups/levels/Level5_20250919_113116.json

@@ -1,118 +0,0 @@
-{
-  "levelId": "Level5",
-  "name": "终极挑战(赛博都市)",
-  "scene": "cyberpunk",
-  "description": "终极挑战关卡,包含多个BOSS和复杂的敌人组合",
-  "backgroundImage": "images/LevelBackground/BG1",
-  "availableWeapons": [
-    "毛豆射手",
-    "尖胡萝卜",
-    "锯齿草",
-    "西瓜炸弹",
-    "回旋镖盆栽"
-  ],
-  "coinReward": 1300,
-  "diamondReward": 100,
-  "initialCoins": 100,
-  "timeLimit": 300,
-  "difficulty": "normal",
-  "healthMultiplier": 1.8,
-  "waves": [
-    {
-      "waveId": 1,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 20,
-          "spawnInterval": 1.5,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 8,
-          "spawnInterval": 3.0,
-          "spawnDelay": 10.0,
-          "characteristics": "高生命, 慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 2,
-      "enemies": [
-        {
-          "enemyType": "mage_zombie",
-          "count": 8,
-          "spawnInterval": 4.0,
-          "spawnDelay": 0.0,
-          "characteristics": "远程魔法攻击, 中等生命"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 6,
-          "spawnInterval": 6.0,
-          "spawnDelay": 15.0,
-          "characteristics": "超高生命, 极慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 3,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 15,
-          "spawnInterval": 1.2,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 10,
-          "spawnInterval": 2.5,
-          "spawnDelay": 8.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "mage_zombie",
-          "count": 8,
-          "spawnInterval": 3.5,
-          "spawnDelay": 20.0,
-          "characteristics": "远程魔法攻击, 中等生命"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 6,
-          "spawnInterval": 5.0,
-          "spawnDelay": 30.0,
-          "characteristics": "超高生命, 极慢速移动"
-        }
-      ]
-    }
-  ],
-  "levelSettings": {
-    "energyMax": 7,
-    "energyMaxUpgrades": [
-      5,
-      10,
-      15,
-      20,
-      25,
-      30,
-      40,
-      50,
-      60,
-      70,
-      80,
-      90,
-      100,
-      120,
-      150,
-      200,
-      300,
-      400,
-      500,
-      500
-    ]
-  }
-}

+ 0 - 11
assets/data/backups/levels/Level5_20250919_113116.json.meta

@@ -1,11 +0,0 @@
-{
-  "ver": "2.0.1",
-  "importer": "json",
-  "imported": true,
-  "uuid": "fd8c2868-72d5-416c-831b-0b83bf9d2ef7",
-  "files": [
-    ".json"
-  ],
-  "subMetas": {},
-  "userData": {}
-}

+ 0 - 119
assets/data/backups/levels/Level6_20250919_113116.json

@@ -1,119 +0,0 @@
-{
-  "levelId": "Level6",
-  "name": "沙漠绿洲(沙漠场景)",
-  "scene": "desert",
-  "description": "沙漠场景的挑战,炎热环境下的生存战斗",
-  "backgroundImage": "images/LevelBackground/BG1",
-  "availableWeapons": [
-    "毛豆射手",
-    "尖胡萝卜",
-    "锯齿草",
-    "西瓜炸弹",
-    "回旋镖盆栽",
-    "炙热辣椒"
-  ],
-  "coinReward": 1800,
-  "diamondReward": 120,
-  "initialCoins": 100,
-  "timeLimit": 300,
-  "difficulty": "normal",
-  "healthMultiplier": 2.0,
-  "waves": [
-    {
-      "waveId": 1,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 18,
-          "spawnInterval": 1.8,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 4,
-          "spawnInterval": 6.0,
-          "spawnDelay": 12.0,
-          "characteristics": "超高生命, 极慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 2,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 15,
-          "spawnInterval": 1.5,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "mage_zombie",
-          "count": 5,
-          "spawnInterval": 5.0,
-          "spawnDelay": 8.0,
-          "characteristics": "远程魔法子弹攻击防御塔"
-        },
-        {
-          "enemyType": "archer_zombie",
-          "count": 3,
-          "spawnInterval": 8.0,
-          "spawnDelay": 15.0,
-          "characteristics": "远程弓箭攻击"
-        }
-      ]
-    },
-    {
-      "waveId": 3,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 20,
-          "spawnInterval": 1.2,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "stealth_zombie",
-          "count": 4,
-          "spawnInterval": 10.0,
-          "spawnDelay": 20.0,
-          "characteristics": "隐身能力, 快速移动"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 6,
-          "spawnInterval": 4.0,
-          "spawnDelay": 25.0,
-          "characteristics": "超高生命, 极慢速移动"
-        }
-      ]
-    }
-  ],
-  "levelSettings": {
-    "energyMax": 7,
-    "energyMaxUpgrades": [
-      5,
-      10,
-      15,
-      20,
-      25,
-      30,
-      40,
-      50,
-      60,
-      70,
-      80,
-      90,
-      100,
-      120,
-      150,
-      200,
-      300,
-      400,
-      500,
-      500
-    ]
-  }
-}

+ 0 - 11
assets/data/backups/levels/Level6_20250919_113116.json.meta

@@ -1,11 +0,0 @@
-{
-  "ver": "2.0.1",
-  "importer": "json",
-  "imported": true,
-  "uuid": "91c547c0-dbcb-460e-b2b7-45c1df642fc3",
-  "files": [
-    ".json"
-  ],
-  "subMetas": {},
-  "userData": {}
-}

+ 0 - 57
assets/data/backups/levels/Level7_20250919_113116.json

@@ -1,57 +0,0 @@
-{
-  "levelId": "Level7",
-  "name": "冰雪王国(冰雪场景)",
-  "scene": "ice",
-  "description": "冰雪场景的极地挑战,寒冷环境下的防御战",
-  "backgroundImage": "images/LevelBackground/BG1",
-  "availableWeapons": [
-    "毛豆射手",
-    "尖胡萝卜",
-    "锯齿草",
-    "西瓜炸弹",
-    "回旋镖盆栽",
-    "炙热辣椒",
-    "仙人散弹"
-  ],
-  "coinReward": 2200,
-  "diamondReward": 150,
-  "initialCoins": 100,
-  "timeLimit": 300,
-  "difficulty": "normal",
-  "healthMultiplier": 2.2,
-  "waves": [
-    {
-      "waveId": 3,
-      "enemies": []
-    },
-    {
-      "waveId": 4,
-      "enemies": []
-    }
-  ],
-  "levelSettings": {
-    "energyMax": 8,
-    "energyMaxUpgrades": [
-      5,
-      10,
-      15,
-      20,
-      25,
-      30,
-      40,
-      50,
-      60,
-      70,
-      80,
-      90,
-      100,
-      120,
-      150,
-      200,
-      300,
-      400,
-      500,
-      500
-    ]
-  }
-}

+ 0 - 11
assets/data/backups/levels/Level7_20250919_113116.json.meta

@@ -1,11 +0,0 @@
-{
-  "ver": "2.0.1",
-  "importer": "json",
-  "imported": true,
-  "uuid": "f7e7fc38-66a5-49d1-9846-7d1ade408ea5",
-  "files": [
-    ".json"
-  ],
-  "subMetas": {},
-  "userData": {}
-}

+ 0 - 154
assets/data/backups/levels/Level8_20250919_113116.json

@@ -1,154 +0,0 @@
-{
-  "levelId": "Level8",
-  "name": "火山熔岩(火山场景)",
-  "scene": "volcano",
-  "description": "火山场景的极限挑战,熔岩环境下的终极考验",
-  "backgroundImage": "images/LevelBackground/BG1",
-  "availableWeapons": [
-    "毛豆射手",
-    "尖胡萝卜",
-    "锯齿草",
-    "西瓜炸弹",
-    "回旋镖盆栽",
-    "炙热辣椒",
-    "仙人散弹",
-    "秋葵导弹"
-  ],
-  "coinReward": 2500,
-  "diamondReward": 170,
-  "initialCoins": 100,
-  "timeLimit": 300,
-  "difficulty": "normal",
-  "healthMultiplier": 2.4,
-  "waves": [
-    {
-      "waveId": 1,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 30,
-          "spawnInterval": 1.2,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 10,
-          "spawnInterval": 3.0,
-          "spawnDelay": 8.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "wandering_zombie",
-          "count": 6,
-          "spawnInterval": 5.0,
-          "spawnDelay": 15.0,
-          "characteristics": "左右摇摆, 近战范围大"
-        }
-      ]
-    },
-    {
-      "waveId": 2,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 25,
-          "spawnInterval": 1.0,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "mage_zombie",
-          "count": 8,
-          "spawnInterval": 4.0,
-          "spawnDelay": 10.0,
-          "characteristics": "远程魔法子弹攻击防御塔"
-        },
-        {
-          "enemyType": "archer_zombie",
-          "count": 6,
-          "spawnInterval": 6.0,
-          "spawnDelay": 18.0,
-          "characteristics": "远程弓箭攻击"
-        },
-        {
-          "enemyType": "barrel_zombie",
-          "count": 4,
-          "spawnInterval": 10.0,
-          "spawnDelay": 25.0,
-          "characteristics": "爆炸伤害, 自爆攻击"
-        }
-      ]
-    },
-    {
-      "waveId": 3,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 20,
-          "spawnInterval": 0.8,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 12,
-          "spawnInterval": 2.5,
-          "spawnDelay": 12.0,
-          "characteristics": "超高生命, 极慢速移动"
-        },
-        {
-          "enemyType": "stealth_zombie",
-          "count": 8,
-          "spawnInterval": 6.0,
-          "spawnDelay": 20.0,
-          "characteristics": "隐身能力, 快速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 4,
-      "enemies": [
-        {
-          "enemyType": "boss2_gravedigger",
-          "count": 1,
-          "spawnInterval": 0.0,
-          "spawnDelay": 30.0,
-          "characteristics": "超高生命, 范围攻击, 召唤增援"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 6,
-          "spawnInterval": 8.0,
-          "spawnDelay": 45.0,
-          "characteristics": "超高生命, 极慢速移动"
-        }
-      ]
-    }
-  ],
-  "levelSettings": {
-    "energyMax": 8,
-    "energyMaxUpgrades": [
-      5,
-      10,
-      15,
-      20,
-      25,
-      30,
-      40,
-      50,
-      60,
-      70,
-      80,
-      90,
-      100,
-      120,
-      150,
-      200,
-      300,
-      400,
-      500,
-      500
-    ]
-  }
-}

+ 0 - 11
assets/data/backups/levels/Level8_20250919_113116.json.meta

@@ -1,11 +0,0 @@
-{
-  "ver": "2.0.1",
-  "importer": "json",
-  "imported": true,
-  "uuid": "e48d4715-dc3b-4b58-88d9-64660482984d",
-  "files": [
-    ".json"
-  ],
-  "subMetas": {},
-  "userData": {}
-}

+ 0 - 174
assets/data/backups/levels/Level9_20250919_113116.json

@@ -1,174 +0,0 @@
-{
-  "levelId": "Level9",
-  "name": "终极试炼(终极场景)",
-  "scene": "ultimate",
-  "description": "终极试炼关卡,解锁最后的植物武器,面对最强挑战",
-  "backgroundImage": "images/LevelBackground/BG1",
-  "availableWeapons": [
-    "毛豆射手",
-    "尖胡萝卜",
-    "锯齿草",
-    "西瓜炸弹",
-    "回旋镖盆栽",
-    "炙热辣椒",
-    "仙人散弹",
-    "秋葵导弹",
-    "狼牙棒"
-  ],
-  "coinReward": 3000,
-  "diamondReward": 200,
-  "initialCoins": 100,
-  "timeLimit": 300,
-  "difficulty": "normal",
-  "healthMultiplier": 2.6,
-  "waves": [
-    {
-      "waveId": 1,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 40,
-          "spawnInterval": 0.8,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "roadblock_zombie",
-          "count": 15,
-          "spawnInterval": 2.5,
-          "spawnDelay": 5.0,
-          "characteristics": "高生命, 慢速移动"
-        },
-        {
-          "enemyType": "wandering_zombie",
-          "count": 10,
-          "spawnInterval": 4.0,
-          "spawnDelay": 12.0,
-          "characteristics": "左右摇摆, 近战范围大"
-        }
-      ]
-    },
-    {
-      "waveId": 2,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 35,
-          "spawnInterval": 0.6,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "mage_zombie",
-          "count": 12,
-          "spawnInterval": 3.0,
-          "spawnDelay": 8.0,
-          "characteristics": "远程魔法子弹攻击防御塔"
-        },
-        {
-          "enemyType": "archer_zombie",
-          "count": 10,
-          "spawnInterval": 4.0,
-          "spawnDelay": 15.0,
-          "characteristics": "远程弓箭攻击"
-        },
-        {
-          "enemyType": "barrel_zombie",
-          "count": 6,
-          "spawnInterval": 8.0,
-          "spawnDelay": 22.0,
-          "characteristics": "爆炸伤害, 自爆攻击"
-        }
-      ]
-    },
-    {
-      "waveId": 3,
-      "enemies": [
-        {
-          "enemyType": "normal_zombie",
-          "count": 30,
-          "spawnInterval": 0.5,
-          "spawnDelay": 0.0,
-          "characteristics": "中速移动, 无技能"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 15,
-          "spawnInterval": 2.0,
-          "spawnDelay": 10.0,
-          "characteristics": "超高生命, 极慢速移动"
-        },
-        {
-          "enemyType": "stealth_zombie",
-          "count": 12,
-          "spawnInterval": 4.0,
-          "spawnDelay": 18.0,
-          "characteristics": "隐身能力, 快速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 4,
-      "enemies": [
-        {
-          "enemyType": "boss1_gatekeeper",
-          "count": 1,
-          "spawnInterval": 0.0,
-          "spawnDelay": 25.0,
-          "characteristics": "超高生命, 多种攻击方式, 召唤小怪"
-        },
-        {
-          "enemyType": "boss2_gravedigger",
-          "count": 1,
-          "spawnInterval": 0.0,
-          "spawnDelay": 60.0,
-          "characteristics": "超高生命, 范围攻击, 召唤增援"
-        },
-        {
-          "enemyType": "bucket_zombie",
-          "count": 10,
-          "spawnInterval": 6.0,
-          "spawnDelay": 40.0,
-          "characteristics": "超高生命, 极慢速移动"
-        }
-      ]
-    },
-    {
-      "waveId": 5,
-      "enemies": [
-        {
-          "enemyType": "终极BOSS",
-          "count": 1,
-          "spawnInterval": 0.0,
-          "spawnDelay": 30.0,
-          "characteristics": "极高生命, 全屏攻击, 无敌阶段, 召唤军团"
-        }
-      ]
-    }
-  ],
-  "levelSettings": {
-    "energyMax": 9,
-    "energyMaxUpgrades": [
-      5,
-      10,
-      15,
-      20,
-      25,
-      30,
-      40,
-      50,
-      60,
-      70,
-      80,
-      90,
-      100,
-      120,
-      150,
-      200,
-      300,
-      400,
-      500,
-      500
-    ]
-  }
-}

+ 0 - 11
assets/data/backups/levels/Level9_20250919_113116.json.meta

@@ -1,11 +0,0 @@
-{
-  "ver": "2.0.1",
-  "importer": "json",
-  "imported": true,
-  "uuid": "7f2d1648-5d44-4e2f-aa2f-1641ec053c42",
-  "files": [
-    ".json"
-  ],
-  "subMetas": {},
-  "userData": {}
-}

+ 20 - 0
assets/data/ball_price_config.json

@@ -0,0 +1,20 @@
+{
+  "addBallPricing": {
+    "initialPrice": 80,
+    "priceIncrement": 10,
+    "maxPrice": 500,
+    "description": "增加小球的价格配置"
+  },
+  "refreshBlockPricing": {
+    "initialPrice": 5,
+    "priceIncrement": 2,
+    "maxPrice": 50,
+    "description": "刷新方块的价格配置"
+  },
+  "priceHistory": {
+    "addBallCurrentPrice": 80,
+    "refreshBlockCurrentPrice": 5,
+    "addBallPurchaseCount": 0,
+    "refreshBlockPurchaseCount": 0
+  }
+}

+ 1 - 1
assets/data/backups/levels/Level3_20250919_113116.json.meta → assets/data/ball_price_config.json.meta

@@ -2,7 +2,7 @@
   "ver": "2.0.1",
   "importer": "json",
   "imported": true,
-  "uuid": "105ac26d-15fa-416e-b230-363a3aca6a64",
+  "uuid": "2c4beb85-fa85-41dc-a32a-b614ec345d96",
   "files": [
     ".json"
   ],

BIN
assets/data/excel/BallController标准配置表.xlsx


BIN
assets/data/excel/小球价格配置表.xlsx


+ 12 - 0
assets/data/excel/小球价格配置表.xlsx.meta

@@ -0,0 +1,12 @@
+{
+  "ver": "1.0.0",
+  "importer": "*",
+  "imported": true,
+  "uuid": "d9060612-b132-4cf3-a8a5-9c9ef959afb6",
+  "files": [
+    ".json",
+    ".xlsx"
+  ],
+  "subMetas": {},
+  "userData": {}
+}

+ 352 - 0
assets/scripts/Ads/AdManager.ts

@@ -0,0 +1,352 @@
+import { _decorator, Component } from 'cc';
+const { ccclass } = _decorator;
+
+interface RewardedVideoAd {
+    show(): Promise<void>;
+    load(): Promise<void>;
+    onLoad(callback: (res?: any) => void): void;
+    onError(callback: (err: any) => void): void;
+    onClose(callback: (res: { isEnded: boolean }) => void): void;
+    offLoad(callback?: (res?: any) => void): void;
+    offError(callback?: (err: any) => void): void;
+    offClose(callback?: (res: { isEnded: boolean }) => void): void;
+}
+
+declare const wx: {
+    createRewardedVideoAd(options: { adUnitId: string; multiton?: boolean }): RewardedVideoAd;
+};
+
+@ccclass('AdManager')
+export class AdManager {
+    private static instance: AdManager = null;
+    private videoAd: RewardedVideoAd = null;
+    private readonly AD_UNIT_ID = 'adunit-ab2f3b2d24b4f214'; // 替换为你的广告位ID
+    
+    private constructor() {
+        // 延迟初始化广告,避免在微信环境未完全准备好时初始化
+        this.delayedInitialize();
+    }
+    
+    public static getInstance(): AdManager {
+        if (!AdManager.instance) {
+            AdManager.instance = new AdManager();
+        }
+        return AdManager.instance;
+    }
+    
+    /**
+     * 静态方法:初始化广告管理器
+     * 建议在游戏启动或场景初始化时调用
+     */
+    public static initialize(): void {
+        AdManager.getInstance();
+        console.log('[AdManager] 广告管理器已初始化');
+    }
+    
+    /**
+     * 延迟初始化广告
+     * 解决微信小游戏环境下广告组件初始化时机问题
+     */
+    private delayedInitialize() {
+        // 延迟500ms初始化,确保微信环境完全准备好
+        setTimeout(() => {
+            this.initializeAd();
+        }, 500);
+    }
+    
+    private initializeAd() {
+        // 检查是否在微信小游戏环境
+        if (typeof wx !== 'undefined' && wx.createRewardedVideoAd) {
+            try {
+                // 创建激励视频广告实例,提前初始化
+                this.videoAd = wx.createRewardedVideoAd({
+                    adUnitId: this.AD_UNIT_ID
+                });
+                
+                // 设置全局错误处理
+                this.setupGlobalErrorHandling();
+                
+                // 预加载广告
+                this.preloadAd();
+                
+                console.log('[AdManager] 激励视频广告初始化成功');
+            } catch (error) {
+                console.error('[AdManager] 激励视频广告初始化失败:', error);
+                // 初始化失败时,延迟重试
+                this.retryInitialize();
+            }
+        } else {
+            console.log('[AdManager] 非微信小游戏环境,跳过广告初始化');
+        }
+    }
+    
+    /**
+     * 重试初始化广告
+     * 当首次初始化失败时进行重试
+     */
+    private retryInitialize() {
+        setTimeout(() => {
+            console.log('[AdManager] 重试初始化广告');
+            this.initializeAd();
+        }, 2000);
+    }
+    
+    /**
+     * 设置全局广告错误处理
+     * 处理广告拉取异常情况
+     */
+    private setupGlobalErrorHandling() {
+        if (!this.videoAd) return;
+        
+        // 设置全局错误监听
+        this.videoAd.onError((err: any) => {
+            console.error('[AdManager] 广告全局错误:', err);
+            
+            // 根据错误码处理不同情况
+            if (err.errCode) {
+                switch (err.errCode) {
+                    case 1000:
+                        console.log('[AdManager] 后端接口调用失败');
+                        break;
+                    case 1001:
+                        console.log('[AdManager] 参数错误');
+                        break;
+                    case 1002:
+                        console.log('[AdManager] 广告单元无效');
+                        break;
+                    case 1003:
+                        console.log('[AdManager] 内部错误');
+                        break;
+                    case 1004:
+                        console.log('[AdManager] 无合适的广告');
+                        // 无广告返回时,建议隐藏激励视频入口
+                        this.handleNoAdAvailable();
+                        break;
+                    case 1005:
+                        console.log('[AdManager] 广告组件审核中');
+                        break;
+                    case 1006:
+                        console.log('[AdManager] 广告组件被驳回');
+                        break;
+                    case 1007:
+                        console.log('[AdManager] 广告组件被封禁');
+                        break;
+                    case 1008:
+                        console.log('[AdManager] 广告单元已关闭');
+                        break;
+                    case 1009:
+                        console.log('[AdManager] 广告单元为适配审核中,请勿调用show()');
+                        break;
+                    default:
+                        console.log('[AdManager] 未知错误码:', err.errCode);
+                        break;
+                }
+            }
+        });
+    }
+    
+    /**
+     * 处理无广告可用的情况
+     * 建议隐藏激励视频入口
+     */
+    private handleNoAdAvailable() {
+        console.log('[AdManager] 无合适广告,建议隐藏激励视频入口');
+        // 这里可以发送事件通知UI隐藏广告入口
+        // 或者设置一个标志位供外部查询
+    }
+    
+    /**
+     * 检查是否有广告可用
+     * @returns 是否有广告可用
+     */
+    public isAdAvailable(): boolean {
+        return this.videoAd !== null;
+    }
+    
+    /**
+     * 检查广告是否已经初始化完成
+     * @returns 广告是否已初始化
+     */
+    public isAdInitialized(): boolean {
+        return this.videoAd !== null;
+    }
+    
+    /**
+     * 获取广告初始化状态
+     * @returns 广告状态信息
+     */
+    public getAdStatus(): { initialized: boolean; available: boolean } {
+        const initialized = this.videoAd !== null;
+        return {
+            initialized,
+            available: initialized
+        };
+    }
+    
+    /**
+     * 显示激励视频广告
+     * @param onReward 广告观看完成后的回调
+     * @param onError 广告显示失败的回调
+     */
+    public showRewardedVideoAd(
+        onReward: () => void,
+        onError?: (error: any) => void
+    ): void {
+        if (!this.videoAd) {
+            console.log('[AdManager] 广告未初始化,等待初始化完成...');
+            // 等待广告初始化完成后再显示
+            this.waitForAdInitialization(() => {
+                this.showRewardedVideoAd(onReward, onError);
+            }, onReward);
+            return;
+        }
+        
+        // 设置广告事件监听
+        const onLoadHandler = (res?: any) => {
+            console.log('[AdManager] 广告加载成功', res);
+            if (res && res.useFallbackSharePage) {
+                console.log('[AdManager] 使用兜底分享页');
+            }
+        };
+        
+        const onErrorHandler = (err: any) => {
+            console.error('[AdManager] 广告加载失败:', err);
+            
+            // 根据错误码决定处理方式
+            let shouldGiveReward = false;
+            if (err.errCode) {
+                switch (err.errCode) {
+                    case 1004: // 无合适的广告
+                        console.log('[AdManager] 无合适广告,不给予奖励');
+                        shouldGiveReward = false;
+                        break;
+                    case 1000: // 后端接口调用失败
+                    case 1003: // 内部错误
+                        console.log('[AdManager] 系统错误,给予奖励');
+                        shouldGiveReward = true;
+                        break;
+                    default:
+                        console.log('[AdManager] 其他错误,给予奖励');
+                        shouldGiveReward = true;
+                        break;
+                }
+            } else {
+                // 没有错误码的情况,默认给予奖励
+                shouldGiveReward = true;
+            }
+            
+            if (onError) {
+                onError(err);
+            } else if (shouldGiveReward) {
+                console.log('[AdManager] 广告失败但给予奖励');
+                onReward();
+            } else {
+                console.log('[AdManager] 广告失败且不给予奖励');
+            }
+        };
+        
+        const onCloseHandler = (res: { isEnded: boolean }) => {
+            console.log('[AdManager] 广告关闭:', res);
+            
+            // 清理事件监听
+            this.videoAd.offLoad(onLoadHandler);
+            this.videoAd.offError(onErrorHandler);
+            this.videoAd.offClose(onCloseHandler);
+            
+            // 根据广告是否完整观看来决定是否给予奖励
+            if (res.isEnded) {
+                console.log('[AdManager] 用户完整观看广告,给予奖励');
+                onReward();
+            } else {
+                console.log('[AdManager] 用户未完整观看广告,不给予奖励');
+            }
+        };
+        
+        // 绑定事件监听
+        this.videoAd.onLoad(onLoadHandler);
+        this.videoAd.onError(onErrorHandler);
+        this.videoAd.onClose(onCloseHandler);
+        
+        // 显示广告
+        this.videoAd.show().catch((showError) => {
+            console.log('[AdManager] 广告显示失败,尝试重新加载');
+            // 失败重试,增加延迟确保广告完全加载
+            this.videoAd.load()
+                .then(() => {
+                    // 加载成功后稍等片刻再显示,避免渲染问题
+                    setTimeout(() => {
+                        this.videoAd.show().catch(err => {
+                            console.error('[AdManager] 激励视频广告二次显示失败', err);
+                            onErrorHandler(err);
+                        });
+                    }, 300);
+                })
+                .catch(err => {
+                    console.error('[AdManager] 激励视频广告加载失败', err);
+                    onErrorHandler(err);
+                });
+        });
+    }
+    
+    /**
+     * 等待广告初始化完成
+     * @param callback 初始化完成后的回调
+     * @param fallback 超时后的回退处理
+     */
+    private waitForAdInitialization(callback: () => void, fallback: () => void): void {
+        let attempts = 0;
+        const maxAttempts = 10; // 最多等待5秒
+        
+        const checkInitialization = () => {
+            if (this.videoAd) {
+                callback();
+                return;
+            }
+            
+            attempts++;
+            if (attempts >= maxAttempts) {
+                console.log('[AdManager] 广告初始化超时,直接给予奖励');
+                fallback();
+                return;
+            }
+            
+            setTimeout(checkInitialization, 500);
+        };
+        
+        checkInitialization();
+    }
+    
+    /**
+     * 预加载广告
+     * 可以在游戏启动时调用,提前加载广告
+     */
+    public preloadAd(): void {
+        if (this.videoAd) {
+            console.log('[AdManager] 开始预加载广告');
+            this.videoAd.load().then(() => {
+                console.log('[AdManager] 广告预加载成功');
+            }).catch(err => {
+                console.error('[AdManager] 预加载广告失败:', err);
+                // 预加载失败时,延迟重试
+                setTimeout(() => {
+                    console.log('[AdManager] 重试预加载广告');
+                    this.preloadAd();
+                }, 3000);
+            });
+        }
+    }
+    
+    /**
+     * 销毁广告管理器
+     */
+    public destroy(): void {
+        if (this.videoAd) {
+            // 清理所有事件监听,包括全局错误监听
+            this.videoAd.offLoad();
+            this.videoAd.offError();
+            this.videoAd.offClose();
+            this.videoAd = null;
+        }
+        AdManager.instance = null;
+    }
+}

+ 9 - 0
assets/scripts/Ads/AdManager.ts.meta

@@ -0,0 +1,9 @@
+{
+  "ver": "4.0.24",
+  "importer": "typescript",
+  "imported": true,
+  "uuid": "40665663-fe17-41e3-a2d2-2ae6287179d0",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

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

@@ -434,9 +434,9 @@ export class GameStartMove extends Component {
                 // }
                 // 动画完成后隐藏diban节点
                 this.dibanNode.active = false;
-                // 动画完成后发送进入战斗状态事件,恢复游戏
-                console.log('[GameStartMove] diban下滑完成,发送游戏恢复事件');
-                EventBus.getInstance().emit(GameEvents.GAME_RESUME);
+                // 动画完成后发送底板选择专用恢复事件
+                console.log('[GameStartMove] diban下滑完成,发送底板选择恢复事件');
+                EventBus.getInstance().emit(GameEvents.GAME_RESUME_BLOCK_SELECTION);
             })
             .start();
             

+ 148 - 0
assets/scripts/AudioManager/AudioCacheOptimization.md

@@ -0,0 +1,148 @@
+# 音频缓存优化解决方案
+
+## 问题描述
+
+在点击广告按钮时,发现会重复加载已经在游戏初始化时加载过的音效资源,导致以下问题:
+
+1. **重复资源加载**:每次播放音效都会重新从Bundle加载资源
+2. **性能影响**:不必要的资源加载消耗性能
+3. **错误风险**:频繁的资源加载可能导致系统错误
+
+### 错误日志示例
+```
+[BundleLoader] 从Bundle data 加载资源: 弹球音效/ui play 
+index.js? [sm]:33 [BundleLoader] 资源加载成功: data/弹球音效/ui play 
+index.js? [sm]:7 [AudioManager] 播放UI音效: data/弹球音效/ui play 
+Error: SystemError (appServiceSDKScriptError) 
+{"errMsg":"updateTextView:fail 33409 not found"}
+```
+
+## 问题根源分析
+
+### 1. 触发链路
+- 点击广告按钮 → 播放UI音效 `Audio.playUISound('data/弹球音效/ui play')`
+- 广告成功回调 → 触发奖励动画 → MoneyAni播放动画 → 播放获得金币音效 `Audio.playUISound('data/弹球音效/get money')`
+
+### 2. 原始AudioManager问题
+```typescript
+// 每次播放都重新加载资源
+const clip = await this.bundleLoader.loadAssetFromBundle<AudioClip>('data', bundlePath, AudioClip);
+```
+
+### 3. BundleLoader无缓存机制
+BundleLoader的`loadAssetFromBundle`方法每次都会重新从Bundle加载资源,没有缓存机制。
+
+## 解决方案
+
+### 1. 音频缓存机制
+
+在AudioManager中添加音频缓存:
+
+```typescript
+// 音频缓存
+private audioClipCache: Map<string, AudioClip> = new Map();
+
+private async playSound(audioSource: AudioSource, sfxPath: string, volume: number | undefined, baseVolume: number, soundType: string) {
+    // 检查缓存中是否已有该音频
+    let clip = this.audioClipCache.get(cleanPath);
+    
+    if (!clip) {
+        // 首次加载并缓存
+        clip = await this.bundleLoader.loadAssetFromBundle<AudioClip>('data', bundlePath, AudioClip);
+        this.audioClipCache.set(cleanPath, clip);
+        console.log(`[AudioManager] 音效已缓存: ${cleanPath}`);
+    } else {
+        console.log(`[AudioManager] 使用缓存音效: ${cleanPath}`);
+    }
+    
+    audioSource.playOneShot(clip);
+}
+```
+
+### 2. 缓存管理方法
+
+```typescript
+// 清理缓存
+public clearAudioCache() {
+    console.log(`[AudioManager] 清理音频缓存,共${this.audioClipCache.size}个音效`);
+    this.audioClipCache.clear();
+}
+
+// 获取缓存信息
+public getCacheInfo(): {count: number, paths: string[]} {
+    return {
+        count: this.audioClipCache.size,
+        paths: Array.from(this.audioClipCache.keys())
+    };
+}
+```
+
+### 3. 静态方法支持
+
+```typescript
+// Audio静态类中添加缓存管理
+static clearAudioCache() {
+    const manager = AudioManager.getInstance();
+    if (manager) {
+        manager.clearAudioCache();
+    }
+}
+
+static getCacheInfo(): {count: number, paths: string[]} {
+    const manager = AudioManager.getInstance();
+    if (manager) {
+        return manager.getCacheInfo();
+    }
+    return {count: 0, paths: []};
+}
+```
+
+## 优化效果
+
+### 1. 性能提升
+- **首次加载**:音效资源从Bundle加载并缓存
+- **后续播放**:直接使用缓存,无需重复加载
+- **减少I/O**:避免频繁的文件系统访问
+
+### 2. 稳定性提升
+- **减少错误**:避免重复加载导致的系统错误
+- **内存管理**:提供缓存清理机制,防止内存泄漏
+
+### 3. 调试支持
+- **缓存状态**:可查看当前缓存的音效数量和路径
+- **日志优化**:区分首次加载和缓存使用
+
+## 使用方法
+
+### 1. 正常使用(无需改动)
+```typescript
+// 现有代码无需修改,自动享受缓存优化
+Audio.playUISound('data/弹球音效/ui play');
+Audio.playUISound('data/弹球音效/get money');
+```
+
+### 2. 缓存管理(可选)
+```typescript
+// 查看缓存状态
+const cacheInfo = Audio.getCacheInfo();
+console.log(`缓存音效数量: ${cacheInfo.count}`);
+console.log(`缓存音效列表:`, cacheInfo.paths);
+
+// 清理缓存(在内存紧张时)
+Audio.clearAudioCache();
+```
+
+## 注意事项
+
+1. **内存使用**:缓存会占用一定内存,但音效文件通常较小
+2. **自动清理**:AudioManager销毁时会自动清理缓存
+3. **向后兼容**:现有代码无需修改,自动享受优化
+4. **调试信息**:控制台会显示缓存使用情况,便于调试
+
+## 测试验证
+
+优化后的表现:
+- **首次播放**:`[AudioManager] 从Bundle加载新音效: 弹球音效/ui play`
+- **后续播放**:`[AudioManager] 使用缓存音效: data/弹球音效/ui play`
+- **无重复加载**:不再出现重复的Bundle加载日志
+- **错误消除**:避免因重复加载导致的系统错误

+ 11 - 0
assets/scripts/AudioManager/AudioCacheOptimization.md.meta

@@ -0,0 +1,11 @@
+{
+  "ver": "1.0.1",
+  "importer": "text",
+  "imported": true,
+  "uuid": "22b078c6-f876-441b-a615-a4ea7ee5dc3f",
+  "files": [
+    ".json"
+  ],
+  "subMetas": {},
+  "userData": {}
+}

+ 61 - 4
assets/scripts/AudioManager/AudioManager.ts

@@ -40,10 +40,13 @@ export class AudioManager extends Component {
     // Bundle加载器
     private bundleLoader: BundleLoader = null;
     
+    // 音频缓存
+    private audioClipCache: Map<string, AudioClip> = new Map();
+    
     // 单例实例
     private static _instance: AudioManager = null;
     
-    onLoad() {
+    start() {
         // 设置单例
         if (AudioManager._instance === null) {
             AudioManager._instance = this;
@@ -232,9 +235,21 @@ export class AudioManager extends Component {
             // 去掉.mp3后缀(如果存在)
             const cleanPath = sfxPath.endsWith('.mp3') ? sfxPath.slice(0, -4) : sfxPath;
             
-            // 转换路径格式:从 "data/弹球音效/xxx" 转换为 "弹球音效/xxx"
-            const bundlePath = cleanPath.replace('data/', '');
-            const clip = await this.bundleLoader.loadAssetFromBundle<AudioClip>('data', bundlePath, AudioClip);
+            // 检查缓存中是否已有该音频
+            let clip = this.audioClipCache.get(cleanPath);
+            
+            if (!clip) {
+                // 转换路径格式:从 "data/弹球音效/xxx" 转换为 "弹球音效/xxx"
+                const bundlePath = cleanPath.replace('data/', '');
+                console.log(`[AudioManager] 从Bundle加载新音效: ${bundlePath}`);
+                clip = await this.bundleLoader.loadAssetFromBundle<AudioClip>('data', bundlePath, AudioClip);
+                
+                // 缓存音频资源
+                this.audioClipCache.set(cleanPath, clip);
+                console.log(`[AudioManager] 音效已缓存: ${cleanPath}`);
+            } else {
+                console.log(`[AudioManager] 使用缓存音效: ${cleanPath}`);
+            }
             
             // 设置临时音量(如果指定)
             const originalVolume = audioSource.volume;
@@ -461,7 +476,28 @@ export class AudioManager extends Component {
         return this.musicAudioSource && this.musicAudioSource.playing;
     }
     
+    /**
+     * 清理音频缓存
+     */
+    public clearAudioCache() {
+        console.log(`[AudioManager] 清理音频缓存,共${this.audioClipCache.size}个音效`);
+        this.audioClipCache.clear();
+    }
+    
+    /**
+     * 获取缓存状态
+     */
+    public getCacheInfo(): {count: number, paths: string[]} {
+        return {
+            count: this.audioClipCache.size,
+            paths: Array.from(this.audioClipCache.keys())
+        };
+    }
+
     onDestroy() {
+        // 清理音频缓存
+        this.clearAudioCache();
+        
         if (AudioManager._instance === this) {
             AudioManager._instance = null;
         }
@@ -672,4 +708,25 @@ export class Audio {
             manager.unmuteAllSounds();
         }
     }
+    
+    /**
+     * 清理音频缓存
+     */
+    static clearAudioCache() {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.clearAudioCache();
+        }
+    }
+    
+    /**
+     * 获取缓存信息
+     */
+    static getCacheInfo(): {count: number, paths: string[]} {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            return manager.getCacheInfo();
+        }
+        return {count: 0, paths: []};
+    }
 }

+ 124 - 1
assets/scripts/CombatSystem/BallController.ts

@@ -76,6 +76,9 @@ export class BallController extends Component {
     // 小球暂停时记录的速度
     private pausedVelocity: Vec2 = new Vec2();
 
+    // 所有小球暂停时记录的速度(包括主球和额外球)
+    private allBallsPausedVelocities: Map<Node, Vec2> = new Map();
+
     // 标记是否处于暂停状态
     private isPaused: boolean = false;
 
@@ -301,9 +304,13 @@ export class BallController extends Component {
         
         // 监听暂停事件
         eventBus.on(GameEvents.GAME_PAUSE, this.onGamePauseEvent, this);
+        eventBus.on(GameEvents.GAME_PAUSE_SKILL_SELECTION, this.onGamePauseSkillSelectionEvent, this);
+        eventBus.on(GameEvents.GAME_PAUSE_BLOCK_SELECTION, this.onGamePauseBlockSelectionEvent, this);
         
         // 监听恢复事件
         eventBus.on(GameEvents.GAME_RESUME, this.onGameResumeEvent, this);
+        eventBus.on(GameEvents.GAME_RESUME_SKILL_SELECTION, this.onGameResumeSkillSelectionEvent, this);
+        eventBus.on(GameEvents.GAME_RESUME_BLOCK_SELECTION, this.onGameResumeBlockSelectionEvent, this);
         
         // 监听重置球控制器事件
         eventBus.on(GameEvents.RESET_BALL_CONTROLLER, this.onResetBallControllerEvent, this);
@@ -335,12 +342,45 @@ export class BallController extends Component {
         this.pauseBall();
     }
 
+    /**
+     * 处理技能选择暂停事件(所有小球完全停止)
+     */
+    private onGamePauseSkillSelectionEvent() {
+        console.log('[BallController] 接收到技能选择暂停事件,暂停所有小球运动');
+        this.pauseAllBalls();
+    }
+
+    /**
+     * 处理底板选择暂停事件(所有小球继续运动)
+     */
+    private onGamePauseBlockSelectionEvent() {
+        console.log('[BallController] 接收到底板选择暂停事件,小球继续运动');
+        // 底板选择时不暂停小球运动,只是标记游戏状态为暂停
+        this.isPaused = true;
+    }
+
     /**
      * 处理游戏恢复事件
      */
     private onGameResumeEvent() {
         console.log('[BallController] 接收到游戏恢复事件,恢复小球运动');
-        this.resumeBall();
+        this.resumeAllBalls();
+    }
+    
+    /**
+     * 处理技能选择恢复事件
+     */
+    private onGameResumeSkillSelectionEvent() {
+        console.log('[BallController] 接收到技能选择恢复事件,恢复小球运动');
+        this.resumeAllBalls();
+    }
+    
+    /**
+     * 处理底板选择恢复事件
+     */
+    private onGameResumeBlockSelectionEvent() {
+        console.log('[BallController] 接收到底板选择恢复事件,恢复小球运动');
+        this.resumeAllBalls();
     }
     
     /**
@@ -1898,6 +1938,86 @@ export class BallController extends Component {
             }
         }
     }
+
+    /**
+     * 暂停所有小球运动:记录当前速度并停止所有刚体
+     */
+    public pauseAllBalls() {
+        if (this.isPaused) return;
+        this.isPaused = true;
+        this.ballStarted = false;
+
+        // 清空之前的暂停速度记录
+        this.allBallsPausedVelocities.clear();
+
+        // 暂停主球
+        if (this.activeBall && this.activeBall.isValid) {
+            const rb = this.activeBall.getComponent(RigidBody2D);
+            if (rb) {
+                this.allBallsPausedVelocities.set(this.activeBall, rb.linearVelocity.clone());
+                rb.linearVelocity = new Vec2(0, 0);
+                rb.sleep();
+            }
+        }
+
+        // 暂停所有额外球
+        const gameArea = find('Canvas/GameLevelUI/GameArea');
+        if (gameArea) {
+            const additionalBalls = gameArea.children.filter(child => 
+                child.name === 'AdditionalBall' && child.isValid
+            );
+            
+            for (const ball of additionalBalls) {
+                const rb = ball.getComponent(RigidBody2D);
+                if (rb) {
+                    this.allBallsPausedVelocities.set(ball, rb.linearVelocity.clone());
+                    rb.linearVelocity = new Vec2(0, 0);
+                    rb.sleep();
+                }
+            }
+        }
+
+        console.log(`[BallController] 已暂停 ${this.allBallsPausedVelocities.size} 个小球`);
+    }
+
+    /**
+     * 恢复所有小球运动:恢复暂停前的速度
+     */
+    public resumeAllBalls() {
+        if (!this.isPaused) return;
+        this.isPaused = false;
+        this.ballStarted = true;
+        
+        console.log(`[BallController] 恢复 ${this.allBallsPausedVelocities.size} 个小球运动`);
+        
+        // 恢复所有记录的小球
+        for (const [ball, velocity] of this.allBallsPausedVelocities) {
+            if (ball && ball.isValid) {
+                const rb = ball.getComponent(RigidBody2D);
+                if (rb) {
+                    rb.wakeUp();
+                    const hasVelocity = velocity && (velocity.x !== 0 || velocity.y !== 0);
+                    if (hasVelocity) {
+                        rb.linearVelocity = velocity.clone();
+                    } else {
+                        // 如果没有记录速度,给一个默认方向
+                        if (ball === this.activeBall) {
+                            this.initializeDirection();
+                        } else {
+                            // 额外球给一个随机方向
+                            const angle = Math.random() * Math.PI * 2;
+                            const speed = this.currentSpeed;
+                            rb.linearVelocity = new Vec2(Math.cos(angle) * speed, Math.sin(angle) * speed);
+                        }
+                    }
+                }
+            }
+        }
+        
+        // 清空暂停速度记录
+        this.allBallsPausedVelocities.clear();
+    }
+
     /**
      * 从给定世界坐标发射子弹
      */
@@ -1936,6 +2056,7 @@ export class BallController extends Component {
         
         // 清理暂停状态
         this.pausedVelocity = new Vec2();
+        this.allBallsPausedVelocities.clear();
         
         // 销毁当前活动的球
         if (this.activeBall && this.activeBall.isValid) {
@@ -2026,6 +2147,8 @@ export class BallController extends Component {
         // 清理事件监听
         const eventBus = EventBus.getInstance();
         eventBus.off(GameEvents.GAME_PAUSE, this.onGamePauseEvent, this);
+        eventBus.off(GameEvents.GAME_PAUSE_SKILL_SELECTION, this.onGamePauseSkillSelectionEvent, this);
+        eventBus.off(GameEvents.GAME_PAUSE_BLOCK_SELECTION, this.onGamePauseBlockSelectionEvent, this);
         eventBus.off(GameEvents.GAME_RESUME, this.onGameResumeEvent, this);
         eventBus.off(GameEvents.RESET_BALL_CONTROLLER, this.onResetBallControllerEvent, this);
         eventBus.off(GameEvents.BALL_CREATE, this.onBallCreateEvent, this);

+ 34 - 0
assets/scripts/CombatSystem/BlockManager.ts

@@ -800,6 +800,23 @@ export class BlockManager extends Component {
     
     // 隐藏整个db标签节点(包括价格标签)
     hideDbLabel(originalBlock: Node) {
+        // 检查方块是否已经放置成功(不在原始容器中),如果是则不需要隐藏价格标签
+        const blockLocation = this.blockLocations.get(originalBlock);
+        if (blockLocation === 'grid' || originalBlock['placedBefore']) {
+            // 已放置成功的方块(包括合成后的方块)不需要隐藏价格标签
+            console.log(`[BlockManager] 方块 ${originalBlock.name} 已放置成功,跳过隐藏价格标签操作`);
+            return;
+        }
+        
+        // 只有在kuang区域的方块才需要隐藏价格标签
+        if (!originalBlock.parent || 
+            (originalBlock.parent !== this.block1Container && 
+             originalBlock.parent !== this.block2Container && 
+             originalBlock.parent !== this.block3Container)) {
+            console.log(`[BlockManager] 方块 ${originalBlock.name} 不在原始容器中,跳过隐藏价格标签操作`);
+            return;
+        }
+        
         // 隐藏价格标签
         this.hidePriceLabel(originalBlock);
         console.log(`[BlockManager] 隐藏价格标签: ${originalBlock.name}`);
@@ -825,6 +842,23 @@ export class BlockManager extends Component {
     
     // 显示整个db标签节点(包括价格标签)
     showDbLabel(originalBlock: Node) {
+        // 检查方块是否已经放置成功(不在原始容器中),如果是则不需要显示价格标签
+        const blockLocation = this.blockLocations.get(originalBlock);
+        if (blockLocation === 'grid' || originalBlock['placedBefore']) {
+            // 已放置成功的方块(包括合成后的方块)不需要显示价格标签
+            console.log(`[BlockManager] 方块 ${originalBlock.name} 已放置成功,跳过显示价格标签操作`);
+            return;
+        }
+        
+        // 只有在kuang区域的方块才需要显示价格标签
+        if (!originalBlock.parent || 
+            (originalBlock.parent !== this.block1Container && 
+             originalBlock.parent !== this.block2Container && 
+             originalBlock.parent !== this.block3Container)) {
+            console.log(`[BlockManager] 方块 ${originalBlock.name} 不在原始容器中,跳过显示价格标签操作`);
+            return;
+        }
+        
         // 根据原始方块找到对应的db节点
         let dbNode: Node = null;
         if (originalBlock.parent === this.block1Container) {

+ 198 - 11
assets/scripts/CombatSystem/BlockSelection/GameBlockSelection.ts

@@ -7,6 +7,7 @@ import { BlockTag } from './BlockTag';
 import { WeaponInfo } from './WeaponInfo';
 import { SkillManager } from '../SkillSelection/SkillManager';
 import { Audio } from '../../AudioManager/AudioManager';
+import { AdManager } from '../../Ads/AdManager';
 
 import EventBus, { GameEvents } from '../../Core/EventBus';
 const { ccclass, property } = _decorator;
@@ -81,10 +82,64 @@ export class GameBlockSelection extends Component {
     })
     public weaponsConfig: JsonAsset = null;
 
+    // 小球价格配置JsonAsset - 通过装饰器预加载
+    @property({
+        type: JsonAsset,
+        tooltip: '拖拽ball_price_config.json文件到这里,实现价格配置预加载'
+    })
+    public ballPriceConfig: JsonAsset = null;
+
     // 常量定义
-    private readonly ADD_BALL_COST = 80;
     private readonly ADD_COIN_AMOUNT = 80;
-    private readonly REFRESH_COST = 5;
+    
+    // 价格配置默认值
+    private readonly DEFAULT_ADD_BALL_BASE_PRICE = 80;
+    private readonly DEFAULT_ADD_BALL_INCREMENT = 10;
+    private readonly DEFAULT_ADD_BALL_MAX_PRICE = 500;
+    private readonly DEFAULT_REFRESH_BASE_PRICE = 5;
+    private readonly DEFAULT_REFRESH_INCREMENT = 2;
+    private readonly DEFAULT_REFRESH_MAX_PRICE = 50;
+    
+    // 价格获取方法
+    private getAddBallCost(): number {
+        if (this.ballPriceConfig && this.ballPriceConfig.json && this.ballPriceConfig.json.priceHistory) {
+            return this.ballPriceConfig.json.priceHistory.addBallCurrentPrice || this.DEFAULT_ADD_BALL_BASE_PRICE;
+        }
+        
+        try {
+            const priceNode = find('Canvas/GameLevelUI/BlockSelectionUI/diban/ann001/Ball/db01/Price');
+            if (priceNode) {
+                const label = priceNode.getComponent(Label);
+                if (label) {
+                    const price = parseInt(label.string);
+                    return isNaN(price) ? this.DEFAULT_ADD_BALL_BASE_PRICE : price;
+                }
+            }
+        } catch (error) {
+            console.warn('[GameBlockSelection] 获取新增小球价格失败:', error);
+        }
+        return this.DEFAULT_ADD_BALL_BASE_PRICE; // 默认价格
+    }
+    
+    private getRefreshCost(): number {
+        if (this.ballPriceConfig && this.ballPriceConfig.json && this.ballPriceConfig.json.priceHistory) {
+            return this.ballPriceConfig.json.priceHistory.refreshBlockCurrentPrice || this.DEFAULT_REFRESH_BASE_PRICE;
+        }
+        
+        try {
+            const priceNode = find('Canvas/GameLevelUI/BlockSelectionUI/diban/ann003/Ball/db01/Price');
+            if (priceNode) {
+                const label = priceNode.getComponent(Label);
+                if (label) {
+                    const price = parseInt(label.string);
+                    return isNaN(price) ? this.DEFAULT_REFRESH_BASE_PRICE : price;
+                }
+            }
+        } catch (error) {
+            console.warn('[GameBlockSelection] 获取刷新方块价格失败:', error);
+        }
+        return this.DEFAULT_REFRESH_BASE_PRICE; // 默认价格
+    }
 
     private session: LevelSessionManager = null;
     private ballController: BallController = null;
@@ -134,6 +189,7 @@ export class GameBlockSelection extends Component {
     private initializeComponent() {        
         // 获取管理器实例
         this.session = LevelSessionManager.inst;
+        
         // 获取BallController
         if (this.ballControllerNode) {
             this.ballController = this.ballControllerNode.getComponent(BallController);
@@ -176,6 +232,9 @@ export class GameBlockSelection extends Component {
         // 设置事件监听器
         this.setupEventListeners();
         
+        // 更新价格显示
+        this.updatePriceDisplay();
+        
         // 标记为已初始化
         this.isInitialized = true;
         
@@ -276,8 +335,9 @@ export class GameBlockSelection extends Component {
     private onAddBallClicked() {
         // 播放UI点击音效
         Audio.playUISound('data/弹球音效/ui play');
-        // 应用便宜技能效果计算实际费用
-        const actualCost = this.getActualCost(this.ADD_BALL_COST);
+        // 从UI节点获取价格并应用便宜技能效果计算实际费用
+        const baseCost = this.getAddBallCost();
+        const actualCost = this.getActualCost(baseCost);
         
         if (!this.canSpendCoins(actualCost)) {
             this.showInsufficientCoinsUI();
@@ -288,6 +348,9 @@ export class GameBlockSelection extends Component {
         if (this.session.spendCoins(actualCost)) {
             this.updateCoinDisplay();
             
+            // 更新价格配置(增加购买次数和价格)
+            this.updateAddBallPrice();
+            
             // 通过事件系统创建新的小球
             const eventBus = EventBus.getInstance();
             eventBus.emit(GameEvents.BALL_CREATE_ADDITIONAL);
@@ -299,19 +362,30 @@ export class GameBlockSelection extends Component {
     private onAddCoinClicked() {
         // 播放UI点击音效
         Audio.playUISound('data/弹球音效/ui play');
-        // 免费增加金币(模拟看广告获得奖励)
-        const coinsToAdd = 80; // 免费获得的金币数量
-        this.session.addCoins(coinsToAdd);        
-        // 更新显示
-        this.updateCoinDisplay();
+        
+        // 显示激励视频广告
+        AdManager.getInstance().showRewardedVideoAd(
+            () => {
+                // 广告观看完成,增加金币
+                const coinsToAdd = 80; // 广告奖励的金币数量
+                this.session.addCoins(coinsToAdd);        
+                // 更新显示
+                this.updateCoinDisplay();
+            },
+            (error) => {
+                console.error('[GameBlockSelection] 广告显示失败:', error);
+                // 广告失败时不给予奖励
+            }
+        );
     }
 
     // 刷新方块按钮点击
     private onRefreshClicked() {
         // 播放UI点击音效
         Audio.playUISound('data/弹球音效/ui play');
-        // 应用便宜技能效果计算实际费用
-        const actualCost = this.getActualCost(this.REFRESH_COST);
+        // 从UI节点获取价格并应用便宜技能效果计算实际费用
+        const baseCost = this.getRefreshCost();
+        const actualCost = this.getActualCost(baseCost);
         
         if (!this.canSpendCoins(actualCost)) {
             this.showInsufficientCoinsUI();
@@ -323,6 +397,9 @@ export class GameBlockSelection extends Component {
             // 成功扣除金币
             this.updateCoinDisplay();
             
+            // 更新价格配置(增加购买次数和价格)
+            this.updateRefreshPrice();
+            
             // 刷新方块
             if (this.blockManager) {
                 console.log('[GameBlockSelection] 开始刷新方块流程');
@@ -1178,4 +1255,114 @@ export class GameBlockSelection extends Component {
         }
         return false;
     }
+    
+    // === 价格配置管理方法 ===
+    
+    // 获取价格配置数据(如果装饰器配置不存在则返回默认值)
+    private getPriceConfigData(): any {
+        if (this.ballPriceConfig && this.ballPriceConfig.json) {
+            return this.ballPriceConfig.json;
+        }
+        
+        // 返回默认配置
+        return {
+            addBallPricing: {
+                initialPrice: this.DEFAULT_ADD_BALL_BASE_PRICE,
+                priceIncrement: this.DEFAULT_ADD_BALL_INCREMENT,
+                maxPrice: this.DEFAULT_ADD_BALL_MAX_PRICE
+            },
+            refreshBlockPricing: {
+                initialPrice: this.DEFAULT_REFRESH_BASE_PRICE,
+                priceIncrement: this.DEFAULT_REFRESH_INCREMENT,
+                maxPrice: this.DEFAULT_REFRESH_MAX_PRICE
+            },
+            priceHistory: {
+                addBallCurrentPrice: this.DEFAULT_ADD_BALL_BASE_PRICE,
+                refreshBlockCurrentPrice: this.DEFAULT_REFRESH_BASE_PRICE,
+                addBallPurchaseCount: 0,
+                refreshBlockPurchaseCount: 0
+            }
+        };
+    }
+    
+    // 更新新增小球价格
+    private updateAddBallPrice() {
+        const configData = this.getPriceConfigData();
+        const config = configData.addBallPricing;
+        const history = configData.priceHistory;
+        
+        // 增加购买次数
+        history.addBallPurchaseCount++;
+        
+        // 计算新价格
+        const newPrice = Math.min(
+            config.initialPrice + (history.addBallPurchaseCount * config.priceIncrement),
+            config.maxPrice
+        );
+        
+        history.addBallCurrentPrice = newPrice;
+        
+        // 更新UI显示
+        this.updatePriceDisplay();
+        
+        // 保存配置(注意:装饰器配置是只读的,这里只是打印日志)
+        this.saveBallPriceConfig();
+        
+        console.log(`[GameBlockSelection] 新增小球价格更新: ${newPrice}, 购买次数: ${history.addBallPurchaseCount}`);
+    }
+    
+    // 更新刷新方块价格
+    private updateRefreshPrice() {
+        const configData = this.getPriceConfigData();
+        const config = configData.refreshBlockPricing;
+        const history = configData.priceHistory;
+        
+        // 增加购买次数
+        history.refreshBlockPurchaseCount++;
+        
+        // 计算新价格
+        const newPrice = Math.min(
+            config.initialPrice + (history.refreshBlockPurchaseCount * config.priceIncrement),
+            config.maxPrice
+        );
+        
+        history.refreshBlockCurrentPrice = newPrice;
+        
+        // 更新UI显示
+        this.updatePriceDisplay();
+        
+        // 保存配置(注意:装饰器配置是只读的,这里只是打印日志)
+        this.saveBallPriceConfig();
+        
+        console.log(`[GameBlockSelection] 刷新方块价格更新: ${newPrice}, 购买次数: ${history.refreshBlockPurchaseCount}`);
+    }
+    
+    // 更新价格显示
+    private updatePriceDisplay() {
+        // 更新新增小球价格显示
+        const addBallPriceNode = find('Canvas/GameLevelUI/BlockSelectionUI/diban/ann001/Ball/db01/Price');
+        if (addBallPriceNode) {
+            const label = addBallPriceNode.getComponent(Label);
+            if (label) {
+                label.string = this.getAddBallCost().toString();
+            }
+        }
+        
+        // 更新刷新方块价格显示
+        const refreshPriceNode = find('Canvas/GameLevelUI/BlockSelectionUI/diban/ann003/Ball/db01/Price');
+        if (refreshPriceNode) {
+            const label = refreshPriceNode.getComponent(Label);
+            if (label) {
+                label.string = this.getRefreshCost().toString();
+            }
+        }
+    }
+    
+    // 保存价格配置(装饰器配置是只读的,这里只是打印日志用于调试)
+    private saveBallPriceConfig() {
+        const configData = this.getPriceConfigData();
+        // 装饰器预加载的配置是只读的,无法直接修改
+        // 在实际项目中,价格变化应该保存到本地存储或服务器
+        console.log('[GameBlockSelection] 价格配置已更新:', JSON.stringify(configData, null, 2));
+    }
 }

+ 27 - 1
assets/scripts/CombatSystem/EnemyController.ts

@@ -199,9 +199,13 @@ export class EnemyController extends BaseSingleton {
         
         // 监听暂停事件
         eventBus.on(GameEvents.GAME_PAUSE, this.onGamePauseEvent, this);
+        eventBus.on(GameEvents.GAME_PAUSE_SKILL_SELECTION, this.onGamePauseEvent, this);
+        eventBus.on(GameEvents.GAME_PAUSE_BLOCK_SELECTION, this.onGamePauseEvent, this);
         
-        // 监听恢复事件
+        // 监听游戏恢复事件
         eventBus.on(GameEvents.GAME_RESUME, this.onGameResumeEvent, this);
+        eventBus.on(GameEvents.GAME_RESUME_SKILL_SELECTION, this.onGameResumeSkillSelectionEvent, this);
+        eventBus.on(GameEvents.GAME_RESUME_BLOCK_SELECTION, this.onGameResumeBlockSelectionEvent, this);
         
         // 监听游戏成功/失败事件
         eventBus.on(GameEvents.GAME_SUCCESS, this.onGameEndEvent, this);
@@ -276,6 +280,24 @@ export class EnemyController extends BaseSingleton {
         // 通过事件检查游戏状态,决定是否恢复敌人生成
         this.resumeSpawning();
     }
+    
+    /**
+     * 处理技能选择恢复事件
+     */
+    private onGameResumeSkillSelectionEvent() {
+        console.log('[EnemyController] 接收到技能选择恢复事件,恢复所有敌人');
+        this.resumeAllEnemies();
+        this.resumeSpawning();
+    }
+    
+    /**
+     * 处理底板选择恢复事件
+     */
+    private onGameResumeBlockSelectionEvent() {
+        console.log('[EnemyController] 接收到底板选择恢复事件,恢复所有敌人');
+        this.resumeAllEnemies();
+        this.resumeSpawning();
+    }
 
     /**
      * 处理游戏结束事件
@@ -1329,7 +1351,11 @@ export class EnemyController extends BaseSingleton {
         // 清理事件监听
         const eventBus = EventBus.getInstance();
         eventBus.off(GameEvents.GAME_PAUSE, this.onGamePauseEvent, this);
+        eventBus.off(GameEvents.GAME_PAUSE_SKILL_SELECTION, this.onGamePauseEvent, this);
+        eventBus.off(GameEvents.GAME_PAUSE_BLOCK_SELECTION, this.onGamePauseEvent, this);
         eventBus.off(GameEvents.GAME_RESUME, this.onGameResumeEvent, this);
+        eventBus.off(GameEvents.GAME_RESUME_SKILL_SELECTION, this.onGameResumeSkillSelectionEvent, this);
+        eventBus.off(GameEvents.GAME_RESUME_BLOCK_SELECTION, this.onGameResumeBlockSelectionEvent, this);
         eventBus.off(GameEvents.GAME_SUCCESS, this.onGameEndEvent, this);
         eventBus.off(GameEvents.GAME_DEFEAT, this.onGameEndEvent, this);
         eventBus.off(GameEvents.CLEAR_ALL_GAME_OBJECTS, this.onClearAllGameObjectsEvent, this);

+ 12 - 3
assets/scripts/CombatSystem/GameEnd.ts

@@ -3,6 +3,7 @@ import { SaveDataManager } from '../LevelSystem/SaveDataManager';
 import { InGameManager, GameState } from '../LevelSystem/IN_game';
 import EventBus, { GameEvents } from '../Core/EventBus';
 import { Audio } from '../AudioManager/AudioManager';
+import { AdManager } from '../Ads/AdManager';
 const { ccclass, property } = _decorator;
 
 /**
@@ -593,9 +594,17 @@ export class GameEnd extends Component {
         
         console.log('[GameEnd] 点击双倍奖励按钮');
         
-        // 这里可以添加观看广告的逻辑
-        // 暂时直接给予双倍奖励
-        this.giveDoubleReward();
+        // 显示激励视频广告
+        AdManager.getInstance().showRewardedVideoAd(
+            () => {
+                // 广告观看完成,给予双倍奖励
+                this.giveDoubleReward();
+            },
+            (error) => {
+                console.error('[GameEnd] 广告显示失败:', error);
+                // 广告失败时不给予奖励
+            }
+        );
     }
     
     /**

+ 9 - 0
assets/scripts/CombatSystem/GamePause.ts

@@ -43,9 +43,13 @@ export class GamePause extends Component {
         
         // 监听游戏暂停事件
         eventBus.on(GameEvents.GAME_PAUSE, this.onGamePauseEvent, this);
+        eventBus.on(GameEvents.GAME_PAUSE_SKILL_SELECTION, this.onGamePauseEvent, this);
+        eventBus.on(GameEvents.GAME_PAUSE_BLOCK_SELECTION, this.onGamePauseEvent, this);
         
         // 监听游戏恢复事件
         eventBus.on(GameEvents.GAME_RESUME, this.onGameResumeEvent, this);
+        eventBus.on(GameEvents.GAME_RESUME_SKILL_SELECTION, this.onGameResumeEvent, this);
+        eventBus.on(GameEvents.GAME_RESUME_BLOCK_SELECTION, this.onGameResumeEvent, this);
         
         // 监听子弹发射检查事件
         eventBus.on(GameEvents.BALL_FIRE_BULLET, this.onBallFireBulletEvent, this);
@@ -302,6 +306,11 @@ 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_PAUSE, this.onGamePauseEvent, this);
+        eventBus.off(GameEvents.GAME_PAUSE_SKILL_SELECTION, this.onGamePauseEvent, this);
+        eventBus.off(GameEvents.GAME_PAUSE_BLOCK_SELECTION, this.onGamePauseEvent, this);
+        eventBus.off(GameEvents.GAME_RESUME, this.onGameResumeEvent, this);
+        eventBus.off(GameEvents.GAME_RESUME_SKILL_SELECTION, this.onGameResumeEvent, this);
+        eventBus.off(GameEvents.GAME_RESUME_BLOCK_SELECTION, this.onGameResumeEvent, this);
         eventBus.off(GameEvents.BALL_FIRE_BULLET, this.onBallFireBulletEvent, this);
         eventBus.off(GameEvents.GAME_CHECK_OVER, this.onGameCheckOverEvent, this);
         eventBus.off('GAME_END', this.onGameEndEvent, this);

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

@@ -7,7 +7,11 @@ export enum GameEvents {
     // 游戏状态事件
     GAME_START = 'GAME_START',
     GAME_PAUSE = 'GAME_PAUSE',
+    GAME_PAUSE_SKILL_SELECTION = 'GAME_PAUSE_SKILL_SELECTION',  // 技能选择时暂停(小球完全停止)
+    GAME_PAUSE_BLOCK_SELECTION = 'GAME_PAUSE_BLOCK_SELECTION',  // 底板选择时暂停(小球继续运动)
     GAME_RESUME = 'GAME_RESUME',
+    GAME_RESUME_SKILL_SELECTION = 'GAME_RESUME_SKILL_SELECTION',  // 技能选择结束后恢复
+    GAME_RESUME_BLOCK_SELECTION = 'GAME_RESUME_BLOCK_SELECTION',  // 底板选择结束后恢复
     GAME_SUCCESS = 'GAME_SUCCESS',
     GAME_DEFEAT = 'GAME_DEFEAT',
     

+ 55 - 0
assets/scripts/Debug/BallPauseTest.ts

@@ -0,0 +1,55 @@
+import { _decorator, Component, Node, KeyCode, input, Input, EventKeyboard } from 'cc';
+import EventBus, { GameEvents } from '../Core/EventBus';
+
+const { ccclass, property } = _decorator;
+
+/**
+ * 小球暂停模式测试脚本
+ * 用于测试技能选择暂停和底板选择暂停的不同表现
+ */
+@ccclass('BallPauseTest')
+export class BallPauseTest extends Component {
+
+    start() {
+        // 监听键盘事件
+        input.on(Input.EventType.KEY_DOWN, this.onKeyDown, this);
+        
+        console.log('[BallPauseTest] 测试脚本已启动');
+        console.log('[BallPauseTest] 按键说明:');
+        console.log('[BallPauseTest] 1 - 触发技能选择暂停(所有小球停止)');
+        console.log('[BallPauseTest] 2 - 触发底板选择暂停(所有小球继续运动)');
+        console.log('[BallPauseTest] 3 - 恢复游戏');
+        console.log('[BallPauseTest] 4 - 创建额外小球(用于测试多球暂停)');
+    }
+
+    private onKeyDown(event: EventKeyboard) {
+        const eventBus = EventBus.getInstance();
+        
+        switch (event.keyCode) {
+            case KeyCode.DIGIT_1:
+                console.log('[BallPauseTest] 触发技能选择暂停 - 所有小球应该停止运动');
+                eventBus.emit(GameEvents.GAME_PAUSE_SKILL_SELECTION);
+                break;
+                
+            case KeyCode.DIGIT_2:
+                console.log('[BallPauseTest] 触发底板选择暂停 - 所有小球应该继续运动');
+                eventBus.emit(GameEvents.GAME_PAUSE_BLOCK_SELECTION);
+                break;
+                
+            case KeyCode.DIGIT_3:
+                console.log('[BallPauseTest] 恢复游戏 - 恢复所有小球运动');
+                eventBus.emit(GameEvents.GAME_RESUME);
+                break;
+                
+            case KeyCode.DIGIT_4:
+                console.log('[BallPauseTest] 创建额外小球');
+                eventBus.emit(GameEvents.BALL_CREATE_ADDITIONAL);
+                break;
+        }
+    }
+
+    onDestroy() {
+        // 清理键盘事件监听
+        input.off(Input.EventType.KEY_DOWN, this.onKeyDown, this);
+    }
+}

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

@@ -0,0 +1,9 @@
+{
+  "ver": "4.0.24",
+  "importer": "typescript",
+  "imported": true,
+  "uuid": "4487efad-8880-47ff-8f88-59fce8c6f8f9",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

+ 24 - 12
assets/scripts/FourUI/MainSystem/MainUIControlller.ts

@@ -8,6 +8,7 @@ import { TopBarController } from '../TopBarController';
 import { MoneyAni } from '../../Animations/MoneyAni';
 import EventBus, { GameEvents } from '../../Core/EventBus';
 import { Audio } from '../../AudioManager/AudioManager';
+import { BundleLoader } from '../../Core/BundleLoader';
 const { ccclass, property } = _decorator;
 
 @ccclass('MainUIController')
@@ -46,7 +47,7 @@ export class MainUIController extends Component {
   private sdm: SaveDataManager = null;
   private wallConfig: any = null;
 
-  onLoad () {
+  async onLoad () {
     console.log('[MainUIController] onLoad 开始执行');
     
     this.sdm = SaveDataManager.getInstance();
@@ -60,8 +61,8 @@ export class MainUIController extends Component {
     // TopArea 默认隐藏,在点击战斗后再显示
     if (this.topArea) this.topArea.active = false;
     
-    // 播放主界面背景音乐
-    this.playMainUIBGM();
+    // 播放主界面背景音乐(等待bundle加载完成)
+    await this.playMainUIBGM();
     
     console.log('[MainUIController] onLoad 执行完成');
   }
@@ -477,17 +478,28 @@ export class MainUIController extends Component {
   /**
    * 播放主界面背景音乐
    */
-  private playMainUIBGM(): void {
+  private async playMainUIBGM(): Promise<void> {
     console.log('[MainUIController] 开始播放主界面背景音乐');
     
-    // 先停止当前音乐(包括战斗背景音乐)
-    Audio.stopMusic();
-    // 恢复正常音乐音量
-    Audio.setMusicVolume(0.8);
-    // 播放主界面BGM,循环播放
-    Audio.playMusic('data/弹球音效/ui bgm', true);
-    
-    console.log('[MainUIController] 主界面背景音乐播放完成');
+    try {
+      // 获取BundleLoader实例
+      const bundleLoader = BundleLoader.getInstance();
+      
+      // 确保data bundle已加载完成
+      await bundleLoader.loadBundle('data');
+      console.log('[MainUIController] data bundle加载完成,开始播放音乐');
+      
+      // 先停止当前音乐(包括战斗背景音乐)
+      Audio.stopMusic();
+      // 恢复正常音乐音量
+      Audio.setMusicVolume(0.8);
+      // 播放主界面BGM,循环播放
+      Audio.playMusic('data/弹球音效/ui bgm', true);
+      
+      console.log('[MainUIController] 主界面背景音乐播放完成');
+    } catch (error) {
+      console.error('[MainUIController] 播放主界面背景音乐失败:', error);
+    }
   }
 
   /* =============== Util =============== */

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

@@ -3,6 +3,7 @@ import { SaveDataManager } from '../../LevelSystem/SaveDataManager';
 import EventBus, { GameEvents } from '../../Core/EventBus';
 import { TopBarController } from '../TopBarController';
 import { MoneyAni } from '../../Animations/MoneyAni';
+import { AdManager } from '../../Ads/AdManager';
 
 const { ccclass, property } = _decorator;
 
@@ -428,19 +429,35 @@ export class ShopController extends Component {
     private showAdForMoneyReward() {
         console.log('[ShopController] 显示钞票奖励广告');
         
-        // 这里应该调用广告SDK显示广告
-        // 立即发放奖励,无延迟
-        console.log('[ShopController] 广告观看完成,发放钞票奖励');
-        this.claimMoneyReward(true);
+        // 显示激励视频广告
+        AdManager.getInstance().showRewardedVideoAd(
+            () => {
+                // 广告观看完成,发放钞票奖励
+                console.log('[ShopController] 广告观看完成,发放钞票奖励');
+                this.claimMoneyReward(true);
+            },
+            (error) => {
+                console.error('[ShopController] 钞票奖励广告显示失败:', error);
+                // 广告失败时不给予奖励
+            }
+        );
     }
     
     private showAdForDiamondReward() {
         console.log('[ShopController] 显示钻石奖励广告');
         
-        // 这里应该调用广告SDK显示广告
-        // 立即发放奖励,无延迟
-        console.log('[ShopController] 广告观看完成,发放钻石奖励');
-        this.claimDiamondReward(true);
+        // 显示激励视频广告
+        AdManager.getInstance().showRewardedVideoAd(
+            () => {
+                // 广告观看完成,发放钻石奖励
+                console.log('[ShopController] 广告观看完成,发放钻石奖励');
+                this.claimDiamondReward(true);
+            },
+            (error) => {
+                console.error('[ShopController] 钻石奖励广告显示失败:', error);
+                // 广告失败时不给予奖励
+            }
+        );
     }
     
     // showRewardEffect方法已被MoneyAni.playReward替代,不再需要

+ 29 - 6
assets/scripts/FourUI/TopBarController.ts

@@ -3,6 +3,7 @@ import { _decorator, Component, Node, Button, Label, find } from 'cc';
 import { SaveDataManager } from '../LevelSystem/SaveDataManager';
 import EventBus, { GameEvents } from '../Core/EventBus';
 import { Audio } from '../AudioManager/AudioManager';
+import { AdManager } from '../Ads/AdManager';
 const { ccclass, property } = _decorator;
 
 @ccclass('TopBarController')
@@ -63,17 +64,39 @@ export class TopBarController extends Component {
   private addMoney(v: number) { 
     // 播放UI点击音效
     Audio.playUISound('data/弹球音效/ui play');
-    this.sdm.addMoney(v, 'ad'); 
-    // 触发货币变化事件
-    EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);
+    
+    // 显示激励视频广告
+    AdManager.getInstance().showRewardedVideoAd(
+      () => {
+        // 广告观看完成,给予奖励
+        this.sdm.addMoney(v, 'ad'); 
+        // 触发货币变化事件
+        EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);
+      },
+      (error) => {
+        console.error('[TopBarController] 广告显示失败:', error);
+        // 可以选择不给予奖励或给予部分奖励
+      }
+    );
   }
   
   private addDiamonds(v: number) { 
     // 播放UI点击音效
     Audio.playUISound('data/弹球音效/ui play');
-    this.sdm.addDiamonds(v, 'ad'); 
-    // 触发货币变化事件
-    EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);
+    
+    // 显示激励视频广告
+    AdManager.getInstance().showRewardedVideoAd(
+      () => {
+        // 广告观看完成,给予奖励
+        this.sdm.addDiamonds(v, 'ad'); 
+        // 触发货币变化事件
+        EventBus.getInstance().emit(GameEvents.CURRENCY_CHANGED);
+      },
+      (error) => {
+        console.error('[TopBarController] 广告显示失败:', error);
+        // 可以选择不给予奖励或给予部分奖励
+      }
+    );
   }
 
 

+ 10 - 0
assets/scripts/LevelSystem/GameManager.ts

@@ -4,6 +4,7 @@ import { LevelConfigManager } from './LevelConfigManager';
 import { SaveDataManager } from './SaveDataManager';
 import { ConfigManager } from '../Core/ConfigManager';
 import { PhysicsManager } from '../Core/PhysicsManager';
+import { AdManager } from '../Ads/AdManager';
 // EnemyController已通过事件系统解耦,不再需要直接导入
 import EventBus, { GameEvents } from '../Core/EventBus';
 import { LevelSessionManager } from '../Core/LevelSessionManager';
@@ -224,6 +225,8 @@ export class GameManager extends Component {
         
         // 监听游戏恢复事件
         eventBus.on(GameEvents.GAME_RESUME, this.onGameResumeEvent, this);
+        eventBus.on(GameEvents.GAME_RESUME_SKILL_SELECTION, this.onGameResumeEvent, this);
+        eventBus.on(GameEvents.GAME_RESUME_BLOCK_SELECTION, this.onGameResumeEvent, this);
         
         // 监听游戏重启事件
         eventBus.on(GameEvents.GAME_RESTART, this.onGameRestartEvent, this);
@@ -358,6 +361,10 @@ export class GameManager extends Component {
         PhysicsManager.getInstance();
         console.log('[GameManager] PhysicsManager初始化完成');
         
+        // 初始化广告管理器
+        AdManager.initialize();
+        console.log('[GameManager] AdManager初始化完成');
+        
         // 存档管理器初始化已迁移到StartGame
         this.saveDataManager = SaveDataManager.getInstance();
     }
@@ -823,6 +830,9 @@ export class GameManager extends Component {
         const eventBus = EventBus.getInstance();
         eventBus.off(GameEvents.GAME_SUCCESS, this.onGameSuccessEvent, this);
         eventBus.off(GameEvents.GAME_DEFEAT, this.onGameDefeatEvent, this);
+        eventBus.off(GameEvents.GAME_RESUME, this.onGameResumeEvent, this);
+        eventBus.off(GameEvents.GAME_RESUME_SKILL_SELECTION, this.onGameResumeEvent, this);
+        eventBus.off(GameEvents.GAME_RESUME_BLOCK_SELECTION, this.onGameResumeEvent, 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);

+ 12 - 9
assets/scripts/LevelSystem/IN_game.ts

@@ -220,6 +220,8 @@ export class InGameManager extends Component {
         eventBus.on(GameEvents.GAME_SUCCESS, this.onGameSuccessEvent, this);
         eventBus.on(GameEvents.GAME_DEFEAT, this.onGameDefeatEvent, this);
         eventBus.on(GameEvents.GAME_RESUME, this.onGameResumeEvent, this);
+        eventBus.on(GameEvents.GAME_RESUME_SKILL_SELECTION, this.onGameResumeEvent, this);
+        eventBus.on(GameEvents.GAME_RESUME_BLOCK_SELECTION, this.onGameResumeEvent, this);
         eventBus.on('ENEMY_KILLED', this.onEnemyKilledEvent, this);
         eventBus.on(GameEvents.RESET_ENERGY_SYSTEM, this.resetEnergySystem, this);
         eventBus.on(GameEvents.WALL_DESTROYED, this.onWallDestroyedEvent, this);
@@ -322,6 +324,9 @@ export class InGameManager extends Component {
         // 恢复游戏
         this.resumeGame();
         
+        // 发射技能选择结束恢复事件
+        EventBus.getInstance().emit(GameEvents.GAME_RESUME_SKILL_SELECTION);
+        
         // 如果有等待的diban动画,现在播放diban动画
         if (this.pendingBlockSelection) {
             console.log('[InGameManager] 技能选择完成,现在播放diban动画');
@@ -373,8 +378,8 @@ export class InGameManager extends Component {
             console.warn('[InGameManager] GameStartMove组件未找到,无法播放diban动画');
         }
         
-        // 通过事件系统暂停游戏
-        EventBus.getInstance().emit(GameEvents.GAME_PAUSE);
+        // 使用底板选择专用暂停事件,小球继续运动
+        EventBus.getInstance().emit(GameEvents.GAME_PAUSE_BLOCK_SELECTION);
     }
 
     /**
@@ -715,18 +720,14 @@ export class InGameManager extends Component {
     private showSkillSelection() {
         if (this.selectSkillUI) {
             this.selectSkillUI.active = true;
-            this.pauseGame();
+            // 使用技能选择专用暂停事件,所有小球停止运动
+            EventBus.getInstance().emit(GameEvents.GAME_PAUSE_SKILL_SELECTION);
             // 注意:不调用StartGame.resetEnergy(),因为那会重置整个能量系统包括最大值
             // 能量点数已在onEnergyFull()中重置为0
         }
     }
     
-    /**
-     * 暂停游戏
-     */
-    private pauseGame() {
-        EventBus.getInstance().emit(GameEvents.GAME_PAUSE);
-    }
+
     
     /**
      * 恢复游戏
@@ -1168,6 +1169,8 @@ export class InGameManager extends Component {
         eventBus.off(GameEvents.GAME_SUCCESS, this.onGameSuccessEvent, this);
         eventBus.off(GameEvents.GAME_DEFEAT, this.onGameDefeatEvent, this);
         eventBus.off(GameEvents.GAME_RESUME, this.onGameResumeEvent, this);
+        eventBus.off(GameEvents.GAME_RESUME_SKILL_SELECTION, this.onGameResumeEvent, this);
+        eventBus.off(GameEvents.GAME_RESUME_BLOCK_SELECTION, this.onGameResumeEvent, this);
         eventBus.off('ENEMY_KILLED', this.onEnemyKilledEvent, this);
         eventBus.off(GameEvents.RESET_ENERGY_SYSTEM, this.resetEnergySystem, this);
         eventBus.off(GameEvents.WALL_DESTROYED, this.onWallDestroyedEvent, this);

+ 1 - 1
assets/scripts/LevelSystem/SaveDataManager.ts

@@ -357,7 +357,7 @@ export class SaveDataManager {
             lastPlayTime: Date.now(),
             totalPlayTime: 0,
             money: 0,           // 初始局外金钱
-            diamonds: 20,
+            diamonds: 0,        // 初始钻石
             wallLevel: 1,        // 初始墙体等级
             currentLevel: 1,
             maxUnlockedLevel: 1,