From da65777a5b820e764cf2042fcbc0bc8feecb29fb Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Tue, 28 Oct 2025 09:48:58 +0100 Subject: [PATCH] migrades les clases Sprite a time based --- .../rendering/surface_animated_sprite.cpp | 84 ++++++++++++++++--- .../rendering/surface_animated_sprite.hpp | 18 +++- .../core/rendering/surface_moving_sprite.cpp | 27 +++++- .../core/rendering/surface_moving_sprite.hpp | 13 ++- source/core/rendering/surface_sprite.cpp | 12 +++ source/core/rendering/surface_sprite.hpp | 7 ++ 6 files changed, 141 insertions(+), 20 deletions(-) diff --git a/source/core/rendering/surface_animated_sprite.cpp b/source/core/rendering/surface_animated_sprite.cpp index dcb7d79..ffebb51 100644 --- a/source/core/rendering/surface_animated_sprite.cpp +++ b/source/core/rendering/surface_animated_sprite.cpp @@ -63,20 +63,72 @@ auto SurfaceAnimatedSprite::getIndex(const std::string& name) -> int { return -1; } -// Calcula el frame correspondiente a la animación -void SurfaceAnimatedSprite::animate() { - if (animations_[current_animation_].speed == 0) { +// Calcula el frame correspondiente a la animación (time-based) +void SurfaceAnimatedSprite::animate(float delta_time) { + if (animations_[current_animation_].speed <= 0.0F) { return; } - // Calcula el frame actual a partir del contador - animations_[current_animation_].current_frame = animations_[current_animation_].counter / animations_[current_animation_].speed; + // Acumula el tiempo transcurrido + animations_[current_animation_].accumulated_time += delta_time; + + // Calcula el frame actual a partir del tiempo acumulado + const int TARGET_FRAME = static_cast( + animations_[current_animation_].accumulated_time / + animations_[current_animation_].speed + ); + + // Si alcanza el final de la animación, maneja el loop + if (TARGET_FRAME >= static_cast(animations_[current_animation_].frames.size())) { + if (animations_[current_animation_].loop == -1) { + // Si no hay loop, congela en el último frame + animations_[current_animation_].current_frame = + static_cast(animations_[current_animation_].frames.size()) - 1; + animations_[current_animation_].completed = true; + + // Establece el clip del último frame + if (animations_[current_animation_].current_frame >= 0) { + setClip(animations_[current_animation_].frames[animations_[current_animation_].current_frame]); + } + } else { + // Si hay loop, vuelve al frame indicado + animations_[current_animation_].accumulated_time = + static_cast(animations_[current_animation_].loop) * + animations_[current_animation_].speed; + animations_[current_animation_].current_frame = animations_[current_animation_].loop; + + // Establece el clip del frame de loop + setClip(animations_[current_animation_].frames[animations_[current_animation_].current_frame]); + } + } else { + // Actualiza el frame actual + animations_[current_animation_].current_frame = TARGET_FRAME; + + // Establece el clip del frame actual + if (animations_[current_animation_].current_frame >= 0 && + animations_[current_animation_].current_frame < + static_cast(animations_[current_animation_].frames.size())) { + setClip(animations_[current_animation_].frames[animations_[current_animation_].current_frame]); + } + } +} + +// Calcula el frame correspondiente a la animación (frame-based, deprecated) +void SurfaceAnimatedSprite::animate() { + if (animations_[current_animation_].speed == 0.0F) { + return; + } + + // Calcula el frame actual a partir del contador (sistema antiguo) + animations_[current_animation_].current_frame = + static_cast(animations_[current_animation_].counter / animations_[current_animation_].speed); // Si alcanza el final de la animación, reinicia el contador de la animación // en función de la variable loop y coloca el nuevo frame if (animations_[current_animation_].current_frame >= static_cast(animations_[current_animation_].frames.size())) { if (animations_[current_animation_].loop == -1) { // Si no hay loop, deja el último frame - animations_[current_animation_].current_frame = animations_[current_animation_].frames.size(); + animations_[current_animation_].current_frame = + static_cast(animations_[current_animation_].frames.size()) - 1; animations_[current_animation_].completed = true; } else { // Si hay loop, vuelve al frame indicado animations_[current_animation_].counter = 0; @@ -104,7 +156,8 @@ void SurfaceAnimatedSprite::setCurrentAnimation(const std::string& name) { if (current_animation_ != NEW_ANIMATION) { current_animation_ = NEW_ANIMATION; animations_[current_animation_].current_frame = 0; - animations_[current_animation_].counter = 0; + animations_[current_animation_].accumulated_time = 0.0F; // Time-based + animations_[current_animation_].counter = 0; // Frame-based (deprecated) animations_[current_animation_].completed = false; setClip(animations_[current_animation_].frames[animations_[current_animation_].current_frame]); } @@ -116,13 +169,20 @@ void SurfaceAnimatedSprite::setCurrentAnimation(int index) { if (current_animation_ != NEW_ANIMATION) { current_animation_ = NEW_ANIMATION; animations_[current_animation_].current_frame = 0; - animations_[current_animation_].counter = 0; + animations_[current_animation_].accumulated_time = 0.0F; // Time-based + animations_[current_animation_].counter = 0; // Frame-based (deprecated) animations_[current_animation_].completed = false; setClip(animations_[current_animation_].frames[animations_[current_animation_].current_frame]); } } -// Actualiza las variables del objeto +// Actualiza las variables del objeto (time-based) +void SurfaceAnimatedSprite::update(float delta_time) { + animate(delta_time); + SurfaceMovingSprite::update(delta_time); +} + +// Actualiza las variables del objeto (frame-based, deprecated) void SurfaceAnimatedSprite::update() { animate(); SurfaceMovingSprite::update(); @@ -131,7 +191,8 @@ void SurfaceAnimatedSprite::update() { // Reinicia la animación void SurfaceAnimatedSprite::resetAnimation() { animations_[current_animation_].current_frame = 0; - animations_[current_animation_].counter = 0; + animations_[current_animation_].accumulated_time = 0.0F; // Time-based + animations_[current_animation_].counter = 0; // Frame-based (deprecated) animations_[current_animation_].completed = false; } @@ -183,7 +244,8 @@ auto parseAnimationParameter(const std::string& key, const std::string& value, A return true; } if (key == "speed") { - animation.speed = std::stoi(value); + // Soporta tanto float (segundos) como int (compatibilidad con sistema antiguo) + animation.speed = std::stof(value); return true; } if (key == "loop") { diff --git a/source/core/rendering/surface_animated_sprite.hpp b/source/core/rendering/surface_animated_sprite.hpp index b926c66..e2d7421 100644 --- a/source/core/rendering/surface_animated_sprite.hpp +++ b/source/core/rendering/surface_animated_sprite.hpp @@ -13,11 +13,14 @@ class Surface; // lines 9-9 struct AnimationData { std::string name; // Nombre de la animacion std::vector frames; // Cada uno de los frames que componen la animación - int speed{5}; // Velocidad de la animación + float speed{0.083F}; // Velocidad de la animación (segundos por frame) int loop{0}; // Indica a que frame vuelve la animación al terminar. -1 para que no vuelva bool completed{false}; // Indica si ha finalizado la animación int current_frame{0}; // Frame actual - int counter{0}; // Contador para las animaciones + float accumulated_time{0.0F}; // Tiempo acumulado para las animaciones (time-based) + + // DEPRECATED: Mantener compatibilidad con sistema antiguo + int counter{0}; // Contador para las animaciones (frame-based, deprecated) AnimationData() @@ -35,7 +38,10 @@ class SurfaceAnimatedSprite : public SurfaceMovingSprite { std::vector animations_; // Vector con las diferentes animaciones int current_animation_ = 0; // Animacion activa - // Calcula el frame correspondiente a la animación actual + // Calcula el frame correspondiente a la animación actual (time-based) + void animate(float delta_time); + + // Calcula el frame correspondiente a la animación actual (frame-based, deprecated) void animate(); // Carga la animación desde un vector de cadenas @@ -51,7 +57,11 @@ class SurfaceAnimatedSprite : public SurfaceMovingSprite { // Destructor ~SurfaceAnimatedSprite() override = default; - // Actualiza las variables del objeto + // Actualiza las variables del objeto (time-based) + void update(float delta_time) override; + + // Actualiza las variables del objeto (frame-based, deprecated) + [[deprecated("Use update(float delta_time) instead")]] void update() override; // Comprueba si ha terminado la animación diff --git a/source/core/rendering/surface_moving_sprite.cpp b/source/core/rendering/surface_moving_sprite.cpp index 8b6b9ba..93c57a7 100644 --- a/source/core/rendering/surface_moving_sprite.cpp +++ b/source/core/rendering/surface_moving_sprite.cpp @@ -39,8 +39,26 @@ void SurfaceMovingSprite::clear() { SurfaceSprite::clear(); } -// Mueve el sprite +// Mueve el sprite (time-based) +// Nota: vx_, vy_ ahora se interpretan como pixels/segundo +// Nota: ax_, ay_ ahora se interpretan como pixels/segundo² +void SurfaceMovingSprite::move(float delta_time) { + // Aplica aceleración a velocidad (time-based) + vx_ += ax_ * delta_time; + vy_ += ay_ * delta_time; + + // Aplica velocidad a posición (time-based) + x_ += vx_ * delta_time; + y_ += vy_ * delta_time; + + // Actualiza posición entera para renderizado + pos_.x = static_cast(x_); + pos_.y = static_cast(y_); +} + +// Mueve el sprite (frame-based, deprecated) void SurfaceMovingSprite::move() { + // Versión antigua: suma directa sin delta_time x_ += vx_; y_ += vy_; @@ -51,7 +69,12 @@ void SurfaceMovingSprite::move() { pos_.y = static_cast(y_); } -// Actualiza las variables internas del objeto +// Actualiza las variables internas del objeto (time-based) +void SurfaceMovingSprite::update(float delta_time) { + move(delta_time); +} + +// Actualiza las variables internas del objeto (frame-based, deprecated) void SurfaceMovingSprite::update() { move(); } diff --git a/source/core/rendering/surface_moving_sprite.hpp b/source/core/rendering/surface_moving_sprite.hpp index 0412d7b..71cdad9 100644 --- a/source/core/rendering/surface_moving_sprite.hpp +++ b/source/core/rendering/surface_moving_sprite.hpp @@ -22,7 +22,10 @@ class SurfaceMovingSprite : public SurfaceSprite { SDL_FlipMode flip_; // Indica como se voltea el sprite - // Mueve el sprite + // Mueve el sprite (time-based) + void move(float delta_time); + + // Mueve el sprite (frame-based, deprecated) void move(); public: @@ -34,8 +37,12 @@ class SurfaceMovingSprite : public SurfaceSprite { // Destructor ~SurfaceMovingSprite() override = default; - // Actualiza las variables internas del objeto - virtual void update(); + // Actualiza las variables internas del objeto (time-based) + void update(float delta_time) override; + + // Actualiza las variables internas del objeto (frame-based, deprecated) + [[deprecated("Use update(float delta_time) instead")]] + void update() override; // Reinicia todas las variables a cero void clear() override; diff --git a/source/core/rendering/surface_sprite.cpp b/source/core/rendering/surface_sprite.cpp index 1f29630..9bfc284 100644 --- a/source/core/rendering/surface_sprite.cpp +++ b/source/core/rendering/surface_sprite.cpp @@ -45,4 +45,16 @@ void SurfaceSprite::setPosition(SDL_FPoint p) { void SurfaceSprite::clear() { pos_ = {.x = 0, .y = 0, .w = 0, .h = 0}; clip_ = {.x = 0, .y = 0, .w = 0, .h = 0}; +} + +// Actualiza el estado del sprite (time-based) +void SurfaceSprite::update(float delta_time) { + // Base implementation does nothing (static sprites) + (void)delta_time; // Evita warning de parámetro no usado +} + +// Actualiza el estado del sprite (frame-based, deprecated) +void SurfaceSprite::update() { + // Llama a la versión time-based con 0.0f para compatibilidad + update(0.0F); } \ No newline at end of file diff --git a/source/core/rendering/surface_sprite.hpp b/source/core/rendering/surface_sprite.hpp index b9d9210..25959f8 100644 --- a/source/core/rendering/surface_sprite.hpp +++ b/source/core/rendering/surface_sprite.hpp @@ -23,6 +23,13 @@ class SurfaceSprite { // Destructor virtual ~SurfaceSprite() = default; + // Actualiza el estado del sprite (time-based) + virtual void update(float delta_time); + + // Actualiza el estado del sprite (frame-based, deprecated) + [[deprecated("Use update(float delta_time) instead")]] + virtual void update(); + // Muestra el sprite por pantalla virtual void render(); virtual void render(Uint8 source_color, Uint8 target_color);