#include "door_manager.hpp" #include // 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) { // 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(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(doors_.size())) { return; } solid_actors_->unregisterActor(doors_[index].get()); doors_.erase(doors_.begin() + index); } #endif