Files
coffee_crisis_arcade_edition/source/path_sprite.cpp

148 lines
3.4 KiB
C++

#include "path_sprite.h"
#include <cmath> // for abs
#include <stdlib.h> // for abs
#include <functional> // for function
#include <utility> // for move
// Devuelve un vector con los puntos que conforman la ruta
std::vector<SDL_Point> createPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function<double(double)> &easingFunction)
{
std::vector<SDL_Point> v;
v.reserve(steps);
for (int i = 0; i < steps; ++i)
{
double t = static_cast<double>(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<int>(value), fixed_pos});
break;
case PathType::VERTICAL:
v.emplace_back(SDL_Point{fixed_pos, static_cast<int>(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<double(double)> &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<SDL_Point> 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<int>(path.spots.size()))
{
path.on_destination = true;
path.counter = static_cast<int>(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<int>(paths_.size()))
enabled_ = false;
}
// Indica si ha terminado todos los recorridos
bool PathSprite::hasFinished()
{
return !enabled_;
}