Files
projecte_2026/source/game/gameplay/room.cpp
2026-04-08 14:09:28 +02:00

250 lines
8.4 KiB
C++

#include "game/gameplay/room.hpp"
#include <utility> // Para std::move
#include "core/rendering/surface.hpp" // Para Surface
#include "core/resources/resource_cache.hpp" // Para Resource
#include "game/defaults.hpp" // Para Defaults::Game
#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/platform_manager.hpp" // Para PlatformManager
#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"
// 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, items y plataformas
enemy_manager_ = std::make_unique<EnemyManager>();
item_manager_ = std::make_unique<ItemManager>(room->number, data_);
platform_manager_ = std::make_unique<PlatformManager>();
initializeRoom(*room);
// Crea el mapa de colisiones desde el collision_tile_map
collision_map_ = std::make_unique<CollisionMap>(room->collision_tile_map, 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(room->collision_tile_map);
}
// Destructor
Room::~Room() = default;
void Room::initializeRoom(const Data& room) {
// Asignar valores a las variables miembro
number_ = room.number;
bg_color_ = room.bg_color;
item_color1_ = room.item_color1;
item_color2_ = 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(Enemy::create(enemy_data));
}
// Crear las plataformas usando el manager
for (const auto& plat_data : room.platforms) {
platform_manager_->addPlatform(std::make_shared<MovingPlatform>(plat_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.number, ITEM_POS)) {
// Crear una copia local de los datos del item
Item::Data item_copy = item;
item_copy.color1 = item_color1_;
item_copy.color2 = item_color2_;
// Crear el objeto Item usando la copia modificada
item_manager_->addItem(std::make_shared<Item>(item_copy));
}
}
}
// Dibuja el mapa en pantalla
void Room::renderMap() {
tilemap_renderer_->render();
}
// Dibuja las plataformas en pantalla
void Room::renderPlatforms() {
platform_manager_->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_->getCollisionTileMap());
}
// Actualiza animaciones sin mover enemigos (para editor de mapas)
void Room::updateEditorMode(float delta_time) {
tilemap_renderer_->update(delta_time);
enemy_manager_->updateAnimations(delta_time);
platform_manager_->updateAnimations(delta_time);
item_manager_->update(delta_time);
}
// Resetea enemigos a posiciones iniciales (para editor de mapas)
void Room::resetEnemyPositions(const std::vector<Enemy::Data>& enemy_data) {
enemy_manager_->resetPositions(enemy_data);
}
// Cambia un tile y repinta la celda (para editor)
void Room::setTile(int index, int tile_value) {
if (index >= 0 && index < static_cast<int>(tile_map_.size())) {
tile_map_[index] = tile_value;
tilemap_renderer_->setTile(index, tile_value);
}
}
// Cambia colores de items en vivo (para editor)
void Room::setItemColors(Uint8 color1, Uint8 color2) {
item_color1_ = color1;
item_color2_ = color2;
auto* item_mgr = item_manager_.get();
for (int i = 0; i < item_mgr->getCount(); ++i) {
item_mgr->getItem(i)->setColors(color1, color2);
}
}
// Cambia un collision tile en vivo (para editor)
void Room::setCollisionTile(int index, int value) {
collision_map_->setCollisionTile(index, value);
}
// Cambia una conexión de habitación en vivo (para editor)
void Room::setConnection(Border border, const std::string& room_name) {
switch (border) {
case Border::TOP:
upper_room_ = room_name;
break;
case Border::BOTTOM:
lower_room_ = room_name;
break;
case Border::LEFT:
left_room_ = room_name;
break;
case Border::RIGHT:
right_room_ = room_name;
break;
default:
break;
}
}
// Cambia el tileset en vivo (para editor)
void Room::setTileSet(const std::string& tile_set_file) {
tile_set_file_ = tile_set_file;
surface_ = Resource::Cache::get()->getSurface(tile_set_file);
tile_set_width_ = surface_->getWidth() / TILE_SIZE;
tilemap_renderer_ = std::make_unique<TilemapRenderer>(
tile_map_,
tile_set_width_,
surface_,
bg_color_,
conveyor_belt_direction_);
tilemap_renderer_->initialize(collision_map_->getCollisionTileMap());
}
// Cambia la dirección del conveyor belt en vivo (para editor)
void Room::setConveyorBeltDirection(int direction) {
conveyor_belt_direction_ = direction;
collision_map_->setConveyorBeltDirection(direction);
}
#endif
// Actualiza las variables y objetos de la habitación
void Room::update(float delta_time) { // NOLINT(readability-make-member-function-const)
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 las plataformas usando el manager
platform_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);
}
auto Room::getTileCollider() const -> const TileCollider& {
return collision_map_->getTileCollider();
}
// Devuelve la cadena del fichero de la habitación contigua segun el borde
auto Room::getRoom(Border border) -> std::string { // NOLINT(readability-convert-member-functions-to-static)
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 "";
}
}
auto Room::enemyCollision(SDL_FRect& rect) -> bool {
return enemy_manager_->checkCollision(rect);
}
auto Room::itemCollision(SDL_FRect& rect) -> bool {
return item_manager_->checkCollision(rect);
}
auto Room::checkPlayerOnPlatform(const SDL_FRect& player_collider, float player_vy) -> MovingPlatform* {
return platform_manager_->checkPlayerOnPlatform(player_collider, player_vy);
}
// Carga una habitación desde un archivo YAML (delegado a RoomLoader)
auto Room::loadYAML(const std::string& file_path, bool verbose) -> Data { // NOLINT(readability-convert-member-functions-to-static)
return RoomLoader::loadYAML(file_path, verbose);
}