656 lines
34 KiB
Markdown
656 lines
34 KiB
Markdown
# Rthythm_archor_game
|
||
|
||
`Rthythm_archor_game` 是一个使用 Godot 4.6 开发的 2D 节奏横板动作游戏原型。项目核心来自《Anchor》策划方案:玩家不是用传统方向键自由移动,而是在音乐拍点窗口内输入动作,通过攻击、蓄力、技能、位移、浮空、击退、时间锚点和 Past / Future 双相位来推进战斗。
|
||
|
||
当前版本已经完成可运行的第一关战斗闭环:菜单与难度选择、第一关小怪流程、Boss 房门控、Boss 战入场、HUD、节奏条、时间锚点、攻击 Buff、玩家与敌人动作、Boss 行为、双层音乐、判定门控与输入锁定(反狂按)、Windows 打包链路、自动化回归测试都已接入。
|
||
|
||
## 快速开始
|
||
|
||
### 环境
|
||
|
||
- 引擎:Godot 4.6.x
|
||
- 主场景:`res://scenes/main/main.tscn`
|
||
- 项目配置:`project.godot`
|
||
- 默认音乐:`res://assets/audio/ev_past1.mp3`
|
||
|
||
在 Godot 中打开本目录后,运行主场景即可进入游戏流程。
|
||
|
||
以下命令中的 `<godot>` 代表 Godot 4.6.3 可执行文件路径。Windows 下请使用
|
||
`Godot_v4.6.3-stable_win64_console.exe`(console 包装器才能看到 stdout 输出;
|
||
它按自身文件名寻找同目录的 GUI 版,两个文件必须按原名放在同一目录)。
|
||
|
||
命令行运行单个测试示例:
|
||
|
||
```bash
|
||
<godot> --headless --path . --script tests/test_level1_spawn_flow.gd
|
||
```
|
||
|
||
重新导入 / 检查项目资源:
|
||
|
||
```bash
|
||
<godot> --headless --path . --import
|
||
```
|
||
|
||
## 基本操作
|
||
|
||
| 输入 | Godot action | 语义 |
|
||
| ----- | -------------------------- | ---------------------------------- |
|
||
| A | `combo_a` | 左向攻击;长按后释放为左向蓄力剑雨 |
|
||
| D | `combo_d` | 右向攻击;长按后释放为右向蓄力剑雨 |
|
||
| W | `combo_w` | 上挑、浮空、空中动作入口 |
|
||
| S | `combo_s` | 下砸、防御或特殊蓄力入口 |
|
||
| Space | `combo_space` | 特殊键,内部符号为 `SP` |
|
||
| E | runtime `toggle_move_list` | 显示 / 隐藏招式表 |
|
||
| Esc | `ui_cancel` | 游戏中暂停;暂停菜单内返回上一层 |
|
||
|
||
注意:
|
||
|
||
- A / D / W / S / Space 不直接自由移动角色。每次输入先进入节奏判定,再决定是否执行动作。
|
||
- **判定门控(2026-07-05 new1 定案,反狂按)**:每个节奏点只能被一次有效输入消耗。同一节奏点被消耗后的第 1 次重复按键按双击容错静默忽略(视同没按、无惩罚);第 2 次重复、或落在 BAD 窗之外的空按,判 MISS——不出招、连击清零、四拍槽写 `Ø`,并触发 **0.5 秒输入锁定**。锁定期间的按键完全无效:不判定、不留痕、也不刷新锁定时长。门控只作用于实时判定的输入(测试 / AI 的预置判定绕过)。实现见 `RhythmManager.gate_judged_input`(`input_lockout_seconds = 0.5`、`consumed_repeat_grace = 1`)。
|
||
- 输入锁定若横跨时间锚点拍,该锚点必破(锁定期无法产生维持锚点的判定 → 超时 → 相位切换)。这是有意设计:失误的代价随连击档位升高而变重。
|
||
- W + A / D 会触发带明显横向位移的空中抛物线式动作表现。
|
||
- S 蓄力后按 Space 释放的斩波按玩家当前朝向发射:朝左即向左,不再自动瞄准最近敌人。
|
||
- A / D 蓄力释放的剑雨落点与玩家可见脚底地面线对齐(角色锚点 y=560、可见脚底线 y=520)。
|
||
- A / D 蓄力已进入 armed / charging 状态时按下 Space 会中断蓄力并按四拍槽派生解算(四拍槽仍保有 `[A]`,故 `[A][SP]` 解算为可穿过 Boss 的冲刺斩);S 蓄力不受此规则影响。
|
||
- 右上角没有常驻暂停按钮,暂停只通过 Esc 触发。
|
||
|
||
## 当前主流程
|
||
|
||
```text
|
||
Title / DifficultySelect
|
||
-> Gameplay_FrontArea
|
||
-> 第一关小怪流程
|
||
-> 全部小怪清场
|
||
-> Boss 房路径解封
|
||
-> 玩家进入 Boss 区域
|
||
-> Boss HUD 立即显示,Boss AI 激活
|
||
-> Gameplay_BossRoom
|
||
-> Victory / Defeat / Result
|
||
```
|
||
|
||
难度选择由 `GameFlowManager` 管理,菜单贴图位于 `assets/ui/menu/`。难度页面点击后会保留选中态,并通过确认按钮进入游戏;返回、暂停、音量、退出确认、结算页面也在同一流程管理器中。
|
||
|
||
标题侧表现:
|
||
|
||
- 标题、难度选择、退出确认界面持续播放节奏音乐(`ev_past1.mp3`,走 Music 总线,由 `GameFlowManager` 的常驻播放器承载,不受 SceneTree 暂停影响)。
|
||
- 标题背景在「过去」与「现在」两张场景图之间循环交叉淡入淡出。
|
||
- 点击开始游戏后标题音乐停止,游戏内音乐从第 0 拍重新播放(`RhythmManager.start()` + `AudioLayerController.restart_layers()`)。
|
||
|
||
难度影响:
|
||
|
||
| 难度 | 判定窗口(Perfect / Good / Bad 秒) | 小怪血量 |
|
||
| ---- | ----------------------------------- | -------- |
|
||
| 简单 | 0.090 / 0.160 / 0.260 | ×1(650)|
|
||
| 普通 | 0.060 / 0.115 / 0.215 | ×3(1950)|
|
||
| 困难 | 0.030 / 0.070 / 0.170 | ×5(3250)|
|
||
|
||
判定窗口定义在 `GameSettings.DIFFICULTY_WINDOWS`,经 `apply_judgement_windows` 写入 `RhythmManager`。
|
||
|
||
小怪血量倍率定义在 `GameSettings.DIFFICULTY_MINION_HEALTH_MULTIPLIER`,由 `minion.gd` 在 `_ready` 时读取;Boss 血量不受该倍率影响。
|
||
|
||
## 核心玩法循环
|
||
|
||
当前战斗循环如下:
|
||
|
||
```text
|
||
RhythmManager 推进音乐时间
|
||
-> ChartRunner 触发谱面事件与预告
|
||
-> 玩家在节奏窗口输入 A / D / W / S / Space
|
||
-> InputComponent 创建 InputIntent
|
||
-> ActionController 调用 RhythmManager 判定
|
||
-> 判定门控 gate_judged_input:锁定期 / 已消耗节奏点的按键在此被拦下
|
||
(ok = 消耗该节奏点继续;ignored = 视同没按;miss = 记 MISS 并锁定 0.5s)
|
||
-> ComboWindow 记录最近四拍输入
|
||
-> ActionResolver 根据四拍槽与角色状态选择 ActionData
|
||
-> ActionExecutor 执行动作、消耗或回复能量、打开命中窗口
|
||
-> CombatManager / Resolver 结算伤害、击退、打断、防御、受击
|
||
-> TimeAnchorSystem 根据判定事实结算时间锚点
|
||
-> UI 刷新节奏、判定、combo、Buff、血量、能量、蓄力和四拍槽
|
||
```
|
||
|
||
A / D 蓄力释放与 S + Space 二段施放两条蓄力路径同样经过判定门控。
|
||
|
||
时间锚点不会新增输入按键。同一次玩家输入同时服务于动作系统和锚点系统:动作系统决定是否出招,锚点系统决定是否维持当前时间相位。
|
||
|
||
## 第一关关卡实现
|
||
|
||
实现入口:
|
||
|
||
- `scenes/stage/stage.tscn`
|
||
- `scenes/stage/stage.gd`
|
||
- `scenes/stage/level_director.gd`
|
||
- `scenes/stage/boss_room_gate.gd`
|
||
- `scenes/enemies/minion_behavior.gd`
|
||
|
||
第一关沿用参考工程的角色、Boss、背景、HUD 和相机相对大小,只调整关卡流程、出怪方式、门控和位置关系。玩家、小怪、Boss 的地面锚点统一在 `y = 560`。
|
||
|
||
### 关键坐标
|
||
|
||
| 对象 | 坐标 / 范围 | 说明 |
|
||
| ---------------------- | --------------: | ----------------------------------------------- |
|
||
| 竞技场左边界 | `x = 1120` | 小怪巡逻 / 后撤左边界 |
|
||
| 左侧增援刷新点 | `x = 1420` | 左侧入场起点 |
|
||
| 玩家出生点 | `(1180, 560)` | 2026-07-05 new2:地图偏左出生,开场向右推进遇敌 |
|
||
| 战斗中心 | `x = 2047` | 增援入场目标基准 |
|
||
| 阶段一近战怪 | `(2200, 560)` | 开局预置;玩家从左侧出生点推进约 1000px 后遭遇 |
|
||
| 右侧增援刷新点 | `x = 2240` | 右侧入场起点(与小怪右侧安全线同值) |
|
||
| 小怪右侧安全线 | `x = 2240` | Boss 空气墙左侧 220px;所有小怪都限制在此线左侧 |
|
||
| Boss 空气墙 / 触发参考 | `gate_x = 2460` | 小怪不会越过该区域 |
|
||
| Boss 初始锚点 | `(2520, 560)` | Boss 战前 `combat_enabled = false` |
|
||
| 相机初始位置 | `(1180, 395)` | 跟随玩家,`camera_follow_offset = (0, -165)` |
|
||
|
||
以上均为 `stage.tscn` 的实际覆盖值;`level_director.gd` / `boss_room_gate.gd` 脚本里的 export 默认值会被场景覆盖,以 tscn 为准。
|
||
|
||
`LevelDirector` 会根据 `BossRoomGate.gate_x` 和 `boss_gate_minion_clearance = 220` 自动计算前场最大活动范围。动态刷新的远程怪、近战怪,以及编辑器内预置的小怪,都会统一套用这条安全边界,避免刷到空气墙右侧或相机边缘。
|
||
|
||
### 出怪阶段
|
||
|
||
第一关总计 6 只小怪。
|
||
|
||
| 阶段 | 触发条件 | 内容 |
|
||
| ------ | ----------------- | ---------------------------------------------------- |
|
||
| 阶段一 | 开局 | 预置近战怪 × 1 |
|
||
| 阶段二 | 击败第一只近战怪 | 玩家附近生成远程怪 × 1,生成点可感知但不贴脸 |
|
||
| 阶段三 | 击败阶段二远程怪 | 按 2 秒间隔生成 4 只增援:近战L、远程R、近战R、远程L |
|
||
| 清场 | 击败全部 6 只小怪 | 解封 Boss 房路径并广播 `front_area_cleared` |
|
||
|
||
阶段三的“右侧”增援也不会刷到空气墙右侧;运行时会被夹到前场安全线以内。
|
||
|
||
### Boss 房门控
|
||
|
||
`BossRoomGate` 当前规则:
|
||
|
||
- 开局 `sealed = true`,阻挡玩家进入 Boss 区域。
|
||
- 小怪全灭后 `LevelDirector` 调用 `unseal()`,空气墙碰撞关闭,视觉保持透明。
|
||
- 玩家跨过门线(`x >= gate_x`)的瞬间 `lock()` 立即触发:Boss 解锁、面板显示,不需要走到 Boss 面前。
|
||
- `lock()` 只触发一次 Boss 战入场逻辑。
|
||
- 进入 Boss 区域后空气墙不会重新显示,也不会重新启用碰撞,会完全消失。
|
||
- Boss 入场时立即激活 Boss AI,并主动刷新 Boss HUD 绑定。
|
||
- Boss 面板只在 `Gameplay_BossRoom` 显示;前场阶段隐藏,即使 Boss 已被绑定也不会提前显示。
|
||
|
||
相机在 Boss 区域未解锁时会限制右侧视野,避免提前看到 Boss 区域。
|
||
|
||
## 玩家系统
|
||
|
||
实现入口:
|
||
|
||
- `scenes/characters/player.tscn`
|
||
- `scenes/characters/player.gd`
|
||
- `scenes/components/`
|
||
- `resources/actions/`
|
||
- `resources/player_action_bindings.tres`
|
||
|
||
玩家由组件组合而成:
|
||
|
||
- `HealthComponent`:生命
|
||
- `EnergyComponent`:能量
|
||
- `ChargeComponent`:蓄力
|
||
- `InputComponent`:输入转 intent
|
||
- `ComboWindow`:四拍槽
|
||
- `ActionController`:动作生命周期(含判定门控接入)
|
||
- `ActionResolver`:四拍槽 + 角色状态 → ActionData 解算
|
||
- `ActionExecutor`:动作效果执行
|
||
- `MotionExecutor`:动作位移
|
||
- `MovementMotor`:浮空、落地、击退等运动处理
|
||
- `StateMachine`:地面 / 动作 / 防御 / 生死状态轴
|
||
- `DamageEmitter` / `DamageReceiver`:攻击与受击区域
|
||
- `EffectContainer`:Buff / Debuff 容器
|
||
- `StreakCounter`:连续成功动作计数
|
||
- `AttackBuffComponent`:时间锚点攻击 Buff(含回血与受伤掉层)
|
||
- `BurstComponent`:爆发动作门槛
|
||
- `FrameCollisionDriver`:帧动画命中框驱动
|
||
- `ContactFxSpawner`:命中接触特效
|
||
- `OverheadChargeSegments`:头顶蓄力段显示
|
||
- `Visual/AttackBuffVisual`、`Visual/FxOverlay` + `Visual/FxAnimationPlayer`:Buff 层数与 FX 贴片表现
|
||
|
||
动作由 `ActionData` 资源驱动,数据包含输入模式、能量、伤害倍率、水平 / 竖直位移、击退、命中类型、Startup / Active / Recovery 拍数、可取消时机、可执行状态、标签、动画名等。
|
||
|
||
当前已接入:
|
||
|
||
- 普通左右攻击
|
||
- 上挑与空中动作
|
||
- 下砸
|
||
- 防御
|
||
- Dash / 冲刺斩
|
||
- A / D 长按蓄力剑雨
|
||
- S + SP 二段式蓄力
|
||
- 四拍槽派生动作
|
||
- 攻击命中特效与蓄力释放世界 FX
|
||
- 强势 Buff 视觉效果,层数越多表现越明显
|
||
|
||
玩家死亡动画会保持地面线一致;死亡动画结束后尸体会消失。
|
||
|
||
## 小怪系统
|
||
|
||
实现入口:
|
||
|
||
- `scenes/enemies/minion.tscn`
|
||
- `scenes/enemies/minion.gd`
|
||
- `scenes/enemies/minion_behavior.gd`
|
||
- `resources/actions/enemies/`
|
||
- `resources/time_phase/profile_past_strong_enemy.tres`
|
||
- `resources/time_phase/profile_future_strong_enemy.tres`
|
||
|
||
小怪分近战与远程两类,并有 Past / Future 两种形态。
|
||
|
||
基础攻击力按职责区分(2026-07-05 new3 定案):**近战 50、远程 25**。由 `LevelDirector` 按 `MinionBehavior.role` 统一写入 `DamageEmitter.damage`(预置怪与动态刷新怪都覆盖),最终伤害仍乘相位强弱倍率。
|
||
|
||
### 近战怪
|
||
|
||
- Past 形态:`jin_zhan_3`,强势
|
||
- Future 形态:`jin_zhan_1`,弱势
|
||
- 会巡逻、警戒、追击、按拍攻击
|
||
- 强势相位 2 拍攻击一次,弱势相位 4 拍攻击一次
|
||
- 距离参数(new3):警戒 360、追踪停步 120、出手距离 120、攻击判定前缘约 140(动作 `range = 130`)、巡逻半径 110
|
||
- 强势相位命中会打断并击退玩家约 86px(`knockback_mult_x = 2.4`);弱势相位命中只掉血
|
||
- 朝向按目标位置正确翻转,不再固定朝右 / 朝左
|
||
|
||
### 远程怪
|
||
|
||
- Past 形态:`yuan_cheng_1`,小女孩,弱势
|
||
- Future 形态:`yuan_cheng_2`,女巫,强势
|
||
- 不巡逻,固定站位射击(站位停步 340、警戒 540)
|
||
- **最大开火距离 450,压在相机可视半宽(约 460px)以内——刚进画面即可开火,但绝不从屏幕外攻击玩家**
|
||
- 近身后撤:玩家进入危险距离 220 持续 0.6 秒 → 向远离玩家方向退开 220px(贴墙无退路时反向跳过玩家身位);后撤结束按节拍停顿 1 拍再恢复攻击;3 秒冷却
|
||
- 受击脱离(2026-07-05 新增):2 秒链窗内连续受击 4 次 → 0.4 秒闪烁无敌 + 跳跃形式高速脱离(3.2× 速度);3 秒冷却防连续触发。无敌通过 `FrameCollisionDriver.damage_receiver_enabled` 实现(直接改 Area2D 会被驱动器每帧重申覆盖)
|
||
- 小女孩和女巫的视觉高度已对齐,两个形态都水平射击,projectile 发射高度一致(`projectile_height = 86`)
|
||
- 小女孩素材原生朝右(`native_facing = RIGHT`),镜像翻转以此为准,攻击朝向始终对准玩家
|
||
|
||
小怪形态切换时会保持脚下锚点稳定,避免动画移动过程中 y 轴突变造成视觉瞬移。
|
||
|
||
## Boss 系统
|
||
|
||
实现入口:
|
||
|
||
- `scenes/enemies/boss.tscn`
|
||
- `scenes/enemies/boss.gd`
|
||
- `scenes/enemies/boss_behavior_tree.gd`
|
||
- `resources/actions/enemies/`
|
||
|
||
Boss 当前支持:
|
||
|
||
- 近战连段
|
||
- 远程射击
|
||
- 二连发射击
|
||
- Dash / retreat
|
||
- 行为树决策
|
||
- 谱面事件优先级
|
||
- 受击链逃脱(1.2 秒链窗内连续受击 4 次 → 取消当前动作、`boss_retreat_dash` 逃脱;4 秒冷却;训练桩状态不逃脱)
|
||
- Past / Future 招式池差异
|
||
- **普攻恒霸体(2026-07-05 new3 定案)**:对不耗能量的攻击(`base_cost <= 0`,即玩家普通攻击)伤害照常结算,但不被打断、不被击退;只有耗能技能能压制 Boss。实现为 `boss.gd` 的 `shrugs_off_hit` + `CombatResolver` 受击方钩子。项目**没有**韧性 / 削韧系统——策划以霸体规则替代了 new3 §6.5 的韧性方案
|
||
- 远程(Future)相位被近身 ≤240px 时优先 `boss_retreat_dash` 拉开距离(后撤本身无伤害、8 拍冷却、后撤完接远程攻击)
|
||
- 相位切换后停顿 1 拍再决策(以事件总线最后拍号为基准)
|
||
- Boss 战前静默,进入 Boss 区域后才激活
|
||
- Boss 血条、名称和头像 HUD
|
||
|
||
行为树距离阈值(2026-07-05 调整后):`melee_distance = 180`、`ranged_distance = 360`、`dash_distance = 460`(超过则考虑突进,4 拍冷却)、远程相位后撤触发 `retreat_trigger_distance = 240`;决策间隔 2 拍(Future 相位 ×0.5)。
|
||
|
||
Boss 入场规则由 `BossRoomGate` 与 `GameFlowManager` 共同处理:玩家进入 Boss 区域后,Boss 从训练桩状态切换为可战斗状态,Boss 面板立即出现。
|
||
|
||
## 时间相位与时间锚点
|
||
|
||
实现入口:
|
||
|
||
- `autoload/time_phase_manager.gd`
|
||
- `autoload/time_anchor_system.gd`
|
||
- `resources/time_anchor_frequency_default.tres`
|
||
- `resources/time_phase/`
|
||
- `scenes/components/time_phase_adapter.gd`
|
||
- `scenes/audio/audio_layer_controller.gd`
|
||
- `scenes/ui/rhythm_track.gd`
|
||
|
||
世界有两个时间相位:
|
||
|
||
```text
|
||
past
|
||
future
|
||
```
|
||
|
||
`TimePhaseManager` 是相位唯一写入者。相位改变后通过 `EventBus.time_phase_changed` 广播,Stage、UI、音乐、敌人强弱、Buff 系统分别响应。
|
||
|
||
时间锚点规则:
|
||
|
||
- 时间锚点是特殊节奏拍,不是额外按键。
|
||
- 锚点拍内 `perfect / good / bad` 都能维持当前相位(锚点带 `min_grade` 字段可提高门槛,当前谱面均用默认 `bad`,即三档都维持)。
|
||
- 锚点超时或 Miss 会切换 Past / Future。空按触发的 0.5 秒输入锁定若横跨锚点拍,该锚点必破。
|
||
- `perfect / good` 成功锚定会增加 1 层攻击 Buff。
|
||
- `bad` 只保持相位,不增加攻击 Buff。
|
||
- 当前攻击 Buff 上限为 7 层;每层对 `damage_mult` 加算 +0.5(每层 +50% 伤害,线性叠加,7 层满层 ×4.5)。effect 资源为 `resources/effects/time_phase/effect_time_anchor_attack_buff.tres`。
|
||
- 每次实际相位切换时,Buff 层数减少 2,最低为 0。
|
||
- 锚点成功会按判定质量回血:Perfect 30、Good 20、Bad 10;生命低于 50% 时回血翻倍。回血按 4 拍窗口限一次——同一窗口内第二次锚点成功只加 Buff 不回血(高连击档位下每 4 拍最多 4 个锚点,只有第一个触发回血)。
|
||
- 受伤掉层与霸体:玩家被攻击进入受伤状态时掉落一半 Buff 层数(向下取整),每掉 1 层获得 0.5 秒霸体(SuperArmor:伤害照吃、不被打断、无击退);霸体期间不会再次进入受伤状态,因此不会连锁掉层。实现见 `AttackBuffComponent` + `resources/effects/effect_hurt_super_armor.tres`。
|
||
|
||
连击数会影响时间锚点频率:
|
||
|
||
| 连击数 | 每 4 拍锚点数 |
|
||
| -----: | ------------: |
|
||
| 0 - 7 | 1 |
|
||
| 8 - 15 | 2 |
|
||
| 16+ | 4 |
|
||
|
||
节奏 UI 当前做过可读性强化:
|
||
|
||
- 特殊节奏点放大,时间锚点比普通节奏点更明显。
|
||
- 节奏点命中中心后的 flash / hit 特效放大且保留更久。
|
||
- 锚点成功、断裂会使用不同颜色反馈。
|
||
- 节奏点从两侧向中心的移动直接由 `RhythmManager` 的歌曲时间驱动(`get_current_beat_progress`),全程连续丝滑,到达中心的时刻与拍点严格重合。
|
||
|
||
## UI 与 HUD
|
||
|
||
实现入口:
|
||
|
||
- `scenes/ui/main_ui.tscn`
|
||
- `scenes/ui/main_ui.gd`
|
||
- `scenes/ui/rhythm_track.tscn`
|
||
- `scenes/ui/rhythm_track.gd`
|
||
- `scenes/ui/combo_window_hud.tscn`
|
||
- `scenes/ui/combo_window_hud.gd`
|
||
- `assets/ui/`
|
||
|
||
当前 HUD 包含:
|
||
|
||
- 玩家状态栏:头像面板、HP、EN、蓄力条、蓄力等级
|
||
- Boss 状态栏:Boss 头像、名称、血条,只在 Boss 战显示
|
||
- 中央节奏条:左右节奏点向中心收束
|
||
- 时间锚点:特殊节奏点纹理与放大显示
|
||
- 判定艺术字:Perfect / Good / Bad / Miss
|
||
- combo 计数
|
||
- ATK Buff 读数
|
||
- 7 格 Buff 点亮条
|
||
- 四拍槽
|
||
- E 键招式表
|
||
- 调试面板,默认隐藏
|
||
|
||
HUD 由主场景绑定玩家和 Boss:
|
||
|
||
```text
|
||
Main
|
||
-> Stage
|
||
-> ActorsContainer
|
||
-> Player
|
||
-> Boss
|
||
-> UILayer
|
||
-> UI
|
||
```
|
||
|
||
Boss 面板显示条件是:
|
||
|
||
```text
|
||
flow state == Gameplay_BossRoom
|
||
and boss_actor is valid
|
||
```
|
||
|
||
因此前场阶段不会提前显示 Boss 血条;进入 Boss 区域时 `BossRoomGate` 会主动绑定 Boss,确保 HUD 立即可见。
|
||
|
||
## 音频
|
||
|
||
实现入口:
|
||
|
||
- `autoload/sfx_manager.gd`
|
||
- `scenes/audio/audio_layer_controller.gd`
|
||
- `assets/audio/`
|
||
|
||
当前音频系统包含:
|
||
|
||
- Past / Future 双音乐层同步播放
|
||
- 相位切换时交叉淡入淡出
|
||
- 节奏时钟不因切相位重置
|
||
- 标题侧节奏音乐(`GameFlowManager` 常驻播放器,Music 总线)
|
||
- 开局重置:`_reset_run_state()` 调 `RhythmManager.start()` 归零时钟后,立即调 `AudioLayerController.restart_layers()` 把双音轨拉回第 0 拍,不等漂移校正
|
||
- UI、攻击、命中、锚点等事件 SFX 入口
|
||
|
||
当前 Future 层仍使用占位处理,可继续替换为正式 Future 音乐资源。
|
||
|
||
## 谱面与事件
|
||
|
||
实现入口:
|
||
|
||
- `resources/beat_chart.gd`
|
||
- `resources/chart_track.gd`
|
||
- `resources/chart_event.gd`
|
||
- `resources/charts/`
|
||
- `scenes/chart/chart_runner.gd`
|
||
|
||
`BeatChart` 由多个 `ChartTrack` 组成,每个 track 内包含若干 `ChartEvent`。当前事件支持:
|
||
|
||
- `enemy_action`
|
||
- `show_accent_marker`
|
||
- `camera_pulse`
|
||
- `time_anchor`
|
||
- `force_time_phase`
|
||
|
||
`ChartRunner` 负责按音乐时间触发事件、提前广播 upcoming 事件给 UI、根据 `time_phase_mask` 过滤当前相位不可触发事件,并将敌人动作事件路由到目标 Actor。
|
||
|
||
当前谱面资源包括:
|
||
|
||
- `resources/charts/stage7_boss_opening.tres`
|
||
- `resources/charts/stage9_boss_duel.tres`
|
||
|
||
## 战斗结算
|
||
|
||
实现入口:
|
||
|
||
- `autoload/combat_manager.gd`
|
||
- `scripts/resolvers/stat_resolver.gd`
|
||
- `scripts/resolvers/combat_resolver.gd`
|
||
- `scripts/resolvers/defense_resolver.gd`
|
||
- `scenes/components/damage_emitter.gd`
|
||
- `scenes/components/damage_receiver.gd`
|
||
- `scenes/components/effect_container.gd`
|
||
|
||
战斗结算采用 resolver 管线:
|
||
|
||
- `StatResolver` 计算伤害、消耗、回复、动作位移。
|
||
- `CombatResolver` 处理命中结果、击退和命中上下文。
|
||
- `DefenseResolver` 处理防御、格挡、减伤、打断规则。
|
||
- `CombatManager` 负责一次命中事实的缓存、生命扣除、击退、打断、效果事件和 `hit_confirmed` 广播。
|
||
|
||
强弱与打断规则:
|
||
|
||
- 只有强势状态小怪能打断玩家。
|
||
- 弱势小怪攻击只结算伤害,不打断、不击退、不取消玩家动作。
|
||
- Boss 恒定视为强势,Boss 攻击可以打断玩家(玩家霸体动作除外)。
|
||
- 强弱状态在动作开始时快照,命中前切相位不会 retroactively 改变本次攻击。
|
||
- 受击方霸体钩子(2026-07-05 新增):`CombatResolver` 结算时调用受击方的 `shrugs_off_hit(action)`,返回 `true` 则本次命中的打断与击退一并取消、伤害照常。目前只有 Boss 实现该钩子(普攻恒霸体、耗能技能可压制)。
|
||
- 击退跟随伤害判定通道:击退判定倍率走 damage 通道(perfect 1.0 / good 0.85 / bad 0.7),且仅在攻击方拥有打断权时结算——弱势攻击与被霸体消化的攻击击退为零;受击方处于 Invincible / SuperArmor 防御态时同样归零。
|
||
- 所有耗能技能都带击退 / 击飞(dash_slash 1.5、combo_finisher 2.0、ground_smash 2.2 + 上挑、zhan_bo 1.0/1.3/1.6、jian_yu 0.8);玩家弹丸由 `ActorsContainer` 注入基准击退 `(120, 304)`。
|
||
|
||
## 目录结构
|
||
|
||
| 路径 | 说明 |
|
||
| ---------------------------- | ------------------------------------------------------------ |
|
||
| `addons/godot_mcp/` | Godot MCP 插件 |
|
||
| `assets/audio/` | 音乐与 SFX |
|
||
| `assets/art/ground/` | 地面、远景、中景背景 |
|
||
| `assets/art/characters/` | 玩家、Boss、小怪素材 |
|
||
| `assets/art/effects/` | 通用特效图集 |
|
||
| `assets/ui/menu/` | 标题、难度、暂停、确认等菜单贴图 |
|
||
| `assets/ui/panels/` | 玩家与 Boss 状态栏面板、Boss 头像 |
|
||
| `assets/ui/rhythm/` | 节奏条、锚点、节奏点、中心纹理 |
|
||
| `assets/ui/buff/` | Buff 点亮 / 未点亮图标 |
|
||
| `assets/ui/buff_effect/` | 玩家攻击 Buff 特效帧 |
|
||
| `assets/ui/combo/` | combo 数字素材 |
|
||
| `assets/ui/judgements/` | Perfect / Good / Bad / Miss 判定艺术字素材 |
|
||
| `assets/ui/strong_buff/` | 强势状态视觉特效 |
|
||
| `autoload/` | 9 个游戏单例:事件总线、节奏、难度设置、统计、战斗、相位、锚点、音效、流程 |
|
||
| `build/windows/` | Windows 打包产物(`Rthythm_archor_game.exe`,单文件内嵌 pck) |
|
||
| `docs/` | 策划、架构、第一关设计和决策文档 |
|
||
| `resources/actions/` | 玩家动作数据 |
|
||
| `resources/actions/enemies/` | 敌人与 Boss 动作数据 |
|
||
| `resources/charts/` | 谱面资源 |
|
||
| `resources/effects/` | Buff / Debuff / 相位效果 |
|
||
| `resources/time_phase/` | Past / Future 强弱 profile |
|
||
| `scenes/audio/` | 双音乐层控制 |
|
||
| `scenes/characters/` | 玩家与角色基类 |
|
||
| `scenes/chart/` | 谱面运行器 |
|
||
| `scenes/combat/` | projectile、一次性 FX、动作解析 |
|
||
| `scenes/components/` | 可复用 Actor 组件 |
|
||
| `scenes/enemies/` | 小怪、Boss、行为树与 AI |
|
||
| `scenes/ground/` | 地面与背景场景 |
|
||
| `scenes/main/` | 主场景入口 |
|
||
| `scenes/stage/` | 关卡、相机、门控、出怪导演、projectile 生成 |
|
||
| `scenes/ui/` | HUD、节奏条、能量条、四拍槽 |
|
||
| `scripts/resolvers/` | 战斗、数值、防御、动作规则 resolver |
|
||
| `tests/` | SceneTree 自动化测试(66 个) |
|
||
| `tools/` | 内容导出、谱面验证和模拟工具 |
|
||
| `export_presets.cfg` | "Windows Desktop" 导出预设(x86_64 / embed_pck 单 exe) |
|
||
|
||
## 自动化测试
|
||
|
||
项目包含 66 个 Godot SceneTree 测试,覆盖:
|
||
|
||
- 架构迁移契约
|
||
- 输入 intent 与节奏判定 payload
|
||
- 判定门控与输入锁定(节奏点一次性消耗、双击容错、MISS + 0.5s 锁定)
|
||
- 动作控制、四拍槽、蓄力、能量
|
||
- 战斗 resolver、Effect、强弱打断规则
|
||
- new3 怪物 / Boss 行为规则(Boss 霸体、按职责基础攻击、远程怪受击脱离)
|
||
- 玩家场景、动画节奏、死亡表现、剑雨落点
|
||
- 小怪节拍、朝向、远程射击、高度、行为状态机
|
||
- 第一关出怪流程与 Boss 房门控
|
||
- Boss 行为、Boss HUD、Boss projectile
|
||
- 菜单、难度选择、暂停、GameFlow
|
||
- 时间相位、时间锚点、攻击 Buff
|
||
- HUD 布局、节奏条、E 键招式表、UI 动画回归
|
||
|
||
常用回归命令(`<godot>` 见「快速开始」):
|
||
|
||
```bash
|
||
<godot> --headless --path . --script tests/test_input_gate.gd
|
||
<godot> --headless --path . --script tests/test_new3_enemy_rules.gd
|
||
<godot> --headless --path . --script tests/test_level1_spawn_flow.gd
|
||
<godot> --headless --path . --script tests/test_boss_room_gate.gd
|
||
<godot> --headless --path . --script tests/test_boss_room_entry_hud_and_wall.gd
|
||
<godot> --headless --path . --script tests/test_minion_behavior_states.gd
|
||
<godot> --headless --path . --script tests/test_minion_cadence_and_facing.gd
|
||
<godot> --headless --path . --script tests/test_player2_fx_and_witch_projectile.gd
|
||
<godot> --headless --path . --script tests/test_rhythm_feedback_and_move_list.gd
|
||
<godot> --headless --path . --script tests/test_phase9_boss_health_ui.gd
|
||
<godot> --headless --path . --script tests/test_title_music_and_background.gd
|
||
<godot> --headless --path . --script tests/test_difficulty_minion_health.gd
|
||
<godot> --headless --path . --script tests/test_hurt_buff_drop_and_super_armor.gd
|
||
<godot> --headless --path . --script tests/test_blade_rain_alignment.gd
|
||
```
|
||
|
||
也可以串行跑一组关键回归:
|
||
|
||
```bash
|
||
GODOT=<godot 可执行文件路径>
|
||
for test_file in \
|
||
tests/test_input_gate.gd \
|
||
tests/test_new3_enemy_rules.gd \
|
||
tests/test_game_flow.gd \
|
||
tests/test_level1_spawn_flow.gd \
|
||
tests/test_boss_room_gate.gd \
|
||
tests/test_boss_room_entry_hud_and_wall.gd \
|
||
tests/test_minion_behavior_states.gd \
|
||
tests/test_level1_melee_contact.gd \
|
||
tests/test_boss_integration.gd \
|
||
tests/test_minion_phase_system.gd \
|
||
tests/test_main_ui_camera_canvas.gd \
|
||
tests/test_phase9_boss_health_ui.gd \
|
||
tests/test_rhythm_ui_layout.gd \
|
||
tests/test_x1_visual_baseline.gd \
|
||
tests/test_player_combo_input.gd \
|
||
tests/test_combo_hud.gd \
|
||
tests/test_blade_rain_alignment.gd
|
||
do
|
||
"$GODOT" --headless --path . --script "$test_file" || exit $?
|
||
done
|
||
```
|
||
|
||
已知存量失败:`test_stage4_player_scene`(期望旧版 2 倍 Visual 缩放的历史基线,与当前实现无关,排查回归时可忽略)。
|
||
|
||
部分测试在加载资源时可能打印 Godot 的 UID fallback 或 MCP port warning;如果最终输出 `PASS ...` 且退出码为 0,则测试通过。
|
||
|
||
## 设计文档
|
||
|
||
| 文档 | 说明 |
|
||
| ---------------------- | -------------------------------------- |
|
||
| `docs/AnchorV1.0.md` | 核心策划方案 |
|
||
| `docs/Level1Design.md` | 第一关关卡与小怪行为设计 |
|
||
| `docs/new1.md` | 策划需求:节奏输入有效范围(判定门控) |
|
||
| `docs/new2.md` | 策划需求:标题固定与出生点左移 |
|
||
| `docs/new3.md` | 策划需求:怪物与 Boss 行为设定 |
|
||
| `docs/decisions.md` | 迁移、调试、玩法手感和技术决策日志 |
|
||
|
||
注意:`new1.md` / `new3.md` 的原文与最终实现有出入(例如 new1 的"零代价无效输入"被改为"MISS + 锁定"、new3 的韧性系统被霸体规则替代、720 射程被否决)——最终口径以 `docs/decisions.md` 顶部的 "2026-07-05 new1/new2/new3 需求落地" 条目为准。
|
||
|
||
## 打包与发布
|
||
|
||
项目已具备完整的 Windows 打包链路:
|
||
|
||
- 导出预设:`export_presets.cfg`(已入库)——预设名 `"Windows Desktop"`,x86_64,`embed_pck = true`(单 exe 内嵌资源包)。
|
||
- 产物路径:`build/windows/Rthythm_archor_game.exe`(约 143MB)。
|
||
- 前提:Godot 4.6.3-stable 导出模板需安装在 `%APPDATA%\Godot\export_templates\4.6.3.stable\`(目录名必须精确匹配引擎版本号去掉 `.official.<hash>` 后缀;升级引擎版本时需换用对应版本的模板包)。
|
||
|
||
重新打包只需两条命令:
|
||
|
||
```bash
|
||
<godot> --headless --path . --import
|
||
<godot> --headless --path . --export-release "Windows Desktop" "build/windows/Rthythm_archor_game.exe"
|
||
```
|
||
|
||
打包注意事项:导出包内 `DirAccess` 列出的资源名带 `.remap` / `.import` 后缀,运行时扫描 `res://` 的代码必须去后缀还原原名再 `load()` 并去重(`action_resolver.gd` 等三处已按此模式修复);新增运行时扫描代码时务必遵守,更稳的做法是预加载资源列表。
|
||
|
||
## Godot MCP
|
||
|
||
项目包含 Godot MCP 插件:
|
||
|
||
- `addons/godot_mcp/`
|
||
- `project.godot` 中已启用插件
|
||
- Autoload 注册了 `MCPScreenshot`、`MCPInputService`、`MCPGameInspector`
|
||
|
||
这允许外部工具对 Godot 运行场景进行截图、输入模拟、节点检查和自动化测试。命令行 headless import 时如果已有其他项目占用 MCP 端口,可能出现 project mismatch warning;通常不影响导入或测试结果。
|
||
|
||
## 当前实现状态
|
||
|
||
已实现:
|
||
|
||
- 标题、难度选择、暂停、确认、胜负和结算流程
|
||
- 第一关 6 小怪流程与 Boss 房解锁
|
||
- 玩家从地图偏左出生(x=1180),开场向右推进遇敌(2026-07-05 new2)
|
||
- 判定门控与输入锁定:节奏点一次性消耗、双击容错、空按 MISS + 0.5 秒锁定(2026-07-05 new1 定案)
|
||
- 小怪全部限制在 Boss 空气墙左侧安全区
|
||
- Boss 区域入场后 Boss HUD 立即显示
|
||
- Boss 区域空气墙进入后完全消失,不再显示或阻挡
|
||
- 玩家节奏输入、四拍槽、动作执行
|
||
- 能量、蓄力、技能释放与剑雨落点对齐
|
||
- 玩家 projectile 与敌人 projectile
|
||
- 小女孩 / 女巫高度对齐,远程水平射击
|
||
- 小怪节拍攻击、朝向、强弱打断规则
|
||
- new3 怪物 / Boss 行为体系:近战基础攻击 50 / 远程 25、距离参数重调、远程怪受击 4 次闪烁无敌跳跃脱离、射程压到视距内、Boss 普攻恒霸体 + 耗能技能压制、Boss 远程相位近身后撤、相位切换停顿(2026-07-05)
|
||
- Boss 行为树与谱面驱动动作
|
||
- 命中、伤害、击退、打断、防御和生命结算
|
||
- Effect / Buff / Debuff 管线
|
||
- Past / Future 时间相位
|
||
- 时间锚点调度、结算和放大视觉反馈
|
||
- 攻击 Buff 7 层显示、伤害加成和玩家特效增强
|
||
- 双音乐层同步切换
|
||
- 世界色调与径向相位切换 wipe
|
||
- HUD:节奏条、combo、ATK、Buff、判定艺术字、状态栏、Boss 栏、四拍槽、E 键招式表
|
||
- Windows 打包链路(export_presets.cfg + 单 exe 内嵌 pck,打包版已做端到端验证)
|
||
- 自动化测试覆盖关键系统(66 个测试)
|
||
|
||
仍可继续打磨:
|
||
|
||
- 替换正式 Future 音乐层
|
||
- 继续扩展 Boss 相位差异和条件锚点
|
||
- 增加更多正式谱面与战斗段落
|
||
- 继续调优 HUD 美术尺寸、透明度和可读性
|
||
- 扩展小怪组合与关卡后续段落
|
||
- 播测校准 2026-07-05 数值:近战小怪强势单跳约 38、Boss 近战翻倍后的压力、高连击档位下单次失误(断连击 + 锁定 + 锚点必破)的代价
|
||
- 进战斗场景瞬间批量启停碰撞体会刷非致命的 "flushing queries" 物理警告,可改 deferred 消除
|
||
|
||
## 开发约定
|
||
|
||
- `EventBus` 是系统间事实广播中心,避免跨系统硬引用。
|
||
- `TimePhaseManager` 是时间相位唯一写入者。
|
||
- `TimeAnchorSystem` 只消费判定事实,不参与输入链路裁决。
|
||
- `GameFlowManager` 管理菜单、暂停、难度、胜负和 BossRoom 状态。
|
||
- 动作数值优先写入 `ActionData` 资源,不硬编码在角色脚本中。
|
||
- Buff / Debuff 优先走 `EffectContainer` 和 effect 资源。
|
||
- 战斗数值通过 resolver 计算,减少场景脚本间耦合。
|
||
- UI 尽量订阅事实信号,不主动推导战斗状态。
|
||
- 关卡坐标优先通过 `Stage` / `LevelDirector` 导出参数表达,并补测试锁定。
|
||
- 新功能或 bugfix 应补充对应 `tests/test_*.gd` 回归测试。 |