Check in... animations are roughly half built
This commit is contained in:
parent
47e823d5b9
commit
d74635ee4e
|
@ -1,81 +1,93 @@
|
||||||
#include "Animation.h"
|
#include "Animation.h"
|
||||||
|
|
||||||
|
Animation::Animation(float _d, void* _t, std::function<void()> _cb, bool _l)
|
||||||
|
:duration(_d), target(_t), callback(_cb), loop(_l), elapsed(0.0f) {}
|
||||||
|
|
||||||
// linear interpolation constructor
|
// linear interpolation constructor
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Animation<T>::Animation(float _d, T _ev, T* _t, std::function<void()> _cb, bool _l)
|
LerpAnimation<T>::LerpAnimation(float _d, T _ev, T* _t, std::function<void()> _cb, bool _l)
|
||||||
:duration(_d), endvalue(_ev), target(_t), callback(_cb), loop(_l),
|
:Animation(_d, _t, _cb, _l), //duration(_d), target(_t), callback(_cb), loop(_l),elapsed(0.0f),
|
||||||
index(-1), startvalue(*_t), elapsed(0.0f) {}
|
startvalue(*_t), endvalue(_ev) {}
|
||||||
|
|
||||||
// discrete values constructor
|
// discrete values constructor
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Animation<T>::Animation(float _d, std::vector<T> _v, T* _t, std::function<void()> _cb, bool _l)
|
DiscreteAnimation<T>::DiscreteAnimation(float _d, std::vector<T> _v, T* _t, std::function<void()> _cb, bool _l)
|
||||||
:duration(_d), target(_t), callback(_cb), values(_v), loop(_l),
|
:Animation(_d, _t, _cb, _l), //duration(_d), target(_t), callback(_cb), loop(_l), elapsed(0.0f),
|
||||||
index(0), startvalue(*_t), elapsed(0.0f), nonelapsed(0.0f) {
|
index(0), nonelapsed(0.0f), values(_v) {
|
||||||
timestep = _v.size() / _d;
|
timestep = _v.size() / _d;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
/* // don't call virtual functions (like cancel()) from base class destructor
|
||||||
Animation<T>::~Animation() {
|
* // child classes destructors' are called first anyway
|
||||||
|
Animation::~Animation() {
|
||||||
// deconstructor sets target to desired end state (no partial values)
|
// deconstructor sets target to desired end state (no partial values)
|
||||||
cancel();
|
cancel();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void Animation<std::string>::lerp() {
|
void LerpAnimation<std::string>::lerp() {
|
||||||
*target = endvalue.substr(0, endvalue.length() * (elapsed / duration));
|
*(std::string*)target = endvalue.substr(0, endvalue.length() * (elapsed / duration));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void Animation<int>::lerp() {
|
void LerpAnimation<int>::lerp() {
|
||||||
int delta = endvalue - startvalue;
|
int delta = endvalue - startvalue;
|
||||||
*target = startvalue + (elapsed / duration * delta);
|
*(int*)target = startvalue + (elapsed / duration * delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void Animation<float>::lerp() {
|
void LerpAnimation<float>::lerp() {
|
||||||
int delta = endvalue - startvalue;
|
int delta = endvalue - startvalue;
|
||||||
*target = startvalue + (elapsed / duration * delta);
|
*(float*)target = startvalue + (elapsed / duration * delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void Animation<sf::Vector2f>::lerp() {
|
void LerpAnimation<sf::Vector2f>::lerp() {
|
||||||
int delta_x = endvalue.x - startvalue.x;
|
int delta_x = endvalue.x - startvalue.x;
|
||||||
int delta_y = endvalue.y - startvalue.y;
|
int delta_y = endvalue.y - startvalue.y;
|
||||||
target->x = startvalue.x + (elapsed / duration * delta_x);
|
((sf::Vector2f*)target)->x = startvalue.x + (elapsed / duration * delta_x);
|
||||||
target->y = startvalue.y + (elapsed / duration * delta_y);
|
((sf::Vector2f*)target)->y = startvalue.y + (elapsed / duration * delta_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void Animation<sf::Vector2i>::lerp() {
|
void LerpAnimation<sf::Vector2i>::lerp() {
|
||||||
int delta_x = endvalue.x - startvalue.y;
|
int delta_x = endvalue.x - startvalue.y;
|
||||||
int delta_y = endvalue.y - startvalue.y;
|
int delta_y = endvalue.y - startvalue.y;
|
||||||
target->x = startvalue.x + (elapsed / duration * delta_x);
|
((sf::Vector2i*)target)->x = startvalue.x + (elapsed / duration * delta_x);
|
||||||
target->y = startvalue.y + (elapsed / duration * delta_y);
|
((sf::Vector2i*)target)->y = startvalue.y + (elapsed / duration * delta_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Animation<T>::step(float delta)
|
void LerpAnimation<T>::step(float delta) {
|
||||||
|
elapsed += delta;
|
||||||
|
lerp();
|
||||||
|
if (isDone()) cancel(); //use the exact value, not my math
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void DiscreteAnimation<T>::step(float delta)
|
||||||
{
|
{
|
||||||
if (index == -1) {
|
nonelapsed += delta;
|
||||||
// lerp function
|
if (nonelapsed < timestep) return;
|
||||||
elapsed += delta;
|
if (index == values.size() - 1) return;
|
||||||
lerp();
|
elapsed += nonelapsed; // or should it be += timestep?
|
||||||
}
|
nonelapsed = 0; // or should it -= timestep?
|
||||||
else {
|
index++;
|
||||||
nonelapsed += delta;
|
*target = values[index];
|
||||||
if (nonelapsed < timestep) return;
|
if (isDone()) cancel(); //use the exact value, not my math
|
||||||
if (index == values.size() - 1) return;
|
|
||||||
elapsed += nonelapsed; // or should it be += timestep?
|
|
||||||
nonelapsed = 0; // or should it -= timestep?
|
|
||||||
index++;
|
|
||||||
*target = values[index];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Animation<T>::cancel() {
|
void LerpAnimation<T>::cancel() {
|
||||||
if (index == -1)
|
*target = endvalue;
|
||||||
*target = endvalue;
|
}
|
||||||
else
|
|
||||||
*target = values[values.size() - 1];
|
template<typename T>
|
||||||
|
void DiscreteAnimation<T>::cancel() {
|
||||||
|
*target = values[values.size() - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Animation::isDone() {
|
||||||
|
return elapsed + Animation::EPSILON >= duration;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,44 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class Animation
|
class Animation
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
static constexpr float EPSILON = 0.05;
|
static constexpr float EPSILON = 0.05;
|
||||||
T startvalue, endvalue;
|
float duration, elapsed;
|
||||||
int index;
|
void* target;
|
||||||
float duration, elapsed, nonelapsed, timestep;
|
|
||||||
T* target;
|
|
||||||
std::vector<T> values;
|
|
||||||
std::function<void()> callback;
|
std::function<void()> callback;
|
||||||
bool loop;
|
bool loop;
|
||||||
public:
|
public:
|
||||||
Animation(float, T, T*, std::function<void()>, bool); // lerp
|
//Animation(float, T, T*, std::function<void()>, bool); // lerp
|
||||||
Animation(float, std::vector<T>, T*, std::function<void()>, bool); // discrete
|
//Animation(float, std::vector<T>, T*, std::function<void()>, bool); // discrete
|
||||||
~Animation();
|
Animation(float, void*, std::function<void()>, bool);
|
||||||
void lerp();
|
virtual void step(float) = 0;
|
||||||
void step(float);
|
virtual void cancel() = 0;
|
||||||
void cancel();
|
|
||||||
bool isDone();
|
bool isDone();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class LerpAnimation: public Animation
|
||||||
|
{
|
||||||
|
T startvalue, endvalue;
|
||||||
|
void lerp();
|
||||||
|
public:
|
||||||
|
~LerpAnimation() { cancel(); }
|
||||||
|
LerpAnimation(float, T, T*, std::function<void()>, bool);
|
||||||
|
void step(float) override final;
|
||||||
|
void cancel() override final;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class DiscreteAnimation: public Animation
|
||||||
|
{
|
||||||
|
std::vector<T> values;
|
||||||
|
float nonelapsed, timestep;
|
||||||
|
int index;
|
||||||
|
public:
|
||||||
|
DiscreteAnimation(float, std::vector<T>, T*, std::function<void()>, bool);
|
||||||
|
~DiscreteAnimation() { cancel(); }
|
||||||
|
void step(float) override final;
|
||||||
|
void cancel() override final;
|
||||||
|
};
|
||||||
|
|
|
@ -27,6 +27,8 @@ GameEngine::GameEngine()
|
||||||
scenes["py"] = new PythonScene(this, "TestScene");
|
scenes["py"] = new PythonScene(this, "TestScene");
|
||||||
|
|
||||||
IndexSprite::game = this;
|
IndexSprite::game = this;
|
||||||
|
|
||||||
|
clock.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
Scene* GameEngine::currentScene() { return scenes[scene]; }
|
Scene* GameEngine::currentScene() { return scenes[scene]; }
|
||||||
|
@ -38,6 +40,7 @@ sf::RenderWindow & GameEngine::getWindow() { return window; }
|
||||||
|
|
||||||
void GameEngine::run()
|
void GameEngine::run()
|
||||||
{
|
{
|
||||||
|
clock.restart();
|
||||||
while (running)
|
while (running)
|
||||||
{
|
{
|
||||||
currentScene()->update();
|
currentScene()->update();
|
||||||
|
@ -47,6 +50,7 @@ void GameEngine::run()
|
||||||
}
|
}
|
||||||
currentScene()->sRender();
|
currentScene()->sRender();
|
||||||
currentFrame++;
|
currentFrame++;
|
||||||
|
frameTime = clock.restart().asSeconds();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,8 @@ class GameEngine
|
||||||
bool paused = false;
|
bool paused = false;
|
||||||
int currentFrame = 0;
|
int currentFrame = 0;
|
||||||
sf::View visible;
|
sf::View visible;
|
||||||
|
sf::Clock clock;
|
||||||
|
float frameTime;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GameEngine();
|
GameEngine();
|
||||||
|
@ -29,6 +31,7 @@ public:
|
||||||
void run();
|
void run();
|
||||||
void sUserInput();
|
void sUserInput();
|
||||||
int getFrame() { return currentFrame; }
|
int getFrame() { return currentFrame; }
|
||||||
|
float getFrameTime() { return frameTime; }
|
||||||
sf::View getView() { return visible; }
|
sf::View getView() { return visible; }
|
||||||
|
|
||||||
// global textures for scripts to access
|
// global textures for scripts to access
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
std::map<std::string, UIMenu*> McRFPy_API::menus;
|
std::map<std::string, UIMenu*> McRFPy_API::menus;
|
||||||
std::map<std::string, Grid*> McRFPy_API::grids;
|
std::map<std::string, Grid*> McRFPy_API::grids;
|
||||||
std::map<std::string, PyObject*> McRFPy_API::callbacks;
|
std::map<std::string, PyObject*> McRFPy_API::callbacks;
|
||||||
|
std::list<Animation*> McRFPy_API::animations;
|
||||||
|
|
||||||
EntityManager McRFPy_API::entities;
|
EntityManager McRFPy_API::entities;
|
||||||
|
|
||||||
static PyMethodDef mcrfpyMethods[] = {
|
static PyMethodDef mcrfpyMethods[] = {
|
||||||
|
@ -46,6 +48,18 @@ static PyMethodDef mcrfpyMethods[] = {
|
||||||
{"modGrid", McRFPy_API::_modGrid, METH_VARARGS,
|
{"modGrid", McRFPy_API::_modGrid, METH_VARARGS,
|
||||||
"call with a Grid object to update all fields"},
|
"call with a Grid object to update all fields"},
|
||||||
|
|
||||||
|
{"createAnimation", McRFPy_API::_createAnimation, METH_VARARGS,
|
||||||
|
"Create a new animation:\n"
|
||||||
|
"createAnimation(duration:float, parent:string, target_type:string, target_id:string or int, field:string, callback:function, loop:bool, frames:list)\n"
|
||||||
|
"duration: total animation time in seconds\n"
|
||||||
|
"parent: the name of a UI menu or grid\n"
|
||||||
|
"target_type: 'caption', 'button', 'sprite', or 'entity'\n"
|
||||||
|
"target_id: integer index of the caption or button, or string ID of entity\n"
|
||||||
|
"field: what to animate. 'position', 'size', 'bgcolor', 'textcolor' or 'sprite'\n"
|
||||||
|
"callback: called when the animation completes\n"
|
||||||
|
"loop: if True, animation repeats; if False, animation is deleted\n"
|
||||||
|
"frames: if animating a sprite, list the frames. For other data types, the value will change in discrete steps at a rate of duration/len(frames).\n"},
|
||||||
|
|
||||||
{NULL, NULL, 0, NULL}
|
{NULL, NULL, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ public:
|
||||||
static std::map<std::string, UIMenu*> menus;
|
static std::map<std::string, UIMenu*> menus;
|
||||||
static EntityManager entities; // this is also kinda good, entities not on the current grid can still act (like monsters following you through doors??)
|
static EntityManager entities; // this is also kinda good, entities not on the current grid can still act (like monsters following you through doors??)
|
||||||
static std::map<std::string, Grid*> grids;
|
static std::map<std::string, Grid*> grids;
|
||||||
|
static std::list<Animation*> animations;
|
||||||
|
|
||||||
static std::map<std::string, PyObject*> callbacks;
|
static std::map<std::string, PyObject*> callbacks;
|
||||||
|
|
||||||
|
@ -68,6 +69,8 @@ public:
|
||||||
static PyObject* _createGrid(PyObject*, PyObject*);
|
static PyObject* _createGrid(PyObject*, PyObject*);
|
||||||
static PyObject* _listGrids(PyObject*, PyObject*);
|
static PyObject* _listGrids(PyObject*, PyObject*);
|
||||||
static PyObject* _modGrid(PyObject*, PyObject*);
|
static PyObject* _modGrid(PyObject*, PyObject*);
|
||||||
|
|
||||||
|
static PyObject* _createAnimation(PyObject*, PyObject*);
|
||||||
|
|
||||||
static PyObject* _registerPyAction(PyObject*, PyObject*);
|
static PyObject* _registerPyAction(PyObject*, PyObject*);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "PythonScene.h"
|
#include "PythonScene.h"
|
||||||
#include "ActionCode.h"
|
#include "ActionCode.h"
|
||||||
#include "McRFPy_API.h"
|
#include "McRFPy_API.h"
|
||||||
|
#include "Animation.h"
|
||||||
|
|
||||||
PythonScene::PythonScene(GameEngine* g, std::string pymodule)
|
PythonScene::PythonScene(GameEngine* g, std::string pymodule)
|
||||||
: Scene(g) {
|
: Scene(g) {
|
||||||
|
@ -42,6 +43,58 @@ PythonScene::PythonScene(GameEngine* g, std::string pymodule)
|
||||||
McRFPy_API::executePyString(pymodule + ".start()");
|
McRFPy_API::executePyString(pymodule + ".start()");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PythonScene::animate() {
|
||||||
|
auto frametime = game->getFrameTime();
|
||||||
|
auto it = McRFPy_API::animations.begin();
|
||||||
|
while (it != animations.end()) {
|
||||||
|
(*it)->step(frametime);
|
||||||
|
if ((*it)->isDone()) {
|
||||||
|
auto prev = it;
|
||||||
|
it++;
|
||||||
|
animations.erase(prev);
|
||||||
|
} else it++;
|
||||||
|
}
|
||||||
|
/* // workin on it
|
||||||
|
for (auto p : animations) {
|
||||||
|
if (p.first == "int") {
|
||||||
|
((Animation<int>)p.second).step(frametime);
|
||||||
|
} else if (p.first == "string") {
|
||||||
|
((Animation<std::string>)p.second).step(frametime);
|
||||||
|
} else if (p.first == "float") {
|
||||||
|
((Animation<float>)p.second).step(frametime);
|
||||||
|
} else if (p.first == "vector2f") {
|
||||||
|
((Animation<sf::Vector2f>)p.second).step(frametime);
|
||||||
|
} else if (p.first == "vector2i") {
|
||||||
|
((Animation<sf::Vector2i>)p.second).step(frametime);
|
||||||
|
} else if (p.first == "color") {
|
||||||
|
((Animation<int>)p.second).step(frametime); // TODO
|
||||||
|
} else {
|
||||||
|
std::cout << "Animation has label " << p.first << "; no type found" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto it = animations.begin();
|
||||||
|
while (it != animations.end()) {
|
||||||
|
bool done = false;
|
||||||
|
if (p.first == "int") {
|
||||||
|
((Animation<int>)p.second).step(frametime);
|
||||||
|
} else if (p.first == "string") {
|
||||||
|
if ((Animation<std::string>)p.second).isDone()
|
||||||
|
delete (Animation<std::string>)p.second
|
||||||
|
} else if (p.first == "float") {
|
||||||
|
((Animation<float>)p.second).step(frametime);
|
||||||
|
} else if (p.first == "vector2f") {
|
||||||
|
((Animation<sf::Vector2f>)p.second).step(frametime);
|
||||||
|
} else if (p.first == "vector2i") {
|
||||||
|
((Animation<sf::Vector2i>)p.second).step(frametime);
|
||||||
|
} else if (p.first == "color") {
|
||||||
|
((Animation<int>)p.second).step(frametime); // TODO
|
||||||
|
if ((*it).second.isDone()) {
|
||||||
|
animations.erase(it++);
|
||||||
|
} else { it++; }
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
void PythonScene::update() {
|
void PythonScene::update() {
|
||||||
McRFPy_API::entities.update();
|
McRFPy_API::entities.update();
|
||||||
|
|
||||||
|
@ -57,6 +110,7 @@ void PythonScene::update() {
|
||||||
mouseprev = mousepos;
|
mouseprev = mousepos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
animate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PythonScene::doLClick(sf::Vector2i mousepos) {
|
void PythonScene::doLClick(sf::Vector2i mousepos) {
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "Scene.h"
|
#include "Scene.h"
|
||||||
#include "GameEngine.h"
|
#include "GameEngine.h"
|
||||||
#include "Grid.h"
|
#include "Grid.h"
|
||||||
|
//#include "Animation.h"
|
||||||
|
//#include <list>
|
||||||
|
|
||||||
class PythonScene: public Scene
|
class PythonScene: public Scene
|
||||||
{
|
{
|
||||||
|
@ -13,6 +15,8 @@ class PythonScene: public Scene
|
||||||
void doLClick(sf::Vector2i);
|
void doLClick(sf::Vector2i);
|
||||||
void doRClick(sf::Vector2i);
|
void doRClick(sf::Vector2i);
|
||||||
void doZoom(sf::Vector2i, int);
|
void doZoom(sf::Vector2i, int);
|
||||||
|
//std::list<Animation*> animations;
|
||||||
|
void animate();
|
||||||
public:
|
public:
|
||||||
PythonScene(GameEngine*, std::string);
|
PythonScene(GameEngine*, std::string);
|
||||||
void update() override final;
|
void update() override final;
|
||||||
|
|
Loading…
Reference in New Issue