spacebox/src/Animation.hpp

122 lines
4.5 KiB
C++

/* ✨ +------------------------------------------------------+
____/ \____ ✨/| Open source game framework licensed to freely use, |
✨\ / / | copy, and modify. Created for 🌠dank.game🌠 |
+--\ . . /--+ | |
| ~/ ︶ \👍| | 🌐 https://open.shampoo.ooo/shampoo/spacebox |
| ~~~🌊~~~~🌊~ | +------------------------------------------------------+
| SPACE 🪐🅱 OX | /
| 🌊 ~ ~~~~ ~~ |/
+-------------*/
#pragma once
#include <vector>
#include <functional>
#include <algorithm>
#include "Timer.hpp"
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);
};
/* Add Animation class to the sb namespace. This should be the default location, but Animation is left in the global namespace
* for backward compatibility.
*/
namespace sb
{
using ::Animation;
}