#include "path_sprite.h" #include // Para abs #include // Para abs #include // Para function #include // Para move // Devuelve un vector con los puntos que conforman la ruta std::vector createPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function &easingFunction) { std::vector v; v.reserve(steps); for (int i = 0; i < steps; ++i) { double t = static_cast(i) / (steps - 1); double value = start + (end - start) * easingFunction(t); if (start > 0 && end < 0) { value = start - std::abs(end - start) * easingFunction(t); } else if (start < 0 && end > 0) { value = start + std::abs(end - start) * easingFunction(t); } switch (type) { case PathType::HORIZONTAL: v.emplace_back(SDL_Point{static_cast(value), fixed_pos}); break; case PathType::VERTICAL: v.emplace_back(SDL_Point{fixed_pos, static_cast(value)}); break; default: break; } } return v; } // Actualiza la posición y comprueba si ha llegado a su destino void PathSprite::update() { if (enabled_) { moveThroughCurrentPath(); goToNextPathOrDie(); } } // Añade un recorrido void PathSprite::addPath(Path path, bool centered) { PathCentered path_centered = PathCentered::NONE; if (centered) path_centered = (path.spots.back().x == path.spots.front().x) ? PathCentered::ON_X : PathCentered::ON_Y; switch (path_centered) { case PathCentered::ON_X: { const int x = path.spots.back().x - pos_.w / 2; for (auto &spot : path.spots) spot.x = x; paths_.emplace_back(path); break; } case PathCentered::ON_Y: { const int y = path.spots.back().y - pos_.h / 2; for (auto &spot : path.spots) spot.y = y; paths_.emplace_back(path); break; } default: paths_.emplace_back(path); break; } } // Añade un recorrido void PathSprite::addPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function &easingFunction, int waiting_counter) { paths_.emplace_back(createPath(start, end, type, fixed_pos, steps, easingFunction), waiting_counter); } // Añade un recorrido void PathSprite::addPath(std::vector spots, int waiting_counter) { paths_.emplace_back(std::move(spots), waiting_counter); } // Habilita el objeto void PathSprite::enable() { enabled_ = true; } // Coloca el sprite en los diferentes puntos del recorrido void PathSprite::moveThroughCurrentPath() { auto &path = paths_.at(current_path_); // Establece la posición const auto &p = path.spots.at(path.counter); setPosition(p); // Comprobar si ha terminado el recorrido if (!path.on_destination) { ++path.counter; if (path.counter >= static_cast(path.spots.size())) { path.on_destination = true; path.counter = static_cast(path.spots.size()) - 1; } } // Comprobar si ha terminado la espera if (path.on_destination) { if (path.waiting_counter == 0) path.finished = true; else --path.waiting_counter; } } // Cambia de recorrido o finaliza void PathSprite::goToNextPathOrDie() { // Comprueba si ha terminado el recorrdo actual if (paths_.at(current_path_).finished) ++current_path_; // Comprueba si quedan mas recorridos if (current_path_ >= static_cast(paths_.size())) enabled_ = false; } // Indica si ha terminado todos los recorridos bool PathSprite::hasFinished() { return !enabled_; }