Browse Source

敌人音效实现

181404010226 3 months ago
parent
commit
6cab0ef21f
100 changed files with 3463 additions and 684 deletions
  1. 1 1
      MenuUI音频控制系统实现说明.md
  2. 285 0
      UnifiedAudioSystemGuide.md
  3. 241 136
      assets/Scenes/GameLevel.scene
  4. 5 5
      assets/assets/Prefabs/Ball.prefab
  5. 1 1
      assets/resources/data/ballController.json
  6. 47 47
      assets/resources/data/enemies.json
  7. 1066 0
      assets/resources/data/enemies_backup_20250820_170519.json
  8. 11 0
      assets/resources/data/enemies_backup_20250820_170519.json.meta
  9. BIN
      assets/resources/data/excel/__pycache__/skill_config_manager.cpython-313.pyc
  10. BIN
      assets/resources/data/excel/__pycache__/weapon_config_manager.cpython-313.pyc
  11. BIN
      assets/resources/data/excel/~$BallController标准配置表.xlsx
  12. 0 12
      assets/resources/data/excel/~$BallController标准配置表.xlsx.meta
  13. BIN
      assets/resources/data/excel/~$局外技能配置表.xlsx
  14. 0 12
      assets/resources/data/excel/~$局外技能配置表.xlsx.meta
  15. BIN
      assets/resources/data/excel/~$技能配置表.xlsx
  16. 0 12
      assets/resources/data/excel/~$技能配置表.xlsx.meta
  17. BIN
      assets/resources/data/excel/~$敌人配置表.xlsx
  18. 1 1
      assets/resources/data/excel/~$敌人配置表.xlsx.meta
  19. BIN
      assets/resources/data/excel/关卡配置/~$关卡配置表.xlsx
  20. 0 12
      assets/resources/data/excel/关卡配置/~$关卡配置表.xlsx.meta
  21. BIN
      assets/resources/data/excel/敌人配置表.xlsx
  22. BIN
      assets/resources/data/excel/方块武器配置/~$方块武器配置表.xlsx
  23. 0 12
      assets/resources/data/excel/方块武器配置/~$方块武器配置表.xlsx.meta
  24. 9 0
      assets/resources/data/弹球音效.meta
  25. BIN
      assets/resources/data/弹球音效/MagicianAttack.mp3
  26. 14 0
      assets/resources/data/弹球音效/MagicianAttack.mp3.meta
  27. BIN
      assets/resources/data/弹球音效/bean atk.mp3
  28. 14 0
      assets/resources/data/弹球音效/bean atk.mp3.meta
  29. BIN
      assets/resources/data/弹球音效/bomb.mp3
  30. 14 0
      assets/resources/data/弹球音效/bomb.mp3.meta
  31. BIN
      assets/resources/data/弹球音效/boss die.mp3
  32. 14 0
      assets/resources/data/弹球音效/boss die.mp3.meta
  33. BIN
      assets/resources/data/弹球音效/bow.mp3
  34. 14 0
      assets/resources/data/弹球音效/bow.mp3.meta
  35. BIN
      assets/resources/data/弹球音效/cawl.mp3
  36. 14 0
      assets/resources/data/弹球音效/cawl.mp3.meta
  37. BIN
      assets/resources/data/弹球音效/dao2.mp3
  38. 14 0
      assets/resources/data/弹球音效/dao2.mp3.meta
  39. BIN
      assets/resources/data/弹球音效/equipment level up finish.mp3
  40. 14 0
      assets/resources/data/弹球音效/equipment level up finish.mp3.meta
  41. BIN
      assets/resources/data/弹球音效/fight bgm.mp3
  42. 14 0
      assets/resources/data/弹球音效/fight bgm.mp3.meta
  43. BIN
      assets/resources/data/弹球音效/fire.mp3
  44. 14 0
      assets/resources/data/弹球音效/fire.mp3.meta
  45. BIN
      assets/resources/data/弹球音效/get money.mp3
  46. 14 0
      assets/resources/data/弹球音效/get money.mp3.meta
  47. BIN
      assets/resources/data/弹球音效/hammer1.mp3
  48. 14 0
      assets/resources/data/弹球音效/hammer1.mp3.meta
  49. BIN
      assets/resources/data/弹球音效/huixuanbiao atk.mp3
  50. 14 0
      assets/resources/data/弹球音效/huixuanbiao atk.mp3.meta
  51. BIN
      assets/resources/data/弹球音效/juchi atk.mp3
  52. 14 0
      assets/resources/data/弹球音效/juchi atk.mp3.meta
  53. BIN
      assets/resources/data/弹球音效/level up 2.mp3
  54. 14 0
      assets/resources/data/弹球音效/level up 2.mp3.meta
  55. BIN
      assets/resources/data/弹球音效/lose.mp3
  56. 14 0
      assets/resources/data/弹球音效/lose.mp3.meta
  57. BIN
      assets/resources/data/弹球音效/money get.mp3
  58. 14 0
      assets/resources/data/弹球音效/money get.mp3.meta
  59. BIN
      assets/resources/data/弹球音效/normal zombie die 1.mp3
  60. 14 0
      assets/resources/data/弹球音效/normal zombie die 1.mp3.meta
  61. BIN
      assets/resources/data/弹球音效/normal zombie die 2.mp3
  62. 14 0
      assets/resources/data/弹球音效/normal zombie die 2.mp3.meta
  63. BIN
      assets/resources/data/弹球音效/normal zombie die 3.mp3
  64. 14 0
      assets/resources/data/弹球音效/normal zombie die 3.mp3.meta
  65. BIN
      assets/resources/data/弹球音效/normal zombie die 4.mp3
  66. 14 0
      assets/resources/data/弹球音效/normal zombie die 4.mp3.meta
  67. BIN
      assets/resources/data/弹球音效/normal zombie die 5.mp3
  68. 14 0
      assets/resources/data/弹球音效/normal zombie die 5.mp3.meta
  69. BIN
      assets/resources/data/弹球音效/normal zombie die 6.mp3
  70. 14 0
      assets/resources/data/弹球音效/normal zombie die 6.mp3.meta
  71. BIN
      assets/resources/data/弹球音效/normal zombie die 7.mp3
  72. 14 0
      assets/resources/data/弹球音效/normal zombie die 7.mp3.meta
  73. BIN
      assets/resources/data/弹球音效/qiukui hit.mp3
  74. 14 0
      assets/resources/data/弹球音效/qiukui hit.mp3.meta
  75. BIN
      assets/resources/data/弹球音效/start zombie.mp3
  76. 14 0
      assets/resources/data/弹球音效/start zombie.mp3.meta
  77. BIN
      assets/resources/data/弹球音效/ui bgm.mp3
  78. 14 0
      assets/resources/data/弹球音效/ui bgm.mp3.meta
  79. BIN
      assets/resources/data/弹球音效/ui play.mp3
  80. 14 0
      assets/resources/data/弹球音效/ui play.mp3.meta
  81. BIN
      assets/resources/data/弹球音效/win.mp3
  82. 14 0
      assets/resources/data/弹球音效/win.mp3.meta
  83. BIN
      assets/resources/data/弹球音效/xianrenzhang hit.mp3
  84. 14 0
      assets/resources/data/弹球音效/xianrenzhang hit.mp3.meta
  85. BIN
      assets/resources/data/弹球音效/zhanshiAtk.mp3
  86. 14 0
      assets/resources/data/弹球音效/zhanshiAtk.mp3.meta
  87. BIN
      assets/resources/images/UI/主界面/3.png
  88. 134 0
      assets/resources/images/UI/主界面/3.png.meta
  89. 9 0
      assets/scripts/AudioManager.meta
  90. 357 0
      assets/scripts/AudioManager/AudioConfig.ts
  91. 9 0
      assets/scripts/AudioManager/AudioConfig.ts.meta
  92. 665 0
      assets/scripts/AudioManager/AudioManager.ts
  93. 1 1
      assets/scripts/AudioManager/AudioManager.ts.meta
  94. 165 0
      assets/scripts/AudioManager/EnemyAudios.ts
  95. 9 0
      assets/scripts/AudioManager/EnemyAudios.ts.meta
  96. 11 0
      assets/scripts/CombatSystem/EnemyInstance.ts
  97. 1 1
      assets/scripts/CombatSystem/MenuSystem/SoundController.ts
  98. 0 319
      assets/scripts/Core/AudioManager.ts
  99. 1 1
      assets/scripts/Examples/AudioExample.ts
  100. 0 111
      docs/AntiTrapMechanism.md

+ 1 - 1
MenuUI音频控制系统实现说明.md

@@ -100,7 +100,7 @@ Canvas/
 ### 3. 在代码中使用音频功能
 
 ```typescript
-import { Audio } from '../Core/AudioManager';
+import { Audio } from '../AudioManager/AudioManager';
 
 // 播放背景音乐
 Audio.playMusic('audio/music/background_music');

+ 285 - 0
UnifiedAudioSystemGuide.md

@@ -0,0 +1,285 @@
+# 统一音频系统使用指南
+
+## 系统概述
+
+统一音频系统是一个完整的游戏音频管理解决方案,支持背景音乐、UI音效、敌人音效、环境音效和武器音效的分类管理。该系统提供了灵活的配置、独立的音量控制和便捷的静态访问接口。
+
+## 系统架构
+
+```
+AudioManager (核心管理器)
+    ├── 背景音乐管理 (Music)
+    ├── UI音效管理 (UI Sounds)
+    ├── 敌人音效管理 (Enemy Sounds) ← EnemyAudios
+    ├── 环境音效管理 (Environment Sounds)
+    └── 武器音效管理 (Weapon Sounds)
+
+AudioConfig (配置管理)
+    └── 统一音频资源配置
+```
+
+### 依赖关系
+- **AudioManager**: 核心音频管理器,提供分类音频播放和音量控制
+- **AudioConfig**: 音频配置管理器,统一管理所有音频资源配置
+- **EnemyAudios**: 敌人音效专用管理器,基于enemies.json配置
+- **Audio**: 静态访问接口,提供便捷的全局音频操作方法
+
+## 文件结构
+
+```
+assets/scripts/AudioManager/
+├── AudioManager.ts        # 核心音频管理器
+├── AudioConfig.ts         # 音频配置管理
+├── EnemyAudios.ts         # 敌人音效管理器
+└── SoundController.ts     # 音频控制器(UI相关)
+```
+
+## 音频分类
+
+### 1. 背景音乐 (Music)
+- **用途**: 游戏背景音乐
+- **特点**: 通常循环播放,音量较低
+- **示例**: 主菜单音乐、游戏内背景音乐、胜利/失败音乐
+
+### 2. UI音效 (UI Sounds)
+- **用途**: 用户界面交互音效
+- **特点**: 短促、清脆,提供即时反馈
+- **示例**: 按钮点击、菜单切换、提示音
+
+### 3. 敌人音效 (Enemy Sounds)
+- **用途**: 敌人相关的所有音效
+- **特点**: 基于敌人类型动态配置
+- **示例**: 攻击声、死亡声、受击声、行走声
+
+### 4. 环境音效 (Environment Sounds)
+- **用途**: 游戏环境和氛围音效
+- **特点**: 增强游戏沉浸感
+- **示例**: 风声、爆炸声、脚步声
+
+### 5. 武器音效 (Weapon Sounds)
+- **用途**: 武器相关音效
+- **特点**: 动作反馈,增强打击感
+- **示例**: 射击声、装弹声、切换武器声
+
+## 使用方法
+
+### 1. 基础音频播放
+
+```typescript
+// 播放背景音乐
+Audio.playMusic('audio/music/game_background', true);
+
+// 播放UI音效
+Audio.playUISound('audio/ui/button_click');
+
+// 播放敌人音效
+Audio.playEnemySound('audio/enemy/goblin_attack');
+
+// 播放环境音效
+Audio.playEnvironmentSound('audio/environment/explosion');
+
+// 播放武器音效
+Audio.playWeaponSound('audio/weapon/gun_shot');
+```
+
+### 2. 音量控制
+
+```typescript
+// 设置音乐音量
+Audio.setMusicVolume(0.6);
+
+// 设置UI音效音量
+Audio.setUISoundVolume(0.8);
+
+// 设置敌人音效音量
+Audio.setEnemySoundVolume(0.7);
+
+// 设置所有音效音量
+Audio.setAllSoundVolume(0.5);
+
+// 静音所有音频
+Audio.muteAll();
+
+// 只静音音效,保留音乐
+Audio.muteAllSounds();
+```
+
+### 3. 敌人音效专用接口
+
+```typescript
+// 播放特定敌人的音效
+EnemyAudio.playAttackSound('goblin');
+EnemyAudio.playDeathSound('orc');
+EnemyAudio.playHitSound('skeleton');
+EnemyAudio.playWalkSound('zombie');
+EnemyAudio.playSpecialSound('boss');
+```
+
+### 4. 直接使用AudioManager
+
+```typescript
+const audioManager = AudioManager.getInstance();
+
+// 播放分类音效
+audioManager.playUISound('audio/ui/button_click');
+audioManager.playEnemySound('audio/enemy/attack');
+
+// 音量控制
+audioManager.setUISoundVolume(0.8);
+audioManager.setEnemySoundVolume(0.7);
+```
+
+## 配置管理
+
+### 音频配置文件 (AudioConfig.ts)
+
+```typescript
+// 获取音频配置
+const config = AudioConfig.getAudioConfig('audio/ui/button_click');
+
+// 获取分类配置
+const uiCategory = AudioConfig.getCategoryConfig(AudioType.UI_SOUND);
+
+// 获取默认音量
+const defaultVolume = AudioConfig.getDefaultVolume(AudioType.ENEMY_SOUND);
+
+// 验证音频路径
+const isValid = AudioConfig.isValidAudioPath('audio/music/background');
+```
+
+### 配置助手类
+
+```typescript
+// 快速访问各类音频配置
+const musicList = AudioConfigHelper.music;
+const uiSounds = AudioConfigHelper.uiSounds;
+const enemySounds = AudioConfigHelper.enemySounds;
+```
+
+## 敌人音效配置
+
+敌人音效通过 `enemies.json` 文件进行配置:
+
+```json
+{
+  "goblin": {
+    "audioConfig": {
+      "attack": "audio/enemy/goblin/attack",
+      "death": "audio/enemy/goblin/death",
+      "hit": "audio/enemy/goblin/hit",
+      "walk": "audio/enemy/goblin/walk"
+    }
+  }
+}
+```
+
+## 组件挂载
+
+### AudioManager 挂载
+1. 在场景中创建 `Canvas/AudioManager` 节点
+2. 添加 `AudioManager` 组件
+3. 系统会自动创建各类音频源节点
+
+### EnemyAudios 挂载
+1. `EnemyAudios` 作为 `AudioManager` 的子模块
+2. 通过单例模式访问,无需手动挂载
+3. 自动初始化并加载敌人音频配置
+
+## 最佳实践
+
+### 1. 音频文件组织
+```
+assets/audio/
+├── music/              # 背景音乐
+│   ├── main_menu.mp3
+│   └── game_background.mp3
+├── ui/                 # UI音效
+│   ├── button_click.wav
+│   └── menu_open.wav
+├── enemy/              # 敌人音效
+│   ├── goblin/
+│   └── orc/
+├── environment/        # 环境音效
+│   └── explosion.wav
+└── weapon/             # 武器音效
+    └── gun_shot.wav
+```
+
+### 2. 性能优化
+- 使用合适的音频格式(WAV用于短音效,MP3用于长音乐)
+- 控制同时播放的音效数量
+- 及时释放不需要的音频资源
+
+### 3. 音量平衡
+- 背景音乐: 0.4-0.6
+- UI音效: 0.6-0.8
+- 敌人音效: 0.5-0.7
+- 环境音效: 0.3-0.5
+- 武器音效: 0.7-0.9
+
+### 4. 错误处理
+- 系统提供默认音效fallback机制
+- 音频文件缺失时不会导致游戏崩溃
+- 控制台会输出详细的调试信息
+
+## 扩展功能
+
+### 1. 添加新的音频分类
+1. 在 `AudioType` 枚举中添加新类型
+2. 在 `AudioManager` 中添加对应的 `AudioSource`
+3. 实现相应的播放和音量控制方法
+4. 在 `AudioConfig` 中添加配置
+
+### 2. 动态音频加载
+```typescript
+// 可以扩展为支持运行时动态加载音频资源
+AudioManager.getInstance().loadAudioClip(path).then(clip => {
+    // 播放动态加载的音频
+});
+```
+
+### 3. 音频效果
+```typescript
+// 可以扩展支持音频效果,如淡入淡出、变调等
+AudioManager.getInstance().playWithFadeIn(audioPath, 2.0); // 2秒淡入
+```
+
+## 故障排除
+
+### 常见问题
+
+1. **音效不播放**
+   - 检查音频文件路径是否正确
+   - 确认音频文件格式是否支持
+   - 检查音量设置是否为0
+
+2. **音效延迟**
+   - 检查音频文件大小
+   - 考虑预加载重要音效
+   - 优化音频文件格式
+
+3. **音量控制无效**
+   - 确认使用了正确的音量控制方法
+   - 检查AudioSource组件是否正确初始化
+
+### 调试信息
+
+系统提供详细的控制台日志:
+```
+[AudioManager] 初始化音频源: UI音效
+[EnemyAudios] 播放攻击音效: audio/enemy/goblin/attack
+[AudioManager] 设置敌人音效音量: 0.7
+```
+
+## 总结
+
+统一音频系统提供了:
+- ✅ 分类音频管理
+- ✅ 独立音量控制
+- ✅ 配置驱动的音效系统
+- ✅ 便捷的静态访问接口
+- ✅ 完善的错误处理
+- ✅ 向后兼容性
+- ✅ 可扩展的架构设计
+
+该系统为游戏提供了专业级的音频管理解决方案,支持从简单的音效播放到复杂的音频系统管理的各种需求。

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


+ 5 - 5
assets/assets/Prefabs/Ball.prefab

@@ -55,8 +55,8 @@
     },
     "_lscale": {
       "__type__": "cc.Vec3",
-      "x": 0.8,
-      "y": 0.8,
+      "x": 0.3,
+      "y": 0.3,
       "z": 1
     },
     "_mobility": 0,
@@ -211,8 +211,8 @@
     },
     "_contentSize": {
       "__type__": "cc.Size",
-      "width": 57,
-      "height": 57
+      "width": 142,
+      "height": 142
     },
     "_anchorPoint": {
       "__type__": "cc.Vec2",
@@ -248,7 +248,7 @@
       "a": 255
     },
     "_spriteFrame": {
-      "__uuid__": "3126e414-a5e1-4681-abf1-59121b6a3723@f9941",
+      "__uuid__": "80f212d1-c325-4e21-b2f5-19f7fa77c9b1@f9941",
       "__expectedType__": "cc.SpriteFrame"
     },
     "_type": 0,

+ 1 - 1
assets/resources/data/ballController.json

@@ -1,5 +1,5 @@
 {
-  "baseSpeed": 12.0,
+  "baseSpeed": 32.0,
   "maxReflectionRandomness": 0.2,
   "antiTrapTimeWindow": 5,
   "antiTrapHitThreshold": 5,

+ 47 - 47
assets/resources/data/enemies.json

@@ -73,10 +73,10 @@
       "weapon_prop": "props/baseball_bat"
     },
     "audio": {
-      "attack_sound": "enemy_attack",
-      "death_sound": "enemy_death",
-      "hit_sound": "enemy_hit",
-      "walk_sound": "audio/zombie_walk",
+      "attack_sound": "data/弹球音效/dao2",
+      "death_sound": "data/弹球音效/normal zombie die 1",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
       "block_sound": "nan",
       "stealth_sound": "nan",
       "armor_break_sound": "nan",
@@ -164,10 +164,10 @@
       "weapon_prop": "props/magic_staff"
     },
     "audio": {
-      "attack_sound": "enemy_attack",
-      "death_sound": "enemy_death",
-      "hit_sound": "enemy_hit",
-      "walk_sound": "audio/roadblock_walk",
+      "attack_sound": "data/弹球音效/bow",
+      "death_sound": "data/弹球音效/normal zombie die 2",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
       "block_sound": "nan",
       "stealth_sound": "nan",
       "armor_break_sound": "nan",
@@ -255,10 +255,10 @@
       "weapon_prop": "props/bow"
     },
     "audio": {
-      "attack_sound": "enemy_attack",
-      "death_sound": "enemy_death",
-      "hit_sound": "enemy_hit",
-      "walk_sound": "audio/wandering_walk",
+      "attack_sound": "data/弹球音效/MagicianAttack",
+      "death_sound": "data/弹球音效/normal zombie die 3",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
       "block_sound": "nan",
       "stealth_sound": "nan",
       "armor_break_sound": "nan",
@@ -346,10 +346,10 @@
       "weapon_prop": "nan"
     },
     "audio": {
-      "attack_sound": "enemy_attack",
-      "death_sound": "enemy_death",
-      "hit_sound": "enemy_hit",
-      "walk_sound": "audio/mage_walk",
+      "attack_sound": "data/弹球音效/zhanshiAtk",
+      "death_sound": "data/弹球音效/normal zombie die 4",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
       "block_sound": "nan",
       "stealth_sound": "nan",
       "armor_break_sound": "nan",
@@ -437,10 +437,10 @@
       "weapon_prop": "nan"
     },
     "audio": {
-      "attack_sound": "enemy_attack",
-      "death_sound": "enemy_death",
-      "hit_sound": "enemy_hit",
-      "walk_sound": "audio/archer_walk",
+      "attack_sound": "data/弹球音效/hammer1",
+      "death_sound": "data/弹球音效/normal zombie die 5",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
       "block_sound": "nan",
       "stealth_sound": "nan",
       "armor_break_sound": "nan",
@@ -528,12 +528,12 @@
       "weapon_prop": "nan"
     },
     "audio": {
-      "attack_sound": "enemy_attack",
-      "death_sound": "enemy_death",
-      "hit_sound": "enemy_hit",
-      "walk_sound": "audio/stealth_walk",
+      "attack_sound": "data/弹球音效/hammer1",
+      "death_sound": "data/弹球音效/normal zombie die 6",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
       "block_sound": "nan",
-      "stealth_sound": "audio/stealth_activate",
+      "stealth_sound": "Null",
       "armor_break_sound": "nan",
       "fuse_sound": "nan"
     },
@@ -619,13 +619,13 @@
       "weapon_prop": "props/iron_gate"
     },
     "audio": {
-      "attack_sound": "enemy_attack",
-      "death_sound": "enemy_death",
-      "hit_sound": "enemy_hit",
-      "walk_sound": "audio/bucket_walk",
+      "attack_sound": "data/弹球音效/hammer1",
+      "death_sound": "data/弹球音效/normal zombie die 7",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
       "block_sound": "nan",
       "stealth_sound": "nan",
-      "armor_break_sound": "audio/armor_break",
+      "armor_break_sound": "Null",
       "fuse_sound": "nan"
     },
     "boss": {
@@ -710,14 +710,14 @@
       "weapon_prop": "props/tombstone"
     },
     "audio": {
-      "attack_sound": "enemy_attack",
-      "death_sound": "enemy_death",
-      "hit_sound": "enemy_hit",
-      "walk_sound": "audio/barrel_walk",
+      "attack_sound": "data/弹球音效/hammer1",
+      "death_sound": "data/弹球音效/boss die",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
       "block_sound": "nan",
       "stealth_sound": "nan",
       "armor_break_sound": "nan",
-      "fuse_sound": "audio/barrel_fuse"
+      "fuse_sound": "Null"
     },
     "boss": {
       "is_boss": false,
@@ -822,10 +822,10 @@
       "weapon_prop": "props/cyber_arm"
     },
     "audio": {
-      "attack_sound": "enemy_attack",
-      "death_sound": "enemy_death",
-      "hit_sound": "enemy_hit",
-      "walk_sound": "audio/boss1_walk",
+      "attack_sound": "data/弹球音效/hammer1",
+      "death_sound": "data/弹球音效/boss die",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
       "block_sound": "nan",
       "stealth_sound": "nan",
       "armor_break_sound": "nan",
@@ -934,10 +934,10 @@
       "weapon_prop": "nan"
     },
     "audio": {
-      "attack_sound": "enemy_attack",
-      "death_sound": "enemy_death",
-      "hit_sound": "enemy_hit",
-      "walk_sound": "audio/boss2_walk",
+      "attack_sound": "data/弹球音效/hammer1",
+      "death_sound": "data/弹球音效/boss die",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
       "block_sound": "nan",
       "stealth_sound": "nan",
       "armor_break_sound": "nan",
@@ -1046,10 +1046,10 @@
       "weapon_prop": "nan"
     },
     "audio": {
-      "attack_sound": "enemy_attack",
-      "death_sound": "enemy_death",
-      "hit_sound": "enemy_hit",
-      "walk_sound": "audio/boss3_walk",
+      "attack_sound": "data/弹球音效/hammer1",
+      "death_sound": "data/弹球音效/boss die",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
       "block_sound": "nan",
       "stealth_sound": "nan",
       "armor_break_sound": "nan",

+ 1066 - 0
assets/resources/data/enemies_backup_20250820_170519.json

@@ -0,0 +1,1066 @@
+[
+  {
+    "id": "normal_zombie",
+    "name": "普通僵尸",
+    "type": "basic",
+    "stats": {
+      "health": 35,
+      "maxHealth": 35,
+      "defense": 0,
+      "speed": 30.0
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 30.0,
+      "patrolRange": 100,
+      "chaseRange": 200,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 1.0,
+      "attackSpeed": 1.0,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 1.0,
+      "attackType": "melee",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "none",
+      "projectileSpeed": 100.0
+    },
+    "visualConfig": {
+      "spritePath": "Animation/EnemyAni/001",
+      "scale": 1.0,
+      "animationSpeed": 1.0,
+      "flipX": false,
+      "tint": "#FFFFFF",
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weaponProp": "props/baseball_bat"
+    },
+    "audioConfig": {
+      "attackSound": "enemy_attack",
+      "deathSound": "enemy_death",
+      "hitSound": "enemy_hit",
+      "walkSound": "audio/zombie_walk",
+      "blockSound": "",
+      "stealthSound": "",
+      "armorBreakSound": "",
+      "fuseSound": "",
+      "volume": 1.0
+    },
+    "visual": {
+      "sprite_path": "Animation/EnemyAni/001",
+      "scale": 1.0,
+      "animation_speed": 1.0,
+      "flip_horizontal": false,
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weapon_prop": "props/baseball_bat"
+    },
+    "audio": {
+      "attack_sound": "enemy_attack",
+      "death_sound": "enemy_death",
+      "hit_sound": "enemy_hit",
+      "walk_sound": "audio/zombie_walk",
+      "block_sound": "nan",
+      "stealth_sound": "nan",
+      "armor_break_sound": "nan",
+      "fuse_sound": "nan"
+    },
+    "boss": {
+      "is_boss": false,
+      "phases": 1,
+      "rage_threshold": 0.3,
+      "rage_damage_multiplier": 1.0,
+      "rage_speed_multiplier": 1.0
+    }
+  },
+  {
+    "id": "roadblock_zombie",
+    "name": "路障僵尸",
+    "type": "armored",
+    "stats": {
+      "health": 50,
+      "maxHealth": 50,
+      "defense": 1,
+      "speed": 25.0
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 40.0,
+      "patrolRange": 100,
+      "chaseRange": 200,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 30.0,
+      "attackSpeed": 0.3,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 3.0,
+      "attackType": "melee",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "none",
+      "projectileSpeed": 100.0
+    },
+    "visualConfig": {
+      "spritePath": "Animation/EnemyAni/002",
+      "scale": 1.0,
+      "animationSpeed": 1.0,
+      "flipX": false,
+      "tint": "#FFFFFF",
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weaponProp": "props/magic_staff"
+    },
+    "audioConfig": {
+      "attackSound": "enemy_attack",
+      "deathSound": "enemy_death",
+      "hitSound": "enemy_hit",
+      "walkSound": "audio/roadblock_walk",
+      "blockSound": "",
+      "stealthSound": "",
+      "armorBreakSound": "",
+      "fuseSound": "",
+      "volume": 1.0
+    },
+    "visual": {
+      "sprite_path": "Animation/EnemyAni/002",
+      "scale": 1.0,
+      "animation_speed": 1.0,
+      "flip_horizontal": false,
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weapon_prop": "props/magic_staff"
+    },
+    "audio": {
+      "attack_sound": "enemy_attack",
+      "death_sound": "enemy_death",
+      "hit_sound": "enemy_hit",
+      "walk_sound": "audio/roadblock_walk",
+      "block_sound": "nan",
+      "stealth_sound": "nan",
+      "armor_break_sound": "nan",
+      "fuse_sound": "nan"
+    },
+    "boss": {
+      "is_boss": false,
+      "phases": 1,
+      "rage_threshold": 0.3,
+      "rage_damage_multiplier": 1.0,
+      "rage_speed_multiplier": 1.0
+    }
+  },
+  {
+    "id": "wandering_zombie",
+    "name": "漫步僵尸",
+    "type": "wanderer",
+    "stats": {
+      "health": 42,
+      "maxHealth": 42,
+      "defense": 0,
+      "speed": 35.0
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 45.0,
+      "patrolRange": 100,
+      "chaseRange": 200,
+      "rotationSpeed": 180.0,
+      "moveType": "sway",
+      "swingAmplitude": 20.0,
+      "swingFrequency": 2.0,
+      "speedVariation": 0.2
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 30.0,
+      "attackSpeed": 0.4,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 3.0,
+      "attackType": "melee_weapon",
+      "attackDelay": 1.0,
+      "weaponType": "baseball_bat",
+      "projectileType": "none",
+      "projectileSpeed": 100.0
+    },
+    "visualConfig": {
+      "spritePath": "Animation/EnemyAni/003",
+      "scale": 1.0,
+      "animationSpeed": 1.0,
+      "flipX": false,
+      "tint": "#FFFFFF",
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weaponProp": "props/bow"
+    },
+    "audioConfig": {
+      "attackSound": "enemy_attack",
+      "deathSound": "enemy_death",
+      "hitSound": "enemy_hit",
+      "walkSound": "audio/wandering_walk",
+      "blockSound": "",
+      "stealthSound": "",
+      "armorBreakSound": "",
+      "fuseSound": "",
+      "volume": 1.0
+    },
+    "visual": {
+      "sprite_path": "Animation/EnemyAni/003",
+      "scale": 1.0,
+      "animation_speed": 1.0,
+      "flip_horizontal": false,
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weapon_prop": "props/bow"
+    },
+    "audio": {
+      "attack_sound": "enemy_attack",
+      "death_sound": "enemy_death",
+      "hit_sound": "enemy_hit",
+      "walk_sound": "audio/wandering_walk",
+      "block_sound": "nan",
+      "stealth_sound": "nan",
+      "armor_break_sound": "nan",
+      "fuse_sound": "nan"
+    },
+    "boss": {
+      "is_boss": false,
+      "phases": 1,
+      "rage_threshold": 0.3,
+      "rage_damage_multiplier": 1.0,
+      "rage_speed_multiplier": 1.0
+    }
+  },
+  {
+    "id": "mage_zombie",
+    "name": "法师僵尸",
+    "type": "ranged_caster",
+    "stats": {
+      "health": 25,
+      "maxHealth": 25,
+      "defense": 0,
+      "speed": 15.0
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 35.0,
+      "patrolRange": 100,
+      "chaseRange": 200,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 200.0,
+      "attackSpeed": 0.2,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 4.0,
+      "attackType": "magic_projectile",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "magic_bolt",
+      "projectileSpeed": 50.0
+    },
+    "visualConfig": {
+      "spritePath": "Animation/EnemyAni/004",
+      "scale": 1.0,
+      "animationSpeed": 1.0,
+      "flipX": false,
+      "tint": "#FFFFFF",
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weaponProp": ""
+    },
+    "audioConfig": {
+      "attackSound": "enemy_attack",
+      "deathSound": "enemy_death",
+      "hitSound": "enemy_hit",
+      "walkSound": "audio/mage_walk",
+      "blockSound": "",
+      "stealthSound": "",
+      "armorBreakSound": "",
+      "fuseSound": "",
+      "volume": 1.0
+    },
+    "visual": {
+      "sprite_path": "Animation/EnemyAni/004",
+      "scale": 1.0,
+      "animation_speed": 1.0,
+      "flip_horizontal": false,
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weapon_prop": "nan"
+    },
+    "audio": {
+      "attack_sound": "enemy_attack",
+      "death_sound": "enemy_death",
+      "hit_sound": "enemy_hit",
+      "walk_sound": "audio/mage_walk",
+      "block_sound": "nan",
+      "stealth_sound": "nan",
+      "armor_break_sound": "nan",
+      "fuse_sound": "nan"
+    },
+    "boss": {
+      "is_boss": false,
+      "phases": 1,
+      "rage_threshold": 0.3,
+      "rage_damage_multiplier": 1.0,
+      "rage_speed_multiplier": 1.0
+    }
+  },
+  {
+    "id": "archer_zombie",
+    "name": "弓箭僵尸",
+    "type": "ranged_archer",
+    "stats": {
+      "health": 25,
+      "maxHealth": 25,
+      "defense": 0,
+      "speed": 15.0
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 40.0,
+      "patrolRange": 100,
+      "chaseRange": 200,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 250.0,
+      "attackSpeed": 0.2,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 4.0,
+      "attackType": "arrow_projectile",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "arrow",
+      "projectileSpeed": 100.0
+    },
+    "visualConfig": {
+      "spritePath": "Animation/EnemyAni/005",
+      "scale": 1.0,
+      "animationSpeed": 1.0,
+      "flipX": false,
+      "tint": "#FFFFFF",
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weaponProp": ""
+    },
+    "audioConfig": {
+      "attackSound": "enemy_attack",
+      "deathSound": "enemy_death",
+      "hitSound": "enemy_hit",
+      "walkSound": "audio/archer_walk",
+      "blockSound": "",
+      "stealthSound": "",
+      "armorBreakSound": "",
+      "fuseSound": "",
+      "volume": 1.0
+    },
+    "visual": {
+      "sprite_path": "Animation/EnemyAni/005",
+      "scale": 1.0,
+      "animation_speed": 1.0,
+      "flip_horizontal": false,
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weapon_prop": "nan"
+    },
+    "audio": {
+      "attack_sound": "enemy_attack",
+      "death_sound": "enemy_death",
+      "hit_sound": "enemy_hit",
+      "walk_sound": "audio/archer_walk",
+      "block_sound": "nan",
+      "stealth_sound": "nan",
+      "armor_break_sound": "nan",
+      "fuse_sound": "nan"
+    },
+    "boss": {
+      "is_boss": false,
+      "phases": 1,
+      "rage_threshold": 0.3,
+      "rage_damage_multiplier": 1.0,
+      "rage_speed_multiplier": 1.0
+    }
+  },
+  {
+    "id": "stealth_zombie",
+    "name": "隐身僵尸",
+    "type": "stealth",
+    "stats": {
+      "health": 42,
+      "maxHealth": 42,
+      "defense": 0,
+      "speed": 35.0
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 60.0,
+      "patrolRange": 100,
+      "chaseRange": 200,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 30.0,
+      "attackSpeed": 0.4,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 3.0,
+      "attackType": "stealth_strike",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "none",
+      "projectileSpeed": 100.0
+    },
+    "visualConfig": {
+      "spritePath": "Animation/EnemyAni/006",
+      "scale": 1.0,
+      "animationSpeed": 1.0,
+      "flipX": false,
+      "tint": "#FFFFFF",
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weaponProp": ""
+    },
+    "audioConfig": {
+      "attackSound": "enemy_attack",
+      "deathSound": "enemy_death",
+      "hitSound": "enemy_hit",
+      "walkSound": "audio/stealth_walk",
+      "blockSound": "",
+      "stealthSound": "audio/stealth_activate",
+      "armorBreakSound": "",
+      "fuseSound": "",
+      "volume": 1.0
+    },
+    "visual": {
+      "sprite_path": "Animation/EnemyAni/006",
+      "scale": 1.0,
+      "animation_speed": 1.0,
+      "flip_horizontal": false,
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weapon_prop": "nan"
+    },
+    "audio": {
+      "attack_sound": "enemy_attack",
+      "death_sound": "enemy_death",
+      "hit_sound": "enemy_hit",
+      "walk_sound": "audio/stealth_walk",
+      "block_sound": "nan",
+      "stealth_sound": "audio/stealth_activate",
+      "armor_break_sound": "nan",
+      "fuse_sound": "nan"
+    },
+    "boss": {
+      "is_boss": false,
+      "phases": 1,
+      "rage_threshold": 0.3,
+      "rage_damage_multiplier": 1.0,
+      "rage_speed_multiplier": 1.0
+    }
+  },
+  {
+    "id": "bucket_zombie",
+    "name": "铁桶僵尸",
+    "type": "heavy_armor",
+    "stats": {
+      "health": 70,
+      "maxHealth": 70,
+      "defense": 2,
+      "speed": 15.0
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 30.0,
+      "patrolRange": 100,
+      "chaseRange": 200,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 30.0,
+      "attackSpeed": 0.3,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 4.0,
+      "attackType": "heavy_melee",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "none",
+      "projectileSpeed": 100.0
+    },
+    "visualConfig": {
+      "spritePath": "Animation/EnemyAni/007",
+      "scale": 1.0,
+      "animationSpeed": 1.0,
+      "flipX": false,
+      "tint": "#FFFFFF",
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weaponProp": "props/iron_gate"
+    },
+    "audioConfig": {
+      "attackSound": "enemy_attack",
+      "deathSound": "enemy_death",
+      "hitSound": "enemy_hit",
+      "walkSound": "audio/bucket_walk",
+      "blockSound": "",
+      "stealthSound": "",
+      "armorBreakSound": "audio/armor_break",
+      "fuseSound": "",
+      "volume": 1.0
+    },
+    "visual": {
+      "sprite_path": "Animation/EnemyAni/007",
+      "scale": 1.0,
+      "animation_speed": 1.0,
+      "flip_horizontal": false,
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weapon_prop": "props/iron_gate"
+    },
+    "audio": {
+      "attack_sound": "enemy_attack",
+      "death_sound": "enemy_death",
+      "hit_sound": "enemy_hit",
+      "walk_sound": "audio/bucket_walk",
+      "block_sound": "nan",
+      "stealth_sound": "nan",
+      "armor_break_sound": "audio/armor_break",
+      "fuse_sound": "nan"
+    },
+    "boss": {
+      "is_boss": false,
+      "phases": 1,
+      "rage_threshold": 0.3,
+      "rage_damage_multiplier": 1.0,
+      "rage_speed_multiplier": 1.0
+    }
+  },
+  {
+    "id": "barrel_zombie",
+    "name": "火药桶僵尸",
+    "type": "explosive",
+    "stats": {
+      "health": 35,
+      "maxHealth": 35,
+      "defense": 0,
+      "speed": 30.0
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 45.0,
+      "patrolRange": 100,
+      "chaseRange": 200,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 30.0,
+      "attackSpeed": 0.3,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 3.0,
+      "attackType": "melee",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "none",
+      "projectileSpeed": 100.0
+    },
+    "visualConfig": {
+      "spritePath": "Animation/EnemyAni/008",
+      "scale": 1.0,
+      "animationSpeed": 1.0,
+      "flipX": false,
+      "tint": "#FFFFFF",
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weaponProp": "props/tombstone"
+    },
+    "audioConfig": {
+      "attackSound": "enemy_attack",
+      "deathSound": "enemy_death",
+      "hitSound": "enemy_hit",
+      "walkSound": "audio/barrel_walk",
+      "blockSound": "",
+      "stealthSound": "",
+      "armorBreakSound": "",
+      "fuseSound": "audio/barrel_fuse",
+      "volume": 1.0
+    },
+    "visual": {
+      "sprite_path": "Animation/EnemyAni/008",
+      "scale": 1.0,
+      "animation_speed": 1.0,
+      "flip_horizontal": false,
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weapon_prop": "props/tombstone"
+    },
+    "audio": {
+      "attack_sound": "enemy_attack",
+      "death_sound": "enemy_death",
+      "hit_sound": "enemy_hit",
+      "walk_sound": "audio/barrel_walk",
+      "block_sound": "nan",
+      "stealth_sound": "nan",
+      "armor_break_sound": "nan",
+      "fuse_sound": "audio/barrel_fuse"
+    },
+    "boss": {
+      "is_boss": false,
+      "phases": 1,
+      "rage_threshold": 0.3,
+      "rage_damage_multiplier": 1.0,
+      "rage_speed_multiplier": 1.0
+    }
+  },
+  {
+    "id": "boss1_gatekeeper",
+    "name": "BOSS1",
+    "type": "boss",
+    "stats": {
+      "health": 500,
+      "maxHealth": 500,
+      "defense": 2,
+      "speed": 10.0
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 25.0,
+      "patrolRange": 100,
+      "chaseRange": 200,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 30.0,
+      "attackSpeed": 0.2,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 4.0,
+      "attackType": "gate_slam",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "none",
+      "projectileSpeed": 100.0
+    },
+    "visualConfig": {
+      "spritePath": "Animation/EnemyAni/009",
+      "scale": 1.0,
+      "animationSpeed": 1.0,
+      "flipX": false,
+      "tint": "#FFFFFF",
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weaponProp": "props/cyber_arm"
+    },
+    "audioConfig": {
+      "attackSound": "enemy_attack",
+      "deathSound": "enemy_death",
+      "hitSound": "enemy_hit",
+      "walkSound": "audio/boss1_walk",
+      "blockSound": "",
+      "stealthSound": "",
+      "armorBreakSound": "",
+      "fuseSound": "",
+      "volume": 1.0
+    },
+    "specialAbilities": [
+      {
+        "type": "charge_attack",
+        "damage": 1,
+        "range": 150.0,
+        "cooldown": 8.0
+      },
+      {
+        "type": "area_attack",
+        "damage": 2,
+        "range": 100.0,
+        "cooldown": 12.0
+      }
+    ],
+    "bossConfig": {
+      "isBoss": true,
+      "phases": 1,
+      "enrageThreshold": 0.3,
+      "enrageDamageMultiplier": 1.5,
+      "enrageSpeedMultiplier": 1.3
+    },
+    "visual": {
+      "sprite_path": "Animation/EnemyAni/009",
+      "scale": 1.0,
+      "animation_speed": 1.0,
+      "flip_horizontal": false,
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weapon_prop": "props/cyber_arm"
+    },
+    "audio": {
+      "attack_sound": "enemy_attack",
+      "death_sound": "enemy_death",
+      "hit_sound": "enemy_hit",
+      "walk_sound": "audio/boss1_walk",
+      "block_sound": "nan",
+      "stealth_sound": "nan",
+      "armor_break_sound": "nan",
+      "fuse_sound": "nan"
+    },
+    "boss": {
+      "is_boss": true,
+      "phases": 1,
+      "rage_threshold": 0.3,
+      "rage_damage_multiplier": 1.5,
+      "rage_speed_multiplier": 1.3
+    }
+  },
+  {
+    "id": "boss2_gravedigger",
+    "name": "BOSS2",
+    "type": "boss",
+    "stats": {
+      "health": 500,
+      "maxHealth": 500,
+      "defense": 3,
+      "speed": 10.0
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 20.0,
+      "patrolRange": 100,
+      "chaseRange": 200,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 30.0,
+      "attackSpeed": 0.2,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 5.0,
+      "attackType": "tombstone_smash",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "none",
+      "projectileSpeed": 100.0
+    },
+    "visualConfig": {
+      "spritePath": "Animation/EnemyAni/010",
+      "scale": 1.0,
+      "animationSpeed": 1.0,
+      "flipX": false,
+      "tint": "#FFFFFF",
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weaponProp": ""
+    },
+    "audioConfig": {
+      "attackSound": "enemy_attack",
+      "deathSound": "enemy_death",
+      "hitSound": "enemy_hit",
+      "walkSound": "audio/boss2_walk",
+      "blockSound": "",
+      "stealthSound": "",
+      "armorBreakSound": "",
+      "fuseSound": "",
+      "volume": 1.0
+    },
+    "specialAbilities": [
+      {
+        "type": "charge_attack",
+        "damage": 1,
+        "range": 150.0,
+        "cooldown": 8.0
+      },
+      {
+        "type": "area_attack",
+        "damage": 2,
+        "range": 100.0,
+        "cooldown": 12.0
+      }
+    ],
+    "bossConfig": {
+      "isBoss": true,
+      "phases": 1,
+      "enrageThreshold": 0.3,
+      "enrageDamageMultiplier": 1.5,
+      "enrageSpeedMultiplier": 1.3
+    },
+    "visual": {
+      "sprite_path": "Animation/EnemyAni/010",
+      "scale": 1.0,
+      "animation_speed": 1.0,
+      "flip_horizontal": false,
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weapon_prop": "nan"
+    },
+    "audio": {
+      "attack_sound": "enemy_attack",
+      "death_sound": "enemy_death",
+      "hit_sound": "enemy_hit",
+      "walk_sound": "audio/boss2_walk",
+      "block_sound": "nan",
+      "stealth_sound": "nan",
+      "armor_break_sound": "nan",
+      "fuse_sound": "nan"
+    },
+    "boss": {
+      "is_boss": true,
+      "phases": 1,
+      "rage_threshold": 0.3,
+      "rage_damage_multiplier": 1.5,
+      "rage_speed_multiplier": 1.3
+    }
+  },
+  {
+    "id": "boss3_cyborg",
+    "name": "BOSS3",
+    "type": "boss",
+    "stats": {
+      "health": 250,
+      "maxHealth": 250,
+      "defense": 1,
+      "speed": 10.0
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 35.0,
+      "patrolRange": 100,
+      "chaseRange": 200,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 80.0,
+      "attackSpeed": 0.2,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 4.0,
+      "attackType": "cyber_arm_combo",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "none",
+      "projectileSpeed": 100.0
+    },
+    "visualConfig": {
+      "spritePath": "Animation/EnemyAni/011",
+      "scale": 1.0,
+      "animationSpeed": 1.0,
+      "flipX": false,
+      "tint": "#FFFFFF",
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weaponProp": ""
+    },
+    "audioConfig": {
+      "attackSound": "enemy_attack",
+      "deathSound": "enemy_death",
+      "hitSound": "enemy_hit",
+      "walkSound": "audio/boss3_walk",
+      "blockSound": "",
+      "stealthSound": "",
+      "armorBreakSound": "",
+      "fuseSound": "",
+      "volume": 1.0
+    },
+    "specialAbilities": [
+      {
+        "type": "charge_attack",
+        "damage": 1,
+        "range": 150.0,
+        "cooldown": 8.0
+      },
+      {
+        "type": "area_attack",
+        "damage": 2,
+        "range": 100.0,
+        "cooldown": 12.0
+      }
+    ],
+    "bossConfig": {
+      "isBoss": true,
+      "phases": 1,
+      "enrageThreshold": 0.3,
+      "enrageDamageMultiplier": 1.5,
+      "enrageSpeedMultiplier": 1.3
+    },
+    "visual": {
+      "sprite_path": "Animation/EnemyAni/011",
+      "scale": 1.0,
+      "animation_speed": 1.0,
+      "flip_horizontal": false,
+      "animations": {
+        "idle": "idle",
+        "walk": "walk",
+        "attack": "attack",
+        "death": "dead"
+      },
+      "weapon_prop": "nan"
+    },
+    "audio": {
+      "attack_sound": "enemy_attack",
+      "death_sound": "enemy_death",
+      "hit_sound": "enemy_hit",
+      "walk_sound": "audio/boss3_walk",
+      "block_sound": "nan",
+      "stealth_sound": "nan",
+      "armor_break_sound": "nan",
+      "fuse_sound": "nan"
+    },
+    "boss": {
+      "is_boss": true,
+      "phases": 1,
+      "rage_threshold": 0.3,
+      "rage_damage_multiplier": 1.5,
+      "rage_speed_multiplier": 1.3
+    }
+  }
+]

+ 11 - 0
assets/resources/data/enemies_backup_20250820_170519.json.meta

@@ -0,0 +1,11 @@
+{
+  "ver": "2.0.1",
+  "importer": "json",
+  "imported": true,
+  "uuid": "b0e53274-1641-466c-a059-8d788642a3e0",
+  "files": [
+    ".json"
+  ],
+  "subMetas": {},
+  "userData": {}
+}

BIN
assets/resources/data/excel/__pycache__/skill_config_manager.cpython-313.pyc


BIN
assets/resources/data/excel/__pycache__/weapon_config_manager.cpython-313.pyc


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


+ 0 - 12
assets/resources/data/excel/~$BallController标准配置表.xlsx.meta

@@ -1,12 +0,0 @@
-{
-  "ver": "1.0.0",
-  "importer": "*",
-  "imported": true,
-  "uuid": "8cdc77e7-7a74-471f-916c-a83d92b2faf7",
-  "files": [
-    ".json",
-    ".xlsx"
-  ],
-  "subMetas": {},
-  "userData": {}
-}

BIN
assets/resources/data/excel/~$局外技能配置表.xlsx


+ 0 - 12
assets/resources/data/excel/~$局外技能配置表.xlsx.meta

@@ -1,12 +0,0 @@
-{
-  "ver": "1.0.0",
-  "importer": "*",
-  "imported": true,
-  "uuid": "dd7c2493-5c63-4637-a174-f96c06d52ebd",
-  "files": [
-    ".json",
-    ".xlsx"
-  ],
-  "subMetas": {},
-  "userData": {}
-}

BIN
assets/resources/data/excel/~$技能配置表.xlsx


+ 0 - 12
assets/resources/data/excel/~$技能配置表.xlsx.meta

@@ -1,12 +0,0 @@
-{
-  "ver": "1.0.0",
-  "importer": "*",
-  "imported": true,
-  "uuid": "7f2616d5-abac-423b-8728-e06940fda1ec",
-  "files": [
-    ".json",
-    ".xlsx"
-  ],
-  "subMetas": {},
-  "userData": {}
-}

BIN
assets/resources/data/excel/~$敌人配置表.xlsx


+ 1 - 1
assets/resources/data/excel/~$敌人配置表.xlsx.meta

@@ -2,7 +2,7 @@
   "ver": "1.0.0",
   "importer": "*",
   "imported": true,
-  "uuid": "4d705a70-570e-43b8-9b6c-8a0ff3670917",
+  "uuid": "e5d52ee3-8d98-44c0-933b-65fbbcf856c8",
   "files": [
     ".json",
     ".xlsx"

BIN
assets/resources/data/excel/关卡配置/~$关卡配置表.xlsx


+ 0 - 12
assets/resources/data/excel/关卡配置/~$关卡配置表.xlsx.meta

@@ -1,12 +0,0 @@
-{
-  "ver": "1.0.0",
-  "importer": "*",
-  "imported": true,
-  "uuid": "c1651dca-9e44-4740-bcd4-79997b6046e2",
-  "files": [
-    ".json",
-    ".xlsx"
-  ],
-  "subMetas": {},
-  "userData": {}
-}

BIN
assets/resources/data/excel/敌人配置表.xlsx


BIN
assets/resources/data/excel/方块武器配置/~$方块武器配置表.xlsx


+ 0 - 12
assets/resources/data/excel/方块武器配置/~$方块武器配置表.xlsx.meta

@@ -1,12 +0,0 @@
-{
-  "ver": "1.0.0",
-  "importer": "*",
-  "imported": true,
-  "uuid": "5110743f-f660-4b03-9d37-c7332d4b8776",
-  "files": [
-    ".json",
-    ".xlsx"
-  ],
-  "subMetas": {},
-  "userData": {}
-}

+ 9 - 0
assets/resources/data/弹球音效.meta

@@ -0,0 +1,9 @@
+{
+  "ver": "1.2.0",
+  "importer": "directory",
+  "imported": true,
+  "uuid": "779ad7a4-dd20-4787-a89f-bec9bee496b5",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

BIN
assets/resources/data/弹球音效/MagicianAttack.mp3


+ 14 - 0
assets/resources/data/弹球音效/MagicianAttack.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "20765851-5beb-4dbe-9cac-211de4bd0316",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/bean atk.mp3


+ 14 - 0
assets/resources/data/弹球音效/bean atk.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "56c6dee1-818c-4beb-8473-626dd0cc54a8",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/bomb.mp3


+ 14 - 0
assets/resources/data/弹球音效/bomb.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "1ff07e93-d592-4c25-84d2-507fc80fb37e",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/boss die.mp3


+ 14 - 0
assets/resources/data/弹球音效/boss die.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "5c01a657-0b46-476c-8b99-6afee50e47e4",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/bow.mp3


+ 14 - 0
assets/resources/data/弹球音效/bow.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "3b1c3f2f-ff94-4c62-a963-853fe1aa9bf0",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/cawl.mp3


+ 14 - 0
assets/resources/data/弹球音效/cawl.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "0f3a6c57-bf1b-488b-bce1-8ecf30df51cf",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/dao2.mp3


+ 14 - 0
assets/resources/data/弹球音效/dao2.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "c2a9bdd3-2d68-4577-b47e-0a0c854e928d",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/equipment level up finish.mp3


+ 14 - 0
assets/resources/data/弹球音效/equipment level up finish.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "d2e0609d-c1ed-40a1-bcc1-2fb99d57bd1e",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/fight bgm.mp3


+ 14 - 0
assets/resources/data/弹球音效/fight bgm.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "9f54b75f-4085-4ec0-8a3c-cfad9aaf7db2",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/fire.mp3


+ 14 - 0
assets/resources/data/弹球音效/fire.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "897e5313-0607-433a-8c6b-155948ca75d3",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/get money.mp3


+ 14 - 0
assets/resources/data/弹球音效/get money.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "2e5987de-697d-47bf-8475-2499305b5df3",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/hammer1.mp3


+ 14 - 0
assets/resources/data/弹球音效/hammer1.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "b5081dc8-1cf2-491a-9436-d4c3cf0bc040",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/huixuanbiao atk.mp3


+ 14 - 0
assets/resources/data/弹球音效/huixuanbiao atk.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "d1ac9e95-bd5a-4626-b910-f9757a0e67b8",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/juchi atk.mp3


+ 14 - 0
assets/resources/data/弹球音效/juchi atk.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "dc203de1-6efa-4567-85b1-652a6c2369f4",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/level up 2.mp3


+ 14 - 0
assets/resources/data/弹球音效/level up 2.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "f7aaf3b7-16dd-4fe1-9e88-ec91c3cc1d7b",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/lose.mp3


+ 14 - 0
assets/resources/data/弹球音效/lose.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "d6a811f5-c47a-4825-88ba-2debc47438f0",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/money get.mp3


+ 14 - 0
assets/resources/data/弹球音效/money get.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "f1399094-fb2e-4bac-a0d3-a70d912d3a85",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/normal zombie die 1.mp3


+ 14 - 0
assets/resources/data/弹球音效/normal zombie die 1.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "752a5efb-175b-4970-910a-4bae1064d713",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/normal zombie die 2.mp3


+ 14 - 0
assets/resources/data/弹球音效/normal zombie die 2.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "b668727f-1467-4c6d-a418-3737f3e7d90b",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/normal zombie die 3.mp3


+ 14 - 0
assets/resources/data/弹球音效/normal zombie die 3.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "e33fba42-4985-4b3c-aaf9-69170114f8ee",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/normal zombie die 4.mp3


+ 14 - 0
assets/resources/data/弹球音效/normal zombie die 4.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "68134717-a37e-47ba-80c4-54e4d70defc6",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/normal zombie die 5.mp3


+ 14 - 0
assets/resources/data/弹球音效/normal zombie die 5.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "25c20df8-5551-42e7-a67f-a6b97f4f9fa6",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/normal zombie die 6.mp3


+ 14 - 0
assets/resources/data/弹球音效/normal zombie die 6.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "84f502c1-f7a4-4fb7-91a9-62922a07876d",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/normal zombie die 7.mp3


+ 14 - 0
assets/resources/data/弹球音效/normal zombie die 7.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "496f4697-af8b-43a3-83b3-7f37881f2750",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/qiukui hit.mp3


+ 14 - 0
assets/resources/data/弹球音效/qiukui hit.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "3402cd57-590a-47f1-9b85-d9b32bcfe00a",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/start zombie.mp3


+ 14 - 0
assets/resources/data/弹球音效/start zombie.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "1d2188b4-78df-4a75-b1c5-9809cff98600",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/ui bgm.mp3


+ 14 - 0
assets/resources/data/弹球音效/ui bgm.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "a37e7ec2-033e-43b8-80c6-5762684a4e4b",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/ui play.mp3


+ 14 - 0
assets/resources/data/弹球音效/ui play.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "fd02587c-8e5e-463d-84ab-518a0d263436",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/win.mp3


+ 14 - 0
assets/resources/data/弹球音效/win.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "e1697ccd-6051-420c-8a20-4e0636b69d8e",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/xianrenzhang hit.mp3


+ 14 - 0
assets/resources/data/弹球音效/xianrenzhang hit.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "08f196f6-009a-43d0-bf06-6435466fcb33",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/data/弹球音效/zhanshiAtk.mp3


+ 14 - 0
assets/resources/data/弹球音效/zhanshiAtk.mp3.meta

@@ -0,0 +1,14 @@
+{
+  "ver": "1.0.0",
+  "importer": "audio-clip",
+  "imported": true,
+  "uuid": "4c1a4e8b-8826-4c05-8a65-ef3c9a21e616",
+  "files": [
+    ".json",
+    ".mp3"
+  ],
+  "subMetas": {},
+  "userData": {
+    "downloadMode": 0
+  }
+}

BIN
assets/resources/images/UI/主界面/3.png


+ 134 - 0
assets/resources/images/UI/主界面/3.png.meta

@@ -0,0 +1,134 @@
+{
+  "ver": "1.0.27",
+  "importer": "image",
+  "imported": true,
+  "uuid": "80f212d1-c325-4e21-b2f5-19f7fa77c9b1",
+  "files": [
+    ".json",
+    ".png"
+  ],
+  "subMetas": {
+    "6c48a": {
+      "importer": "texture",
+      "uuid": "80f212d1-c325-4e21-b2f5-19f7fa77c9b1@6c48a",
+      "displayName": "3",
+      "id": "6c48a",
+      "name": "texture",
+      "userData": {
+        "wrapModeS": "clamp-to-edge",
+        "wrapModeT": "clamp-to-edge",
+        "imageUuidOrDatabaseUri": "80f212d1-c325-4e21-b2f5-19f7fa77c9b1",
+        "isUuid": true,
+        "visible": false,
+        "minfilter": "linear",
+        "magfilter": "linear",
+        "mipfilter": "none",
+        "anisotropy": 0
+      },
+      "ver": "1.0.22",
+      "imported": true,
+      "files": [
+        ".json"
+      ],
+      "subMetas": {}
+    },
+    "f9941": {
+      "importer": "sprite-frame",
+      "uuid": "80f212d1-c325-4e21-b2f5-19f7fa77c9b1@f9941",
+      "displayName": "3",
+      "id": "f9941",
+      "name": "spriteFrame",
+      "userData": {
+        "trimThreshold": 1,
+        "rotated": false,
+        "offsetX": 0,
+        "offsetY": 0,
+        "trimX": 0,
+        "trimY": 0,
+        "width": 142,
+        "height": 142,
+        "rawWidth": 142,
+        "rawHeight": 142,
+        "borderTop": 0,
+        "borderBottom": 0,
+        "borderLeft": 0,
+        "borderRight": 0,
+        "packable": true,
+        "pixelsToUnit": 100,
+        "pivotX": 0.5,
+        "pivotY": 0.5,
+        "meshType": 0,
+        "vertices": {
+          "rawPosition": [
+            -71,
+            -71,
+            0,
+            71,
+            -71,
+            0,
+            -71,
+            71,
+            0,
+            71,
+            71,
+            0
+          ],
+          "indexes": [
+            0,
+            1,
+            2,
+            2,
+            1,
+            3
+          ],
+          "uv": [
+            0,
+            142,
+            142,
+            142,
+            0,
+            0,
+            142,
+            0
+          ],
+          "nuv": [
+            0,
+            0,
+            1,
+            0,
+            0,
+            1,
+            1,
+            1
+          ],
+          "minPos": [
+            -71,
+            -71,
+            0
+          ],
+          "maxPos": [
+            71,
+            71,
+            0
+          ]
+        },
+        "isUuid": true,
+        "imageUuidOrDatabaseUri": "80f212d1-c325-4e21-b2f5-19f7fa77c9b1@6c48a",
+        "atlasUuid": "",
+        "trimType": "auto"
+      },
+      "ver": "1.0.12",
+      "imported": true,
+      "files": [
+        ".json"
+      ],
+      "subMetas": {}
+    }
+  },
+  "userData": {
+    "type": "sprite-frame",
+    "hasAlpha": true,
+    "fixAlphaTransparencyArtifacts": false,
+    "redirect": "80f212d1-c325-4e21-b2f5-19f7fa77c9b1@6c48a"
+  }
+}

+ 9 - 0
assets/scripts/AudioManager.meta

@@ -0,0 +1,9 @@
+{
+  "ver": "1.2.0",
+  "importer": "directory",
+  "imported": true,
+  "uuid": "d456a0ee-393f-466f-83e7-3c155b3dc539",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

+ 357 - 0
assets/scripts/AudioManager/AudioConfig.ts

@@ -0,0 +1,357 @@
+import { _decorator, Component } from 'cc';
+const { ccclass, property } = _decorator;
+
+/**
+ * 音频类型枚举
+ */
+export enum AudioType {
+    MUSIC = 'music',           // 背景音乐
+    UI_SOUND = 'ui_sound',     // UI音效
+    ENEMY_SOUND = 'enemy_sound', // 敌人音效
+    ENVIRONMENT_SOUND = 'environment_sound', // 环境音效
+    WEAPON_SOUND = 'weapon_sound' // 武器音效
+}
+
+/**
+ * 音频配置接口
+ */
+export interface IAudioConfig {
+    /** 音频文件路径 */
+    path: string;
+    /** 音频类型 */
+    type: AudioType;
+    /** 默认音量 (0-1) */
+    volume?: number;
+    /** 是否循环播放 */
+    loop?: boolean;
+    /** 音频描述 */
+    description?: string;
+}
+
+/**
+ * 音频分类配置
+ */
+export interface IAudioCategoryConfig {
+    /** 分类名称 */
+    name: string;
+    /** 分类类型 */
+    type: AudioType;
+    /** 分类默认音量 */
+    defaultVolume: number;
+    /** 分类描述 */
+    description: string;
+    /** 该分类下的音频列表 */
+    audios: IAudioConfig[];
+}
+
+/**
+ * 音频系统配置管理器
+ */
+@ccclass('AudioConfig')
+export class AudioConfig extends Component {
+    
+    /**
+     * 音频分类配置
+     */
+    public static readonly AUDIO_CATEGORIES: IAudioCategoryConfig[] = [
+        {
+            name: '背景音乐',
+            type: AudioType.MUSIC,
+            defaultVolume: 0.6,
+            description: '游戏背景音乐,包括主菜单、游戏内、胜利失败等场景音乐',
+            audios: [
+                {
+                    path: 'audio/music/main_menu',
+                    type: AudioType.MUSIC,
+                    volume: 0.6,
+                    loop: true,
+                    description: '主菜单背景音乐'
+                },
+                {
+                    path: 'audio/music/game_background',
+                    type: AudioType.MUSIC,
+                    volume: 0.5,
+                    loop: true,
+                    description: '游戏内背景音乐'
+                },
+                {
+                    path: 'audio/music/victory',
+                    type: AudioType.MUSIC,
+                    volume: 0.7,
+                    loop: false,
+                    description: '胜利音乐'
+                },
+                {
+                    path: 'audio/music/defeat',
+                    type: AudioType.MUSIC,
+                    volume: 0.7,
+                    loop: false,
+                    description: '失败音乐'
+                }
+            ]
+        },
+        {
+            name: 'UI音效',
+            type: AudioType.UI_SOUND,
+            defaultVolume: 0.8,
+            description: '用户界面相关音效,包括按钮点击、菜单切换等',
+            audios: [
+                {
+                    path: 'audio/ui/button_click',
+                    type: AudioType.UI_SOUND,
+                    volume: 0.8,
+                    loop: false,
+                    description: '按钮点击音效'
+                },
+                {
+                    path: 'audio/ui/button_hover',
+                    type: AudioType.UI_SOUND,
+                    volume: 0.6,
+                    loop: false,
+                    description: '按钮悬停音效'
+                },
+                {
+                    path: 'audio/ui/menu_open',
+                    type: AudioType.UI_SOUND,
+                    volume: 0.7,
+                    loop: false,
+                    description: '菜单打开音效'
+                },
+                {
+                    path: 'audio/ui/menu_close',
+                    type: AudioType.UI_SOUND,
+                    volume: 0.7,
+                    loop: false,
+                    description: '菜单关闭音效'
+                }
+            ]
+        },
+        {
+            name: '敌人音效',
+            type: AudioType.ENEMY_SOUND,
+            defaultVolume: 0.7,
+            description: '敌人相关音效,包括攻击、死亡、受击、行走等',
+            audios: [
+                // 敌人音效由 EnemyAudios 系统动态管理,基于 enemies.json 配置
+                // 这里提供一些通用的默认音效
+                {
+                    path: 'audio/enemy/default_attack',
+                    type: AudioType.ENEMY_SOUND,
+                    volume: 0.7,
+                    loop: false,
+                    description: '默认攻击音效'
+                },
+                {
+                    path: 'audio/enemy/default_death',
+                    type: AudioType.ENEMY_SOUND,
+                    volume: 0.8,
+                    loop: false,
+                    description: '默认死亡音效'
+                },
+                {
+                    path: 'audio/enemy/default_hit',
+                    type: AudioType.ENEMY_SOUND,
+                    volume: 0.6,
+                    loop: false,
+                    description: '默认受击音效'
+                },
+                {
+                    path: 'audio/enemy/default_walk',
+                    type: AudioType.ENEMY_SOUND,
+                    volume: 0.4,
+                    loop: true,
+                    description: '默认行走音效'
+                }
+            ]
+        },
+        {
+            name: '环境音效',
+            type: AudioType.ENVIRONMENT_SOUND,
+            defaultVolume: 0.5,
+            description: '环境相关音效,包括风声、水声、爆炸等',
+            audios: [
+                {
+                    path: 'audio/environment/wind',
+                    type: AudioType.ENVIRONMENT_SOUND,
+                    volume: 0.3,
+                    loop: true,
+                    description: '风声'
+                },
+                {
+                    path: 'audio/environment/explosion',
+                    type: AudioType.ENVIRONMENT_SOUND,
+                    volume: 0.8,
+                    loop: false,
+                    description: '爆炸音效'
+                },
+                {
+                    path: 'audio/environment/footsteps',
+                    type: AudioType.ENVIRONMENT_SOUND,
+                    volume: 0.4,
+                    loop: false,
+                    description: '脚步声'
+                }
+            ]
+        },
+        {
+            name: '武器音效',
+            type: AudioType.WEAPON_SOUND,
+            defaultVolume: 0.8,
+            description: '武器相关音效,包括射击、装弹、切换武器等',
+            audios: [
+                {
+                    path: 'audio/weapon/gun_shot',
+                    type: AudioType.WEAPON_SOUND,
+                    volume: 0.8,
+                    loop: false,
+                    description: '枪声'
+                },
+                {
+                    path: 'audio/weapon/reload',
+                    type: AudioType.WEAPON_SOUND,
+                    volume: 0.6,
+                    loop: false,
+                    description: '装弹音效'
+                },
+                {
+                    path: 'audio/weapon/weapon_switch',
+                    type: AudioType.WEAPON_SOUND,
+                    volume: 0.7,
+                    loop: false,
+                    description: '切换武器音效'
+                }
+            ]
+        }
+    ];
+    
+    /**
+     * 根据音频类型获取分类配置
+     * @param type 音频类型
+     * @returns 分类配置
+     */
+    public static getCategoryConfig(type: AudioType): IAudioCategoryConfig | null {
+        return this.AUDIO_CATEGORIES.find(category => category.type === type) || null;
+    }
+    
+    /**
+     * 根据路径获取音频配置
+     * @param path 音频路径
+     * @returns 音频配置
+     */
+    public static getAudioConfig(path: string): IAudioConfig | null {
+        for (const category of this.AUDIO_CATEGORIES) {
+            const audio = category.audios.find(audio => audio.path === path);
+            if (audio) {
+                return audio;
+            }
+        }
+        return null;
+    }
+    
+    /**
+     * 获取指定类型的所有音频配置
+     * @param type 音频类型
+     * @returns 音频配置数组
+     */
+    public static getAudiosByType(type: AudioType): IAudioConfig[] {
+        const category = this.getCategoryConfig(type);
+        return category ? category.audios : [];
+    }
+    
+    /**
+     * 获取默认音量
+     * @param type 音频类型
+     * @returns 默认音量
+     */
+    public static getDefaultVolume(type: AudioType): number {
+        const category = this.getCategoryConfig(type);
+        return category ? category.defaultVolume : 0.5;
+    }
+    
+    /**
+     * 验证音频路径是否存在于配置中
+     * @param path 音频路径
+     * @returns 是否存在
+     */
+    public static isValidAudioPath(path: string): boolean {
+        return this.getAudioConfig(path) !== null;
+    }
+    
+    /**
+     * 获取所有音频类型
+     * @returns 音频类型数组
+     */
+    public static getAllAudioTypes(): AudioType[] {
+        return [
+            AudioType.MUSIC,
+            AudioType.UI_SOUND,
+            AudioType.ENEMY_SOUND,
+            AudioType.ENVIRONMENT_SOUND,
+            AudioType.WEAPON_SOUND
+        ];
+    }
+    
+    /**
+     * 获取音频系统统计信息
+     * @returns 统计信息
+     */
+    public static getAudioStats(): {
+        totalCategories: number;
+        totalAudios: number;
+        audiosByType: Record<AudioType, number>;
+    } {
+        const audiosByType = {} as Record<AudioType, number>;
+        let totalAudios = 0;
+        
+        for (const category of this.AUDIO_CATEGORIES) {
+            audiosByType[category.type] = category.audios.length;
+            totalAudios += category.audios.length;
+        }
+        
+        return {
+            totalCategories: this.AUDIO_CATEGORIES.length,
+            totalAudios,
+            audiosByType
+        };
+    }
+}
+
+/**
+ * 音频配置的静态访问接口
+ */
+export class AudioConfigHelper {
+    /**
+     * 获取音乐配置
+     */
+    static get music() {
+        return AudioConfig.getAudiosByType(AudioType.MUSIC);
+    }
+    
+    /**
+     * 获取UI音效配置
+     */
+    static get uiSounds() {
+        return AudioConfig.getAudiosByType(AudioType.UI_SOUND);
+    }
+    
+    /**
+     * 获取敌人音效配置
+     */
+    static get enemySounds() {
+        return AudioConfig.getAudiosByType(AudioType.ENEMY_SOUND);
+    }
+    
+    /**
+     * 获取环境音效配置
+     */
+    static get environmentSounds() {
+        return AudioConfig.getAudiosByType(AudioType.ENVIRONMENT_SOUND);
+    }
+    
+    /**
+     * 获取武器音效配置
+     */
+    static get weaponSounds() {
+        return AudioConfig.getAudiosByType(AudioType.WEAPON_SOUND);
+    }
+}

+ 9 - 0
assets/scripts/AudioManager/AudioConfig.ts.meta

@@ -0,0 +1,9 @@
+{
+  "ver": "4.0.24",
+  "importer": "typescript",
+  "imported": true,
+  "uuid": "a7ed8454-9f02-4552-9f0d-7a9c4c2d67a7",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

+ 665 - 0
assets/scripts/AudioManager/AudioManager.ts

@@ -0,0 +1,665 @@
+import { _decorator, Component, AudioClip, AudioSource, resources, Node } from 'cc';
+const { ccclass, property } = _decorator;
+
+/**
+ * 音频管理器
+ * 统一管理游戏中的音乐和音效播放
+ */
+@ccclass('AudioManager')
+export class AudioManager extends Component {
+    // 音频源组件
+    @property({ type: AudioSource, tooltip: '背景音乐播放器' })
+    public musicAudioSource: AudioSource = null;
+    
+    @property({ type: AudioSource, tooltip: 'UI音效播放器' })
+    public uiSoundAudioSource: AudioSource = null;
+    
+    @property({ type: AudioSource, tooltip: '敌人音效播放器' })
+    public enemySoundAudioSource: AudioSource = null;
+    
+    @property({ type: AudioSource, tooltip: '环境音效播放器' })
+    public environmentSoundAudioSource: AudioSource = null;
+    
+    @property({ type: AudioSource, tooltip: '武器音效播放器' })
+    public weaponSoundAudioSource: AudioSource = null;
+    
+    // 音量设置
+    private musicVolume: number = 0.8;
+    private uiSoundVolume: number = 0.8;
+    private enemySoundVolume: number = 0.8;
+    private environmentSoundVolume: number = 0.8;
+    private weaponSoundVolume: number = 0.8;
+    
+    // 主音效音量(向后兼容)
+    private soundEffectVolume: number = 0.8;
+    
+    // 当前播放的音乐
+    private currentMusicClip: AudioClip = null;
+    
+    // 单例实例
+    private static _instance: AudioManager = null;
+    
+    onLoad() {
+        // 设置单例
+        if (AudioManager._instance === null) {
+            AudioManager._instance = this;
+            // 防止场景切换时被销毁
+            // this.node.parent = null;
+            // director.addPersistRootNode(this.node);
+        } else {
+            this.node.destroy();
+            return;
+        }
+        
+        this.initializeAudioSources();
+    }
+    
+    /**
+     * 获取单例实例
+     */
+    public static getInstance(): AudioManager {
+        return AudioManager._instance;
+    }
+    
+    /**
+     * 初始化音频源
+     */
+    private initializeAudioSources() {
+        // 如果没有指定音频源,尝试自动创建
+        if (!this.musicAudioSource) {
+            const musicNode = new Node('MusicAudioSource');
+            musicNode.parent = this.node;
+            this.musicAudioSource = musicNode.addComponent(AudioSource);
+            this.musicAudioSource.loop = true;
+        }
+        
+        if (!this.uiSoundAudioSource) {
+            const uiSfxNode = new Node('UISoundAudioSource');
+            uiSfxNode.parent = this.node;
+            this.uiSoundAudioSource = uiSfxNode.addComponent(AudioSource);
+            this.uiSoundAudioSource.loop = false;
+        }
+        
+        if (!this.enemySoundAudioSource) {
+            const enemySfxNode = new Node('EnemySoundAudioSource');
+            enemySfxNode.parent = this.node;
+            this.enemySoundAudioSource = enemySfxNode.addComponent(AudioSource);
+            this.enemySoundAudioSource.loop = false;
+        }
+        
+        if (!this.environmentSoundAudioSource) {
+            const envSfxNode = new Node('EnvironmentSoundAudioSource');
+            envSfxNode.parent = this.node;
+            this.environmentSoundAudioSource = envSfxNode.addComponent(AudioSource);
+            this.environmentSoundAudioSource.loop = false;
+        }
+        
+        if (!this.weaponSoundAudioSource) {
+            const weaponSfxNode = new Node('WeaponSoundAudioSource');
+            weaponSfxNode.parent = this.node;
+            this.weaponSoundAudioSource = weaponSfxNode.addComponent(AudioSource);
+            this.weaponSoundAudioSource.loop = false;
+        }
+        
+
+        
+        // 设置初始音量
+        this.updateAllVolumes();
+    }
+    
+    /**
+     * 播放背景音乐
+     * @param musicPath 音乐资源路径
+     * @param loop 是否循环播放
+     */
+    public playMusic(musicPath: string, loop: boolean = true) {
+        if (!this.musicAudioSource) {
+            console.warn('[AudioManager] 音乐播放器未初始化');
+            return;
+        }
+        
+        resources.load(musicPath, AudioClip, (err, clip) => {
+            if (err) {
+                console.error(`[AudioManager] 加载音乐失败: ${musicPath}`, err);
+                return;
+            }
+            
+            this.currentMusicClip = clip;
+            this.musicAudioSource.clip = clip;
+            this.musicAudioSource.loop = loop;
+            this.musicAudioSource.play();
+            
+            console.log(`[AudioManager] 播放音乐: ${musicPath}`);
+        });
+    }
+    
+    /**
+     * 停止背景音乐
+     */
+    public stopMusic() {
+        if (this.musicAudioSource && this.musicAudioSource.playing) {
+            this.musicAudioSource.stop();
+            console.log('[AudioManager] 停止音乐播放');
+        }
+    }
+    
+    /**
+     * 暂停背景音乐
+     */
+    public pauseMusic() {
+        if (this.musicAudioSource && this.musicAudioSource.playing) {
+            this.musicAudioSource.pause();
+            console.log('[AudioManager] 暂停音乐播放');
+        }
+    }
+    
+    /**
+     * 恢复背景音乐
+     */
+    public resumeMusic() {
+        if (this.musicAudioSource && this.currentMusicClip) {
+            this.musicAudioSource.play();
+            console.log('[AudioManager] 恢复音乐播放');
+        }
+    }
+    
+    /**
+     * 播放音效(向后兼容)
+     * @param sfxPath 音效资源路径
+     * @param volume 音量(可选,0-1)
+     */
+    public playSoundEffect(sfxPath: string, volume?: number) {
+        this.playUISound(sfxPath, volume);
+    }
+    
+    /**
+     * 播放UI音效
+     * @param sfxPath 音效资源路径
+     * @param volume 音量(可选,0-1)
+     */
+    public playUISound(sfxPath: string, volume?: number) {
+        this.playSound(this.uiSoundAudioSource, sfxPath, volume, this.uiSoundVolume, 'UI音效');
+    }
+    
+    /**
+     * 播放敌人音效
+     * @param sfxPath 音效资源路径
+     * @param volume 音量(可选,0-1)
+     */
+    public playEnemySound(sfxPath: string, volume?: number) {
+        this.playSound(this.enemySoundAudioSource, sfxPath, volume, this.enemySoundVolume, '敌人音效');
+    }
+    
+    /**
+     * 播放环境音效
+     * @param sfxPath 音效资源路径
+     * @param volume 音量(可选,0-1)
+     */
+    public playEnvironmentSound(sfxPath: string, volume?: number) {
+        this.playSound(this.environmentSoundAudioSource, sfxPath, volume, this.environmentSoundVolume, '环境音效');
+    }
+    
+    /**
+     * 播放武器音效
+     * @param sfxPath 音效资源路径
+     * @param volume 音量(可选,0-1)
+     */
+    public playWeaponSound(sfxPath: string, volume?: number) {
+        this.playSound(this.weaponSoundAudioSource, sfxPath, volume, this.weaponSoundVolume, '武器音效');
+    }
+    
+    /**
+     * 通用音效播放方法
+     * @param audioSource 音频源
+     * @param sfxPath 音效资源路径
+     * @param volume 音量(可选,0-1)
+     * @param baseVolume 基础音量
+     * @param soundType 音效类型(用于日志)
+     */
+    private playSound(audioSource: AudioSource, sfxPath: string, volume: number | undefined, baseVolume: number, soundType: string) {
+        if (!audioSource) {
+            console.warn(`[AudioManager] ${soundType}播放器未初始化`);
+            return;
+        }
+        
+        resources.load(sfxPath, AudioClip, (err, clip) => {
+            if (err) {
+                console.error(`[AudioManager] 加载${soundType}失败: ${sfxPath}`, err);
+                return;
+            }
+            
+            // 设置临时音量(如果指定)
+            const originalVolume = audioSource.volume;
+            if (volume !== undefined) {
+                audioSource.volume = volume * baseVolume;
+            }
+            
+            audioSource.playOneShot(clip);
+            
+            // 恢复原始音量
+            if (volume !== undefined) {
+                audioSource.volume = originalVolume;
+            }
+            
+            console.log(`[AudioManager] 播放${soundType}: ${sfxPath}`);
+        });
+    }
+    
+    /**
+     * 设置音乐音量
+     * @param volume 音量值(0-1)
+     */
+    public setMusicVolume(volume: number) {
+        this.musicVolume = Math.max(0, Math.min(1, volume));
+        this.updateMusicVolume();
+        //console.log(`[AudioManager] 设置音乐音量: ${this.musicVolume}`);
+    }
+    
+    /**
+     * 设置音效音量(向后兼容)
+     * @param volume 音量值(0-1)
+     */
+    public setSoundEffectVolume(volume: number) {
+        this.soundEffectVolume = Math.max(0, Math.min(1, volume));
+        this.setUISoundVolume(volume);
+        //console.log(`[AudioManager] 设置音效音量: ${this.soundEffectVolume}`);
+    }
+    
+    /**
+     * 设置UI音效音量
+     * @param volume 音量值(0-1)
+     */
+    public setUISoundVolume(volume: number) {
+        this.uiSoundVolume = Math.max(0, Math.min(1, volume));
+        this.updateUISoundVolume();
+    }
+    
+    /**
+     * 设置敌人音效音量
+     * @param volume 音量值(0-1)
+     */
+    public setEnemySoundVolume(volume: number) {
+        this.enemySoundVolume = Math.max(0, Math.min(1, volume));
+        this.updateEnemySoundVolume();
+    }
+    
+    /**
+     * 设置环境音效音量
+     * @param volume 音量值(0-1)
+     */
+    public setEnvironmentSoundVolume(volume: number) {
+        this.environmentSoundVolume = Math.max(0, Math.min(1, volume));
+        this.updateEnvironmentSoundVolume();
+    }
+    
+    /**
+     * 设置武器音效音量
+     * @param volume 音量值(0-1)
+     */
+    public setWeaponSoundVolume(volume: number) {
+        this.weaponSoundVolume = Math.max(0, Math.min(1, volume));
+        this.updateWeaponSoundVolume();
+    }
+    
+    /**
+     * 设置所有音效音量
+     * @param volume 音量值(0-1)
+     */
+    public setAllSoundVolume(volume: number) {
+        this.setUISoundVolume(volume);
+        this.setEnemySoundVolume(volume);
+        this.setEnvironmentSoundVolume(volume);
+        this.setWeaponSoundVolume(volume);
+        this.setSoundEffectVolume(volume);
+    }
+    
+    /**
+     * 获取音乐音量
+     */
+    public getMusicVolume(): number {
+        return this.musicVolume;
+    }
+    
+    /**
+     * 获取音效音量(向后兼容)
+     */
+    public getSoundEffectVolume(): number {
+        return this.soundEffectVolume;
+    }
+    
+    /**
+     * 获取UI音效音量
+     */
+    public getUISoundVolume(): number {
+        return this.uiSoundVolume;
+    }
+    
+    /**
+     * 获取敌人音效音量
+     */
+    public getEnemySoundVolume(): number {
+        return this.enemySoundVolume;
+    }
+    
+    /**
+     * 获取环境音效音量
+     */
+    public getEnvironmentSoundVolume(): number {
+        return this.environmentSoundVolume;
+    }
+    
+    /**
+     * 获取武器音效音量
+     */
+    public getWeaponSoundVolume(): number {
+        return this.weaponSoundVolume;
+    }
+    
+    /**
+     * 更新音乐音量
+     */
+    private updateMusicVolume() {
+        if (this.musicAudioSource) {
+            this.musicAudioSource.volume = this.musicVolume;
+        }
+    }
+    
+
+    
+    /**
+     * 更新UI音效音量
+     */
+    private updateUISoundVolume() {
+        if (this.uiSoundAudioSource) {
+            this.uiSoundAudioSource.volume = this.uiSoundVolume;
+        }
+    }
+    
+    /**
+     * 更新敌人音效音量
+     */
+    private updateEnemySoundVolume() {
+        if (this.enemySoundAudioSource) {
+            this.enemySoundAudioSource.volume = this.enemySoundVolume;
+        }
+    }
+    
+    /**
+     * 更新环境音效音量
+     */
+    private updateEnvironmentSoundVolume() {
+        if (this.environmentSoundAudioSource) {
+            this.environmentSoundAudioSource.volume = this.environmentSoundVolume;
+        }
+    }
+    
+    /**
+     * 更新武器音效音量
+     */
+    private updateWeaponSoundVolume() {
+        if (this.weaponSoundAudioSource) {
+            this.weaponSoundAudioSource.volume = this.weaponSoundVolume;
+        }
+    }
+    
+    /**
+     * 更新所有音量
+     */
+    private updateAllVolumes() {
+        this.updateMusicVolume();
+        this.updateUISoundVolume();
+        this.updateEnemySoundVolume();
+        this.updateEnvironmentSoundVolume();
+        this.updateWeaponSoundVolume();
+
+    }
+    
+    /**
+     * 静音所有音频
+     */
+    public muteAll() {
+        this.setMusicVolume(0);
+        this.setAllSoundVolume(0);
+    }
+    
+    /**
+     * 恢复所有音频音量
+     */
+    public unmuteAll() {
+        this.setMusicVolume(0.8);
+        this.setAllSoundVolume(0.8);
+    }
+    
+    /**
+     * 静音所有音效(保留音乐)
+     */
+    public muteAllSounds() {
+        this.setAllSoundVolume(0);
+    }
+    
+    /**
+     * 恢复所有音效音量(保留音乐)
+     */
+    public unmuteAllSounds() {
+        this.setAllSoundVolume(0.8);
+    }
+    
+    /**
+     * 检查音乐是否正在播放
+     */
+    public isMusicPlaying(): boolean {
+        return this.musicAudioSource && this.musicAudioSource.playing;
+    }
+    
+    onDestroy() {
+        if (AudioManager._instance === this) {
+            AudioManager._instance = null;
+        }
+    }
+}
+
+/**
+ * 音频管理器的静态接口
+ * 提供便捷的全局访问方法
+ */
+export class Audio {
+    /**
+     * 播放背景音乐
+     */
+    static playMusic(musicPath: string, loop: boolean = true) {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.playMusic(musicPath, loop);
+        }
+    }
+    
+    /**
+     * 播放音效(向后兼容)
+     */
+    static playSFX(sfxPath: string, volume?: number) {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.playSoundEffect(sfxPath, volume);
+        }
+    }
+    
+    /**
+     * 播放UI音效
+     */
+    static playUISound(sfxPath: string, volume?: number) {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.playUISound(sfxPath, volume);
+        }
+    }
+    
+    /**
+     * 播放敌人音效
+     */
+    static playEnemySound(sfxPath: string, volume?: number) {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.playEnemySound(sfxPath, volume);
+        }
+    }
+    
+    /**
+     * 播放环境音效
+     */
+    static playEnvironmentSound(sfxPath: string, volume?: number) {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.playEnvironmentSound(sfxPath, volume);
+        }
+    }
+    
+    /**
+     * 播放武器音效
+     */
+    static playWeaponSound(sfxPath: string, volume?: number) {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.playWeaponSound(sfxPath, volume);
+        }
+    }
+    
+    /**
+     * 设置音乐音量
+     */
+    static setMusicVolume(volume: number) {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.setMusicVolume(volume);
+        }
+    }
+    
+    /**
+     * 设置音效音量(向后兼容)
+     */
+    static setSFXVolume(volume: number) {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.setSoundEffectVolume(volume);
+        }
+    }
+    
+    /**
+     * 设置UI音效音量
+     */
+    static setUISoundVolume(volume: number) {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.setUISoundVolume(volume);
+        }
+    }
+    
+    /**
+     * 设置敌人音效音量
+     */
+    static setEnemySoundVolume(volume: number) {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.setEnemySoundVolume(volume);
+        }
+    }
+    
+    /**
+     * 设置环境音效音量
+     */
+    static setEnvironmentSoundVolume(volume: number) {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.setEnvironmentSoundVolume(volume);
+        }
+    }
+    
+    /**
+     * 设置武器音效音量
+     */
+    static setWeaponSoundVolume(volume: number) {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.setWeaponSoundVolume(volume);
+        }
+    }
+    
+    /**
+     * 设置所有音效音量
+     */
+    static setAllSoundVolume(volume: number) {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.setAllSoundVolume(volume);
+        }
+    }
+    
+    /**
+     * 停止音乐
+     */
+    static stopMusic() {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.stopMusic();
+        }
+    }
+    
+    /**
+     * 暂停音乐
+     */
+    static pauseMusic() {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.pauseMusic();
+        }
+    }
+    
+    /**
+     * 恢复音乐
+     */
+    static resumeMusic() {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.resumeMusic();
+        }
+    }
+    
+    /**
+     * 静音所有音频
+     */
+    static muteAll() {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.muteAll();
+        }
+    }
+    
+    /**
+     * 恢复所有音频
+     */
+    static unmuteAll() {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.unmuteAll();
+        }
+    }
+    
+    /**
+     * 静音所有音效(保留音乐)
+     */
+    static muteAllSounds() {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.muteAllSounds();
+        }
+    }
+    
+    /**
+     * 恢复所有音效(保留音乐)
+     */
+    static unmuteAllSounds() {
+        const manager = AudioManager.getInstance();
+        if (manager) {
+            manager.unmuteAllSounds();
+        }
+    }
+}

+ 1 - 1
assets/scripts/Core/AudioManager.ts.meta → assets/scripts/AudioManager/AudioManager.ts.meta

@@ -2,7 +2,7 @@
   "ver": "4.0.24",
   "importer": "typescript",
   "imported": true,
-  "uuid": "dd3e5d1f-933f-41b0-9580-f180b03133f1",
+  "uuid": "7833c090-818f-40d8-8a31-0c7a5024cccf",
   "files": [],
   "subMetas": {},
   "userData": {}

+ 165 - 0
assets/scripts/AudioManager/EnemyAudios.ts

@@ -0,0 +1,165 @@
+import { _decorator, Component, Node } from 'cc';
+import { AudioManager } from './AudioManager';
+const { ccclass, property } = _decorator;
+
+/**
+ * 敌人音效管理器
+ * 负责播放敌人相关的各种音效
+ */
+@ccclass('EnemyAudios')
+export class EnemyAudios extends Component {
+    // 单例实例
+    private static _instance: EnemyAudios = null;
+    
+    // 音频管理器引用
+    @property({ type: AudioManager, tooltip: '音频管理器组件引用' })
+    public audioManager: AudioManager = null;
+    
+    onLoad() {
+        console.log('[EnemyAudios] onLoad 被调用,节点路径:', this.getNodePath());
+        
+        // 设置单例
+        if (EnemyAudios._instance === null) {
+            EnemyAudios._instance = this;
+            console.log('[EnemyAudios] 单例实例已设置');
+        } else {
+            console.warn('[EnemyAudios] 单例实例已存在,销毁重复节点');
+            this.node.destroy();
+            return;
+        }
+        
+        // 检查音频管理器引用
+        if (!this.audioManager) {
+            console.error('[EnemyAudios] AudioManager组件未绑定,请在编辑器中将AudioManager节点拖拽到audioManager属性上');
+        } else {
+            console.log('[EnemyAudios] AudioManager组件绑定成功');
+        }
+    }
+    
+    /**
+     * 获取单例实例
+     */
+    public static getInstance(): EnemyAudios {
+        if (!EnemyAudios._instance) {
+            console.error('[EnemyAudios] 单例实例未初始化,请确保EnemyAudios组件已挂载到场景中');
+        }
+        return EnemyAudios._instance;
+    }
+    
+    /**
+     * 获取节点路径(用于调试)
+     */
+    private getNodePath(): string {
+        let path = this.node.name;
+        let current = this.node;
+        
+        while (current.parent) {
+            current = current.parent;
+            path = current.name + '/' + path;
+        }
+        
+        return path;
+    }
+    
+    /**
+     * 播放敌人攻击音效
+     * @param enemyConfig 敌人配置数据
+     */
+    public playAttackSound(enemyConfig: any): void {
+        if (!this.audioManager || !enemyConfig) return;
+        
+        // 优先使用audio配置中的attack_sound
+        let soundPath = enemyConfig.audio?.attack_sound;
+        
+        // 如果audio配置中没有或为"Null",则使用audioConfig中的attackSound
+        if (!soundPath || soundPath === 'Null' || soundPath === 'nan') {
+            soundPath = enemyConfig.audioConfig?.attackSound;
+        }
+        
+        // 如果还是没有有效音效路径,使用默认音效
+        if (!soundPath || soundPath === 'Null' || soundPath === 'nan' || soundPath === '') {
+            soundPath = '弹球音效/hammer1.mp3'; // 默认攻击音效
+        }
+        
+        // 获取音量设置
+        const volume = enemyConfig.audioConfig?.volume || 1.0;
+        
+        console.log(`[EnemyAudios] 播放攻击音效: ${soundPath}`);
+        this.audioManager.playEnemySound(soundPath, volume);
+    }
+    
+    /**
+     * 播放敌人死亡音效
+     * @param enemyConfig 敌人配置数据
+     */
+    public playDeathSound(enemyConfig: any): void {
+        if (!this.audioManager || !enemyConfig) return;
+        
+        // 优先使用audio配置中的death_sound
+        let soundPath = enemyConfig.audio?.death_sound;
+        
+        // 如果audio配置中没有或为"Null",则使用audioConfig中的deathSound
+        if (!soundPath || soundPath === 'Null' || soundPath === 'nan') {
+            soundPath = enemyConfig.audioConfig?.deathSound;
+        }
+        
+        // 如果还是没有有效音效路径,使用默认音效
+        if (!soundPath || soundPath === 'Null' || soundPath === 'nan' || soundPath === '') {
+            soundPath = '弹球音效/normal zombie die 1.mp3'; // 默认死亡音效
+        }
+        
+        // 获取音量设置
+        const volume = enemyConfig.audioConfig?.volume || 1.0;
+        
+        console.log(`[EnemyAudios] 播放死亡音效: ${soundPath}`);
+        this.audioManager.playEnemySound(soundPath, volume);
+    }
+    
+
+    
+
+    
+
+    
+    onDestroy() {
+        if (EnemyAudios._instance === this) {
+            EnemyAudios._instance = null;
+        }
+    }
+}
+
+/**
+ * 敌人音效的静态接口
+ * 提供便捷的全局访问方法
+ */
+export class EnemyAudio {
+    /**
+     * 播放敌人攻击音效
+     * @param enemyConfig 敌人配置数据
+     */
+    static playAttackSound(enemyConfig: any): void {
+        console.log('[EnemyAudio] 静态方法 playAttackSound 被调用');
+        const instance = EnemyAudios.getInstance();
+        if (instance) {
+            instance.playAttackSound(enemyConfig);
+        } else {
+            console.error('[EnemyAudio] EnemyAudios实例未找到,无法播放攻击音效');
+        }
+    }
+
+    /**
+     * 播放敌人死亡音效
+     * @param enemyConfig 敌人配置数据
+     */
+    static playDeathSound(enemyConfig: any): void {
+        console.log('[EnemyAudio] 静态方法 playDeathSound 被调用');
+        const instance = EnemyAudios.getInstance();
+        if (instance) {
+            instance.playDeathSound(enemyConfig);
+        } else {
+            console.error('[EnemyAudio] EnemyAudios实例未找到,无法播放死亡音效');
+        }
+    }
+
+
+}

+ 9 - 0
assets/scripts/AudioManager/EnemyAudios.ts.meta

@@ -0,0 +1,9 @@
+{
+  "ver": "4.0.24",
+  "importer": "typescript",
+  "imported": true,
+  "uuid": "704d8a81-7c4b-4ab7-bb1b-dacd6744b29b",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

+ 11 - 0
assets/scripts/CombatSystem/EnemyInstance.ts

@@ -3,6 +3,7 @@ import { sp } from 'cc';
 import { DamageNumberAni } from '../Animations/DamageNumberAni';
 import { HPBarAnimation } from '../Animations/HPBarAnimation';
 import { EnemyComponent } from './EnemyComponent';
+import { EnemyAudio } from '../AudioManager/EnemyAudios';
 const { ccclass, property } = _decorator;
 
 // 前向声明EnemyController接口,避免循环引用
@@ -351,6 +352,8 @@ export class EnemyInstance extends Component {
         // 日志显示武器的真实伤害值,而不是血量差值
         console.log(`[EnemyInstance] 敌人受到伤害: ${damage} (武器伤害), 实际血量损失: ${actualHealthLoss}, 剩余血量: ${this.health}/${this.maxHealth}`);
         
+        // 受击音效已移除
+        
         // 显示伤害数字动画(在敌人头顶)- 显示武器的真实伤害
         // 优先使用EnemyController节点上的DamageNumberAni组件实例
         if (this.controller) {
@@ -507,6 +510,9 @@ export class EnemyInstance extends Component {
             return;
         }
         
+        // 播放攻击音效
+        EnemyAudio.playAttackSound(this.enemyConfig);
+        
         // 对墙体造成伤害
         this.controller.damageWall(this.attackPower);
     }
@@ -521,6 +527,7 @@ export class EnemyInstance extends Component {
 
         if (this.skeleton.findAnimation(walkName)) {
             this.skeleton.setAnimation(0, walkName, true);
+            // 行走音效已移除
         } else if (this.skeleton.findAnimation(idleName)) {
             this.skeleton.setAnimation(0, idleName, true);
         }
@@ -542,6 +549,10 @@ export class EnemyInstance extends Component {
 
     private playDeathAnimationAndDestroy() {
         console.log(`[EnemyInstance] 开始播放死亡动画并销毁`);
+        
+        // 播放死亡音效
+        EnemyAudio.playDeathSound(this.enemyConfig);
+        
         if (this.skeleton) {
             const enemyComp = this.getComponent('EnemyComponent') as any;
             const anims = enemyComp?.getAnimations ? enemyComp.getAnimations() : {};

+ 1 - 1
assets/scripts/CombatSystem/MenuSystem/SoundController.ts

@@ -1,5 +1,5 @@
 import { _decorator, Component, Node, Slider, Button, Sprite, SpriteFrame, ProgressBar, resources, tween, Vec3 } from 'cc';
-import { AudioManager } from '../../Core/AudioManager';
+import { AudioManager } from '../../AudioManager/AudioManager';
 import { SaveDataManager } from '../../LevelSystem/SaveDataManager';
 const { ccclass, property } = _decorator;
 

+ 0 - 319
assets/scripts/Core/AudioManager.ts

@@ -1,319 +0,0 @@
-import { _decorator, Component, AudioClip, AudioSource, resources, Node } from 'cc';
-const { ccclass, property } = _decorator;
-
-/**
- * 音频管理器
- * 统一管理游戏中的音乐和音效播放
- */
-@ccclass('AudioManager')
-export class AudioManager extends Component {
-    // 音频源组件
-    @property({ type: AudioSource, tooltip: '音乐播放器' })
-    public musicAudioSource: AudioSource = null;
-    
-    @property({ type: AudioSource, tooltip: '音效播放器' })
-    public soundEffectAudioSource: AudioSource = null;
-    
-    // 音量设置
-    private musicVolume: number = 0.8;
-    private soundEffectVolume: number = 0.8;
-    
-    // 当前播放的音乐
-    private currentMusicClip: AudioClip = null;
-    
-    // 单例实例
-    private static _instance: AudioManager = null;
-    
-    onLoad() {
-        // 设置单例
-        if (AudioManager._instance === null) {
-            AudioManager._instance = this;
-            // 防止场景切换时被销毁
-            // this.node.parent = null;
-            // director.addPersistRootNode(this.node);
-        } else {
-            this.node.destroy();
-            return;
-        }
-        
-        this.initializeAudioSources();
-    }
-    
-    /**
-     * 获取单例实例
-     */
-    public static getInstance(): AudioManager {
-        return AudioManager._instance;
-    }
-    
-    /**
-     * 初始化音频源
-     */
-    private initializeAudioSources() {
-        // 如果没有指定音频源,尝试自动创建
-        if (!this.musicAudioSource) {
-            const musicNode = new Node('MusicAudioSource');
-            musicNode.parent = this.node;
-            this.musicAudioSource = musicNode.addComponent(AudioSource);
-            this.musicAudioSource.loop = true;
-        }
-        
-        if (!this.soundEffectAudioSource) {
-            const sfxNode = new Node('SFXAudioSource');
-            sfxNode.parent = this.node;
-            this.soundEffectAudioSource = sfxNode.addComponent(AudioSource);
-            this.soundEffectAudioSource.loop = false;
-        }
-        
-        // 设置初始音量
-        this.updateMusicVolume();
-        this.updateSoundEffectVolume();
-    }
-    
-    /**
-     * 播放背景音乐
-     * @param musicPath 音乐资源路径
-     * @param loop 是否循环播放
-     */
-    public playMusic(musicPath: string, loop: boolean = true) {
-        if (!this.musicAudioSource) {
-            console.warn('[AudioManager] 音乐播放器未初始化');
-            return;
-        }
-        
-        resources.load(musicPath, AudioClip, (err, clip) => {
-            if (err) {
-                console.error(`[AudioManager] 加载音乐失败: ${musicPath}`, err);
-                return;
-            }
-            
-            this.currentMusicClip = clip;
-            this.musicAudioSource.clip = clip;
-            this.musicAudioSource.loop = loop;
-            this.musicAudioSource.play();
-            
-            console.log(`[AudioManager] 播放音乐: ${musicPath}`);
-        });
-    }
-    
-    /**
-     * 停止背景音乐
-     */
-    public stopMusic() {
-        if (this.musicAudioSource && this.musicAudioSource.playing) {
-            this.musicAudioSource.stop();
-            console.log('[AudioManager] 停止音乐播放');
-        }
-    }
-    
-    /**
-     * 暂停背景音乐
-     */
-    public pauseMusic() {
-        if (this.musicAudioSource && this.musicAudioSource.playing) {
-            this.musicAudioSource.pause();
-            console.log('[AudioManager] 暂停音乐播放');
-        }
-    }
-    
-    /**
-     * 恢复背景音乐
-     */
-    public resumeMusic() {
-        if (this.musicAudioSource && this.currentMusicClip) {
-            this.musicAudioSource.play();
-            console.log('[AudioManager] 恢复音乐播放');
-        }
-    }
-    
-    /**
-     * 播放音效
-     * @param sfxPath 音效资源路径
-     * @param volume 音量(可选,0-1)
-     */
-    public playSoundEffect(sfxPath: string, volume?: number) {
-        if (!this.soundEffectAudioSource) {
-            console.warn('[AudioManager] 音效播放器未初始化');
-            return;
-        }
-        
-        resources.load(sfxPath, AudioClip, (err, clip) => {
-            if (err) {
-                console.error(`[AudioManager] 加载音效失败: ${sfxPath}`, err);
-                return;
-            }
-            
-            // 设置临时音量(如果指定)
-            const originalVolume = this.soundEffectAudioSource.volume;
-            if (volume !== undefined) {
-                this.soundEffectAudioSource.volume = volume * this.soundEffectVolume;
-            }
-            
-            this.soundEffectAudioSource.playOneShot(clip);
-            
-            // 恢复原始音量
-            if (volume !== undefined) {
-                this.soundEffectAudioSource.volume = originalVolume;
-            }
-            
-            console.log(`[AudioManager] 播放音效: ${sfxPath}`);
-        });
-    }
-    
-    /**
-     * 设置音乐音量
-     * @param volume 音量值(0-1)
-     */
-    public setMusicVolume(volume: number) {
-        this.musicVolume = Math.max(0, Math.min(1, volume));
-        this.updateMusicVolume();
-        //console.log(`[AudioManager] 设置音乐音量: ${this.musicVolume}`);
-    }
-    
-    /**
-     * 设置音效音量
-     * @param volume 音量值(0-1)
-     */
-    public setSoundEffectVolume(volume: number) {
-        this.soundEffectVolume = Math.max(0, Math.min(1, volume));
-        this.updateSoundEffectVolume();
-        //console.log(`[AudioManager] 设置音效音量: ${this.soundEffectVolume}`);
-    }
-    
-    /**
-     * 获取音乐音量
-     */
-    public getMusicVolume(): number {
-        return this.musicVolume;
-    }
-    
-    /**
-     * 获取音效音量
-     */
-    public getSoundEffectVolume(): number {
-        return this.soundEffectVolume;
-    }
-    
-    /**
-     * 更新音乐音量
-     */
-    private updateMusicVolume() {
-        if (this.musicAudioSource) {
-            this.musicAudioSource.volume = this.musicVolume;
-        }
-    }
-    
-    /**
-     * 更新音效音量
-     */
-    private updateSoundEffectVolume() {
-        if (this.soundEffectAudioSource) {
-            this.soundEffectAudioSource.volume = this.soundEffectVolume;
-        }
-    }
-    
-    /**
-     * 静音所有音频
-     */
-    public muteAll() {
-        this.setMusicVolume(0);
-        this.setSoundEffectVolume(0);
-    }
-    
-    /**
-     * 恢复所有音频音量
-     */
-    public unmuteAll() {
-        this.setMusicVolume(0.8);
-        this.setSoundEffectVolume(0.8);
-    }
-    
-    /**
-     * 检查音乐是否正在播放
-     */
-    public isMusicPlaying(): boolean {
-        return this.musicAudioSource && this.musicAudioSource.playing;
-    }
-    
-    onDestroy() {
-        if (AudioManager._instance === this) {
-            AudioManager._instance = null;
-        }
-    }
-}
-
-/**
- * 音频管理器的静态接口
- * 提供便捷的全局访问方法
- */
-export class Audio {
-    /**
-     * 播放背景音乐
-     */
-    static playMusic(musicPath: string, loop: boolean = true) {
-        const manager = AudioManager.getInstance();
-        if (manager) {
-            manager.playMusic(musicPath, loop);
-        }
-    }
-    
-    /**
-     * 播放音效
-     */
-    static playSFX(sfxPath: string, volume?: number) {
-        const manager = AudioManager.getInstance();
-        if (manager) {
-            manager.playSoundEffect(sfxPath, volume);
-        }
-    }
-    
-    /**
-     * 设置音乐音量
-     */
-    static setMusicVolume(volume: number) {
-        const manager = AudioManager.getInstance();
-        if (manager) {
-            manager.setMusicVolume(volume);
-        }
-    }
-    
-    /**
-     * 设置音效音量
-     */
-    static setSFXVolume(volume: number) {
-        const manager = AudioManager.getInstance();
-        if (manager) {
-            manager.setSoundEffectVolume(volume);
-        }
-    }
-    
-    /**
-     * 停止音乐
-     */
-    static stopMusic() {
-        const manager = AudioManager.getInstance();
-        if (manager) {
-            manager.stopMusic();
-        }
-    }
-    
-    /**
-     * 暂停音乐
-     */
-    static pauseMusic() {
-        const manager = AudioManager.getInstance();
-        if (manager) {
-            manager.pauseMusic();
-        }
-    }
-    
-    /**
-     * 恢复音乐
-     */
-    static resumeMusic() {
-        const manager = AudioManager.getInstance();
-        if (manager) {
-            manager.resumeMusic();
-        }
-    }
-}

+ 1 - 1
assets/scripts/Examples/AudioExample.ts

@@ -1,5 +1,5 @@
 import { _decorator, Component, Node, Button } from 'cc';
-import { Audio } from '../Core/AudioManager';
+import { Audio } from '../AudioManager/AudioManager';
 const { ccclass, property } = _decorator;
 
 /**

+ 0 - 111
docs/AntiTrapMechanism.md

@@ -1,111 +0,0 @@
-# 小球防围困机制
-
-## 功能描述
-
-防围困机制是为了防止小球被方块围住而无法继续游戏的情况。当小球在规定时间内撞击方块的次数达到阈值时,系统会采用两阶段防围困策略:
-1. **优先偏移**:首先尝试通过增强的角度偏移来帮助小球脱困
-2. **备用穿透**:当偏移尝试失败后,才激活穿透状态使小球无视碰撞体积穿过方块
-
-## 配置参数
-
-在 `BallController` 组件中可以配置以下参数:
-
-### antiTrapTimeWindow (防围困检测时间窗口)
-- **类型**: number
-- **默认值**: 2.0 秒
-- **说明**: 用于检测频繁撞击的时间窗口。只有在这个时间窗口内的撞击才会被计入防围困检测。
-
-### antiTrapHitThreshold (防围困撞击次数阈值)
-- **类型**: number
-- **默认值**: 5 次
-- **说明**: 在时间窗口内达到这个撞击次数时,将触发防围困机制。
-
-### deflectionAttemptThreshold (偏移尝试次数阈值)
-- **类型**: number
-- **默认值**: 3 次
-- **说明**: 偏移尝试次数阈值。系统会优先尝试偏移方式,只有在偏移尝试次数达到此阈值后才会使用穿透方式。
-
-### antiTrapDeflectionMultiplier (防围困偏移强度倍数)
-- **类型**: number
-- **默认值**: 3.0 倍
-- **说明**: 防围困偏移强度倍数。用于增强偏移效果,帮助小球更容易脱困。
-
-## 工作原理
-
-### 两阶段防围困策略
-
-#### 第一阶段:偏移尝试
-1. **撞击记录**: 每当小球撞击方块时,系统会记录撞击时间。
-
-2. **时间窗口清理**: 系统会自动清理超出时间窗口的旧撞击记录。
-
-3. **阈值检测**: 当时间窗口内的撞击次数达到阈值时,触发防围困机制。
-
-4. **偏移应用**: 达到阈值时,首先尝试应用增强的角度偏移
-   - 计算当前速度方向和碰撞法线
-   - 应用防围困增强偏移算法
-   - 重新设置小球的运动方向
-   - 清空撞击历史,给偏移一个机会
-
-#### 第二阶段:穿透备用
-5. **偏移失效检测**: 如果偏移尝试次数达到 `deflectionAttemptThreshold`
-
-6. **穿透状态**: 激活0.5秒的穿透状态,小球可无视碰撞体积穿过方块但仍会播放撞击特效。
-
-7. **状态清理**: 穿透状态结束后,小球恢复正常碰撞,撞击历史被清空,重置偏移尝试计数。
-
-## 技术实现
-
-### 核心数据结构
-
-```typescript
-// 记录每个球的撞击时间历史
-private ballHitHistory: Map<string, number[]> = new Map();
-
-// 记录每个球的穿透结束时间
-private ballPhaseThrough: Map<string, number> = new Map();
-
-// 记录每个球的偏移尝试次数
-private ballDeflectionAttempts: Map<string, number> = new Map();
-```
-
-### 关键方法
-
-- `onBeginContact()`: 碰撞检测的核心方法,包含两阶段防围困逻辑
-- `calculateAntiTrapReflection()`: 计算防围困增强偏移反弹方向
-- `cleanupExpiredAntiTrapStates()`: 清理过期的穿透状态
-- `cleanupBallAntiTrapState()`: 清理单个小球的防围困状态
-
-## 注意事项
-
-1. **不改变碰撞组**: 该机制不会修改方块的碰撞组设置,只是临时禁用碰撞。
-
-2. **视觉反馈**: 即使在穿透状态下,仍会播放撞击特效,保持视觉一致性。
-
-3. **内存管理**: 系统会自动清理过期数据,防止内存泄漏。
-
-4. **多球支持**: 每个小球都有独立的防围困状态,互不影响。
-
-## 调试信息
-
-系统会在控制台输出以下调试信息:
-```
-Ball {ballId} applied anti-trap deflection (attempt {current}/{max})
-Ball {ballId} entered phase-through mode after {threshold} deflection attempts failed
-Cleaned up anti-trap state for ball {ballId}
-```
-
-## 配置建议
-
-- **时间窗口**: 建议设置为1.5-2.5秒,太短可能误触发,太长可能反应迟钝
-- **撞击阈值**: 建议设置为3-7次,根据游戏难度调整
-- **偏移尝试阈值**: 建议设置为2-5次,平衡偏移和穿透的使用频率
-- **偏移强度倍数**: 建议设置为2.0-5.0,过低可能无效,过高可能过于激进
-- **测试方法**: 可以通过创建密集的方块布局来测试两阶段防围困效果
-
-## 优势
-
-1. **减少穿透频率**: 优先使用偏移方式,只在必要时才使用穿透
-2. **保持游戏体验**: 偏移方式保持了物理碰撞的真实感
-3. **渐进式解决**: 从轻微干预到强力干预的渐进式防围困策略
-4. **可配置性**: 多个参数可根据游戏需求灵活调整

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