#pragma once #include #include "external/fkyaml_node.hpp" #include "game/entities/animation_component.hpp" #include "game/entities/interactable.hpp" // Porta de sortida del nivell. Tres estats: // CLOSED → inicial; el passadís de Map bloqueja el pas via `Map::collides`. // OPENING → animació d'obertura en curs. Quan el component acaba → // transita a OPEN. El passadís ja és transitable (s'allibera // a `open()` amb `Map::door_open = true`). // OPEN → accessible. Al contacte amb un jugador, crida `Player::exit()` // — el jugador queda despawnat i emet `player_exited` al bus. // L'agregació "tots els jugadors han eixit → `level_complete`" // viu a EntityManager. // // El que decideix quan s'obri és extern (`EntityManager` comptant sarcs // oberts) via `open()`. L'animació `opening` es fa servir com a // temporitzador de transició (s'espera a `completed()`); si només té un // frame i és loop=false, es completa immediatament al següent tick. class Door : public Interactable { public: enum class State : std::uint8_t { CLOSED, OPENING, OPEN }; explicit Door(const fkyaml::node& yaml); void update(float delta_time) override; void onPlayerContact(Player* player) override; // Passa de CLOSED → OPENING. Idempotent: crides posteriors en estat // OPENING/OPEN són no-op. void open(); [[nodiscard]] auto getState() const -> State { return state_; } private: void setAnimation(const AnimationComponent& anim); State state_{State::CLOSED}; // Les 3 animacions precalculades al ctor des del YAML. L'activa // s'assigna a `anim_` (heretat d'Entity) segons l'estat. AnimationComponent anim_closed_; AnimationComponent anim_opening_; AnimationComponent anim_open_; };