granera
motor de animacio
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include "core/rendering/sprite/animated_sprite.hpp"
|
||||
|
||||
#include <cmath> // Para std::fmod
|
||||
#include <cstddef> // Para size_t
|
||||
#include <fstream> // Para basic_ostream, basic_istream, operator<<, basic...
|
||||
#include <iostream> // Para cout, cerr
|
||||
@@ -88,17 +89,7 @@ auto AnimatedSprite::loadAnimationsFromYAML(const std::string& file_path, std::s
|
||||
animation.name = anim_node["name"].get_value<std::string>();
|
||||
}
|
||||
|
||||
// Parse speed (seconds per frame)
|
||||
if (anim_node.contains("speed")) {
|
||||
animation.speed = anim_node["speed"].get_value<float>();
|
||||
}
|
||||
|
||||
// Parse loop frame index
|
||||
if (anim_node.contains("loop")) {
|
||||
animation.loop = anim_node["loop"].get_value<int>();
|
||||
}
|
||||
|
||||
// Parse frames array
|
||||
// Parse frames array (antes de speeds, para saber cuántos frames hay)
|
||||
if (anim_node.contains("frames") && anim_node["frames"].is_sequence()) {
|
||||
animation.frames = convertYAMLFramesToRects(
|
||||
anim_node["frames"],
|
||||
@@ -108,6 +99,26 @@ auto AnimatedSprite::loadAnimationsFromYAML(const std::string& file_path, std::s
|
||||
max_tiles);
|
||||
}
|
||||
|
||||
// Parse speed: escalar (uniforme) o array (por frame)
|
||||
if (anim_node.contains("speed")) {
|
||||
const auto& speed_node = anim_node["speed"];
|
||||
if (speed_node.is_sequence()) {
|
||||
for (const auto& s : speed_node) {
|
||||
animation.speeds.push_back(s.get_value<float>());
|
||||
}
|
||||
} else {
|
||||
float spd = speed_node.get_value<float>();
|
||||
if (spd > 0.0F) {
|
||||
animation.speeds.assign(animation.frames.size(), spd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse loopFrom
|
||||
if (anim_node.contains("loopFrom")) {
|
||||
animation.loop_from = anim_node["loopFrom"].get_value<int>();
|
||||
}
|
||||
|
||||
animations.push_back(animation);
|
||||
}
|
||||
}
|
||||
@@ -172,17 +183,7 @@ AnimatedSprite::AnimatedSprite(const AnimationResource& cached_data) {
|
||||
animation.name = anim_node["name"].get_value<std::string>();
|
||||
}
|
||||
|
||||
// Parse speed (seconds per frame)
|
||||
if (anim_node.contains("speed")) {
|
||||
animation.speed = anim_node["speed"].get_value<float>();
|
||||
}
|
||||
|
||||
// Parse loop frame index
|
||||
if (anim_node.contains("loop")) {
|
||||
animation.loop = anim_node["loop"].get_value<int>();
|
||||
}
|
||||
|
||||
// Parse frames array
|
||||
// Parse frames array (antes de speeds, para saber cuántos frames hay)
|
||||
if (anim_node.contains("frames") && anim_node["frames"].is_sequence()) {
|
||||
animation.frames = convertYAMLFramesToRects(
|
||||
anim_node["frames"],
|
||||
@@ -192,6 +193,26 @@ AnimatedSprite::AnimatedSprite(const AnimationResource& cached_data) {
|
||||
max_tiles);
|
||||
}
|
||||
|
||||
// Parse speed: escalar (uniforme) o array (por frame)
|
||||
if (anim_node.contains("speed")) {
|
||||
const auto& speed_node = anim_node["speed"];
|
||||
if (speed_node.is_sequence()) {
|
||||
for (const auto& s : speed_node) {
|
||||
animation.speeds.push_back(s.get_value<float>());
|
||||
}
|
||||
} else {
|
||||
float spd = speed_node.get_value<float>();
|
||||
if (spd > 0.0F) {
|
||||
animation.speeds.assign(animation.frames.size(), spd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse loopFrom
|
||||
if (anim_node.contains("loopFrom")) {
|
||||
animation.loop_from = anim_node["loopFrom"].get_value<int>();
|
||||
}
|
||||
|
||||
animations_.push_back(animation);
|
||||
}
|
||||
}
|
||||
@@ -240,51 +261,45 @@ auto AnimatedSprite::getIndex(const std::string& name) -> int { // NOLINT(reada
|
||||
// Calcula el frame correspondiente a la animación (time-based)
|
||||
void AnimatedSprite::animate(float delta_time) { // NOLINT(readability-convert-member-functions-to-static)
|
||||
if (animations_.empty()) { return; }
|
||||
if (animations_[current_animation_].speed <= 0.0F) {
|
||||
return;
|
||||
auto& anim = animations_[current_animation_];
|
||||
if (anim.speeds.empty()) { return; } // Animación estática
|
||||
|
||||
anim.accumulated_time += delta_time;
|
||||
|
||||
// Calcular duración total de la animación
|
||||
float total = 0.0F;
|
||||
for (auto s : anim.speeds) { total += s; }
|
||||
|
||||
// Si hemos superado la duración total, manejar loop o congelar
|
||||
if (anim.accumulated_time >= total) {
|
||||
if (anim.loop_from < 0) {
|
||||
// Sin loop: congelar en el último frame
|
||||
anim.current_frame = static_cast<int>(anim.frames.size()) - 1;
|
||||
anim.completed = true;
|
||||
setClip(anim.frames[anim.current_frame]);
|
||||
return;
|
||||
}
|
||||
// Con loop: envolver el tiempo en el rango del loop
|
||||
float loop_start = 0.0F;
|
||||
for (int i = 0; i < anim.loop_from; ++i) { loop_start += anim.speeds[i]; }
|
||||
float loop_len = total - loop_start;
|
||||
anim.accumulated_time = loop_start + std::fmod(anim.accumulated_time - loop_start, loop_len);
|
||||
}
|
||||
|
||||
// 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<int>(
|
||||
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<int>(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<int>(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<float>(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<int>(animations_[current_animation_].frames.size())) {
|
||||
setClip(animations_[current_animation_].frames[animations_[current_animation_].current_frame]);
|
||||
// Buscar el frame correspondiente al tiempo acumulado
|
||||
float cursor = 0.0F;
|
||||
for (int i = 0; i < static_cast<int>(anim.frames.size()); ++i) {
|
||||
cursor += anim.speeds[i];
|
||||
if (anim.accumulated_time < cursor) {
|
||||
anim.current_frame = i;
|
||||
setClip(anim.frames[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Seguridad: último frame
|
||||
anim.current_frame = static_cast<int>(anim.frames.size()) - 1;
|
||||
setClip(anim.frames[anim.current_frame]);
|
||||
}
|
||||
|
||||
// Comprueba si ha terminado la animación
|
||||
|
||||
@@ -20,8 +20,8 @@ class AnimatedSprite : public MovingSprite {
|
||||
struct AnimationData {
|
||||
std::string name; // Nombre de la animacion
|
||||
std::vector<SDL_FRect> frames; // Cada uno de los frames que componen 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
|
||||
std::vector<float> speeds; // Duración de cada frame en segundos (vacío = animación estática)
|
||||
int loop_from{-1}; // Frame al que volver al acabar (-1 = sin loop, congela en el último)
|
||||
bool completed{false}; // Indica si ha finalizado la animación
|
||||
int current_frame{0}; // Frame actual
|
||||
float accumulated_time{0.0F}; // Tiempo acumulado para las animaciones (time-based)
|
||||
|
||||
Reference in New Issue
Block a user