96 lines
3.2 KiB
C++
96 lines
3.2 KiB
C++
#include "door_manager.hpp"
|
|
|
|
#include <utility> // Para std::move
|
|
|
|
#include "game/entities/door.hpp" // Para Door
|
|
#include "game/gameplay/door_tracker.hpp" // Para DoorTracker
|
|
#include "game/gameplay/inventory.hpp" // Para Inventory
|
|
#include "game/gameplay/solid_actor_manager.hpp" // Para SolidActorManager
|
|
#include "utils/utils.hpp" // Para checkCollision
|
|
|
|
// Constructor
|
|
DoorManager::DoorManager(std::string room_id, SolidActorManager* solid_actors)
|
|
: room_id_(std::move(room_id)),
|
|
solid_actors_(solid_actors) {
|
|
}
|
|
|
|
// Añade una puerta y la registra en el SolidActorManager. El bit
|
|
// BLOCKS_PLAYER del propio Door determina si bloquea al Player (se setea en
|
|
// el constructor si la puerta no arranca ya abierta desde el DoorTracker).
|
|
void DoorManager::addDoor(std::shared_ptr<Door> door) { // NOLINT(readability-identifier-naming)
|
|
solid_actors_->registerActor(door.get());
|
|
doors_.push_back(std::move(door));
|
|
}
|
|
|
|
// Elimina todas las puertas y las desregistra del SolidActorManager
|
|
void DoorManager::clear() {
|
|
for (const auto& door : doors_) {
|
|
solid_actors_->unregisterActor(door.get());
|
|
}
|
|
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, persistir en DoorTracker.
|
|
// El flag BLOCKS_PLAYER ya se limpió dentro de Door::update(), así que
|
|
// el sweep del SolidActorManager deja de verla como muro automáticamente.
|
|
if (door->justOpened()) {
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
// Mueve una puerta del editor: reposiciona su sprite y AABB. El registro
|
|
// en el SolidActorManager se mantiene (el manager lee el AABB actual).
|
|
void DoorManager::moveDoor(int index, float x, float y) {
|
|
if (index < 0 || index >= static_cast<int>(doors_.size())) { return; }
|
|
doors_[index]->setPosition(x, y);
|
|
}
|
|
|
|
// Elimina una puerta del editor, desregistrándola del SolidActorManager
|
|
void DoorManager::removeDoor(int index) {
|
|
if (index < 0 || index >= static_cast<int>(doors_.size())) { return; }
|
|
solid_actors_->unregisterActor(doors_[index].get());
|
|
doors_.erase(doors_.begin() + index);
|
|
}
|
|
#endif
|