181404010226 1 сар өмнө
parent
commit
c14f24efc0

BIN
assets/Animation/EnemyAni/003/ball.png


+ 134 - 0
assets/Animation/EnemyAni/003/ball.png.meta

@@ -0,0 +1,134 @@
+{
+  "ver": "1.0.27",
+  "importer": "image",
+  "imported": true,
+  "uuid": "487fb87d-4d4f-437c-86ee-3e18c6e072fb",
+  "files": [
+    ".json",
+    ".png"
+  ],
+  "subMetas": {
+    "6c48a": {
+      "importer": "texture",
+      "uuid": "487fb87d-4d4f-437c-86ee-3e18c6e072fb@6c48a",
+      "displayName": "ball",
+      "id": "6c48a",
+      "name": "texture",
+      "userData": {
+        "wrapModeS": "clamp-to-edge",
+        "wrapModeT": "clamp-to-edge",
+        "imageUuidOrDatabaseUri": "487fb87d-4d4f-437c-86ee-3e18c6e072fb",
+        "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": "487fb87d-4d4f-437c-86ee-3e18c6e072fb@f9941",
+      "displayName": "ball",
+      "id": "f9941",
+      "name": "spriteFrame",
+      "userData": {
+        "trimThreshold": 1,
+        "rotated": false,
+        "offsetX": 0,
+        "offsetY": 0,
+        "trimX": 1,
+        "trimY": 1,
+        "width": 130,
+        "height": 129,
+        "rawWidth": 132,
+        "rawHeight": 131,
+        "borderTop": 0,
+        "borderBottom": 0,
+        "borderLeft": 0,
+        "borderRight": 0,
+        "packable": true,
+        "pixelsToUnit": 100,
+        "pivotX": 0.5,
+        "pivotY": 0.5,
+        "meshType": 0,
+        "vertices": {
+          "rawPosition": [
+            -65,
+            -64.5,
+            0,
+            65,
+            -64.5,
+            0,
+            -65,
+            64.5,
+            0,
+            65,
+            64.5,
+            0
+          ],
+          "indexes": [
+            0,
+            1,
+            2,
+            2,
+            1,
+            3
+          ],
+          "uv": [
+            1,
+            130,
+            131,
+            130,
+            1,
+            1,
+            131,
+            1
+          ],
+          "nuv": [
+            0.007575757575757576,
+            0.007633587786259542,
+            0.9924242424242424,
+            0.007633587786259542,
+            0.007575757575757576,
+            0.9923664122137404,
+            0.9924242424242424,
+            0.9923664122137404
+          ],
+          "minPos": [
+            -65,
+            -64.5,
+            0
+          ],
+          "maxPos": [
+            65,
+            64.5,
+            0
+          ]
+        },
+        "isUuid": true,
+        "imageUuidOrDatabaseUri": "487fb87d-4d4f-437c-86ee-3e18c6e072fb@6c48a",
+        "atlasUuid": "",
+        "trimType": "auto"
+      },
+      "ver": "1.0.12",
+      "imported": true,
+      "files": [
+        ".json"
+      ],
+      "subMetas": {}
+    }
+  },
+  "userData": {
+    "type": "sprite-frame",
+    "hasAlpha": true,
+    "fixAlphaTransparencyArtifacts": false,
+    "redirect": "487fb87d-4d4f-437c-86ee-3e18c6e072fb@6c48a"
+  }
+}

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 203 - 231
assets/Scenes/GameLevel.scene


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

@@ -0,0 +1,9 @@
+{
+  "ver": "1.2.0",
+  "importer": "directory",
+  "imported": true,
+  "uuid": "0bbe9d85-6a27-476c-a881-fa23798148d4",
+  "files": [],
+  "subMetas": {},
+  "userData": {}
+}

+ 1103 - 0
assets/data/enemies_backup_20251025_192831.json

@@ -0,0 +1,1103 @@
+[
+  {
+    "id": "normal_zombie",
+    "name": "普通僵尸",
+    "type": "basic",
+    "stats": {
+      "health": 40,
+      "maxHealth": 9999,
+      "defense": 0,
+      "speed": 20.0,
+      "dropEnergy": 1,
+      "dropCoins": 2
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 20.0,
+      "patrolRange": 100,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 0.0,
+      "attackSpeed": 2.0,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 2.0,
+      "attackType": "melee",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "none",
+      "projectileSpeed": 0.0,
+      "causesWallShake": false
+    },
+    "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": "data/弹球音效/dao2.mp3",
+      "death_sound": "data/弹球音效/normal zombie die 1.mp3",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
+      "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
+    },
+    "special_abilities": []
+  },
+  {
+    "id": "roadblock_zombie",
+    "name": "路障僵尸",
+    "type": "armored",
+    "stats": {
+      "health": 50,
+      "maxHealth": 9999,
+      "defense": 0,
+      "speed": 20.0,
+      "dropEnergy": 1,
+      "dropCoins": 2
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 15.0,
+      "patrolRange": 100,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 0.0,
+      "attackSpeed": 2.0,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 3.0,
+      "attackType": "melee",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "none",
+      "projectileSpeed": 0.0,
+      "causesWallShake": true
+    },
+    "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": "data/弹球音效/bow.mp3",
+      "death_sound": "data/弹球音效/normal zombie die 2.mp3",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
+      "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
+    },
+    "special_abilities": []
+  },
+  {
+    "id": "wandering_zombie",
+    "name": "漫步僵尸",
+    "type": "wanderer",
+    "stats": {
+      "health": 40,
+      "maxHealth": 9999,
+      "defense": 0,
+      "speed": 20.0,
+      "dropEnergy": 1,
+      "dropCoins": 2
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 15.0,
+      "patrolRange": 100,
+      "rotationSpeed": 180.0,
+      "moveType": "sway",
+      "swingAmplitude": 100.0,
+      "swingFrequency": 2.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 0.0,
+      "attackSpeed": 2.0,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 3.0,
+      "attackType": "melee_weapon",
+      "attackDelay": 1.0,
+      "weaponType": "baseball_bat",
+      "projectileType": "none",
+      "projectileSpeed": 0.0,
+      "causesWallShake": true
+    },
+    "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": "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/004",
+      "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": "data/弹球音效/MagicianAttack.mp3",
+      "death_sound": "data/弹球音效/normal zombie die 3.mp3",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
+      "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
+    },
+    "special_abilities": []
+  },
+  {
+    "id": "mage_zombie",
+    "name": "法师僵尸",
+    "type": "ranged_caster",
+    "stats": {
+      "health": 40,
+      "maxHealth": 9999,
+      "defense": 0,
+      "speed": 15.0,
+      "dropEnergy": 1,
+      "dropCoins": 2
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 10.0,
+      "patrolRange": 100,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 120.0,
+      "attackSpeed": 0.5,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 4.0,
+      "attackType": "magic_projectile",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "magic_bolt",
+      "projectileSpeed": 300.0,
+      "causesWallShake": true
+    },
+    "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/magic_staff"
+    },
+    "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/003",
+      "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": "data/弹球音效/zhanshiAtk.mp3",
+      "death_sound": "data/弹球音效/normal zombie die 4.mp3",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
+      "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
+    },
+    "special_abilities": []
+  },
+  {
+    "id": "archer_zombie",
+    "name": "弓箭僵尸",
+    "type": "ranged_archer",
+    "stats": {
+      "health": 40,
+      "maxHealth": 9999,
+      "defense": 0,
+      "speed": 15.0,
+      "dropEnergy": 1,
+      "dropCoins": 2
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 15.0,
+      "patrolRange": 100,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 150.0,
+      "attackSpeed": 0.5,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 4.0,
+      "attackType": "arrow_projectile",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "arrow",
+      "projectileSpeed": 300.0,
+      "causesWallShake": true
+    },
+    "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": "props/bow"
+    },
+    "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": "props/bow"
+    },
+    "audio": {
+      "attack_sound": "data/弹球音效/hammer1.mp3",
+      "death_sound": "data/弹球音效/normal zombie die 5.mp3",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
+      "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
+    },
+    "special_abilities": []
+  },
+  {
+    "id": "stealth_zombie",
+    "name": "隐身僵尸",
+    "type": "stealth",
+    "stats": {
+      "health": 40,
+      "maxHealth": 9999,
+      "defense": 0,
+      "speed": 20.0,
+      "dropEnergy": 1,
+      "dropCoins": 2
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 20.0,
+      "patrolRange": 100,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 0.0,
+      "attackSpeed": 3.0,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 3.0,
+      "attackType": "stealth_strike",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "none",
+      "projectileSpeed": 0.0,
+      "causesWallShake": true
+    },
+    "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/stealth_walk",
+      "blockSound": "",
+      "stealthSound": "audio/stealth_activate",
+      "armorBreakSound": "",
+      "fuseSound": "",
+      "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": "data/弹球音效/hammer1.mp3",
+      "death_sound": "data/弹球音效/normal zombie die 6.mp3",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
+      "block_sound": "nan",
+      "stealth_sound": "Null",
+      "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
+    },
+    "special_abilities": [
+      {
+        "type": "stealth",
+        "damage": 0,
+        "range": 0,
+        "cooldown": 3
+      }
+    ]
+  },
+  {
+    "id": "bucket_zombie",
+    "name": "铁桶僵尸",
+    "type": "heavy_armor",
+    "stats": {
+      "health": 60,
+      "maxHealth": 9999,
+      "defense": 0,
+      "speed": 15.0,
+      "dropEnergy": 1,
+      "dropCoins": 2
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 10.0,
+      "patrolRange": 100,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 0.0,
+      "attackSpeed": 1.0,
+      "canBlock": true,
+      "blockChance": 30.0,
+      "blockDamageReduction": 1.0,
+      "attackCooldown": 3.0,
+      "attackType": "heavy_melee",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "none",
+      "projectileSpeed": 0.0,
+      "causesWallShake": true
+    },
+    "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": "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/006",
+      "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": "data/弹球音效/hammer1.mp3",
+      "death_sound": "data/弹球音效/normal zombie die 7.mp3",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
+      "block_sound": "nan",
+      "stealth_sound": "nan",
+      "armor_break_sound": "Null",
+      "fuse_sound": "nan"
+    },
+    "boss": {
+      "is_boss": false,
+      "phases": 1,
+      "rage_threshold": 0.3,
+      "rage_damage_multiplier": 1.0,
+      "rage_speed_multiplier": 1.0
+    },
+    "special_abilities": []
+  },
+  {
+    "id": "barrel_zombie",
+    "name": "火药桶僵尸",
+    "type": "explosive",
+    "stats": {
+      "health": 40,
+      "maxHealth": 9999,
+      "defense": 0,
+      "speed": 20.0,
+      "dropEnergy": 1,
+      "dropCoins": 2
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 20.0,
+      "patrolRange": 100,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 1,
+      "attackRange": 120.0,
+      "attackSpeed": 0.5,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 3.0,
+      "attackType": "melee",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "none",
+      "projectileSpeed": 150.0,
+      "causesWallShake": true
+    },
+    "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/barrel_walk",
+      "blockSound": "",
+      "stealthSound": "",
+      "armorBreakSound": "",
+      "fuseSound": "audio/barrel_fuse",
+      "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": "data/弹球音效/hammer1.mp3",
+      "death_sound": "data/弹球音效/boss die.mp3",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
+      "block_sound": "nan",
+      "stealth_sound": "nan",
+      "armor_break_sound": "nan",
+      "fuse_sound": "Null"
+    },
+    "boss": {
+      "is_boss": false,
+      "phases": 1,
+      "rage_threshold": 0.3,
+      "rage_damage_multiplier": 1.0,
+      "rage_speed_multiplier": 1.0
+    },
+    "special_abilities": []
+  },
+  {
+    "id": "boss1_gatekeeper",
+    "name": "BOSS1",
+    "type": "boss",
+    "stats": {
+      "health": 200,
+      "maxHealth": 9999,
+      "defense": 0,
+      "speed": 10.0,
+      "dropEnergy": 1,
+      "dropCoins": 2
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 10.0,
+      "patrolRange": 100,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 2,
+      "attackRange": 0.0,
+      "attackSpeed": 1.0,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 4.0,
+      "attackType": "gate_slam",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "none",
+      "projectileSpeed": 0.0,
+      "causesWallShake": true
+    },
+    "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/iron_gate"
+    },
+    "audioConfig": {
+      "attackSound": "enemy_attack",
+      "deathSound": "enemy_death",
+      "hitSound": "enemy_hit",
+      "walkSound": "audio/boss1_walk",
+      "blockSound": "",
+      "stealthSound": "",
+      "armorBreakSound": "",
+      "fuseSound": "",
+      "volume": 1.0
+    },
+    "special_abilities": [
+      {
+        "type": "charge_attack",
+        "damage": 1,
+        "range": 150,
+        "cooldown": 8
+      },
+      {
+        "type": "area_attack",
+        "damage": 2,
+        "range": 100,
+        "cooldown": 12
+      }
+    ],
+    "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/iron_gate"
+    },
+    "audio": {
+      "attack_sound": "data/弹球音效/hammer1.mp3",
+      "death_sound": "data/弹球音效/boss die.mp3",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
+      "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": 300,
+      "maxHealth": 9999,
+      "defense": 0,
+      "speed": 10.0,
+      "dropEnergy": 1,
+      "dropCoins": 2
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 10.0,
+      "patrolRange": 100,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 2,
+      "attackRange": 0.0,
+      "attackSpeed": 1.0,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 4.0,
+      "attackType": "tombstone_smash",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "none",
+      "projectileSpeed": 0.0,
+      "causesWallShake": true
+    },
+    "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": "props/tombstone"
+    },
+    "audioConfig": {
+      "attackSound": "enemy_attack",
+      "deathSound": "enemy_death",
+      "hitSound": "enemy_hit",
+      "walkSound": "audio/boss2_walk",
+      "blockSound": "",
+      "stealthSound": "",
+      "armorBreakSound": "",
+      "fuseSound": "",
+      "volume": 1.0
+    },
+    "special_abilities": [
+      {
+        "type": "charge_attack",
+        "damage": 1,
+        "range": 150,
+        "cooldown": 8
+      },
+      {
+        "type": "area_attack",
+        "damage": 2,
+        "range": 100,
+        "cooldown": 12
+      }
+    ],
+    "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": "props/tombstone"
+    },
+    "audio": {
+      "attack_sound": "data/弹球音效/hammer1.mp3",
+      "death_sound": "data/弹球音效/boss die.mp3",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
+      "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": 500,
+      "maxHealth": 9999,
+      "defense": 0,
+      "speed": 10.0,
+      "dropEnergy": 1,
+      "dropCoins": 2
+    },
+    "movement": {
+      "pattern": "direct",
+      "speed": 10.0,
+      "patrolRange": 100,
+      "rotationSpeed": 180.0,
+      "moveType": "straight",
+      "swingAmplitude": 0.0,
+      "swingFrequency": 0.0,
+      "speedVariation": 0.1
+    },
+    "combat": {
+      "attackDamage": 2,
+      "attackRange": 0.0,
+      "attackSpeed": 1.0,
+      "canBlock": false,
+      "blockChance": 0.0,
+      "blockDamageReduction": 0.5,
+      "attackCooldown": 4.0,
+      "attackType": "cyber_arm_combo",
+      "attackDelay": 1.0,
+      "weaponType": "none",
+      "projectileType": "none",
+      "projectileSpeed": 0.0,
+      "causesWallShake": true
+    },
+    "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": "props/cyber_arm"
+    },
+    "audioConfig": {
+      "attackSound": "enemy_attack",
+      "deathSound": "enemy_death",
+      "hitSound": "enemy_hit",
+      "walkSound": "audio/boss3_walk",
+      "blockSound": "",
+      "stealthSound": "",
+      "armorBreakSound": "",
+      "fuseSound": "",
+      "volume": 1.0
+    },
+    "special_abilities": [
+      {
+        "type": "charge_attack",
+        "damage": 1,
+        "range": 150,
+        "cooldown": 8
+      },
+      {
+        "type": "area_attack",
+        "damage": 2,
+        "range": 100,
+        "cooldown": 12
+      }
+    ],
+    "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": "props/cyber_arm"
+    },
+    "audio": {
+      "attack_sound": "data/弹球音效/hammer1.mp3",
+      "death_sound": "data/弹球音效/boss die.mp3",
+      "hit_sound": "Null",
+      "walk_sound": "Null",
+      "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/data/enemies_backup_20251025_192831.json.meta

@@ -0,0 +1,11 @@
+{
+  "ver": "2.0.1",
+  "importer": "json",
+  "imported": true,
+  "uuid": "d1c0d300-c3bd-423f-8755-ae87f4b06c53",
+  "files": [
+    ".json"
+  ],
+  "subMetas": {},
+  "userData": {}
+}

+ 146 - 286
assets/scripts/AudioManager/AudioManager.ts

@@ -1,14 +1,9 @@
-import { _decorator, Component, AudioClip, AudioSource, resources, Node } from 'cc';
+import { _decorator, Component, AudioClip, AudioSource, resources, Node, find, director } from 'cc';
 import { BundleLoader } from '../Core/BundleLoader';
 const { ccclass, property } = _decorator;
 
-/**
- * 音频管理器
- * 统一管理游戏中的音乐和音效播放
- */
 @ccclass('AudioManager')
 export class AudioManager extends Component {
-    // 音频源组件
     @property({ type: AudioSource, tooltip: '背景音乐播放器' })
     public musicAudioSource: AudioSource = null;
     
@@ -24,33 +19,32 @@ export class AudioManager extends Component {
     @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;
     
-    // Bundle加载器
     private bundleLoader: BundleLoader = null;
     
-    // 音频缓存
     private audioClipCache: Map<string, AudioClip> = new Map();
-    
+
+    // 并发播放保护
+    private _musicRequestId: number = 0;
+    private _currentMusicPath: string | null = null;
+
     // 单例实例
     private static _instance: AudioManager = null;
     
-    start() {
-        // 设置单例
+    onLoad() {
+        // 设置单例(在 onLoad 阶段更早创建,确保静态调用可用)
         if (AudioManager._instance === null) {
             AudioManager._instance = this;
-            // 防止场景切换时被销毁
+            // 如需跨场景保留,可取消注释以下两行
             // this.node.parent = null;
             // director.addPersistRootNode(this.node);
         } else {
@@ -62,26 +56,19 @@ export class AudioManager extends Component {
         this.initializeAudioSources();
     }
     
-    /**
-     * 获取单例实例
-     */
     public static getInstance(): AudioManager {
         return AudioManager._instance;
     }
     
-    /**
-     * 初始化音频源
-     */
     private initializeAudioSources() {
         console.log('[AudioManager] 开始初始化音频源');
         
-        // 如果没有指定音频源,尝试自动创建
         if (!this.musicAudioSource) {
             console.log('[AudioManager] 创建音乐播放器AudioSource');
-            const musicNode = new Node('MusicAudioSource');
-            musicNode.parent = this.node;
+            const musicNode = new Node('MusicPlayer');
+            this.node.addChild(musicNode);
             this.musicAudioSource = musicNode.addComponent(AudioSource);
-            this.musicAudioSource.loop = true;
+            this.musicAudioSource.volume = this.musicVolume;
             console.log('[AudioManager] 音乐播放器AudioSource创建完成');
         } else {
             console.log('[AudioManager] 音乐播放器AudioSource已存在');
@@ -89,31 +76,31 @@ export class AudioManager extends Component {
         
         if (!this.uiSoundAudioSource) {
             console.log('[AudioManager] 创建UI音效播放器AudioSource');
-            const uiSfxNode = new Node('UISoundAudioSource');
-            uiSfxNode.parent = this.node;
+            const uiSfxNode = new Node('UISoundPlayer');
+            this.node.addChild(uiSfxNode);
             this.uiSoundAudioSource = uiSfxNode.addComponent(AudioSource);
-            this.uiSoundAudioSource.loop = false;
+            this.uiSoundAudioSource.volume = this.uiSoundVolume;
         }
         
         if (!this.enemySoundAudioSource) {
-            const enemySfxNode = new Node('EnemySoundAudioSource');
-            enemySfxNode.parent = this.node;
+            const enemySfxNode = new Node('EnemySoundPlayer');
+            this.node.addChild(enemySfxNode);
             this.enemySoundAudioSource = enemySfxNode.addComponent(AudioSource);
-            this.enemySoundAudioSource.loop = false;
+            this.enemySoundAudioSource.volume = this.enemySoundVolume;
         }
         
         if (!this.environmentSoundAudioSource) {
-            const envSfxNode = new Node('EnvironmentSoundAudioSource');
-            envSfxNode.parent = this.node;
+            const envSfxNode = new Node('EnvironmentSoundPlayer');
+            this.node.addChild(envSfxNode);
             this.environmentSoundAudioSource = envSfxNode.addComponent(AudioSource);
-            this.environmentSoundAudioSource.loop = false;
+            this.environmentSoundAudioSource.volume = this.environmentSoundVolume;
         }
         
         if (!this.weaponSoundAudioSource) {
-            const weaponSfxNode = new Node('WeaponSoundAudioSource');
-            weaponSfxNode.parent = this.node;
+            const weaponSfxNode = new Node('WeaponSoundPlayer');
+            this.node.addChild(weaponSfxNode);
             this.weaponSoundAudioSource = weaponSfxNode.addComponent(AudioSource);
-            this.weaponSoundAudioSource.loop = false;
+            this.weaponSoundAudioSource.volume = this.weaponSoundVolume;
         }
         
         console.log('[AudioManager] 音频源初始化完成');
@@ -123,40 +110,57 @@ export class AudioManager extends Component {
         this.updateAllVolumes();
     }
     
-    /**
-     * 播放背景音乐
-     * @param musicPath 音乐资源路径
-     * @param loop 是否循环播放
-     */
     public async playMusic(musicPath: string, loop: boolean = true) {
         if (!this.musicAudioSource) {
             console.warn('[AudioManager] 音乐播放器未初始化');
             return;
         }
+
+        // 避免重复请求同一首已在播放的音乐
+        if (this._currentMusicPath === musicPath && this.musicAudioSource.playing) {
+            this.musicAudioSource.loop = loop;
+            console.log(`[AudioManager] 已在播放目标音乐,忽略重复请求: ${musicPath}`);
+            return;
+        }
+
+        const requestId = ++this._musicRequestId; // 为本次播放分配请求ID
+        console.log(`[AudioManager] 发起音乐播放请求#${requestId}: ${musicPath}`);
         
         try {
-            // 转换路径格式:从 "data/弹球音效/fight bgm" 转换为 "弹球音效/fight bgm"
             const bundlePath = musicPath.replace('data/', '');
             const clip = await this.bundleLoader.loadAssetFromBundle<AudioClip>('data', bundlePath, AudioClip);
+
+            // 若在加载期间有新的播放请求,丢弃本次播放
+            if (requestId !== this._musicRequestId) {
+                console.log(`[AudioManager] 丢弃过期音乐请求#${requestId}: ${musicPath}(当前请求ID为#${this._musicRequestId})`);
+                return;
+            }
+            
+            // 保险:在开始新音乐前停止当前播放,避免叠加
+            if (this.musicAudioSource.playing) {
+                this.musicAudioSource.stop();
+            }
             
             this.currentMusicClip = clip;
+            this._currentMusicPath = musicPath;
             this.musicAudioSource.clip = clip;
             this.musicAudioSource.loop = loop;
             this.musicAudioSource.play();
             
-            console.log(`[AudioManager] 播放音乐: ${musicPath}`);
+            console.log(`[AudioManager] 播放音乐#${requestId}: ${musicPath}`);
         } catch (error) {
             console.error(`[AudioManager] 加载音乐失败: ${musicPath}`, error);
         }
     }
     
-    /**
-     * 停止背景音乐
-     */
     public stopMusic() {
         console.log('[AudioManager] stopMusic方法被调用');
         console.log(`[AudioManager] musicAudioSource状态: ${this.musicAudioSource ? '存在' : '不存在'}`);
         
+        // 取消所有正在进行的音乐加载/播放请求
+        this._musicRequestId++;
+        console.log(`[AudioManager] 取消到请求ID#${this._musicRequestId}(后续仅处理更新后的请求)`);
+        
         if (this.musicAudioSource) {
             console.log(`[AudioManager] musicAudioSource.playing: ${this.musicAudioSource.playing}`);
             console.log(`[AudioManager] currentMusicClip: ${this.currentMusicClip ? this.currentMusicClip.name : '无'}`);
@@ -167,8 +171,8 @@ export class AudioManager extends Component {
             } else {
                 console.log('[AudioManager] 音乐未在播放,无需停止');
             }
-            // 清除当前音乐剪辑引用
             this.currentMusicClip = null;
+            this._currentMusicPath = null;
             this.musicAudioSource.clip = null;
             console.log('[AudioManager] 已清除音乐剪辑引用');
         } else {
@@ -176,9 +180,6 @@ export class AudioManager extends Component {
         }
     }
     
-    /**
-     * 暂停背景音乐
-     */
     public pauseMusic() {
         if (this.musicAudioSource && this.musicAudioSource.playing) {
             this.musicAudioSource.pause();
@@ -186,69 +187,33 @@ export class AudioManager extends Component {
         }
     }
     
-    /**
-     * 恢复背景音乐
-     */
     public resumeMusic() {
-        if (this.musicAudioSource && this.currentMusicClip) {
+        if (this.musicAudioSource && this.currentMusicClip && !this.musicAudioSource.playing) {
             this.musicAudioSource.play();
             console.log('[AudioManager] 恢复音乐播放');
         }
     }
     
-    /**
-     * 播放音效(向后兼容)
-     * @param sfxPath 音效资源路径
-     * @param volume 音量(可选,0-1)
-     */
     public playSoundEffect(sfxPath: string, volume?: number) {
-        this.playUISound(sfxPath, volume);
+        this.playSound(this.uiSoundAudioSource, sfxPath, volume, this.soundEffectVolume, '音效');
     }
     
-    /**
-     * 播放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 async playSound(audioSource: AudioSource, sfxPath: string, volume: number | undefined, baseVolume: number, soundType: string) {
         if (!audioSource) {
             console.warn(`[AudioManager] ${soundType}播放器未初始化`);
@@ -256,286 +221,164 @@ export class AudioManager extends Component {
         }
         
         try {
-            // 去掉.mp3后缀(如果存在)
-            const cleanPath = sfxPath.endsWith('.mp3') ? sfxPath.slice(0, -4) : sfxPath;
-            
-            // 检查缓存中是否已有该音频
-            let clip = this.audioClipCache.get(cleanPath);
-            
-            if (!clip) {
-                // 转换路径格式:从 "data/弹球音效/xxx" 转换为 "弹球音效/xxx"
-                const bundlePath = cleanPath.replace('data/', '');
-                console.log(`[AudioManager] 从Bundle加载新音效: ${bundlePath}`);
-                clip = await this.bundleLoader.loadAssetFromBundle<AudioClip>('data', bundlePath, AudioClip);
-                
-                // 缓存音频资源
-                this.audioClipCache.set(cleanPath, clip);
-                console.log(`[AudioManager] 音效已缓存: ${cleanPath}`);
-            } else {
-                console.log(`[AudioManager] 使用缓存音效: ${cleanPath}`);
-            }
+            const cleanPath = sfxPath.replace('data/', '');
+            const bundlePath = cleanPath;
+            const clip = await this.bundleLoader.loadAssetFromBundle<AudioClip>('data', bundlePath, AudioClip);
             
-            // 设置临时音量(如果指定)
-            const originalVolume = audioSource.volume;
             if (volume !== undefined) {
-                audioSource.volume = volume * baseVolume;
+                audioSource.volume = Math.max(0, Math.min(1, volume));
+            } else {
+                audioSource.volume = baseVolume;
             }
             
             audioSource.playOneShot(clip);
-            
-            // 恢复原始音量
-            if (volume !== undefined) {
-                audioSource.volume = originalVolume;
-            }
-            
             console.log(`[AudioManager] 播放${soundType}: ${cleanPath}`);
         } catch (error) {
             console.error(`[AudioManager] 加载${soundType}失败: ${sfxPath}`, error);
         }
     }
     
-    /**
-     * 设置音乐音量
-     * @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.setSoundEffectVolume(volume);
         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;
+        return !!(this.musicAudioSource && this.musicAudioSource.playing);
     }
     
-    /**
-     * 清理音频缓存
-     */
     public clearAudioCache() {
         console.log(`[AudioManager] 清理音频缓存,共${this.audioClipCache.size}个音效`);
         this.audioClipCache.clear();
     }
     
-    /**
-     * 获取缓存状态
-     */
     public getCacheInfo(): {count: number, paths: string[]} {
-        return {
-            count: this.audioClipCache.size,
-            paths: Array.from(this.audioClipCache.keys())
-        };
+        return { count: this.audioClipCache.size, paths: Array.from(this.audioClipCache.keys()) };
     }
 
     onDestroy() {
-        // 清理音频缓存
         this.clearAudioCache();
-        
         if (AudioManager._instance === this) {
             AudioManager._instance = null;
         }
     }
 }
 
-/**
- * 音频管理器的静态接口
- * 提供便捷的全局访问方法
- */
 export class Audio {
-    /**
-     * 播放背景音乐
-     */
     static playMusic(musicPath: string, loop: boolean = true) {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -543,9 +386,6 @@ export class Audio {
         }
     }
     
-    /**
-     * 播放音效(向后兼容)
-     */
     static playSFX(sfxPath: string, volume?: number) {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -553,9 +393,6 @@ export class Audio {
         }
     }
     
-    /**
-     * 播放UI音效
-     */
     static playUISound(sfxPath: string, volume?: number) {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -563,9 +400,6 @@ export class Audio {
         }
     }
     
-    /**
-     * 播放敌人音效
-     */
     static playEnemySound(sfxPath: string, volume?: number) {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -573,9 +407,6 @@ export class Audio {
         }
     }
     
-    /**
-     * 播放环境音效
-     */
     static playEnvironmentSound(sfxPath: string, volume?: number) {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -583,9 +414,6 @@ export class Audio {
         }
     }
     
-    /**
-     * 播放武器音效
-     */
     static playWeaponSound(sfxPath: string, volume?: number) {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -593,9 +421,6 @@ export class Audio {
         }
     }
     
-    /**
-     * 设置音乐音量
-     */
     static setMusicVolume(volume: number) {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -603,9 +428,6 @@ export class Audio {
         }
     }
     
-    /**
-     * 设置音效音量(向后兼容)
-     */
     static setSFXVolume(volume: number) {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -613,9 +435,6 @@ export class Audio {
         }
     }
     
-    /**
-     * 设置UI音效音量
-     */
     static setUISoundVolume(volume: number) {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -623,9 +442,6 @@ export class Audio {
         }
     }
     
-    /**
-     * 设置敌人音效音量
-     */
     static setEnemySoundVolume(volume: number) {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -633,9 +449,6 @@ export class Audio {
         }
     }
     
-    /**
-     * 设置环境音效音量
-     */
     static setEnvironmentSoundVolume(volume: number) {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -643,9 +456,6 @@ export class Audio {
         }
     }
     
-    /**
-     * 设置武器音效音量
-     */
     static setWeaponSoundVolume(volume: number) {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -653,9 +463,6 @@ export class Audio {
         }
     }
     
-    /**
-     * 设置所有音效音量
-     */
     static setAllSoundVolume(volume: number) {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -663,21 +470,13 @@ export class Audio {
         }
     }
     
-    /**
-     * 停止音乐
-     */
     static stopMusic() {
         const manager = AudioManager.getInstance();
         if (manager) {
             manager.stopMusic();
-        } else {
-            console.warn('[Audio] AudioManager实例未找到,无法停止音乐');
         }
     }
     
-    /**
-     * 暂停音乐
-     */
     static pauseMusic() {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -685,9 +484,6 @@ export class Audio {
         }
     }
     
-    /**
-     * 恢复音乐
-     */
     static resumeMusic() {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -695,9 +491,6 @@ export class Audio {
         }
     }
     
-    /**
-     * 静音所有音频
-     */
     static muteAll() {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -705,9 +498,6 @@ export class Audio {
         }
     }
     
-    /**
-     * 恢复所有音频
-     */
     static unmuteAll() {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -715,9 +505,6 @@ export class Audio {
         }
     }
     
-    /**
-     * 静音所有音效(保留音乐)
-     */
     static muteAllSounds() {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -725,9 +512,6 @@ export class Audio {
         }
     }
     
-    /**
-     * 恢复所有音效(保留音乐)
-     */
     static unmuteAllSounds() {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -735,9 +519,6 @@ export class Audio {
         }
     }
     
-    /**
-     * 清理音频缓存
-     */
     static clearAudioCache() {
         const manager = AudioManager.getInstance();
         if (manager) {
@@ -745,14 +526,93 @@ export class Audio {
         }
     }
     
-    /**
-     * 获取缓存信息
-     */
     static getCacheInfo(): {count: number, paths: string[]} {
         const manager = AudioManager.getInstance();
         if (manager) {
             return manager.getCacheInfo();
         }
-        return {count: 0, paths: []};
+        return { count: 0, paths: [] };
+    }
+
+    static ensureManager(): AudioManager | null {
+        let manager = AudioManager.getInstance();
+        if (manager) return manager;
+        try {
+            const canvas = find('Canvas') as Node | null;
+            const sceneRoot: any = director.getScene();
+            const parent: Node | null = canvas || (sceneRoot as Node | null);
+            if (!parent) {
+                console.warn('[Audio] 场景未准备好,无法创建AudioManager');
+                return null;
+            }
+
+            // 先尝试在场景中查找已存在的 AudioManager 组件
+            if (canvas && typeof (canvas as any).getComponentInChildren === 'function') {
+                const existing = (canvas as any).getComponentInChildren(AudioManager);
+                if (existing) {
+                    return existing;
+                }
+            }
+            if (sceneRoot && typeof sceneRoot.getComponentInChildren === 'function') {
+                const existingInScene = sceneRoot.getComponentInChildren(AudioManager);
+                if (existingInScene) {
+                    return existingInScene;
+                }
+            }
+
+            // 查找名为 AudioManager 的节点,复用其组件
+            let node = parent.getChildByName && parent.getChildByName('AudioManager');
+            if (!node) {
+                node = new Node('AudioManager');
+                parent.addChild(node as Node);
+            }
+            const reused = (node as Node).getComponent(AudioManager);
+            manager = reused ? reused : (node as Node).addComponent(AudioManager);
+            return manager;
+        } catch (e) {
+            console.error('[Audio] 创建AudioManager失败:', e);
+            return null;
+        }
+    }
+
+    static updateBGMByTopUI(): void {
+        try {
+            const manager = Audio.ensureManager();
+            if (!manager) {
+                console.warn('[Audio] AudioManager未初始化,稍后重试BGM切换');
+                return;
+            }
+
+            const mainUI = find('Canvas/MainUI');
+            const gameUI = find('Canvas/GameLevelUI');
+            const isMainVisible = !!(mainUI && (mainUI as Node).activeInHierarchy);
+            const isGameVisible = !!(gameUI && (gameUI as Node).activeInHierarchy);
+
+            let playTarget: 'main' | 'game' | null = null;
+            if (isMainVisible && !isGameVisible) {
+                playTarget = 'main';
+            } else if (!isMainVisible && isGameVisible) {
+                playTarget = 'game';
+            } else if (isMainVisible && isGameVisible) {
+                const mainIndex = (mainUI as Node).getSiblingIndex();
+                const gameIndex = (gameUI as Node).getSiblingIndex();
+                playTarget = gameIndex >= mainIndex ? 'game' : 'main';
+            } else {
+                Audio.stopMusic();
+                return;
+            }
+
+            Audio.stopMusic();
+            Audio.setMusicVolume(0.8);
+            if (playTarget === 'game') {
+                Audio.playMusic('data/弹球音效/fight bgm', true);
+                console.log('[Audio] 切换到游戏战斗音乐');
+            } else {
+                Audio.playMusic('data/弹球音效/ui bgm', true);
+                console.log('[Audio] 切换到主界面背景音乐');
+            }
+        } catch (err) {
+            console.error('[Audio] updateBGMByTopUI 失败:', err);
+        }
     }
 }

+ 21 - 29
assets/scripts/FourUI/MainSystem/MainUIControlller.ts

@@ -77,13 +77,14 @@ export class MainUIController extends Component {
   }
 
   onEnable() {
-    console.log('[MainUIController] MainUI节点显示,开始播放主界面音乐');
-    // 当MainUI节点显示时,播放主界面背景音乐
-    if (!this.newbieGuideManager?.isNewbieGuideInProgress()) {
-      this.playMainUIBGM();
-      console.log('[MainUIController] 主界面背景音乐已播放');
-    }
-  }
+    // 移除旧的主界面bgm播放,改为统一入口
+    // this.playMainUIBGM();
+    Audio.updateBGMByTopUI();
+    // 下一帧再次复判,确保返回主界面时稳定播放 ui bgm
+    this.scheduleOnce(() => {
+        Audio.updateBGMByTopUI();
+    }, 0);
+}
 
   onDisable() {
     console.log('[MainUIController] MainUI节点隐藏,停止主界面音乐');
@@ -296,6 +297,11 @@ export class MainUIController extends Component {
     if (this.mainUI) this.mainUI.active = false;
     if (this.gameUI) this.gameUI.active = true;
 
+    // 在下一帧根据当前顶层UI重新判定并更新BGM,避免同帧内两个onEnable竞争导致误判
+    this.scheduleOnce(() => {
+      Audio.updateBGMByTopUI();
+    }, 0);
+
     const gm = this.gameManagerNode?.getComponent(GameManager);
     // 设置应用状态为游戏中(会自动隐藏TopBar和NavBar)
     gm?.setAppState(AppState.IN_GAME);
@@ -503,6 +509,10 @@ export class MainUIController extends Component {
     }
     
     // 不再在这里播放音乐,由onEnable自动处理
+    // 为防止同帧竞争导致音乐被stop覆盖,下一帧再执行一次复判
+    this.scheduleOnce(() => {
+      Audio.updateBGMByTopUI();
+    }, 0);
 
     // 刷新UI显示
     this.refreshAll();
@@ -580,28 +590,10 @@ export class MainUIController extends Component {
    * 播放主界面背景音乐
    */
   private async playMainUIBGM(): Promise<void> {
-    console.log('[MainUIController] 开始播放主界面背景音乐');
-    
-    try {
-      // 获取BundleLoader实例
-      const bundleLoader = BundleLoader.getInstance();
-      
-      // 确保data bundle已加载完成
-      await bundleLoader.loadBundle('data');
-      console.log('[MainUIController] data bundle加载完成,开始播放音乐');
-      
-      // 先停止当前音乐(包括战斗背景音乐)
-      Audio.stopMusic();
-      // 恢复正常音乐音量
-      Audio.setMusicVolume(0.8);
-      // 播放主界面BGM,循环播放
-      Audio.playMusic('data/弹球音效/ui bgm', true);
-      
-      console.log('[MainUIController] 主界面背景音乐播放完成');
-    } catch (error) {
-      console.error('[MainUIController] 播放主界面背景音乐失败:', error);
-    }
-  }
+    // 旧逻辑废弃:直接走统一入口,根据顶层UI播放
+    // Audio.playMusic('data/弹球音效/ui bgm', true);
+    Audio.updateBGMByTopUI();
+}
 
   /**
    * 预加载当前关卡和下一关的资源

+ 4 - 4
assets/scripts/LevelSystem/IN_game.ts

@@ -185,9 +185,9 @@ export class InGameManager extends Component {
     }
 
     onEnable() {
-        console.log('[InGameManager] GameLevelUI节点显示,开始播放战斗音乐');
-        // 当GameLevelUI节点显示时,立即播放战斗音乐(同步调用)
-        this.playBattleMusicSync();
+        // 旧战斗音乐播放逻辑移除,改为统一入口
+        // this.playBattleMusicSync();
+        Audio.updateBGMByTopUI();
     }
 
     onDisable() {
@@ -1212,7 +1212,7 @@ export class InGameManager extends Component {
             Audio.setMusicVolume(0.8);
             
             // 播放战斗音乐(循环播放)- 不等待异步操作
-            Audio.playMusic('data/弹球音效/fight bgm', true);
+            Audio.updateBGMByTopUI();
             
             console.log('[InGameManager] 战斗音乐播放指令已发送');
         } catch (error) {

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно