262 lines
9.0 KiB
C++
262 lines
9.0 KiB
C++
#include "game/gameplay/room.hpp"
|
|
|
|
#include <utility> // 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<Scoreboard::Data> 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<EnemyManager>();
|
|
item_manager_ = std::make_unique<ItemManager>(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<CollisionMap>(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<TilemapRenderer>(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>(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>(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<Tile>(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<Tile>(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<CollisionMap::Tile>(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);
|
|
}
|