8.6 KiB
8.6 KiB
Engine Capability Audit
目标:后续游戏层尽量复用 Frostbite2D 已有能力,避免在游戏项目里重复造资源、动画、地图、渲染、输入和存档轮子。本文基于当前引擎代码和游戏层现状整理。
结论
当前游戏层已经用了引擎的核心框架,但地图和角色动画仍有明显“游戏层自造/硬编码”倾向。
最重要的调整是:场景地图不要继续在 C++ 里手写 Rect,下一步应接入 .map 文件加载,并优先通过引擎 Asset / PvfArchive / ScriptParser 读取和解析。
当前第一轮骨架接入已完成:游戏启动时通过 GameServices 探测/初始化 AudioSystem、PvfArchive、NpkArchive、SoundPackArchive、AudioDatabase 和 SaveSystem 状态,并通过 StageMapResource 接入 .map 资源读取入口。详细状态见 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
已使用:
ApplicationSceneManagerSceneActorRefPtr/MakePtr
当前状态:
WhiteboxScene继承frostbite2D::Scene。PlayerActor继承frostbite2D::Actor。- 场景生命周期、Actor 子节点、Render/Update 流程已接入引擎。
保留原则:
- 后续敌人、道具、特效仍应优先做成
Actor子类或 Actor 子节点。 - 不在游戏层另写对象树、生命周期系统或场景管理器。
Graphics / Camera / Render
已使用:
Renderer::drawQuadRenderer::drawSpriteTexture::loadFromFileCameraRenderStyleProfileId::PixelArt2DResolutionScaleMode::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::openPvfArchive::getFileContentPvfArchive::getFileBytesPvfArchive::getFileRawDataPvfArchive::resolvePathScriptParserScriptValue
当前状态:
- 游戏层还没使用。
- 引擎已经具备从
Script.pvf按逻辑路径取脚本文件的能力。 ScriptParser支持 PVF 脚本二进制格式,不是普通文本 parser。
地图结论:
- 如果我们的
.map是 PVF 内的二进制脚本格式,就应使用PvfArchive + ScriptParser。 - 如果我们的
.map是普通文本/JSON/自定义文本格式,就应先用Asset读取,再由游戏层做最小 parser。 - 无论哪种格式,最终都应该落到
LevelDefinition,不要让WhiteboxScene直接理解文件格式。
NPK / Sprite / Animation
引擎已有:
NpkArchiveSprite::createFromNpkSprite::createFromFileAnimationparseAniFromPvfparseAlsFromPvf
当前状态:
- 玩家现在使用
Sprite::createFromFile加载 PNG spritesheet。 - 玩家动画帧切换在
PlayerActor内手写。 - 还没有使用
Animation、.ani、.als、PVF 动画数据或 NPK 图包。
风险:
- 如果继续手写动画,后续敌人、玩家连招、受击、死亡都会重复造动画系统。
下一步建议:
- 在地图框架后,角色动画应迁移到引擎
Animation。 - 若素材来自 NPK/PVF 体系,优先用
Animation + NpkArchive + parseAniFromPvf。 - 若当前临时素材仍是 PNG spritesheet,可以短期保留,但不要扩展成复杂自研动画状态系统。
Audio / Save
引擎已有:
AudioSystemSoundMusicSoundPackArchiveAudioDatabaseSaveSystem
当前状态:
- 游戏层尚未使用音频和存档。
后续原则:
- 音效、BGM、环境音直接接引擎音频系统。
- 设置、进度、调试存档优先用
SaveSystem,不要在游戏层重新写文件存档服务。
Event / Input
已使用:
KeyEventEventType::KeyDown
游戏层自定义:
InputStateInputStateProvider
判断:
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()临时变成:
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。 - 不要为了地图单独造一套渲染系统。
推荐执行顺序
StageMapResource:定义地图文件路径、普通资源读取和 PVF 读取优先级。StageMapLoader:把.map转成LevelDefinition。stage_01.map:把当前whitebox_level.cpp数据迁移成外部地图文件。CreateWhiteboxLevel():改为加载stage_01.map,失败时回退旧白盒数据。StageRenderer:继续消费LevelDefinition,不直接关心.map。- 文档:把地图编辑流程写入
scene_acceptance.md和场景计划。
总体原则
- 引擎已有的资源、归档、动画、音频、事件、Actor 和 Scene 能力优先使用。
- 游戏层只做“游戏语义转换”:地图语义、战斗语义、角色状态、关卡流程。
- 外部资源文件优先通过
Asset/PvfArchive进入。 - C++ 硬编码只作为 fallback,不作为长期地图生产方式。