# Boss 系统架构设计 > **关联切片**:S6 P0(Mini Boss Wave 8 / Final Boss Wave 20) > **依赖系统**:EnemyManager、StatusManager、EventBus、VFXManager、ZoneManager --- ## 1. 设计原则 - **阶段驱动(Phase-Driven)**:Boss 行为由明确的阶段(Phase)枚举驱动,阶段切换在 `_physics_process` 中以血量阈值触发,不使用独立 Timer Node。 - **与 EnemyManager 解耦**:Boss 不进入 EnemyManager SoA(避免 stride 污染和 AI 逻辑膨胀),由独立的 `BossManager` Autoload 管理;但向 SpatialGrid 注册自身坐标,使子弹归航与 ZoneManager 能命中 Boss。 - **数据驱动**:每个 Boss 的阶段配置存储于 `.tres` Resource(`BossPhaseDef`),美术/策划可在不修改代码的情况下调整阈值与攻击模式。 - **EventBus 集成**:阶段切换、死亡均通过 EventBus 广播,HUD/BGM/成就系统订阅。 --- ## 2. BossManager Autoload ```gdscript # boss_manager.gd (Autoload: BossManager) # Boss 实体数量极少(≤ 2 同屏),不使用 SoA,用 Array[BossInstance] 即可。 const MAX_BOSSES: int = 2 # 同屏 Boss 上限 var _active: Array[BossInstance] = [] func spawn_boss(boss_def_id: String, spawn_pos: Vector2) -> int: # 从 BossRegistry 加载 BossDef,实例化 BossInstance,注册到 SpatialGrid pass func _physics_process(delta: float) -> void: for boss in _active: boss.tick(delta) ``` --- ## 3. Phase 状态机模板 ### 3.1 枚举与切换条件 每个 Boss 的阶段定义在 `BossPhaseDef` Resource 中: ```gdscript # boss_phase_def.gd class_name BossPhaseDef extends Resource @export var phase_id: int # 阶段编号(0 起始) @export var hp_threshold: float # 进入此阶段的血量百分比(0.0~1.0),如 0.5 = 50% HP @export var attack_patterns: Array[String] # 此阶段可用的攻击模式 ID 列表 @export var move_speed_mult: float = 1.0 # 移动速度倍率(狂暴阶段可设 1.5) @export var enrage_vfx: String = "" # 阶段切换时触发的 VFX ID(空=无) @export var phase_bgm_layer: int = 0 # 动态音乐层级(0=基础,1=紧张,2=狂暴) ``` ### 3.2 BossInstance 状态机 ```gdscript # boss_instance.gd class_name BossInstance extends RefCounted enum BossPhaseState { PHASE_0, # 初始阶段(100% HP) PHASE_1, # 受伤阶段(阈值由 BossDef 配置,通常 70%) PHASE_2, # 危机阶段(通常 40%) PHASE_DYING # 死亡动画阶段(HP ≤ 0,播放死亡序列后才真正移除) } var boss_def: BossDef var hp: float var hp_max: float var position: Vector2 var current_phase: BossPhaseState = BossPhaseState.PHASE_0 var _attack_cooldown: float = 0.0 var _pattern_index: int = 0 # 当前阶段攻击模式的轮询索引 var _phase_just_changed: bool = false # 本帧刚切换阶段的标志,用于触发 enrage VFX func tick(delta: float) -> void: _check_phase_transition() if current_phase == BossPhaseState.PHASE_DYING: _tick_dying(delta) return _tick_movement(delta) _tick_attack(delta) _sync_render() # 血量阈值检查(每帧) func _check_phase_transition() -> void: var hp_pct: float = hp / hp_max var phases: Array = boss_def.phases # Array[BossPhaseDef],按 hp_threshold 降序排列 for i in phases.size(): var phase_def: BossPhaseDef = phases[i] if hp_pct <= phase_def.hp_threshold and int(current_phase) < i + 1: _enter_phase(i + 1, phase_def) break func _enter_phase(new_phase: int, phase_def: BossPhaseDef) -> void: current_phase = new_phase as BossPhaseState _pattern_index = 0 _attack_cooldown = 0.0 # 阶段切换 VFX if phase_def.enrage_vfx != "": VFXManager.play(phase_def.enrage_vfx, position, 1.0) # 通知 EventBus(HUD 高亮、BGM 切换) EventBus.emit(EventID.BOSS_PHASE_CHANGED, { "boss_id": boss_def.id, "phase": new_phase, "bgm_layer": phase_def.phase_bgm_layer }) ``` --- ## 4. 攻击模式系统 (Attack Pattern) 攻击模式以 ID 字符串存储,在 `BossAttackRegistry` 中注册(类比 `SpellRegistry`),运行时由 `_tick_attack` 调用: ```gdscript # boss_instance.gd(续) func _tick_attack(delta: float) -> void: _attack_cooldown -= delta if _attack_cooldown > 0.0: return var phase_def: BossPhaseDef = boss_def.phases[int(current_phase)] if phase_def.attack_patterns.is_empty(): return # 轮询攻击模式 var pattern_id: String = phase_def.attack_patterns[ _pattern_index % phase_def.attack_patterns.size() ] _pattern_index += 1 var cooldown: float = BossAttackRegistry.execute(pattern_id, self) _attack_cooldown = cooldown ``` `BossAttackRegistry.execute(id, boss)` 返回该攻击模式的冷却时间(秒)。每种攻击模式是一个独立的 GDScript 函数或 Resource,通过 SpellEvaluator 发射子弹(走标准 BulletManager 路径)。 --- ## 5. 具体 Boss 设计模板 ### 5.1 Mini Boss — Wave 8(待策划填充) | 字段 | 值 | | :--- | :--- | | `boss_id` | `"mini_boss_w8"` | | `hp_max` | 2000(约为普通精英 6.6×) | | `move_speed` | 120(比杂鱼慢,靠范围攻击弥补) | | **Phase 0**(100%→60% HP)| 攻击模式:`"charge_slam"` + `"spread_shot_3"` | | **Phase 1**(60%→30% HP)| 追加:`"summon_minion_x2"`;move_speed_mult=1.2 | | **Phase 2**(30%→0% HP)| 追加:`"zone_aoe_fire"`;move_speed_mult=1.5;enrage_vfx="boss_enrage" | | 死亡事件 | `BOSS_KILLED`(EventID 待分配,建议 ID=15)| | 战场机制 | 无(Mini Boss 不设场地机制,Final Boss 才有)| ### 5.2 Final Boss — Wave 20(待策划填充) | 字段 | 值 | | :--- | :--- | | `boss_id` | `"final_boss_w20"` | | `hp_max` | 10000 | | `move_speed` | 80(极慢,靠弹幕覆盖)| | **Phase 0**(100%→70% HP)| 攻击模式:`"spiral_shot_8"` + `"summon_turrets_x4"` | | **Phase 1**(70%→40% HP)| 追加:`"zone_ice_wall"`;场地:随机生成 4 个冰墙障碍(`ZoneManager` 驱动)| | **Phase 2**(40%→15% HP)| 追加:`"enrage_laser_sweep"`;场地收缩:边界每 10 秒向中心缩小 50px | | **Phase 3**(15%→0% HP)| 全弹幕覆盖;`"phase3_barrage"`;恢复部分 HP 后进入死亡序列(演出用)| | 死亡事件 | `BOSS_KILLED`(`EventID` **16**)+ `GAME_CLEARED`(**17**);阶段切换为 **15**(均以 `implementation_plan.md` §2.1 为准)| | 战场机制 | 场地收缩(Phase 2+)、冰墙障碍(Phase 1+)| --- ## 6. EventBus 扩展(Boss 专用事件) > **权威登记**:以下 ID 已并入 `technical/implementation_plan.md` §2.1 事件目录与 `event_ids.gd`,本节表为语义说明(勿改号)。 | 事件 ID | 常量名 | Payload | 订阅方 | | :--- | :--- | :--- | :--- | | 15 | `BOSS_PHASE_CHANGED` | `{boss_id, phase, bgm_layer}` | HUD(阶段提示)、AudioManager(BGM 切换)| | 16 | `BOSS_KILLED` | `{boss_id, wave_num}` | WaveManager(进入结算)、AchievementManager | | 17 | `GAME_CLEARED` | `{elapsed_sec, wave_num}` | GameCycleManager(结算屏)、排行榜 | --- ## 7. 与现有系统的接口约定 | 接口 | 调用方向 | 说明 | | :--- | :--- | :--- | | `SpatialGrid.register_boss(id, pos, radius)` | BossManager → SpatialGrid | Boss 作为可被子弹命中的实体,每帧更新坐标 | | `BulletManager._on_bullet_hit(bullet_id, target_id)` | BulletManager → BossManager | `target_id` 前缀区分:`enemy_xxx` vs `boss_xxx`(或通过 faction 位掩码判断)| | `ZoneManager.spawn_zone(...)` | BossAttackPattern → ZoneManager | Boss 攻击模式可生成 Zone(如冰墙、火圈)| | `VFXManager.play(vfx_id, pos, scale)` | BossInstance → VFXManager | 阶段切换 + 死亡演出 VFX | | `SpellEvaluator.execute_boss_pattern(pattern_id, origin)` | BossAttackRegistry → SpellEvaluator | Boss 弹幕走标准 SpellEvaluator 路径,复用子弹生成管线 | --- ## 8. 目录规范 ```text scripts/autoloads/ boss_manager.gd # Autoload BossManager scripts/domain/boss/ boss_def.gd # class_name BossDef (Resource) boss_phase_def.gd # class_name BossPhaseDef (Resource) boss_instance.gd # class_name BossInstance (RefCounted) boss_attack_registry.gd # BossAttackRegistry(类比 SpellRegistry) resources/bosses/ mini_boss_w8.tres final_boss_w20.tres resources/boss_patterns/ charge_slam.tres spread_shot_3.tres spiral_shot_8.tres # ... ```