Files
NS_unknown_game/game/docs/engine_capability_audit.md

9.9 KiB
Raw Permalink Blame History

Engine Capability Audit

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

结论

当前游戏层已经用了引擎核心框架,并且已把地图、动画、UI、音频、存档和 NPK/SoundPack 资源入口接到真实调用路径。

最重要的调整已经完成:场景地图不再以 C++ 硬编码为主,stage_01.map 通过 Asset / PvfArchive / ScriptParser 读取入口进入 LevelDefinition

当前骨架接入状态:游戏启动时通过 GameServices 探测/初始化 AudioSystemFontManagerPvfArchiveNpkArchiveSoundPackArchiveAudioDatabaseSaveSystem 状态;PlayerActor 已接入 Animation/NPK/PNG 优先级;WhiteboxScene 已接入 UIScene、音频 cue 和 debug 存档。详细状态见 game_skeleton.md

推荐方向:

.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 做位置控制。
  • GameUiOverlay 通过 UIScene 进入 UI scene stack。
  • 游戏入口已设置像素风渲染风格。

需要调整:

  • StageRenderer 当前自己维护贴图缓存。后续如果引擎已有统一资源缓存或纹理缓存,应迁移过去。
  • 地图层和 tile 层不应该额外造渲染管线,继续输出到引擎 Renderer 即可。

Resource / Asset

已部分使用:

  • Asset 被引擎纹理加载间接使用。
  • Windows / Switch 的资源根目录、RomFS 路径已经由引擎 Asset 解析。

当前状态:

  • StageMapResource 已直接使用 Asset::readFileToString 读取 map/stage_01.mapassets/map/stage_01.map
  • Windows 和 Switch 构建会把 game/assets/* 复制到产物 assets/,保证 assets/map/stage_01.map 路径可用。
  • stage_01 主地图已迁移到外部 .map 文件。
  • GameAudioGameServicesPlayerAnimationAssets 都通过 Asset 检查可选资源。

下一步:

  • 继续把输入配置、角色动画配置等文本/脚本配置接入 Asset 或 PVF。

PVF / ScriptParser

引擎已有:

  • PvfArchive::open
  • PvfArchive::getFileContent
  • PvfArchive::getFileBytes
  • PvfArchive::getFileRawData
  • PvfArchive::resolvePath
  • ScriptParser
  • ScriptValue

当前状态:

  • StageMapResource 已能在 PvfArchive 打开后尝试读取 map/stage_01.map
  • 若资源像 PVF 二进制脚本,会先用 ScriptParser 解析出 script values。
  • 若资源是 PVF 文本,会作为普通 .map 文本交给 StageMapLoader
  • ScriptParser 支持 PVF 脚本二进制格式,不是普通文本 parser。

地图结论:

  • 如果我们的 .map 是 PVF 内的二进制脚本格式,就应使用 PvfArchive + ScriptParser
  • 如果我们的 .map 是普通文本/JSON/自定义文本格式,就应先用 Asset 读取,再由游戏层做最小 parser。
  • 无论哪种格式,最终都应该落到 LevelDefinition,不要让 WhiteboxScene 直接理解文件格式。

NPK / Sprite / Animation

引擎已有:

  • NpkArchive
  • Sprite::createFromNpk
  • Sprite::createFromFile
  • Animation
  • parseAniFromPvf
  • parseAlsFromPvf

当前状态:

  • 玩家动画加载顺序为 PVF .ani -> NPK IMG -> PNG fallback。
  • 如果 PVF 中存在 character/male/*.aniPlayerActor 会使用引擎 Animation
  • 如果 NPK 中存在 sprite/character/male/*.img,会使用 Sprite::createFromNpk
  • 当前仓库没有正式 PVF/NPK 动画资源,因此运行时仍会回退到 PNG spritesheet。

风险:

  • 只要正式动画资源未进入 PVF/NPK,临时 PNG fallback 仍需要少量手写帧切换。

下一步建议:

  • 为玩家和敌人补齐 PVF .ani 或 NPK IMG 后,逐步移除 PNG fallback 的手写帧切换。
  • 将 attack/damage box 从 Animation::GetCurrentFrameInfo() 接入战斗 hitbox。

Audio / Save

引擎已有:

  • AudioSystem
  • Sound
  • Music
  • SoundPackArchive
  • AudioDatabase
  • SaveSystem

当前状态:

  • GameAudio 已接入 SoundMusicAudioDatabase 查询。
  • WhiteboxScene 会尝试播放 stage_01 BGM 和 battle zone 进入音效。
  • PlayerActor 会尝试播放跳跃、攻击音效。
  • GameSave 已用 SaveSystem 保存 debug overlay 开关。

后续原则:

  • 正式音效、BGM、环境音直接放入资源槽位或 audio.xml
  • 设置、进度继续用 SaveSystem,不要在游戏层重新写文件存档服务。

UI / Text

引擎已有:

  • UIScene
  • TextSprite
  • FontManager

当前状态:

  • GameUiOverlay 已作为 UIScene 接入。
  • assets/fonts/debug.ttfassets/fonts/ui.ttf 时,状态 UI 使用 TextSprite
  • 缺字体时使用 Renderer::drawQuad 色条 fallback,避免 Switch/PC 因字体缺失黑屏。

Event / Input

已使用:

  • KeyEvent
  • EventType::KeyDown

游戏层自定义:

  • InputState
  • InputStateProvider

判断:

  • InputState 作为游戏语义输入是合理的,能隔离 PC/Switch 差异。
  • 但底层输入事件和生命周期应继续使用引擎事件系统。

下一步:

  • InputConfig 可以作为游戏层配置,但读取配置应走 Asset 或 PVF。
  • Debug 输入和 gameplay 输入要分离,避免正式版本保留开发快捷键。

当前游戏层自造/硬编码点

1. 地图硬编码

文件:

  • game/src/data/whitebox_level.cpp

当前状态:

  • 已新增 game/assets/map/stage_01.map
  • 已新增 StageMapLoader,把 .map 文本解析成 LevelDefinition
  • CreateWhiteboxLevel() 已改为优先加载 .map,失败时才回退 C++ 白盒数据。
  • C++ 中保留的世界尺寸、平台、视觉层、props、battle zone、spawn point 现在只作为 fallback。

后续建议:

  • 继续扩展 .map 的 tileset/tile entry 表达。
  • 逐步把 level_visual 的长色块替换成 tile 数据。

2. PNG fallback 手写动画帧切换

文件:

  • game/src/actor/player_actor.cpp

当前状态:

  • 已接入 Animation 和 NPK 优先路径。
  • 临时 PNG fallback 仍在 C++ 里硬编码帧数、帧时间和 source rect。

建议:

  • 等正式 .ani / .img 资源补齐后,删除 PNG fallback 的手写帧切换。

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