Actualizado animatedsprite.cpp

This commit is contained in:
2022-12-07 08:11:49 +01:00
parent 3cca4373d3
commit cbdee55148
2 changed files with 245 additions and 215 deletions

View File

@@ -1,186 +1,16 @@
#include "animatedsprite.h"
// Constructor
AnimatedSprite::AnimatedSprite(Texture *texture, SDL_Renderer *renderer, std::string file, std::vector<std::string> *buffer)
{
// Copia los punteros
setTexture(texture);
setRenderer(renderer);
// Carga las animaciones
if (file != "")
{
loadFromFile(file);
}
else if (buffer)
{
loadFromVector(buffer);
}
// Inicializa variables
currentAnimation = 0;
}
// Destructor
AnimatedSprite::~AnimatedSprite()
{
for (auto &a : animation)
{
a.frames.clear();
}
animation.clear();
}
// Obtiene el indice de la animación a partir del nombre
int AnimatedSprite::getIndex(std::string name)
{
int index = -1;
for (auto a : animation)
{
index++;
if (a.name == name)
{
return index;
}
}
printf("** Warning: could not find \"%s\" animation\n", name.c_str());
return -1;
}
// Calcula el frame correspondiente a la animación
void AnimatedSprite::animate()
{
if (!enabled || animation.at(currentAnimation).speed == 0)
{
return;
}
// Calcula el frame actual a partir del contador
animation.at(currentAnimation).currentFrame = animation.at(currentAnimation).counter / animation.at(currentAnimation).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 (animation.at(currentAnimation).currentFrame >= (int)animation.at(currentAnimation).frames.size())
{
if (animation.at(currentAnimation).loop == -1)
{ // Si no hay loop, deja el último frame
animation.at(currentAnimation).currentFrame = animation.at(currentAnimation).frames.size();
animation.at(currentAnimation).completed = true;
}
else
{ // Si hay loop, vuelve al frame indicado
animation.at(currentAnimation).counter = 0;
animation.at(currentAnimation).currentFrame = animation.at(currentAnimation).loop;
}
}
// En caso contrario
else
{
// Escoge el frame correspondiente de la animación
setSpriteClip(animation.at(currentAnimation).frames.at(animation.at(currentAnimation).currentFrame));
// Incrementa el contador de la animacion
animation.at(currentAnimation).counter++;
}
}
// Obtiene el numero de frames de la animación actual
int AnimatedSprite::getNumFrames()
{
return (int)animation.at(currentAnimation).frames.size();
}
// Establece el frame actual de la animación
void AnimatedSprite::setCurrentFrame(int num)
{
// Descarta valores fuera de rango
if (num >= (int)animation.at(currentAnimation).frames.size())
{
num = 0;
}
// Cambia el valor de la variable
animation.at(currentAnimation).counter = animation.at(currentAnimation).speed * num;
// Escoge el frame correspondiente de la animación
setSpriteClip(animation.at(currentAnimation).frames.at(animation.at(currentAnimation).currentFrame));
}
// Establece el valor del contador
void AnimatedSprite::setAnimationCounter(std::string name, int num)
{
animation.at(getIndex(name)).counter = num;
}
// Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(std::string name, int speed)
{
animation.at(getIndex(name)).counter = speed;
}
// Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(int index, int speed)
{
animation.at(index).counter = speed;
}
// Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(std::string name, int loop)
{
animation.at(getIndex(name)).loop = loop;
}
// Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(int index, int loop)
{
animation.at(index).loop = loop;
}
// Establece el valor de la variable
void AnimatedSprite::setAnimationCompleted(std::string name, bool value)
{
animation.at(getIndex(name)).completed = value;
}
// OLD - Establece el valor de la variable
void AnimatedSprite::setAnimationCompleted(int index, bool value)
{
animation.at(index).completed = value;
}
// Comprueba si ha terminado la animación
bool AnimatedSprite::animationIsCompleted()
{
return animation.at(currentAnimation).completed;
}
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(std::string name, Uint8 index)
{
return animation.at(getIndex(name)).frames.at(index);
}
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(int indexA, Uint8 indexF)
{
return animation.at(indexA).frames.at(indexF);
}
// Carga la animación desde un fichero
bool AnimatedSprite::loadFromFile(std::string filePath)
animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, bool verbose)
{
// Inicializa variables
animatedSprite_t as;
as.texture = texture;
int framesPerRow = 0;
int frameWidth = 0;
int frameHeight = 0;
int maxTiles = 0;
// Indicador de éxito en la carga
bool success = true;
const std::string filename = filePath.substr(filePath.find_last_of("\\/") + 1);
std::ifstream file(filePath);
std::string line;
@@ -189,13 +19,16 @@ bool AnimatedSprite::loadFromFile(std::string filePath)
if (file.good())
{
// Procesa el fichero linea a linea
std::cout << "Loading animation from file: " << filePath.c_str() << std::endl;
if (verbose)
{
std::cout << "Animation loaded: " << filename << std::endl;
}
while (std::getline(file, line))
{
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]")
{
t_animation buffer;
animation_t buffer;
buffer.counter = 0;
buffer.currentFrame = 0;
buffer.completed = false;
@@ -243,14 +76,13 @@ bool AnimatedSprite::loadFromFile(std::string filePath)
else
{
printf("Warning: file %s, unknown parameter \"%s\"\n", filename.c_str(), line.substr(0, pos).c_str());
success = false;
std::cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
}
}
} while (line != "[/animation]");
// Añade la animación al vector de animaciones
animation.push_back(buffer);
as.animations.push_back(buffer);
}
// En caso contrario se parsea el fichero para buscar las variables y los valores
@@ -279,8 +111,7 @@ bool AnimatedSprite::loadFromFile(std::string filePath)
else
{
printf("Warning: file %s, unknown parameter \"%s\"\n", filename.c_str(), line.substr(0, pos).c_str());
success = false;
std::cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
}
// Normaliza valores
@@ -305,14 +136,207 @@ bool AnimatedSprite::loadFromFile(std::string filePath)
// El fichero no se puede abrir
else
{
printf("Warning: Unable to open %s file\n", filename.c_str());
success = false;
if (verbose)
{
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << std::endl;
}
}
// Pone un valor por defecto
setRect({0, 0, frameWidth, frameHeight});
return as;
}
return success;
// Constructor
AnimatedSprite::AnimatedSprite(Texture *texture, SDL_Renderer *renderer, std::string file, std::vector<std::string> *buffer)
{
// Copia los punteros
setTexture(texture);
setRenderer(renderer);
// Carga las animaciones
if (file != "")
{
animatedSprite_t as = loadAnimationFromFile(texture, file);
// Copia los datos de las animaciones
for (auto animation : as.animations)
{
this->animation.push_back(animation);
}
}
else if (buffer)
{
loadFromVector(buffer);
}
// Inicializa variables
currentAnimation = 0;
}
// Constructor
AnimatedSprite::AnimatedSprite(SDL_Renderer *renderer, animatedSprite_t *animation)
{
// Copia los punteros
setTexture(animation->texture);
setRenderer(renderer);
// Inicializa variables
currentAnimation = 0;
// Copia los datos de las animaciones
for (auto a : animation->animations)
{
this->animation.push_back(a);
}
}
// Destructor
AnimatedSprite::~AnimatedSprite()
{
for (auto &a : animation)
{
a.frames.clear();
}
animation.clear();
}
// Obtiene el indice de la animación a partir del nombre
int AnimatedSprite::getIndex(std::string name)
{
int index = -1;
for (auto a : animation)
{
index++;
if (a.name == name)
{
return index;
}
}
std::cout << "** Warning: could not find \"" << name.c_str() << "\" animation" << std::endl;
return -1;
}
// Calcula el frame correspondiente a la animación
void AnimatedSprite::animate()
{
if (!enabled || animation[currentAnimation].speed == 0)
{
return;
}
// Calcula el frame actual a partir del contador
animation[currentAnimation].currentFrame = animation[currentAnimation].counter / animation[currentAnimation].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 (animation[currentAnimation].currentFrame >= (int)animation[currentAnimation].frames.size())
{
if (animation[currentAnimation].loop == -1)
{ // Si no hay loop, deja el último frame
animation[currentAnimation].currentFrame = animation[currentAnimation].frames.size();
animation[currentAnimation].completed = true;
}
else
{ // Si hay loop, vuelve al frame indicado
animation[currentAnimation].counter = 0;
animation[currentAnimation].currentFrame = animation[currentAnimation].loop;
}
}
// En caso contrario
else
{
// Escoge el frame correspondiente de la animación
setSpriteClip(animation[currentAnimation].frames[animation[currentAnimation].currentFrame]);
// Incrementa el contador de la animacion
animation[currentAnimation].counter++;
}
}
// Obtiene el numero de frames de la animación actual
int AnimatedSprite::getNumFrames()
{
return (int)animation[currentAnimation].frames.size();
}
// Establece el frame actual de la animación
void AnimatedSprite::setCurrentFrame(int num)
{
// Descarta valores fuera de rango
if (num >= (int)animation[currentAnimation].frames.size())
{
num = 0;
}
// Cambia el valor de la variable
animation[currentAnimation].currentFrame = num;
animation[currentAnimation].counter = 0;
// Escoge el frame correspondiente de la animación
setSpriteClip(animation[currentAnimation].frames[animation[currentAnimation].currentFrame]);
}
// Establece el valor del contador
void AnimatedSprite::setAnimationCounter(std::string name, int num)
{
animation[getIndex(name)].counter = num;
}
// Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(std::string name, int speed)
{
animation[getIndex(name)].counter = speed;
}
// Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(int index, int speed)
{
animation[index].counter = speed;
}
// Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(std::string name, int loop)
{
animation[getIndex(name)].loop = loop;
}
// Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(int index, int loop)
{
animation[index].loop = loop;
}
// Establece el valor de la variable
void AnimatedSprite::setAnimationCompleted(std::string name, bool value)
{
animation[getIndex(name)].completed = value;
}
// OLD - Establece el valor de la variable
void AnimatedSprite::setAnimationCompleted(int index, bool value)
{
animation[index].completed = value;
}
// Comprueba si ha terminado la animación
bool AnimatedSprite::animationIsCompleted()
{
return animation[currentAnimation].completed;
}
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(std::string name, Uint8 index)
{
return animation[getIndex(name)].frames[index];
}
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(int indexA, Uint8 indexF)
{
return animation[indexA].frames[indexF];
}
// Carga la animación desde un vector
@@ -338,7 +362,7 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]")
{
t_animation buffer;
animation_t buffer;
buffer.counter = 0;
buffer.currentFrame = 0;
buffer.completed = false;
@@ -460,9 +484,9 @@ void AnimatedSprite::setCurrentAnimation(std::string name)
if (currentAnimation != newAnimation)
{
currentAnimation = newAnimation;
animation.at(currentAnimation).currentFrame = 0;
animation.at(currentAnimation).counter = 0;
animation.at(currentAnimation).completed = false;
animation[currentAnimation].currentFrame = 0;
animation[currentAnimation].counter = 0;
animation[currentAnimation].completed = false;
}
}
@@ -473,9 +497,9 @@ void AnimatedSprite::setCurrentAnimation(int index)
if (currentAnimation != newAnimation)
{
currentAnimation = newAnimation;
animation.at(currentAnimation).currentFrame = 0;
animation.at(currentAnimation).counter = 0;
animation.at(currentAnimation).completed = false;
animation[currentAnimation].currentFrame = 0;
animation[currentAnimation].counter = 0;
animation[currentAnimation].completed = false;
}
}
@@ -489,7 +513,7 @@ void AnimatedSprite::update()
// Establece el rectangulo para un frame de una animación
void AnimatedSprite::setAnimationFrames(Uint8 index_animation, Uint8 index_frame, int x, int y, int w, int h)
{
animation.at(index_animation).frames.push_back({x, y, w, h});
animation[index_animation].frames.push_back({x, y, w, h});
}
// OLD - Establece el contador para todas las animaciones
@@ -504,7 +528,7 @@ void AnimatedSprite::setAnimationCounter(int value)
// Reinicia la animación
void AnimatedSprite::resetAnimation()
{
animation.at(currentAnimation).currentFrame = 0;
animation.at(currentAnimation).counter = 0;
animation.at(currentAnimation).completed = false;
animation[currentAnimation].currentFrame = 0;
animation[currentAnimation].counter = 0;
animation[currentAnimation].completed = false;
}

View File

@@ -11,28 +11,37 @@
#ifndef ANIMATEDSPRITE_H
#define ANIMATEDSPRITE_H
// Clase AnimatedSprite
struct animation_t
{
std::string name; // Nombre de la animacion
std::vector<SDL_Rect> frames; // Cada uno de los frames que componen la animación
int speed; // Velocidad de la animación
int loop; // Indica a que frame vuelve la animación al terminar. -1 para que no vuelva
bool completed; // Indica si ha finalizado la animación
int currentFrame; // Frame actual
int counter; // Contador para las animaciones
};
struct animatedSprite_t
{
std::vector<animation_t> animations; // Vector con las diferentes animaciones
Texture *texture; // Textura con los graficos para el sprite
};
// Carga la animación desde un fichero
animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, bool verbose = false);
class AnimatedSprite : public MovingSprite
{
private:
struct t_animation
{
std::string name; // Nombre de la animacion
std::vector<SDL_Rect> frames; // Cada uno de los frames que componen la animación
int speed; // Velocidad de la animación
int loop; // Indica a que frame vuelve la animación al terminar. -1 para que no vuelva
bool completed; // Indica si ha finalizado la animación
int currentFrame; // Frame actual
int counter; // Contador para las animaciones
};
// Variables
std::vector<t_animation> animation; // Vector con las diferentes animaciones
std::vector<animation_t> animation; // Vector con las diferentes animaciones
int currentAnimation; // Animacion activa
public:
// Constructor
AnimatedSprite(Texture *texture = nullptr, SDL_Renderer *renderer = nullptr, std::string file = "", std::vector<std::string> *buffer = nullptr);
AnimatedSprite(SDL_Renderer *renderer, animatedSprite_t *animation);
// Destructor
~AnimatedSprite();
@@ -65,15 +74,12 @@ public:
bool animationIsCompleted();
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect getAnimationClip(std::string name, Uint8 index);
SDL_Rect getAnimationClip(int indexA, Uint8 indexF);
SDL_Rect getAnimationClip(std::string name = "default", Uint8 index = 0);
SDL_Rect getAnimationClip(int indexA = 0, Uint8 indexF = 0);
// Obtiene el indice de la animación a partir del nombre
int getIndex(std::string name);
// Carga la animación desde un fichero
bool loadFromFile(std::string filePath);
// Carga la animación desde un vector
bool loadFromVector(std::vector<std::string> *source);