Files
projecte_2026/source/game/gameplay/door_manager.cpp

93 lines
3.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "door_manager.hpp"
#include <utility> // Para std::move
#include "game/entities/door.hpp" // Para Door
#include "game/gameplay/collision_map.hpp" // Para CollisionMap
#include "game/gameplay/door_tracker.hpp" // Para DoorTracker
#include "game/gameplay/inventory.hpp" // Para Inventory
#include "game/gameplay/tile_collider.hpp" // Para TileCollider::Tile
#include "utils/defines.hpp" // Para Map::WIDTH, Tile::SIZE
#include "utils/utils.hpp" // Para checkCollision
// Constructor
DoorManager::DoorManager(std::string room_id, CollisionMap* collision_map)
: room_id_(std::move(room_id)),
collision_map_(collision_map) {
}
// Añade una puerta. Si está bloqueante (CLOSED), pinta sus 4 tiles como WALL
// en el CollisionMap. Si ya está OPENED (porque venía persistida del
// DoorTracker), no se tocan los tiles.
void DoorManager::addDoor(std::shared_ptr<Door> door) { // NOLINT(readability-identifier-naming)
if (door->isBlocking()) {
writeDoorTiles(*door, static_cast<int>(TileCollider::Tile::WALL));
}
doors_.push_back(std::move(door));
}
// Elimina todas las puertas
void DoorManager::clear() {
doors_.clear();
}
// Actualiza animaciones y procesa transiciones a OPENED
void DoorManager::update(float delta_time) {
for (const auto& door : doors_) {
door->update(delta_time);
// Si la puerta acaba de transicionar a OPENED, liberar los tiles y persistir
if (door->justOpened()) {
writeDoorTiles(*door, static_cast<int>(TileCollider::Tile::EMPTY));
DoorTracker::get()->addDoor(room_id_, door->getPos());
}
}
}
// Renderiza todas las puertas
void DoorManager::render() {
for (const auto& door : doors_) {
door->render();
}
}
// Pausa/despausa todas las puertas
void DoorManager::setPaused(bool paused) {
for (const auto& door : doors_) {
door->setPaused(paused);
}
}
// Intenta abrir las puertas cercanas al jugador
void DoorManager::tryUnlock(const SDL_FRect& player_rect) {
// Infla el rect del jugador 1 px en cada lado para detectar contacto
const SDL_FRect INFLATED = {
.x = player_rect.x - 1.0F,
.y = player_rect.y - 1.0F,
.w = player_rect.w + 2.0F,
.h = player_rect.h + 2.0F,
};
for (const auto& door : doors_) {
if (door->getState() != Door::State::CLOSED) {
continue;
}
if (::checkCollision(INFLATED, door->getCollider()) && Inventory::get()->hasKey(door->getId())) {
door->startOpening();
}
}
}
// Setea las 4 celdas que ocupa la puerta (1 col × 4 filas) al valor indicado
void DoorManager::writeDoorTiles(const Door& door, int tile_value) {
// Convertir posición en píxeles a coordenadas de tile
const SDL_FPoint POS = door.getPos();
const int COL = static_cast<int>(POS.x) / Tile::SIZE;
const int ROW = static_cast<int>(POS.y) / Tile::SIZE;
for (int i = 0; i < DOOR_TILES_HEIGHT; ++i) {
const int INDEX = ((ROW + i) * Map::WIDTH) + COL;
collision_map_->setCollisionTile(INDEX, tile_value);
}
}