spacebox/src/Animation.hpp
Cocktail Frank a9437c0551 Keep a list of unlocked achievements in sb::progress
Add a function for syncing all stats and unlocked achievements to Steam
2024-12-22 13:09:06 -05:00

164 lines
5.5 KiB
C++

/* +=======================================================+
____/ \____ /: Open source game framework licensed to freely use, :
\ / / : copy, and modify - created for dank.game :
+==\ ^__^ /==+ : :
: ~/ \~ : : Download at https://open.shampoo.ooo/shampoo/spacebox :
: ~~~~~~~~~~~~ : +=======================================================+
: SPACE ~~~~~ : /
: ~~~~~~~ BOX :/
+=============*/
#pragma once
#include <vector>
#include <functional>
#include <algorithm>
#include "glm/common.hpp"
#include "Timer.hpp"
namespace sb
{
class Animation
{
private:
typedef std::function<void()> Callback;
bool play_state = false, ending = false, paused = false;
float delay = 0.0f, overflow = 0.0f, _frame_length = 0.0f, previous_step_time = 0.0f;
sb::Timer timer;
Callback step = [](){};
public:
Animation();
/*!
* @deprecated It is preferable to use Animation::Animation() or Animation::Animation(float) and omit the
* callback function, which will eventually be removed from this object. This is because storing the callback
* function can create copying issues when std::bind is used to create the callback and the bound object is
* destroyed before the callback is called. Instead, check the return value of Animation::update(float) to
* determine whether or not to call the desired callback externally.
*
* Create an Animation object by supplying a function and interval at which the function should run. Run
* Animation::update(float) regularly with an updated timestamp from Game::update(float), and the function will
* be launched automatically at the given interval. If the interval is omitted, the function will run every time
* Animation::update(float) is run.
*
* @param step function to be run every given amount of seconds, or zero to run every update
* @param frame_length seconds between each run of the function
*/
Animation(Callback step, float frame_length = 0.0f) : _frame_length(frame_length), step(step)
{
timer.off();
}
/*!
* Create an Animation object with a specific amount of time in seconds between each frame.
* Animation::update(float) will only return true when it is time to display another frame.
*
* @param frame_length seconds between each frame
*/
Animation(float frame_length) : _frame_length(frame_length)
{
timer.off();
}
/*!
* Set the duration in seconds of each frame of the animation.
*
* @param length frame length in seconds
*/
void frame_length(float length);
/*!
* Turn the play state to on, causing the animation's callback to run once every frame length. If a delay is
* given, wait before running. If the play_once flag is set to true, only play the callback once after the
* delay.
*
* @param delay Amount of seconds to delay before running
* @param play_once If true, only run the callback once instead of once every frame length
*/
void play(float delay = 0.0f, bool play_once = false);
/*!
* Run the animation's callback only once, optionally after a specified delay. If no delay is specified, it will
* run immediately.
*
* @param delay Amount of seconds to delay before running
*/
void play_once(float delay = 0.0f);
void pause();
void unpause();
/*!
* @param state True to unpause, false to pause
*/
void toggle(bool state);
void reset();
/*!
* @param include_delay Specify whether or not to include the delay time in the check
*
* @return True if the animation is playing
*/
bool playing(bool include_delay = true) const;
/*!
* Update the timer and check the function's return value to determine whether a new frame of the animation
* should be produced.
*
* This will run the callback automatically if it is stored in this object, but the ability to store the
* callback in this object is deprecated and will be removed soon.
*
* @param timestamp Seconds since the program has started, which can be obtained from Game::update(float)
*
* @return True if the next frame of animation should be triggered, false otherwise
*/
bool update(float timestamp);
};
namespace animation
{
template<typename Edge>
class LERP
{
enum Playback { _clamp, _repeat, _mirror, _overflow };
enum Interpolation { _linear, _smooth, _spherical };
Timer timer;
float time = 0.0f;
float length;
Edge start;
Edge end;
Playback playback = _clamp;
Interpolation interpolation = _linear;
public:
LERP(Edge start, Edge end, float length) : start(start), end(end), length(length) {};
void clamp();
void repeat();
void mirror();
void overflow();
void smooth(bool state);
void play();
Edge update(float timestamp)
{
timer.update(timestamp);
}
};
}
}