#include "game/gameplay/room.hpp" #include // Para std::move #include "core/rendering/screen.hpp" // Para Screen #include "core/rendering/surface.hpp" // Para Surface #include "core/resources/resource_cache.hpp" // Para Resource #include "game/gameplay/collision_map.hpp" // Para CollisionMap #include "game/gameplay/enemy_manager.hpp" // Para EnemyManager #include "game/gameplay/item_manager.hpp" // Para ItemManager #include "game/gameplay/item_tracker.hpp" // Para ItemTracker #include "game/gameplay/room_loader.hpp" // Para RoomLoader #include "game/gameplay/scoreboard.hpp" // Para Scoreboard::Data #include "game/gameplay/tilemap_renderer.hpp" // Para TilemapRenderer #include "utils/defines.hpp" // Para TILE_SIZE #include "utils/utils.hpp" // Para stringToColor // Constructor Room::Room(const std::string& room_path, std::shared_ptr data) : data_(std::move(data)) { auto room = Resource::Cache::get()->getRoom(room_path); // Crea los managers de enemigos e items enemy_manager_ = std::make_unique(); item_manager_ = std::make_unique(room->name, data_); initializeRoom(*room); openTheJail(); // Abre la Jail si se da el caso // Crea el mapa de colisiones (necesita tile_map_, tile_set_width_, conveyor_belt_direction_) collision_map_ = std::make_unique(tile_map_, tile_set_width_, conveyor_belt_direction_); // Crea el renderizador del tilemap (necesita tile_map_, tile_set_width_, surface_, bg_color_, conveyor_belt_direction_) tilemap_renderer_ = std::make_unique(tile_map_, tile_set_width_, surface_, bg_color_, conveyor_belt_direction_); tilemap_renderer_->initialize(collision_map_.get()); // Inicializa (crea map_surface, pinta tiles, busca animados) Screen::get()->setBorderColor(stringToColor(border_color_)); // Establece el color del borde } // Destructor Room::~Room() = default; void Room::initializeRoom(const Data& room) { // Asignar valores a las variables miembro number_ = room.number; name_ = room.name; bg_color_ = room.bg_color; border_color_ = room.border_color; item_color1_ = room.item_color1.empty() ? "yellow" : room.item_color1; item_color2_ = room.item_color2.empty() ? "magenta" : room.item_color2; upper_room_ = room.upper_room; lower_room_ = room.lower_room; left_room_ = room.left_room; right_room_ = room.right_room; tile_set_file_ = room.tile_set_file; conveyor_belt_direction_ = room.conveyor_belt_direction; tile_map_ = room.tile_map; // Tilemap viene embebido en el YAML surface_ = Resource::Cache::get()->getSurface(room.tile_set_file); tile_set_width_ = surface_->getWidth() / TILE_SIZE; is_paused_ = false; // Crear los enemigos usando el manager for (const auto& enemy_data : room.enemies) { enemy_manager_->addEnemy(std::make_shared(enemy_data)); } // Crear los items usando el manager for (const auto& item : room.items) { const SDL_FPoint ITEM_POS = {item.x, item.y}; if (!ItemTracker::get()->hasBeenPicked(room.name, ITEM_POS)) { // Crear una copia local de los datos del item Item::Data item_copy = item; item_copy.color1 = stringToColor(item_color1_); item_copy.color2 = stringToColor(item_color2_); // Crear el objeto Item usando la copia modificada item_manager_->addItem(std::make_shared(item_copy)); } } } // Abre la jail para poder entrar void Room::openTheJail() { if (data_->jail_is_open && name_ == "THE JAIL") { // Elimina el último enemigo (Bry debe ser el último enemigo definido en el fichero) if (!enemy_manager_->isEmpty()) { enemy_manager_->removeLastEnemy(); } // Abre las puertas constexpr int TILE_A = 16 + (13 * 32); constexpr int TILE_B = 16 + (14 * 32); if (TILE_A < tile_map_.size()) { tile_map_[TILE_A] = -1; } if (TILE_B < tile_map_.size()) { tile_map_[TILE_B] = -1; } } } // Dibuja el mapa en pantalla void Room::renderMap() { tilemap_renderer_->render(); } // Dibuja los enemigos en pantalla void Room::renderEnemies() { enemy_manager_->render(); } // Dibuja los objetos en pantalla void Room::renderItems() { item_manager_->render(); } #ifdef _DEBUG // Redibuja el mapa (para actualizar modo debug) void Room::redrawMap() { tilemap_renderer_->redrawMap(collision_map_.get()); } #endif // Actualiza las variables y objetos de la habitación void Room::update(float delta_time) { if (is_paused_) { // Si está en modo pausa no se actualiza nada return; } // Actualiza los tiles animados usando el renderer tilemap_renderer_->update(delta_time); // Actualiza los enemigos usando el manager enemy_manager_->update(delta_time); // Actualiza los items usando el manager item_manager_->update(delta_time); } // Pone el mapa en modo pausa void Room::setPaused(bool value) { is_paused_ = value; tilemap_renderer_->setPaused(value); item_manager_->setPaused(value); } // Devuelve la cadena del fichero de la habitación contigua segun el borde auto Room::getRoom(Border border) -> std::string { switch (border) { case Border::TOP: return upper_room_; case Border::BOTTOM: return lower_room_; case Border::RIGHT: return right_room_; case Border::LEFT: return left_room_; default: return ""; } } // Devuelve el tipo de tile que hay en ese pixel auto Room::getTile(SDL_FPoint point) -> Tile { // Delega a CollisionMap y convierte el resultado const auto COLLISION_TILE = collision_map_->getTile(point); return static_cast(COLLISION_TILE); } // Devuelve el tipo de tile en un índice del tilemap auto Room::getTile(int index) -> Tile { // Delega a CollisionMap y convierte el resultado const auto COLLISION_TILE = collision_map_->getTile(index); return static_cast(COLLISION_TILE); } // Indica si hay colision con un enemigo a partir de un rectangulo auto Room::enemyCollision(SDL_FRect& rect) -> bool { return enemy_manager_->checkCollision(rect); } // Indica si hay colision con un objeto a partir de un rectangulo auto Room::itemCollision(SDL_FRect& rect) -> bool { return item_manager_->checkCollision(rect); } // Obten la coordenada de la cuesta a partir de un punto perteneciente a ese tile auto Room::getSlopeHeight(SDL_FPoint p, Tile slope) -> int { // Delega a CollisionMap (método estático) const auto COLLISION_TILE = static_cast(slope); return CollisionMap::getSlopeHeight(p, COLLISION_TILE); } // === Métodos de colisión (delegados a CollisionMap) === // Comprueba las colisiones con paredes derechas auto Room::checkRightSurfaces(const SDL_FRect& rect) -> int { return collision_map_->checkRightSurfaces(rect); } // Comprueba las colisiones con paredes izquierdas auto Room::checkLeftSurfaces(const SDL_FRect& rect) -> int { return collision_map_->checkLeftSurfaces(rect); } // Comprueba las colisiones con techos auto Room::checkTopSurfaces(const SDL_FRect& rect) -> int { return collision_map_->checkTopSurfaces(rect); } // Comprueba las colisiones punto con techos auto Room::checkTopSurfaces(const SDL_FPoint& p) -> bool { return collision_map_->checkTopSurfaces(p); } // Comprueba las colisiones con suelos auto Room::checkBottomSurfaces(const SDL_FRect& rect) -> int { return collision_map_->checkBottomSurfaces(rect); } // Comprueba las colisiones con conveyor belts auto Room::checkAutoSurfaces(const SDL_FRect& rect) -> int { return collision_map_->checkAutoSurfaces(rect); } // Comprueba las colisiones punto con conveyor belts auto Room::checkConveyorBelts(const SDL_FPoint& p) -> bool { return collision_map_->checkConveyorBelts(p); } // Comprueba las colisiones línea con rampas izquierdas auto Room::checkLeftSlopes(const LineVertical& line) -> int { return collision_map_->checkLeftSlopes(line); } // Comprueba las colisiones punto con rampas izquierdas auto Room::checkLeftSlopes(const SDL_FPoint& p) -> bool { return collision_map_->checkLeftSlopes(p); } // Comprueba las colisiones línea con rampas derechas auto Room::checkRightSlopes(const LineVertical& line) -> int { return collision_map_->checkRightSlopes(line); } // Comprueba las colisiones punto con rampas derechas auto Room::checkRightSlopes(const SDL_FPoint& p) -> bool { return collision_map_->checkRightSlopes(p); } // Obtiene puntero a slope en un punto auto Room::getSlopeAtPoint(const SDL_FPoint& p) const -> const LineDiagonal* { return collision_map_->getSlopeAtPoint(p); } // Carga una habitación desde un archivo YAML (delegado a RoomLoader) auto Room::loadYAML(const std::string& file_path, bool verbose) -> Data { return RoomLoader::loadYAML(file_path, verbose); }