#pragma once #include #include // Mapa d'una piràmide: sala rectangular amb marcador superior, muros pels // quatre costats i graella de sarcòfags envoltada per un passadís a cada // cantó. La geometria (graella, pitch, amplada de murs) es carrega des del // bloc `geometry:` del YAML de la piràmide — així cada sala pot tenir la // seua forma sense recompilar. // // `Map` és un namespace (no una classe) perquè no té estat d'instància: // els membres viuen com a globals del namespace i els callers hi accedeixen // amb `Map::grid_cols`, `Map::collides(...)`, etc. El canvi respecte a // l'anterior `class Map { static ... };` és purament sintàctic. // // `MapInfo` (POD trivialment copiable) empaqueta la geometria + dos // punters a funció de col·lisió per injectar-la a entitats que han // d'evitar conèixer el namespace `Map::` directament. Construïda via // `Map::makeInfo()` després de `loadFrom`. Avui només l'usa el Player // (COUP-02 a docs/audit-game.md); momies, roques i `loadFromLevel` // continuen llegint `Map::*` directament — la nota original justifica // que mentre hi hagi un Map global actiu, l'acoblament és acceptable. namespace Map { // Geometria de la graella (carregada de pyramid.yaml > geometry). inline int grid_cols = 0; inline int grid_rows = 0; inline int sarc_w = 0; inline int sarc_h = 0; inline int pitch_x = 0; inline int pitch_y = 0; // Metadades del tilemap (carregades de l'arrel del YAML: `tile_size:` i // `origin: [x, y]`). Són necessàries per a consumidors externs com el // sistema d'entitats, que tradueix coordenades píxel ↔ tile amb // tile_col = floor((px - tilemap_origin_x) / tile_size) // El grid és 16-alineat respecte a l'origen del tilemap (no del canvas); // origen habitual a pyramid.yaml és [-8, 0] (overscan horitzontal CPC). inline int tile_size = 0; inline int tilemap_origin_x = 0; inline int tilemap_origin_y = 0; // Cromat de la sala: marcador (HUD), mur posterior (dalt) i murs // laterals. El mur frontal es deriva del passadís exterior inferior. inline int hud_h = 0; inline int back_wall_h = 0; inline int side_wall_w = 0; // Derivats de la geometria base: el pas entre sarcòfags ha de cabre // exactament el jugador, i el mateix passadís s'usa a l'exterior. inline int corridor_w = 0; inline int corridor_h = 0; inline int outer_corridor = 0; inline int board_w = 0; inline int board_h = 0; inline int origin_x = 0; inline int origin_y = 0; inline int playfield_x = 0; inline int playfield_y = 0; inline int playfield_w = 0; inline int playfield_h = 0; // Carrega el bloc `geometry:` del YAML i recalcula tots els derivats. // Ha de cridar-se abans d'instanciar `Player` o consultar `collides()`: // GameScene ho fa al ctor. void loadFrom(const std::string& yaml_path); // Rectangle ocupat pel sarcòfag a la posició (col, row) de la graella. [[nodiscard]] auto getSarcRect(int col, int row) -> SDL_FRect; // Mapa de colisions (separat del mapa de dibuix): retorna true si el // rectangle `base_box` (la base del jugador, per exemple) s'encavalca // amb cap sarcòfag. [[nodiscard]] auto collides(const SDL_FRect& base_box) -> bool; // true si la caixa `box` queda completament dins del playfield (zona // interior, sense tocar els murs exteriors). El Player ja té clamp // propi que aplica el mateix constrenyiment; això serveix a les // entitats dinàmiques per validar posicions candidates del seu step. [[nodiscard]] auto insidePlayfield(const SDL_FRect& box) -> bool; // true si el tile (col, row) — coordenades del tilemap, amb origen // `tilemap_origin_*` — és "sòl transitable" i per tant pintable: cau // completament dins del playfield i no s'encavalca cap sarcòfag. Ho // usa el `PaintLayer` per filtrar quines cel·les accepten pintat. [[nodiscard]] auto isPaintable(int col, int row) -> bool; // Snapshot plà de la geometria del mapa + punters a `collides` / // `insidePlayfield`. Pensat per ser passat per valor (POD petit, // trivialment copiable). Un cop construïda, llegeix els valors // congelats — si `Map::loadFrom` es torna a cridar amb un mapa // diferent, cal demanar un MapInfo nou. struct Info { int playfield_x{0}; int playfield_y{0}; int playfield_w{0}; int playfield_h{0}; int pitch_x{0}; int pitch_y{0}; int grid_cols{0}; int grid_rows{0}; int tile_size{0}; int tilemap_origin_x{0}; int tilemap_origin_y{0}; bool (*collides)(const SDL_FRect&){nullptr}; bool (*inside_playfield)(const SDL_FRect&){nullptr}; }; [[nodiscard]] auto makeInfo() -> Info; } // namespace Map