diff --git a/game/docs/planning/game_architecture_board.md b/game/docs/planning/game_architecture_board.md index 05a8c92..b51bb2f 100644 --- a/game/docs/planning/game_architecture_board.md +++ b/game/docs/planning/game_architecture_board.md @@ -168,12 +168,14 @@ mindmap - `data/whitebox_level.cpp` - `movement/platform_world.*` - `stage/stage_renderer.*` +- `StageLayer` 灰盒数据已接入:远景、中景、地面/平台、后景 props 先用色块占位。 +- 第一关宽度已扩展到 3200 像素,并加入 3 个 battle zone 占位与敌人出生点。 下一步: -- 增加 `StageLayer` 数据结构。 -- 关卡宽度扩展到 2400 到 3200 像素。 -- 引入远景/中景/地面三层绘制。 +- 将 `StageLayer` 色块替换为 tileset、背景图和 props 素材。 +- 将 battle zone 占位升级为触发、锁镜头、清场解锁逻辑。 +- 将敌人出生点接入 `EnemyActor`。 ### 4. Actor @@ -297,9 +299,7 @@ mindmap - `debug/debug_overlay.*` 已经提供碰撞和玩家包围盒绘制。 - `F1` 切换 debug overlay。 -- 绘制平台碰撞。 -- 绘制 battle zone。 -- 绘制 spawn point。 +- 绘制平台碰撞、battle zone、camera lock 和 spawn point。 - 绘制 hitbox / hurtbox。 - 输出当前场景、角色状态、FPS。 @@ -408,15 +408,12 @@ mindmap 下一步建议按这个顺序做: -1. `StageLayer`:把白盒视觉层扩展为背景、地面、平台和 props。 -2. `LevelDefinition`:补齐世界尺寸、玩家出生点、镜头限制、敌人出生点和 battle zone 数据。 -3. `StageRenderer`:支持远景/中景/地面/props 分层绘制,先用色块或占位图也可以。 -4. `SceneDebug`:显示碰撞、出生点、battle zone、镜头锁定范围,补 `F1` 开关。 -5. `BattleZone`:在场景数据稳定后做触发、锁镜头、清场解锁。 -6. `EnemyActor`:做第一个敌人占位,接入出生点。 -7. `CombatSystem`:把 hitbox/hurtbox 真正跑起来。 -8. `SpriteAnimator`:把玩家动画从硬编码改成组件。 -9. `InputConfig`:把默认键位/手柄映射迁移到可配置数据。 +1. `StageAssets`:把灰盒 `StageLayer` 替换为 `stage_01` 背景、tiles 和 props 素材。 +2. `BattleZone`:在现有 zone 数据上做触发、锁镜头、清场解锁。 +3. `EnemyActor`:做第一个敌人占位,接入出生点。 +4. `CombatSystem`:把 hitbox/hurtbox 真正跑起来。 +5. `SpriteAnimator`:把玩家动画从硬编码改成组件。 +6. `InputConfig`:把默认键位/手柄映射迁移到可配置数据。 ## 素材协作提示 diff --git a/game/docs/planning/scene_build_plan.md b/game/docs/planning/scene_build_plan.md index aed7f85..0c5c726 100644 --- a/game/docs/planning/scene_build_plan.md +++ b/game/docs/planning/scene_build_plan.md @@ -14,6 +14,14 @@ 当前白盒只解决“能跑、能跳、能看到关卡结构”。下一步要把场景拆成数据层、视觉层和玩法层。 +第一轮场景骨架进度: + +- `LevelDefinition` 已扩展世界尺寸、玩家出生点、镜头范围、分层视觉、battle zone 和敌人出生点数据。 +- 第一关灰盒宽度已扩展到 3200 像素。 +- `StageRenderer` 已支持远景、中景、地面/平台、后景 props 分层绘制,当前先用色块占位。 +- `DebugOverlay` 已能显示碰撞、玩家框、battle zone、camera lock 范围和 spawn point。 +- `WhiteboxScene` 已支持 `F1` 切换 debug overlay。 + ## 2. 第一关场景目标 第一关不急着做最终题材,先做通用 ACT 测试关: @@ -205,12 +213,12 @@ game/assets/stage/stage_01/ ### 先做工程骨架 -1. 扩展 `LevelDefinition`:加入世界尺寸、玩家出生点、镜头限制、敌人出生点、battle zone 占位数据。 -2. 扩展 `StageRenderer`:支持背景层、地面/平台视觉层、后景 props,第一版可以继续用色块。 -3. 扩展白盒关卡宽度到 2400 到 3200 像素,并整理成 3 段推进节奏。 -4. 加入 3 个 battle zone debug 标记,但暂不做锁镜头和刷敌逻辑。 -5. 加入 spawn point debug 标记,用于后续接 `EnemyActor`。 -6. 补 `F1` debug 开关,至少能切换碰撞、battle zone、spawn point。 +1. 已完成:扩展 `LevelDefinition`,加入世界尺寸、玩家出生点、镜头限制、敌人出生点、battle zone 占位数据。 +2. 已完成:扩展 `StageRenderer`,支持背景层、地面/平台视觉层、后景 props,第一版继续用色块。 +3. 已完成:扩展白盒关卡宽度到 3200 像素,并整理成 3 段推进节奏。 +4. 已完成:加入 3 个 battle zone debug 标记,但暂不做锁镜头和刷敌逻辑。 +5. 已完成:加入 spawn point debug 标记,用于后续接 `EnemyActor`。 +6. 已完成:补 `F1` debug 开关,可切换碰撞、battle zone、spawn point。 ### 素材回来后再替换 @@ -225,8 +233,6 @@ game/assets/stage/stage_01/ 下一轮优先做: -- 扩展 `LevelDefinition`。 -- 扩展 `StageRenderer`。 -- 将第一关扩到 2400 到 3200 像素。 -- 加入 battle zone / spawn point debug 数据。 -- 保留 debug 碰撞显示。 +- 如果素材已准备:创建 `game/assets/stage/stage_01/`,接入背景、tiles 和 props,替换灰盒色块。 +- 如果素材未准备:先做 `BattleZone` 运行时逻辑,让现有 debug zone 可以触发、锁镜头、清场解锁。 +- 保持 debug 碰撞、battle zone、spawn point 显示可用。 diff --git a/game/src/core/debug_flags.h b/game/src/core/debug_flags.h index b9aaf2c..d5d264d 100644 --- a/game/src/core/debug_flags.h +++ b/game/src/core/debug_flags.h @@ -6,6 +6,8 @@ struct DebugFlags { bool showStageGrid = true; bool showCollision = true; bool showActorBounds = true; + bool showBattleZones = true; + bool showSpawnPoints = true; }; } // namespace ns_game diff --git a/game/src/data/level_definition.h b/game/src/data/level_definition.h index 6df0029..8c5f037 100644 --- a/game/src/data/level_definition.h +++ b/game/src/data/level_definition.h @@ -3,18 +3,58 @@ #include "../movement/platform_world.h" #include #include +#include #include namespace ns_game { +enum class StageLayerRole { + BackgroundFar, + BackgroundMid, + LevelVisual, + PropsBack, + PropsFront +}; + +struct StageRect { + frostbite2D::Rect bounds; + frostbite2D::Color color; + StageLayerRole layer = StageLayerRole::PropsBack; +}; + +struct SpawnPoint { + std::string id; + frostbite2D::Vec2 position; +}; + +struct BattleZoneDefinition { + std::string id; + frostbite2D::Rect trigger; + frostbite2D::Rect cameraBounds; + std::vector enemySpawns; +}; + +struct StageLayer { + std::string id; + StageLayerRole role = StageLayerRole::LevelVisual; + float parallax = 1.0f; + std::vector rects; +}; + struct WhiteboxProp { frostbite2D::Rect bounds; frostbite2D::Color color; }; struct LevelDefinition { + float worldWidth = 0.0f; + float worldHeight = 0.0f; + frostbite2D::Vec2 playerSpawn; + frostbite2D::Rect cameraBounds; PlatformWorld collision; + std::vector layers; std::vector props; + std::vector battleZones; }; LevelDefinition CreateWhiteboxLevel(); diff --git a/game/src/data/whitebox_level.cpp b/game/src/data/whitebox_level.cpp index 4a66e4c..99dc2e2 100644 --- a/game/src/data/whitebox_level.cpp +++ b/game/src/data/whitebox_level.cpp @@ -4,14 +4,102 @@ namespace ns_game { LevelDefinition CreateWhiteboxLevel() { LevelDefinition level; + level.worldWidth = 3200.0f; + level.worldHeight = 720.0f; + level.playerSpawn = frostbite2D::Vec2(160.0f, 380.0f); + level.cameraBounds = frostbite2D::Rect(0.0f, 0.0f, level.worldWidth, + level.worldHeight); level.collision.levelLeft = 0.0f; - level.collision.levelRight = 1600.0f; + level.collision.levelRight = level.worldWidth; level.collision.platforms = { - frostbite2D::Rect(0.0f, 600.0f, 1600.0f, 80.0f), + frostbite2D::Rect(0.0f, 600.0f, 3200.0f, 80.0f), frostbite2D::Rect(230.0f, 500.0f, 220.0f, 28.0f), frostbite2D::Rect(560.0f, 430.0f, 260.0f, 28.0f), frostbite2D::Rect(930.0f, 510.0f, 260.0f, 28.0f), frostbite2D::Rect(1250.0f, 420.0f, 230.0f, 28.0f), + frostbite2D::Rect(1760.0f, 500.0f, 300.0f, 28.0f), + frostbite2D::Rect(2180.0f, 455.0f, 260.0f, 28.0f), + frostbite2D::Rect(2650.0f, 515.0f, 360.0f, 28.0f), + }; + level.layers = { + {"background_far", + StageLayerRole::BackgroundFar, + 0.25f, + {{frostbite2D::Rect(0.0f, 0.0f, 3200.0f, 720.0f), + frostbite2D::Color(0.08f, 0.10f, 0.14f, 1.0f), + StageLayerRole::BackgroundFar}, + {frostbite2D::Rect(360.0f, 120.0f, 420.0f, 220.0f), + frostbite2D::Color(0.13f, 0.16f, 0.21f, 1.0f), + StageLayerRole::BackgroundFar}, + {frostbite2D::Rect(1380.0f, 90.0f, 560.0f, 260.0f), + frostbite2D::Color(0.12f, 0.15f, 0.20f, 1.0f), + StageLayerRole::BackgroundFar}, + {frostbite2D::Rect(2440.0f, 140.0f, 520.0f, 210.0f), + frostbite2D::Color(0.13f, 0.16f, 0.21f, 1.0f), + StageLayerRole::BackgroundFar}}}, + {"background_mid", + StageLayerRole::BackgroundMid, + 0.55f, + {{frostbite2D::Rect(80.0f, 360.0f, 280.0f, 240.0f), + frostbite2D::Color(0.18f, 0.22f, 0.27f, 1.0f), + StageLayerRole::BackgroundMid}, + {frostbite2D::Rect(1020.0f, 310.0f, 340.0f, 290.0f), + frostbite2D::Color(0.18f, 0.22f, 0.27f, 1.0f), + StageLayerRole::BackgroundMid}, + {frostbite2D::Rect(2020.0f, 330.0f, 360.0f, 270.0f), + frostbite2D::Color(0.18f, 0.22f, 0.27f, 1.0f), + StageLayerRole::BackgroundMid}, + {frostbite2D::Rect(2860.0f, 280.0f, 260.0f, 320.0f), + frostbite2D::Color(0.18f, 0.22f, 0.27f, 1.0f), + StageLayerRole::BackgroundMid}}}, + {"level_visual", + StageLayerRole::LevelVisual, + 1.0f, + {{frostbite2D::Rect(0.0f, 600.0f, 3200.0f, 80.0f), + frostbite2D::Color(0.62f, 0.68f, 0.73f, 1.0f), + StageLayerRole::LevelVisual}, + {frostbite2D::Rect(230.0f, 500.0f, 220.0f, 28.0f), + frostbite2D::Color(0.62f, 0.68f, 0.73f, 1.0f), + StageLayerRole::LevelVisual}, + {frostbite2D::Rect(560.0f, 430.0f, 260.0f, 28.0f), + frostbite2D::Color(0.62f, 0.68f, 0.73f, 1.0f), + StageLayerRole::LevelVisual}, + {frostbite2D::Rect(930.0f, 510.0f, 260.0f, 28.0f), + frostbite2D::Color(0.62f, 0.68f, 0.73f, 1.0f), + StageLayerRole::LevelVisual}, + {frostbite2D::Rect(1250.0f, 420.0f, 230.0f, 28.0f), + frostbite2D::Color(0.62f, 0.68f, 0.73f, 1.0f), + StageLayerRole::LevelVisual}, + {frostbite2D::Rect(1760.0f, 500.0f, 300.0f, 28.0f), + frostbite2D::Color(0.62f, 0.68f, 0.73f, 1.0f), + StageLayerRole::LevelVisual}, + {frostbite2D::Rect(2180.0f, 455.0f, 260.0f, 28.0f), + frostbite2D::Color(0.62f, 0.68f, 0.73f, 1.0f), + StageLayerRole::LevelVisual}, + {frostbite2D::Rect(2650.0f, 515.0f, 360.0f, 28.0f), + frostbite2D::Color(0.62f, 0.68f, 0.73f, 1.0f), + StageLayerRole::LevelVisual}}}, + {"props_back", + StageLayerRole::PropsBack, + 1.0f, + {{frostbite2D::Rect(118.0f, 392.0f, 88.0f, 208.0f), + frostbite2D::Color(0.26f, 0.30f, 0.34f, 1.0f), + StageLayerRole::PropsBack}, + {frostbite2D::Rect(780.0f, 250.0f, 72.0f, 180.0f), + frostbite2D::Color(0.26f, 0.30f, 0.34f, 1.0f), + StageLayerRole::PropsBack}, + {frostbite2D::Rect(1440.0f, 300.0f, 80.0f, 300.0f), + frostbite2D::Color(0.26f, 0.30f, 0.34f, 1.0f), + StageLayerRole::PropsBack}, + {frostbite2D::Rect(1880.0f, 360.0f, 110.0f, 240.0f), + frostbite2D::Color(0.26f, 0.30f, 0.34f, 1.0f), + StageLayerRole::PropsBack}, + {frostbite2D::Rect(2520.0f, 390.0f, 92.0f, 210.0f), + frostbite2D::Color(0.26f, 0.30f, 0.34f, 1.0f), + StageLayerRole::PropsBack}, + {frostbite2D::Rect(3040.0f, 315.0f, 82.0f, 285.0f), + frostbite2D::Color(0.26f, 0.30f, 0.34f, 1.0f), + StageLayerRole::PropsBack}}}, }; level.props = { {frostbite2D::Rect(118.0f, 392.0f, 88.0f, 208.0f), @@ -21,6 +109,23 @@ LevelDefinition CreateWhiteboxLevel() { {frostbite2D::Rect(1440.0f, 300.0f, 80.0f, 300.0f), frostbite2D::Color(0.26f, 0.30f, 0.34f, 1.0f)}, }; + level.battleZones = { + {"zone_01_intro", + frostbite2D::Rect(520.0f, 260.0f, 560.0f, 340.0f), + frostbite2D::Rect(320.0f, 0.0f, 760.0f, 720.0f), + {{"zone_01_enemy_a", frostbite2D::Vec2(760.0f, 560.0f)}, + {"zone_01_enemy_b", frostbite2D::Vec2(980.0f, 560.0f)}}}, + {"zone_02_platform", + frostbite2D::Rect(1420.0f, 250.0f, 680.0f, 350.0f), + frostbite2D::Rect(1280.0f, 0.0f, 900.0f, 720.0f), + {{"zone_02_enemy_a", frostbite2D::Vec2(1620.0f, 560.0f)}, + {"zone_02_enemy_b", frostbite2D::Vec2(1900.0f, 560.0f)}}}, + {"zone_03_exit", + frostbite2D::Rect(2380.0f, 250.0f, 720.0f, 350.0f), + frostbite2D::Rect(2240.0f, 0.0f, 960.0f, 720.0f), + {{"zone_03_enemy_a", frostbite2D::Vec2(2580.0f, 560.0f)}, + {"zone_03_enemy_b", frostbite2D::Vec2(2860.0f, 560.0f)}}}, + }; return level; } diff --git a/game/src/debug/debug_overlay.cpp b/game/src/debug/debug_overlay.cpp index e65e212..f5e518a 100644 --- a/game/src/debug/debug_overlay.cpp +++ b/game/src/debug/debug_overlay.cpp @@ -24,6 +24,19 @@ void drawOutline(const frostbite2D::Rect& rect, const frostbite2D::Color& color, color); } +void drawCross(const frostbite2D::Vec2& position, + const frostbite2D::Color& color) { + constexpr float kSize = 18.0f; + constexpr float kThickness = 3.0f; + drawRect(frostbite2D::Rect(position.x - kSize * 0.5f, + position.y - kThickness * 0.5f, kSize, + kThickness), + color); + drawRect(frostbite2D::Rect(position.x - kThickness * 0.5f, + position.y - kSize * 0.5f, kThickness, kSize), + color); +} + } // namespace void DebugOverlay::Render(const LevelDefinition& level, const DebugFlags& flags, @@ -31,6 +44,12 @@ void DebugOverlay::Render(const LevelDefinition& level, const DebugFlags& flags, if (flags.showCollision) { drawCollision(level); } + if (flags.showBattleZones) { + drawBattleZones(level); + } + if (flags.showSpawnPoints) { + drawSpawnPoints(level); + } if (flags.showActorBounds && playerBounds) { drawActorBounds(*playerBounds); } @@ -46,4 +65,21 @@ void DebugOverlay::drawActorBounds(const frostbite2D::Rect& bounds) const { drawOutline(bounds, frostbite2D::Color(1.0f, 0.78f, 0.1f, 0.9f)); } +void DebugOverlay::drawBattleZones(const LevelDefinition& level) const { + for (const BattleZoneDefinition& zone : level.battleZones) { + drawOutline(zone.trigger, frostbite2D::Color(0.95f, 0.25f, 0.25f, 0.9f), + 3.0f); + drawOutline(zone.cameraBounds, + frostbite2D::Color(0.25f, 0.55f, 1.0f, 0.75f), 2.0f); + } +} + +void DebugOverlay::drawSpawnPoints(const LevelDefinition& level) const { + for (const BattleZoneDefinition& zone : level.battleZones) { + for (const SpawnPoint& spawn : zone.enemySpawns) { + drawCross(spawn.position, frostbite2D::Color(1.0f, 0.2f, 0.9f, 0.95f)); + } + } +} + } // namespace ns_game diff --git a/game/src/debug/debug_overlay.h b/game/src/debug/debug_overlay.h index 7376960..c99b4e1 100644 --- a/game/src/debug/debug_overlay.h +++ b/game/src/debug/debug_overlay.h @@ -15,6 +15,8 @@ public: private: void drawCollision(const LevelDefinition& level) const; void drawActorBounds(const frostbite2D::Rect& bounds) const; + void drawBattleZones(const LevelDefinition& level) const; + void drawSpawnPoints(const LevelDefinition& level) const; }; } // namespace ns_game diff --git a/game/src/scene/whitebox_scene.cpp b/game/src/scene/whitebox_scene.cpp index 4364048..378236a 100644 --- a/game/src/scene/whitebox_scene.cpp +++ b/game/src/scene/whitebox_scene.cpp @@ -3,6 +3,7 @@ #include "../core/game_config.h" #include +#include #include #include #include @@ -14,6 +15,7 @@ void WhiteboxScene::onEnter() { level_ = CreateWhiteboxLevel(); player_ = frostbite2D::MakePtr(); + player_->SetTopLeftPosition(level_.playerSpawn); player_->SetMovementWorld(&level_.collision); AddChild(player_); } @@ -23,6 +25,19 @@ void WhiteboxScene::OnUpdate(float deltaTime) { updateCamera(); } +bool WhiteboxScene::OnEvent(const frostbite2D::Event& event) { + if (event.getType() == frostbite2D::EventType::KeyDown) { + const auto& keyEvent = static_cast(event); + if (!keyEvent.isRepeat() && + keyEvent.getKeyCode() == frostbite2D::KeyCode::F1) { + toggleDebugOverlay(); + return true; + } + } + + return frostbite2D::Scene::OnEvent(event); +} + void WhiteboxScene::Render() { stageRenderer_.Render(level_, debugFlags_); frostbite2D::Scene::Render(); @@ -31,6 +46,18 @@ void WhiteboxScene::Render() { debugOverlay_.Render(level_, debugFlags_, player_ ? &playerBounds : nullptr); } +void WhiteboxScene::toggleDebugOverlay() { + const bool enabled = !(debugFlags_.showStageGrid || debugFlags_.showCollision || + debugFlags_.showActorBounds || + debugFlags_.showBattleZones || + debugFlags_.showSpawnPoints); + debugFlags_.showStageGrid = enabled; + debugFlags_.showCollision = enabled; + debugFlags_.showActorBounds = enabled; + debugFlags_.showBattleZones = enabled; + debugFlags_.showSpawnPoints = enabled; +} + void WhiteboxScene::updateCamera() { if (!player_) { return; @@ -43,8 +70,8 @@ void WhiteboxScene::updateCamera() { const auto playerPos = player_->GetTopLeftPosition(); const float targetX = std::clamp(playerPos.x - 420.0f, - level_.collision.levelLeft, - level_.collision.levelRight - + level_.cameraBounds.left(), + level_.cameraBounds.right() - static_cast(config::kVirtualWidth)); renderer->getCamera()->setPosition(frostbite2D::Vec2(targetX, 0.0f)); } diff --git a/game/src/scene/whitebox_scene.h b/game/src/scene/whitebox_scene.h index 6ed8d76..a9de451 100644 --- a/game/src/scene/whitebox_scene.h +++ b/game/src/scene/whitebox_scene.h @@ -15,9 +15,11 @@ class WhiteboxScene : public frostbite2D::Scene { public: void onEnter() override; void OnUpdate(float deltaTime) override; + bool OnEvent(const frostbite2D::Event& event) override; void Render() override; private: + void toggleDebugOverlay(); void updateCamera(); LevelDefinition level_; diff --git a/game/src/stage/stage_renderer.cpp b/game/src/stage/stage_renderer.cpp index 3069369..e6424cd 100644 --- a/game/src/stage/stage_renderer.cpp +++ b/game/src/stage/stage_renderer.cpp @@ -2,6 +2,7 @@ #include "../core/game_config.h" +#include #include namespace ns_game { @@ -21,11 +22,12 @@ float worldWidthOf(const LevelDefinition& level) { void StageRenderer::Render(const LevelDefinition& level, const DebugFlags& debugFlags) const { drawBackground(level); + for (const StageLayer& layer : level.layers) { + drawLayer(level, layer); + } if (debugFlags.showStageGrid) { drawGrid(level); } - drawProps(level); - drawPlatforms(level); } void StageRenderer::drawBackground(const LevelDefinition& level) const { @@ -47,18 +49,26 @@ void StageRenderer::drawGrid(const LevelDefinition& level) const { } } -void StageRenderer::drawProps(const LevelDefinition& level) const { - for (const auto& prop : level.props) { - drawRect(prop.bounds, prop.color); +void StageRenderer::drawLayer(const LevelDefinition& level, + const StageLayer& layer) const { + (void)level; + frostbite2D::Vec2 parallaxOffset; + if (auto* camera = frostbite2D::Renderer::get().getCamera()) { + const frostbite2D::Vec2 cameraPos = camera->getPosition(); + parallaxOffset.x = cameraPos.x * (1.0f - layer.parallax); + parallaxOffset.y = cameraPos.y * (1.0f - layer.parallax); } -} -void StageRenderer::drawPlatforms(const LevelDefinition& level) const { - for (const auto& platform : level.collision.platforms) { - drawRect(platform, frostbite2D::Color(0.62f, 0.68f, 0.73f, 1.0f)); - drawRect(frostbite2D::Rect(platform.left(), platform.top(), - platform.width(), 4.0f), - frostbite2D::Color(0.91f, 0.95f, 0.98f, 1.0f)); + for (const StageRect& rect : layer.rects) { + frostbite2D::Rect bounds(rect.bounds.left() + parallaxOffset.x, + rect.bounds.top() + parallaxOffset.y, + rect.bounds.width(), rect.bounds.height()); + drawRect(bounds, rect.color); + if (layer.role == StageLayerRole::LevelVisual) { + drawRect(frostbite2D::Rect(bounds.left(), bounds.top(), bounds.width(), + 4.0f), + frostbite2D::Color(0.91f, 0.95f, 0.98f, 1.0f)); + } } } diff --git a/game/src/stage/stage_renderer.h b/game/src/stage/stage_renderer.h index 44dbd82..0a522d2 100644 --- a/game/src/stage/stage_renderer.h +++ b/game/src/stage/stage_renderer.h @@ -12,8 +12,7 @@ public: private: void drawBackground(const LevelDefinition& level) const; void drawGrid(const LevelDefinition& level) const; - void drawProps(const LevelDefinition& level) const; - void drawPlatforms(const LevelDefinition& level) const; + void drawLayer(const LevelDefinition& level, const StageLayer& layer) const; }; } // namespace ns_game