feat(game_scene): integra PaintLayer i llegeix paint_tile del YAML del mapa
This commit is contained in:
1 parent
e3cf2eb773
commit
d0503ff8b1
2 files changed
+47
-3
No files matched your search
@@ -21,7 +21,9 @@
|
||||
#include "core/rendering/screen.hpp"
|
||||
#include "core/rendering/text.hpp"
|
||||
#include "core/resources/resource_cache.hpp"
|
||||
#include "core/resources/resource_helper.hpp"
|
||||
#include "core/system/event_buffer.hpp"
|
||||
#include "external/fkyaml_node.hpp"
|
||||
#include "game/entities/entity.hpp"
|
||||
#include "game/entities/event_bus.hpp"
|
||||
#include "game/entities/player.hpp"
|
||||
@@ -42,6 +44,21 @@ namespace {
|
||||
return Tilemap(yaml_path);
|
||||
}
|
||||
|
||||
// Llegeix un camp sencer opcional del YAML del mapa. Si no hi és,
|
||||
// retorna `fallback` (per defecte -1, que al Player indica "no pinta").
|
||||
// S'usa per `player1_paint_tile` i `player2_paint_tile`: cada jugador
|
||||
// pinta amb l'índex declarat al mapa, i un mapa sense aquests camps
|
||||
// simplement no deixa rastre visual.
|
||||
auto readOptionalInt(const std::string& yaml_path, const std::string& key, int fallback = -1) -> int {
|
||||
auto bytes = Resource::Helper::loadFile(yaml_path);
|
||||
if (bytes.empty()) { return fallback; }
|
||||
const auto* begin = reinterpret_cast<const char*>(bytes.data());
|
||||
const auto* end = begin + bytes.size();
|
||||
auto yaml = fkyaml::node::deserialize(begin, end);
|
||||
if (!yaml.contains(key)) { return fallback; }
|
||||
return yaml[key].get_value<int>();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto GameScene::defaultConfig() -> Config {
|
||||
@@ -103,10 +120,23 @@ GameScene::GameScene(Config config)
|
||||
static_cast<float>(Map::playfield_y) + (static_cast<float>(Map::outer_corridor) / 2.0F);
|
||||
const auto SPAWN_X = CORRIDOR_CENTER_X - (static_cast<float>(Player::sprite_w) / 2.0F);
|
||||
const auto SPAWN_Y = CORRIDOR_CENTER_Y - static_cast<float>(Player::collision_y_offset) - (static_cast<float>(Player::collision_size) / 2.0F);
|
||||
players_.emplace_back(std::make_unique<Player>(ANIM_KEY, SPAWN_X, SPAWN_Y, CONTROLS_P1, Map::makeInfo()));
|
||||
// Índex de tile amb què pinta cada jugador — llegit del YAML del mapa
|
||||
// (camps opcionals `player1_paint_tile` / `player2_paint_tile`). Si no
|
||||
// hi són, `paint_tile_index_ = -1` i el Player no deixa rastre.
|
||||
const int P1_PAINT = readOptionalInt(config_.map_yaml, "player1_paint_tile", -1);
|
||||
players_.emplace_back(std::make_unique<Player>(ANIM_KEY, SPAWN_X, SPAWN_Y, CONTROLS_P1, Map::makeInfo(), P1_PAINT));
|
||||
|
||||
// Connectem el Player al bus perquè emeti `on_tile_entered` i els
|
||||
// sarcòfags rebin les notificacions de pas per tile.
|
||||
// PaintLayer: font única del pintat del nivell. Es crea després de
|
||||
// `loadFromLevel` perquè l'EntityManager ja ha de tenir els sarcòfags
|
||||
// registrats (tot i que el sarc escolta via fan-out, no directament
|
||||
// al bus; l'ordre de subscripcions aquí és irrellevant per la
|
||||
// correcció, però sí pel log d'arrencada). Connectat al bus del
|
||||
// manager per subscriure's a `on_tile_entered` i publicar `tile_painted`.
|
||||
paint_layer_ = std::make_unique<PaintLayer>(tilemap_, &entity_manager_.getBus());
|
||||
|
||||
// Connectem el Player al bus perquè emeti `on_tile_entered` i el
|
||||
// PaintLayer (subscrit ja) processe el pintat; el fan-out cap als
|
||||
// sarcòfags passa per `tile_painted`.
|
||||
players_.back()->setEventBus(&entity_manager_.getBus());
|
||||
|
||||
// Música de fons en bucle infinit. El track ja està al Resource::Cache
|
||||
@@ -228,6 +258,10 @@ void GameScene::render() {
|
||||
#else
|
||||
constexpr bool SKIP_ACTORS = false;
|
||||
#endif
|
||||
// Capa de pintat: va entre el tilemap base i els actors, perquè els
|
||||
// sarcòfags i el jugador la tapen. S'amaga al mode editor (decisió
|
||||
// explícita: l'editor edita el tilemap, no la capa de pintat).
|
||||
if (!SKIP_ACTORS && paint_layer_) { paint_layer_->render(); }
|
||||
if (!SKIP_ACTORS) {
|
||||
// Z-order interleaving entitats ↔ players per `getFeetY()` ascendent:
|
||||
// els actors amb els peus més amunt queden dibuixats primer (al fons),
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "core/scene/scene.hpp"
|
||||
#include "game/entities/entity_manager.hpp"
|
||||
#include "game/map/paint_layer.hpp"
|
||||
#include "game/map/tilemap.hpp"
|
||||
|
||||
#ifdef _DEBUG
|
||||
@@ -53,6 +54,15 @@ class GameScene : public Scene {
|
||||
// té els seus propis Controls i entra al vector amb una crida extra.
|
||||
std::vector<std::unique_ptr<Player>> players_;
|
||||
|
||||
// Capa de "pintat" del terra. Escolta `on_tile_entered` al bus,
|
||||
// filtra pintabilitat (sòl transitable) i re-publica `tile_painted`
|
||||
// per als sarcòfags. `unique_ptr` per controlar l'ordre de
|
||||
// construcció/destrucció: es crea al ctor un cop `entity_manager_` i
|
||||
// `tilemap_` estan llestos, i es destrueix abans que `entity_manager_`
|
||||
// (on viu el bus al qual està subscrit). Declarat després d'aquests
|
||||
// dos membres per garantir l'ordre invers a la destrucció.
|
||||
std::unique_ptr<PaintLayer> paint_layer_;
|
||||
|
||||
// Pausa de gameplay. Quan `paused_` és true, l'update de jugadors i
|
||||
// entitats es salta (el món es congela); l'input d'UI (GlobalInputs,
|
||||
// Notifier, RenderInfo) continua per no perdre hotkeys ni l'overlay de
|
||||
|
||||
Reference in new issue
Block a user