Files
NS_unknown_game/game/docs/engine_capability_audit.md
T

8.3 KiB
Raw Blame History

Engine Capability Audit

目标:后续游戏层尽量复用 Frostbite2D 已有能力,避免在游戏项目里重复造资源、动画、地图、渲染、输入和存档轮子。本文基于当前引擎代码和游戏层现状整理。

结论

当前游戏层已经用了引擎的核心框架,但地图和角色动画仍有明显“游戏层自造/硬编码”倾向。

最重要的调整是:场景地图不要继续在 C++ 里手写 Rect,下一步应接入 .map 文件加载,并优先通过引擎 Asset / PvfArchive / ScriptParser 读取和解析。

推荐方向:

.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.mapgame/assets/map/stage_01.map
  • CreateWhiteboxLevel() 临时变成:
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 框架建议

加载优先级

第一阶段先支持普通资源文件:

Asset::readTextFile("map/stage_01.map")

第二阶段支持 PVF

PvfArchive::getFileContent("map/stage_01.map")

如果 .map 是 PVF 二进制脚本,则改用:

PvfArchive::getFileRawData("map/stage_01.map")
ScriptParser parser(rawData, "map/stage_01.map")

数据流

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,不作为长期地图生产方式。