Load stage map into level definition

This commit is contained in:
2026-06-09 22:16:19 +08:00
parent 45a8712b00
commit 3fc9caa80b
9 changed files with 574 additions and 61 deletions
+23 -25
View File
@@ -8,7 +8,7 @@
最重要的调整是:**场景地图不要继续在 C++ 里手写 `Rect`,下一步应接入 `.map` 文件加载,并优先通过引擎 `Asset` / `PvfArchive` / `ScriptParser` 读取和解析。**
当前第一轮骨架接入已完成:游戏启动时通过 `GameServices` 探测/初始化 `AudioSystem``PvfArchive``NpkArchive``SoundPackArchive``AudioDatabase``SaveSystem` 状态,并通过 `StageMapResource` 接入 `.map` 资源读取入口。详细状态见 `game_skeleton.md`
当前第一轮骨架接入已完成:游戏启动时通过 `GameServices` 探测/初始化 `AudioSystem``PvfArchive``NpkArchive``SoundPackArchive``AudioDatabase``SaveSystem` 状态,并通过 `StageMapResource` + `StageMapLoader` 接入 `.map` 资源读取和解析入口。详细状态见 `game_skeleton.md`
推荐方向:
@@ -74,15 +74,15 @@
- `Asset` 被引擎纹理加载间接使用。
- Windows / Switch 的资源根目录、RomFS 路径已经由引擎 `Asset` 解析。
未充分使用
当前状态
- 游戏层目前没有直接用 `Asset::readTextFile` / `readBinaryFile` 读取地图和配置
- `stage_01` 地图仍写死在 C++
- `StageMapResource`直接使`Asset::readFileToString` 读取 `map/stage_01.map``assets/map/stage_01.map`
- Windows 和 Switch 构建会把 `game/assets/*` 复制到产物 `assets/`,保证 `assets/map/stage_01.map` 路径可用
- `stage_01` 主地图已迁移到外部 `.map` 文件。
下一步:
- `.map` 普通文件先用 `Asset` 读取
- 同一套 loader 后续支持从 PVF 中读取。
- 继续把输入配置、角色动画配置等文本/脚本配置接入 `Asset` 或 PVF
### PVF / ScriptParser
@@ -98,8 +98,9 @@
当前状态:
- 游戏层还没使用
- 引擎已经具备从 `Script.pvf` 按逻辑路径取脚本文件的能力
- `StageMapResource` 已能在 `PvfArchive` 打开后尝试读取 `map/stage_01.map`
- 若资源像 PVF 二进制脚本,会先用 `ScriptParser` 解析出 script values
- 若资源是 PVF 文本,会作为普通 `.map` 文本交给 `StageMapLoader`
- `ScriptParser` 支持 PVF 脚本二进制格式,不是普通文本 parser。
地图结论:
@@ -185,20 +186,17 @@
- `game/src/data/whitebox_level.cpp`
问题
当前状态
- 世界尺寸、平台、视觉层、props、battle zone、spawn point 全部写在 C++
- 这不适合后续反复调地图,也不适合你要的 `.map` 工作流
- 已新增 `game/assets/map/stage_01.map`
- 已新增 `StageMapLoader`,把 `.map` 文本解析成 `LevelDefinition`
- `CreateWhiteboxLevel()` 已改为优先加载 `.map`,失败时才回退 C++ 白盒数据。
- C++ 中保留的世界尺寸、平台、视觉层、props、battle zone、spawn point 现在只作为 fallback。
建议:
后续建议:
- 新增 `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());
```
- 继续扩展 `.map` 的 tileset/tile entry 表达
- 逐步把 `level_visual` 的长色块替换成 tile 数据
### 2. 手写动画帧切换
@@ -245,13 +243,13 @@ return LoadStageMap("map/stage_01.map").value_or(CreateFallbackWhiteboxLevel());
### 加载优先级
第一阶段支持普通资源文件:
第一阶段支持普通资源文件:
```text
Asset::readTextFile("map/stage_01.map")
```
第二阶段支持 PVF
第二阶段已预留 PVF
```text
PvfArchive::getFileContent("map/stage_01.map")
@@ -312,10 +310,10 @@ StageMapLoader
## 推荐执行顺序
1. `StageMapResource`定义地图文件路径、普通资源读取和 PVF 读取优先级。
2. `StageMapLoader``.map` 转成 `LevelDefinition`
3. `stage_01.map`把当前 `whitebox_level.cpp` 数据迁移成外部地图文件。
4. `CreateWhiteboxLevel()`改为加载 `stage_01.map`,失败时回退旧白盒数据。
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` 和场景计划。
+24 -9
View File
@@ -38,10 +38,11 @@
## 地图资源入口
新增 `StageMapResource`
新增 `StageMapResource``StageMapLoader`
```text
LoadStageMapResource("map/stage_01.map")
LoadStageMap("map/stage_01.map")
```
读取优先级:
@@ -53,22 +54,36 @@ LoadStageMapResource("map/stage_01.map")
当前状态:
- 已新增 `game/assets/map/stage_01.map` 占位文件
- `CreateWhiteboxLevel()` 会读取地图资源并记录来源
- 地图内容尚未接管 `LevelDefinition`,当前仍使用 C++ 白盒数据作为 fallback
- `game/assets/map/stage_01.map` 已接管第一关主数据
- `StageMapLoader` 会把 `.map` 文本解析成 `LevelDefinition`
- 已迁移世界尺寸、玩家出生点、相机边界、碰撞平台、视觉层、props、battle zone 和 spawn point
- `CreateWhiteboxLevel()` 优先读取 `.map`,读取或解析失败时才使用 C++ 白盒 fallback。
- Windows 和 Switch 构建会把 `game/assets/*` 复制到产物 `assets/`,保证运行时 `assets/map/stage_01.map` 路径可用。
下一步
`.map` 当前支持的命令
- 实现 `StageMapLoader`,把 `.map` 转成 `LevelDefinition`
-`whitebox_level.cpp` 中的硬编码平台、props、battle zone 迁移到 `.map`
- 失败时保留 `CreateFallbackWhiteboxLevel()`
```text
map <id>
world <width> <height>
camera <x> <y> <width> <height>
player_spawn <x> <y>
collision <x> <y> <width> <height>
layer <id> <BackgroundFar|BackgroundMid|LevelVisual|PropsBack|PropsFront> <parallax>
rect <x> <y> <width> <height> <r> <g> <b> <a>
rect_sprite <x> <y> <width> <height> <r> <g> <b> <a> <texture>
rect_sprite_src <x> <y> <width> <height> <r> <g> <b> <a> <texture> <sx> <sy> <sw> <sh>
endlayer
battle_zone <id> <trigger_x> <trigger_y> <trigger_w> <trigger_h> <camera_x> <camera_y> <camera_w> <camera_h>
spawn <id> <x> <y>
endbattle_zone
```
## 仍待迁移的能力
- 玩家动画:从手写 spritesheet 帧切换迁移到引擎 `Animation` / PVF ANI。
- 场景视觉资源:如果素材进入 NPK,迁移到 `NpkArchive` / `Sprite::createFromNpk`
- 音频:使用 `AudioSystem``Sound``Music``AudioDatabase`
- 地图:完成 `.map` parser,不再用 C++ 手写地图
- 地图:后续可把 `.map` 扩展为工具导出格式或 PVF 脚本格式,当前 C++ 地图只作为 fallback
- 输入配置:通过 `Asset` 或 PVF 读取 `InputConfig`
## 原则
+12 -2
View File
@@ -269,9 +269,19 @@ game/assets/stage/stage_01/
当前场景骨架已经达到“可直接放素材”的工程状态。后续素材接入主要修改 `game/assets/stage/stage_01/` 和关卡 layer 数据,不需要再重写 `WhiteboxScene` 主流程。
下一步地图框架调整:优先复用引擎 `Asset``PvfArchive``ScriptParser` 能力,把地图从 C++ 硬编码迁移到 `.map` 外部资源文件。详细复盘见 `../engine_capability_audit.md`
地图框架调整已完成第一步:优先复用引擎 `Asset``PvfArchive``ScriptParser` 能力,`stage_01.map` 已从占位文件升级为第一关主数据源。`StageMapLoader` 会把 `.map` 解析成 `LevelDefinition`,C++ 白盒地图仅作为读取或解析失败时的 fallback。详细复盘见 `../engine_capability_audit.md`
第一轮引擎能力接入已完成:`GameServices` 统一接入音频、PVF、NPK、SoundPack、AudioDB、SaveSystem 状态;`StageMapResource` 已能读取 `map/stage_01.map`当前仍使用白盒 C++ 地图作为 fallback。完整骨架说明见 `../game_skeleton.md`
第一轮引擎能力接入已完成:`GameServices` 统一接入音频、PVF、NPK、SoundPack、AudioDB、SaveSystem 状态;`StageMapResource` 负责从 Asset/PVF 读取 `map/stage_01.map``StageMapLoader` 负责转成游戏层 `LevelDefinition`。完整骨架说明见 `../game_skeleton.md`
### 下一轮建议任务
继续沿着“优先使用引擎能力”的方向,把地图从色块灰盒推进到可放素材的完整骨架:
1.`.map` 增加 tileset/tile entry 约定,先不做编辑器,只保证工具或手写数据能表达重复地砖。
2.`StageRenderer` 中增加 tile 绘制路径,复用当前 `Texture` 加载和 source rect 支持。
3.`level_visual` 的长色块逐步替换成 tile entries,碰撞仍独立保留在 `collision`
4. 给 map loader 增加更严格的错误日志,例如重复 block、空 layer、battle zone 无 spawn 的提示。
5. 补一个轻量 map 验收流程:启动时日志确认加载 `.map`RomFS/Windows 产物确认存在 `assets/map/stage_01.map`
### Debug 快捷键
+17 -2
View File
@@ -5,13 +5,15 @@
## 验收范围
- 场景入口:`WhiteboxScene`
- 关卡数据:`CreateWhiteboxLevel()`
- 关卡数据:`game/assets/map/stage_01.map`
- 关卡 fallback`CreateWhiteboxLevel()` 内置 C++ 白盒数据
- 世界尺寸:`3200 x 720`
- 玩家出生点:`(160, 380)`
- 关卡边界:`0 -> 3200`
- 视口:`1280 x 720`
- Battle zones`zone_01_intro``zone_02_platform``zone_03_exit`
- 资源槽位:`game/assets/stage/stage_01/`
- 地图资源:`game/assets/map/stage_01.map`
## 构建检查
@@ -31,6 +33,12 @@ Start-Sleep -Seconds 3
if (!$p.HasExited) { Stop-Process -Id $p.Id -Force }
```
资源路径检查:
```powershell
Test-Path build\windows\x64\release\assets\map\stage_01.map
```
### Switch
```powershell
@@ -44,6 +52,12 @@ if (!$p.HasExited) { Stop-Process -Id $p.Id -Force }
build\switch\aarch64\release\switch_game\NSUnknownGame.nro
```
RomFS 地图检查:
```powershell
Test-Path build\switch\aarch64\release\switch_game\romfs\assets\map\stage_01.map
```
## 手动跑图检查
操作映射见 `controls.md`
@@ -66,7 +80,8 @@ build\switch\aarch64\release\switch_game\NSUnknownGame.nro
- Windows release 构建:通过。
- Windows 3 秒短启动:通过。
- Switch `Frostbite2DGameSwitch` 构建:通过。
- Switch RomFS:已包含 character、shader`stage_01` 资源槽位。
- Switch RomFS:已包含 character、shader`stage_01` 资源槽位`assets/map/stage_01.map`
- 地图加载:`stage_01.map` 已作为第一关主数据源;C++ 白盒数据仅作为 fallback。
- 手动跑图:未在本轮执行,等待后续素材/战斗区域进一步接入时复测。
## 后续补充