From f64bb5e2672671203b1db1bcede99b3f2904a988 Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Mon, 20 Apr 2026 18:10:17 +0200 Subject: [PATCH] PATCH-05+PATCH-06+DEAD-05: neteja defenses i sort cerimonial a GameScene MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PATCH-05: `if (Audio::get() != nullptr)` eliminat; Director::init crida Audio::init abans de GameScene, comentari ho documenta. Si mai salta, és un bug real que val detectar. - PATCH-06/DEAD-05: short-circuit per `players_.size() <= 1` — no vector temporal ni sort amb un sol jugador. La branca multi-jugador queda preparada per quan n'hi haja >1 o sarcs-sprites. --- docs/audit-game.md | 6 +++--- source/game/scenes/game_scene.cpp | 36 +++++++++++++++---------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/audit-game.md b/docs/audit-game.md index 61161fd..7f42026 100644 --- a/docs/audit-game.md +++ b/docs/audit-game.md @@ -57,8 +57,8 @@ Els IDs es mantenen estables una vegada assignats. Cada entrada apunta al fitxer | PATCH-02 | `player.cpp:13-15` | Comentari tipus TODO ("si més endavant volem sprint...") | Menor | DONE | Eliminat en HC-01 (la constant ja no viu al `.cpp`, sinó a `Defaults::Player`) | | PATCH-03 | `map.cpp:13-15` | `overlapStrict` custom perquè SDL3 considera el toc com intersecció | Menor | PENDING | Si s'usa més, mourea `utils/` | | PATCH-04 | `options.cpp:361-363,371-375,475-480,528-533` | Reescriure silenciosament `config.yaml` al fallar parseig o canviar versió | Crítico | DONE | Helper `backupFile()` que copia a `.bak` si existeix. Cridat abans de cada reescriptura forçada (versió mismatch + catch a `loadFromFile`, `presets:` absent/invàlid/buit + catch a `loadPresetsFromFile`). Primera execució no genera `.bak`. Missatge explícit per motiu de reescriptura | -| PATCH-05 | `game_scene.cpp:51` | `if (Audio::get() != nullptr)` com a defensa sobre un singleton Meyers | Menor | PENDING | Assumir invariant, treure | -| PATCH-06 | `game_scene.cpp:78-91` | Ordenació per `getFeetY()` amb 1 jugador i sense sarcs-sprite: cerimonial | Menor | PENDING | Comentar "reactivar quan hi haja sarcs-sprite" o treure | +| PATCH-05 | `game_scene.cpp:51` | `if (Audio::get() != nullptr)` com a defensa sobre un singleton Meyers | Menor | DONE | `if` eliminat; comentari documenta l'invariant (Director::init crida Audio::init abans). Si algun dia salta, serà un bug real que val la pena detectar | +| PATCH-06 | `game_scene.cpp:78-91` | Ordenació per `getFeetY()` amb 1 jugador i sense sarcs-sprite: cerimonial | Menor | DONE | Short-circuit si `players_.size() <= 1`: no es construeix vector temporal ni s'ordena. La branca multi-jugador queda preparada per al dia que hi haja 2+ jugadors o sarcs-sprites | | PATCH-07 | `map.hpp:64` + `map.cpp:19` | `Map` declara ctor però tots els mètodes són `static` (transició a mitges) | Importante | PENDING | Decidir: namespace o instanciar | ## 4. Acoplament innecessari @@ -88,7 +88,7 @@ Els IDs es mantenen estables una vegada assignats. Cada entrada apunta al fitxer | DEAD-02 | `map.hpp:59-62` | Índexs `HUD_BG/WALL/FLOOR/SARC` només usats pel codi mort | Importante | DONE | Eliminats amb DEAD-01 | | DEAD-03 | `map.cpp:3-5` | Includes `screen.hpp/resource_cache.hpp/defines.hpp` orfes si es neteja DEAD-01 | Menor | DONE | Eliminats amb DEAD-01 | | DEAD-04 | `map.hpp:64` + `map.cpp:19` | Ctor de `Map` mai instanciat | Menor | DONE | Ja eliminat durant HC-03 | -| DEAD-05 | `game_scene.cpp:78-86` | Ordenació Z-order cerimonial (1 jugador, sense sarcs-sprite) | Menor | PENDING | Veure PATCH-06 | +| DEAD-05 | `game_scene.cpp:78-86` | Ordenació Z-order cerimonial (1 jugador, sense sarcs-sprite) | Menor | DONE | Resolt amb PATCH-06 | ## 7. Violacions de convencions diff --git a/source/game/scenes/game_scene.cpp b/source/game/scenes/game_scene.cpp index 98e3196..a3869f2 100644 --- a/source/game/scenes/game_scene.cpp +++ b/source/game/scenes/game_scene.cpp @@ -81,10 +81,9 @@ GameScene::GameScene(Config config) // Música de fons en bucle infinit. El track ja està al Resource::Cache // (preload al Director), així que playMusic només mou el punter cap a - // jail_audio i obri l'stream. - if (Audio::get() != nullptr) { - Audio::get()->playMusic(config_.music_track, -1); - } + // jail_audio i obri l'stream. Audio::get() està garantit no-null: + // Director::init crida Audio::init abans d'instanciar GameScene. + Audio::get()->playMusic(config_.music_track, -1); } GameScene::~GameScene() = default; @@ -109,20 +108,21 @@ void GameScene::render() { // col·lisions del jugador. tilemap_.render(); - // Ordenem punters a jugadors per Y dels peus (ascendent = més al fons - // primer). Usem un vector auxiliar per no tocar l'ordre d'entrada de - // players_, que és el d'assignació de controls. - std::vector sorted; - sorted.reserve(players_.size()); - std::ranges::transform(players_, std::back_inserter(sorted), [](const auto& p) { return p.get(); }); - std::ranges::sort(sorted, [](const Player* a, const Player* b) { - return a->getFeetY() < b->getFeetY(); - }); - - // De moment els sarcòfags no es pinten (seran actors independents); - // dibuixem tots els jugadors sobre el tilemap ja ordenats per Y. Quan - // els sarcs siguen sprites, tornarem a interleave per al Z-order. - for (auto* player : sorted) { player->render(); } + // Amb un sol jugador, l'ordre és irrellevant i ens estalviem el vector + // temporal. Quan n'hi haja més d'un (o quan els sarcs siguen sprites) + // caldrà ordenar per `getFeetY()` ascendent i interleaveing amb les + // files de sarcs — l'ordre ascendent manté els més al fons darrere. + if (players_.size() <= 1) { + for (auto& player : players_) { player->render(); } + } else { + std::vector sorted; + sorted.reserve(players_.size()); + std::ranges::transform(players_, std::back_inserter(sorted), [](const auto& p) { return p.get(); }); + std::ranges::sort(sorted, [](const Player* a, const Player* b) { + return a->getFeetY() < b->getFeetY(); + }); + for (auto* player : sorted) { player->render(); } + } Notifier::get().render(); RenderInfo::get().render();