#include "game/map/map.hpp" #include "core/rendering/screen.hpp" #include "core/resources/resource_cache.hpp" #include "utils/defines.hpp" namespace { // AABB amb inequitat estricta: dos rects que es toquen exactament (la // cantonada o una vora al píxel) NO es consideren intersecció. SDL3 // SDL_HasRectIntersectionFloat tracta el toc com a intersecció, cosa // que bloqueja el moviment als encreuaments del nostre laberint. auto overlapStrict(const SDL_FRect& a, const SDL_FRect& b) -> bool { return (a.x + a.w) > b.x && (b.x + b.w) > a.x && (a.y + a.h) > b.y && (b.y + b.h) > a.y; } } // namespace Map::Map() = default; auto Map::getSarcRowBottomY(int row) -> int { return ORIGIN_Y + (row * PITCH_Y) + SARC_H; } auto Map::getSarcRect(int col, int row) -> SDL_FRect { return { .x = static_cast(ORIGIN_X + (col * PITCH_X)), .y = static_cast(ORIGIN_Y + (row * PITCH_Y)), .w = static_cast(SARC_W), .h = static_cast(SARC_H), }; } void Map::renderBackground() { auto& screen = Screen::get(); const auto& palette = Resource::Cache::get().getPalette("ui"); // Comencem pintant el sòl a tota la pantalla; després tapem marcador i // murs. Els rectangles dels murs s'encavalquen a les cantonades: no // importa perquè són del mateix color. screen.fillRect(0, 0, GameCanvas::WIDTH, GameCanvas::HEIGHT, palette[FLOOR]); // Marcador (dalt). screen.fillRect(0, 0, GameCanvas::WIDTH, HUD_H, palette[HUD_BG]); // Mur posterior: banda horitzontal sota el marcador. screen.fillRect(0, HUD_H, GameCanvas::WIDTH, BACK_WALL_H, palette[WALL]); // Murs laterals (des del marcador fins al final). screen.fillRect(0, HUD_H, SIDE_WALL_W, GameCanvas::HEIGHT - HUD_H, palette[WALL]); screen.fillRect(GameCanvas::WIDTH - SIDE_WALL_W, HUD_H, SIDE_WALL_W, GameCanvas::HEIGHT - HUD_H, palette[WALL]); // Mur frontal: de la vora inferior del passadís de baix fins al final del // canvas. Assumeix els 40 px extra de 320×240 i fa de primer pla. const int FRONT_WALL_Y = ORIGIN_Y + BOARD_H + OUTER_CORRIDOR; screen.fillRect(0, FRONT_WALL_Y, GameCanvas::WIDTH, GameCanvas::HEIGHT - FRONT_WALL_Y, palette[WALL]); } void Map::renderSarcsRow(int row) { auto& screen = Screen::get(); const auto& palette = Resource::Cache::get().getPalette("ui"); const int Y = ORIGIN_Y + (row * PITCH_Y); for (int col = 0; col < GRID_COLS; ++col) { const int X = ORIGIN_X + (col * PITCH_X); screen.fillRect(X, Y, SARC_W, SARC_H, palette[SARC]); } } auto Map::collides(const SDL_FRect& base_box) -> bool { // Recorregut trivial dels 20 sarcòfags. Amb una graella tan petita no // val la pena indexar per col/row prèviament; si algun dia creix, es pot // calcular el rang de columnes/files candidates a partir de base_box. for (int row = 0; row < GRID_ROWS; ++row) { for (int col = 0; col < GRID_COLS; ++col) { if (overlapStrict(base_box, getSarcRect(col, row))) { return true; } } } return false; }