treballant en sistema de portes i claus

This commit is contained in:
2026-04-10 09:47:48 +02:00
parent 9aff4432df
commit 97c30bf9a1
37 changed files with 1236 additions and 110 deletions

View File

@@ -0,0 +1,65 @@
#include "game/entities/door.hpp"
#include "core/rendering/sprite/animated_sprite.hpp" // Para AnimatedSprite
#include "core/resources/resource_cache.hpp" // Para Resource
// Constructor: carga la animación y posiciona la puerta. Si start_opened es
// true, la puerta se crea ya abierta (estado OPENED, animación "opened"); en
// caso contrario, se crea cerrada (estado CLOSED, animación "closed").
Door::Door(const Data& data, bool start_opened)
: sprite_(std::make_shared<AnimatedSprite>(Resource::Cache::get()->getAnimationData(data.animation_path))),
id_(data.id),
state_(start_opened ? State::OPENED : State::CLOSED) {
sprite_->setPosX(data.x);
sprite_->setPosY(data.y);
sprite_->setCurrentAnimation(start_opened ? "opened" : "closed");
collider_ = sprite_->getRect();
}
// Pinta la puerta en pantalla
void Door::render() {
sprite_->render();
}
// Avanza la animación. Solo OPENING anima de verdad; CLOSED y OPENED son
// frames estáticos. Cuando la animación de OPENING termina, transiciona a
// OPENED, fija el frame final y marca just_opened_ para que el DoorManager
// libere los tiles de colisión.
void Door::update(float delta_time) {
if (is_paused_) {
return;
}
if (state_ == State::OPENING) {
sprite_->animate(delta_time);
if (sprite_->animationIsCompleted()) {
state_ = State::OPENED;
sprite_->setCurrentAnimation("opened");
just_opened_ = true;
}
}
}
// Posición actual (para registrar el estado abierto en DoorTracker)
auto Door::getPos() const -> SDL_FPoint {
return SDL_FPoint{.x = sprite_->getX(), .y = sprite_->getY()};
}
// Transición CLOSED → OPENING: cambia el estado y arranca la animación de apertura
void Door::startOpening() {
if (state_ != State::CLOSED) {
return;
}
state_ = State::OPENING;
sprite_->setCurrentAnimation("opening");
sprite_->resetAnimation();
}
// Flag one-shot: devuelve true exactamente una vez después de transicionar a OPENED
auto Door::justOpened() -> bool {
if (just_opened_) {
just_opened_ = false;
return true;
}
return false;
}

View File

@@ -0,0 +1,62 @@
#pragma once
#include <SDL3/SDL.h>
#include <memory> // Para shared_ptr
#include <string> // Para string
class AnimatedSprite;
/**
* @brief Puerta que actúa como muro hasta que se abre con la llave correcta
*
* Entidad de 8x32 px (1 columna × 4 filas de tiles) con tres animaciones:
* - "closed": estado inicial bloqueante (frame estático)
* - "opening": animación de transición que se reproduce una sola vez
* - "opened": estado final no bloqueante (frame estático)
*
* El comportamiento de "muro" se implementa marcando los 4 tiles que ocupa
* la puerta como WALL en el CollisionMap (lo gestiona el DoorManager). Cuando
* la puerta termina de abrirse, los tiles vuelven a EMPTY y el jugador puede
* pasar.
*/
class Door {
public:
enum class State : int {
CLOSED = 0,
OPENING = 1,
OPENED = 2
};
struct Data {
std::string animation_path; // Ruta al fichero de animación (ej. "door1.yaml")
std::string id; // Identificador que coincide con el id de la llave que la abre
float x{0.0F}; // Posición X en píxeles (alineada al grid de 8 px)
float y{0.0F}; // Posición Y en píxeles (alineada al grid de 8 px)
};
explicit Door(const Data& data, bool start_opened);
~Door() = default;
void render(); // Pinta la puerta en pantalla
void update(float delta_time); // Avanza la animación; si OPENING termina → OPENED
auto getCollider() -> SDL_FRect& { return collider_; } // Rectángulo de colisión (8x32)
[[nodiscard]] auto getPos() const -> SDL_FPoint; // Posición en píxeles
[[nodiscard]] auto getId() const -> const std::string& { return id_; } // Identificador
[[nodiscard]] auto getState() const -> State { return state_; } // Estado actual
[[nodiscard]] auto isBlocking() const -> bool { return state_ != State::OPENED; } // True si bloquea al jugador
void startOpening(); // Transición CLOSED → OPENING
auto justOpened() -> bool; // Flag one-shot consumido por el manager
void setPaused(bool paused) { is_paused_ = paused; } // Pausa/despausa la animación
private:
std::shared_ptr<AnimatedSprite> sprite_; // Sprite animado de la puerta
SDL_FRect collider_{}; // Rectángulo de colisión
std::string id_; // Identificador
State state_{State::CLOSED}; // Estado actual
bool just_opened_{false}; // Flag one-shot: la puerta acaba de transicionar a OPENED
bool is_paused_{false}; // Indica si la puerta está pausada
};

View File

@@ -0,0 +1,32 @@
#include "game/entities/key.hpp"
#include "core/rendering/sprite/animated_sprite.hpp" // Para AnimatedSprite
#include "core/resources/resource_cache.hpp" // Para Resource
// Constructor: carga la animación, posiciona el sprite y crea el collider
Key::Key(const Data& data)
: sprite_(std::make_shared<AnimatedSprite>(Resource::Cache::get()->getAnimationData(data.animation_path))),
id_(data.id) {
sprite_->setPosX(data.x);
sprite_->setPosY(data.y);
sprite_->setCurrentAnimation("default");
collider_ = sprite_->getRect();
}
// Pinta la llave en pantalla
void Key::render() {
sprite_->render();
}
// Avanza la animación de la llave
void Key::update(float delta_time) {
if (is_paused_) {
return;
}
sprite_->animate(delta_time);
}
// Posición actual (para registrar pickup en KeyTracker)
auto Key::getPos() const -> SDL_FPoint {
return SDL_FPoint{.x = sprite_->getX(), .y = sprite_->getY()};
}

View File

@@ -0,0 +1,44 @@
#pragma once
#include <SDL3/SDL.h>
#include <memory> // Para shared_ptr
#include <string> // Para string
class AnimatedSprite;
/**
* @brief Llave coleccionable
*
* Entidad de 16x16 px con una animación "default". Al ser recogida por el
* jugador, su identificador (id_) se añade al Inventory global y la llave
* desaparece de la habitación. Una llave puede abrir todas las puertas con
* el mismo id; no se consume al usarse.
*/
class Key {
public:
struct Data {
std::string animation_path; // Ruta al fichero de animación (ej. "key1.yaml")
std::string id; // Identificador que abre las puertas con el mismo id
float x{0.0F}; // Posición X en píxeles
float y{0.0F}; // Posición Y en píxeles
};
explicit Key(const Data& data);
~Key() = default;
void render(); // Pinta la llave en pantalla
void update(float delta_time); // Avanza la animación
auto getCollider() -> SDL_FRect& { return collider_; } // Rectángulo de colisión
[[nodiscard]] auto getPos() const -> SDL_FPoint; // Posición actual (para tracker)
[[nodiscard]] auto getId() const -> const std::string& { return id_; } // Identificador de la llave
void setPaused(bool paused) { is_paused_ = paused; } // Pausa/despausa la animación
private:
std::shared_ptr<AnimatedSprite> sprite_; // Sprite animado de la llave
SDL_FRect collider_{}; // Rectángulo de colisión
std::string id_; // Identificador
bool is_paused_{false}; // Indica si la llave está pausada
};

View File

@@ -10,13 +10,14 @@ class AnimatedSprite;
// Punto de paso en la ruta de una plataforma
struct Waypoint {
float x{0.0F}; // Posición en pixels
float x{0.0F}; // Posición en pixels
float y{0.0F};
float wait{0.0F}; // Tiempo de parada en este punto (segundos, 0 = sin parada)
};
// Modo de recorrido de la ruta
enum class LoopMode { PINGPONG, CIRCULAR };
enum class LoopMode { PINGPONG,
CIRCULAR };
// Tipo de función de easing
using EasingFunc = float (*)(float);
@@ -25,11 +26,11 @@ class MovingPlatform {
public:
struct Data {
std::string animation_path;
float speed{30.0F}; // px/s a lo largo del path
float speed{30.0F}; // px/s a lo largo del path
LoopMode loop{LoopMode::PINGPONG};
std::string easing{"linear"}; // Nombre del easing
int frame{0}; // Frame inicial (-1 = random)
std::vector<Waypoint> path; // Mínimo 2 puntos
std::string easing{"linear"}; // Nombre del easing
int frame{0}; // Frame inicial (-1 = random)
std::vector<Waypoint> path; // Mínimo 2 puntos
};
explicit MovingPlatform(const Data& data);