#include "const.h" #include "animatedsprite.h" // Constructor AnimatedSprite::AnimatedSprite(LTexture *texture, SDL_Renderer *renderer, std::string file) { // Copia los punteros setTexture(texture); setRenderer(renderer); // Carga las animaciones load(file); // 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 result = -1; for (int i = 0; i < animation.size(); i++) { if (animation[i].name == name) { result = i; } } return result; } // Calcula el frame correspondiente a la animación void AnimatedSprite::animate() { if (mEnabled) { // 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 >= 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++; } } } // Establece el frame actual de la animación void AnimatedSprite::setCurrentFrame(std::string name, int num) { animation[getIndex(name)].currentFrame = num; } // 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 si la animación se reproduce en bucle void AnimatedSprite::setAnimationLoop(std::string name, int loop) { animation[getIndex(name)].loop = loop; } // Establece el valor de la variable void AnimatedSprite::setAnimationCompleted(std::string name, bool value) { animation[getIndex(name)].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]; } // Carga la animación desde un fichero bool AnimatedSprite::load(std::string filePath) { int frames_per_row = 0; int frame_width = 0; int frame_height = 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; // El fichero se puede abrir if (file.good()) { // Procesa el fichero linea a linea printf("Reading file %s\n", filename.c_str()); while (std::getline(file, line)) { // Si la linea contiene el texto [enemy] se realiza el proceso de carga de un enemigo if (line == "[animation]") { t_animation buffer; buffer.counter = 0; buffer.currentFrame = 0; buffer.completed = false; do { std::getline(file, line); // Encuentra la posición del caracter '=' int pos = line.find("="); // Procesa las dos subcadenas if (pos != line.npos) { if (line.substr(0, pos) == "name") { buffer.name = line.substr(pos + 1, line.length()); } else if (line.substr(0, pos) == "speed") { buffer.speed = std::stoi(line.substr(pos + 1, line.length())); } else if (line.substr(0, pos) == "loop") { buffer.loop = std::stoi(line.substr(pos + 1, line.length())); } else if (line.substr(0, pos) == "frames") { // Se introducen los valores separados por comas en un vector std::stringstream ss(line.substr(pos + 1, line.length())); std::string tmp; SDL_Rect rect = {0, 0, frame_width, frame_height}; while (getline(ss, tmp, ',')) { int num_tile = std::stoi(tmp); rect.x = (num_tile % frames_per_row) * frame_width; rect.y = (num_tile / frames_per_row) * frame_height; buffer.frames.push_back(rect); } } else { printf("Warning: file %s, unknown parameter \"%s\"\n", filename.c_str(), line.substr(0, pos).c_str()); success = false; } } } while (line != "[/animation]"); // Añade el enemigo al vector de enemigos animation.push_back(buffer); } // En caso contrario se parsea el fichero para buscar las variables y los valores else { // Encuentra la posición del caracter '=' int pos = line.find("="); // Procesa las dos subcadenas if (pos != line.npos) { if (line.substr(0, pos) == "frames_per_row") { frames_per_row = std::stoi(line.substr(pos + 1, line.length())); } else if (line.substr(0, pos) == "frame_width") { frame_width = std::stoi(line.substr(pos + 1, line.length())); } else if (line.substr(0, pos) == "frame_height") { frame_height = std::stoi(line.substr(pos + 1, line.length())); } else { printf("Warning: file %s, unknown parameter \"%s\"\n", filename.c_str(), line.substr(0, pos).c_str()); success = false; } } } } // Cierra el fichero printf("Closing file %s\n", filename.c_str()); file.close(); } // El fichero no se puede abrir else { printf("Warning: Unable to open %s file\n", filename.c_str()); success = false; } // Pone un valor por defecto setPos({0, 0, frame_width, frame_height}); return success; } // Establece la animacion actual void AnimatedSprite::setCurrentAnimation(std::string name) { const int newAnimation = getIndex(name); if (currentAnimation != newAnimation) { currentAnimation = newAnimation; animation[currentAnimation].currentFrame = 0; animation[currentAnimation].counter = 0; animation[currentAnimation].completed = false; } } // Actualiza las variables del objeto void AnimatedSprite::update() { animate(); MovingSprite::update(); }