From 562f9618c47e8fbdaf9b9e83d3842ce1c91e8378 Mon Sep 17 00:00:00 2001 From: 1165565692-lang <1165565692@qq.com> Date: Tue, 9 Jun 2026 21:31:38 +0800 Subject: [PATCH] Audit engine capabilities for map workflow --- game/docs/README.md | 1 + game/docs/engine_capability_audit.md | 325 +++++++++++++++++++++++++ game/docs/planning/scene_build_plan.md | 2 + 3 files changed, 328 insertions(+) create mode 100644 game/docs/engine_capability_audit.md diff --git a/game/docs/README.md b/game/docs/README.md index 82ce974..9347b4b 100644 --- a/game/docs/README.md +++ b/game/docs/README.md @@ -10,6 +10,7 @@ ## References - `controls.md`:玩家操作、平台输入映射和开发调试快捷键。 +- `engine_capability_audit.md`:引擎已有能力复盘,以及游戏层应优先复用的系统。 - `scene_acceptance.md`:第一关场景骨架验收流程和最近一次验收结果。 ## Naming diff --git a/game/docs/engine_capability_audit.md b/game/docs/engine_capability_audit.md new file mode 100644 index 0000000..a999700 --- /dev/null +++ b/game/docs/engine_capability_audit.md @@ -0,0 +1,325 @@ +# Engine Capability Audit + +目标:后续游戏层尽量复用 Frostbite2D 已有能力,避免在游戏项目里重复造资源、动画、地图、渲染、输入和存档轮子。本文基于当前引擎代码和游戏层现状整理。 + +## 结论 + +当前游戏层已经用了引擎的核心框架,但地图和角色动画仍有明显“游戏层自造/硬编码”倾向。 + +最重要的调整是:**场景地图不要继续在 C++ 里手写 `Rect`,下一步应接入 `.map` 文件加载,并优先通过引擎 `Asset` / `PvfArchive` / `ScriptParser` 读取和解析。** + +推荐方向: + +```text +.map 文件 + -> Asset 普通资源读取,或 PvfArchive 从 Script.pvf 内读取 + -> ScriptParser / map parser 解析 + -> 转成 LevelDefinition + -> StageRenderer / DebugOverlay / WhiteboxScene 继续复用 +``` + +这样地图可以外部维护,素材、图层、碰撞、出生点、camera bounds 和 battle zone 都能从数据文件进入游戏,而不是继续写死在 `whitebox_level.cpp`。 + +## 已经用上的引擎能力 + +### Core / Scene / Actor + +已使用: + +- `Application` +- `SceneManager` +- `Scene` +- `Actor` +- `RefPtr` / `MakePtr` + +当前状态: + +- `WhiteboxScene` 继承 `frostbite2D::Scene`。 +- `PlayerActor` 继承 `frostbite2D::Actor`。 +- 场景生命周期、Actor 子节点、Render/Update 流程已接入引擎。 + +保留原则: + +- 后续敌人、道具、特效仍应优先做成 `Actor` 子类或 Actor 子节点。 +- 不在游戏层另写对象树、生命周期系统或场景管理器。 + +### Graphics / Camera / Render + +已使用: + +- `Renderer::drawQuad` +- `Renderer::drawSprite` +- `Texture::loadFromFile` +- `Camera` +- `RenderStyleProfileId::PixelArt2D` +- `ResolutionScaleMode::Fit` + +当前状态: + +- `StageRenderer` 已复用引擎 Renderer 和 Texture。 +- `CameraController` 使用引擎 `Camera` 做位置控制。 +- 游戏入口已设置像素风渲染风格。 + +需要调整: + +- `StageRenderer` 当前自己维护贴图缓存。后续如果引擎已有统一资源缓存或纹理缓存,应迁移过去。 +- 地图层和 tile 层不应该额外造渲染管线,继续输出到引擎 Renderer 即可。 + +### Resource / Asset + +已部分使用: + +- `Asset` 被引擎纹理加载间接使用。 +- Windows / Switch 的资源根目录、RomFS 路径已经由引擎 `Asset` 解析。 + +未充分使用: + +- 游戏层目前没有直接用 `Asset::readTextFile` / `readBinaryFile` 读取地图和配置。 +- `stage_01` 地图仍写死在 C++。 + +下一步: + +- `.map` 普通文件先用 `Asset` 读取。 +- 同一套 loader 后续支持从 PVF 中读取。 + +### PVF / ScriptParser + +引擎已有: + +- `PvfArchive::open` +- `PvfArchive::getFileContent` +- `PvfArchive::getFileBytes` +- `PvfArchive::getFileRawData` +- `PvfArchive::resolvePath` +- `ScriptParser` +- `ScriptValue` + +当前状态: + +- 游戏层还没使用。 +- 引擎已经具备从 `Script.pvf` 按逻辑路径取脚本文件的能力。 +- `ScriptParser` 支持 PVF 脚本二进制格式,不是普通文本 parser。 + +地图结论: + +- 如果我们的 `.map` 是 PVF 内的二进制脚本格式,就应使用 `PvfArchive + ScriptParser`。 +- 如果我们的 `.map` 是普通文本/JSON/自定义文本格式,就应先用 `Asset` 读取,再由游戏层做最小 parser。 +- 无论哪种格式,最终都应该落到 `LevelDefinition`,不要让 `WhiteboxScene` 直接理解文件格式。 + +### NPK / Sprite / Animation + +引擎已有: + +- `NpkArchive` +- `Sprite::createFromNpk` +- `Sprite::createFromFile` +- `Animation` +- `parseAniFromPvf` +- `parseAlsFromPvf` + +当前状态: + +- 玩家现在使用 `Sprite::createFromFile` 加载 PNG spritesheet。 +- 玩家动画帧切换在 `PlayerActor` 内手写。 +- 还没有使用 `Animation`、`.ani`、`.als`、PVF 动画数据或 NPK 图包。 + +风险: + +- 如果继续手写动画,后续敌人、玩家连招、受击、死亡都会重复造动画系统。 + +下一步建议: + +- 在地图框架后,角色动画应迁移到引擎 `Animation`。 +- 若素材来自 NPK/PVF 体系,优先用 `Animation + NpkArchive + parseAniFromPvf`。 +- 若当前临时素材仍是 PNG spritesheet,可以短期保留,但不要扩展成复杂自研动画状态系统。 + +### Audio / Save + +引擎已有: + +- `AudioSystem` +- `Sound` +- `Music` +- `SoundPackArchive` +- `AudioDatabase` +- `SaveSystem` + +当前状态: + +- 游戏层尚未使用音频和存档。 + +后续原则: + +- 音效、BGM、环境音直接接引擎音频系统。 +- 设置、进度、调试存档优先用 `SaveSystem`,不要在游戏层重新写文件存档服务。 + +### Event / Input + +已使用: + +- `KeyEvent` +- `EventType::KeyDown` + +游戏层自定义: + +- `InputState` +- `InputStateProvider` + +判断: + +- `InputState` 作为游戏语义输入是合理的,能隔离 PC/Switch 差异。 +- 但底层输入事件和生命周期应继续使用引擎事件系统。 + +下一步: + +- `InputConfig` 可以作为游戏层配置,但读取配置应走 `Asset` 或 PVF。 +- Debug 输入和 gameplay 输入要分离,避免正式版本保留开发快捷键。 + +## 当前游戏层自造/硬编码点 + +### 1. 地图硬编码 + +文件: + +- `game/src/data/whitebox_level.cpp` + +问题: + +- 世界尺寸、平台、视觉层、props、battle zone、spawn point 全部写在 C++。 +- 这不适合后续反复调地图,也不适合你要的 `.map` 工作流。 + +建议: + +- 新增 `StageMapLoader`。 +- 创建 `game/assets/stage/stage_01/stage_01.map` 或 `game/assets/map/stage_01.map`。 +- 让 `CreateWhiteboxLevel()` 临时变成: + +```cpp +return LoadStageMap("map/stage_01.map").value_or(CreateFallbackWhiteboxLevel()); +``` + +### 2. 手写动画帧切换 + +文件: + +- `game/src/actor/player_actor.cpp` + +问题: + +- idle/run/punch 都在 C++ 里硬编码帧数、帧时间和 source rect。 + +建议: + +- 先记录为短期可接受。 +- 后续迁移到引擎 `Animation`,尤其当角色素材进入 PVF/NPK/ANI 体系后。 + +### 3. 游戏层贴图缓存 + +文件: + +- `game/src/stage/stage_renderer.*` + +问题: + +- `StageRenderer` 自己维护 `textureCache_`。 + +建议: + +- 短期可接受,避免每帧重复加载。 +- 如果引擎后续提供统一 Texture cache,迁移到引擎资源缓存。 + +### 4. 调试绘制工具 + +文件: + +- `game/src/debug/debug_overlay.*` + +判断: + +- 这是游戏特定调试可视化,保留合理。 +- 但底层绘制继续用 `Renderer::drawQuad`,不要另造 debug render backend。 + +## `.map` 框架建议 + +### 加载优先级 + +第一阶段先支持普通资源文件: + +```text +Asset::readTextFile("map/stage_01.map") +``` + +第二阶段支持 PVF: + +```text +PvfArchive::getFileContent("map/stage_01.map") +``` + +如果 `.map` 是 PVF 二进制脚本,则改用: + +```text +PvfArchive::getFileRawData("map/stage_01.map") +ScriptParser parser(rawData, "map/stage_01.map") +``` + +### 数据流 + +```text +StageMapLoader + -> 读取 .map + -> 解析 world / camera / spawn / layers / collision / zones + -> 输出 LevelDefinition + -> WhiteboxScene 使用 LevelDefinition +``` + +### `.map` 应表达的字段 + +- `world` + - width + - height +- `camera` + - bounds +- `player` + - spawn +- `layers` + - id + - role + - parallax + - rect / tile / sprite source +- `collision` + - platforms + - walls + - bounds +- `battle_zones` + - id + - trigger + - camera_bounds + - enemy_spawns +- `assets` + - background + - tileset + - props + - effects + +### 不建议做的事 + +- 不要在 `WhiteboxScene` 里解析 `.map`。 +- 不要绕开 `Asset` 直接用 `std::ifstream` 读资源。 +- 不要继续把地图扩展写死在 `whitebox_level.cpp`。 +- 不要为了地图单独造一套渲染系统。 + +## 推荐执行顺序 + +1. `StageMapResource`:定义地图文件路径、普通资源读取和 PVF 读取优先级。 +2. `StageMapLoader`:把 `.map` 转成 `LevelDefinition`。 +3. `stage_01.map`:把当前 `whitebox_level.cpp` 数据迁移成外部地图文件。 +4. `CreateWhiteboxLevel()`:改为加载 `stage_01.map`,失败时回退旧白盒数据。 +5. `StageRenderer`:继续消费 `LevelDefinition`,不直接关心 `.map`。 +6. 文档:把地图编辑流程写入 `scene_acceptance.md` 和场景计划。 + +## 总体原则 + +- 引擎已有的资源、归档、动画、音频、事件、Actor 和 Scene 能力优先使用。 +- 游戏层只做“游戏语义转换”:地图语义、战斗语义、角色状态、关卡流程。 +- 外部资源文件优先通过 `Asset` / `PvfArchive` 进入。 +- C++ 硬编码只作为 fallback,不作为长期地图生产方式。 diff --git a/game/docs/planning/scene_build_plan.md b/game/docs/planning/scene_build_plan.md index 621ad8d..83cf570 100644 --- a/game/docs/planning/scene_build_plan.md +++ b/game/docs/planning/scene_build_plan.md @@ -269,6 +269,8 @@ game/assets/stage/stage_01/ 当前场景骨架已经达到“可直接放素材”的工程状态。后续素材接入主要修改 `game/assets/stage/stage_01/` 和关卡 layer 数据,不需要再重写 `WhiteboxScene` 主流程。 +下一步地图框架调整:优先复用引擎 `Asset`、`PvfArchive` 和 `ScriptParser` 能力,把地图从 C++ 硬编码迁移到 `.map` 外部资源文件。详细复盘见 `../engine_capability_audit.md`。 + ### Debug 快捷键 场景 debug 快捷键统一记录在 `../controls.md`。