diff --git a/source/common/animatedsprite.cpp b/source/common/animatedsprite.cpp index a218957..d53889e 100644 --- a/source/common/animatedsprite.cpp +++ b/source/common/animatedsprite.cpp @@ -1,186 +1,16 @@ #include "animatedsprite.h" -// Constructor -AnimatedSprite::AnimatedSprite(Texture *texture, SDL_Renderer *renderer, std::string file, std::vector *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 *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 *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; } \ No newline at end of file diff --git a/source/common/animatedsprite.h b/source/common/animatedsprite.h index c9bab9d..39f6f90 100644 --- a/source/common/animatedsprite.h +++ b/source/common/animatedsprite.h @@ -11,28 +11,37 @@ #ifndef ANIMATEDSPRITE_H #define ANIMATEDSPRITE_H -// Clase AnimatedSprite +struct animation_t +{ + std::string name; // Nombre de la animacion + std::vector 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 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 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 animation; // Vector con las diferentes animaciones + std::vector 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 *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 *source);