159 lines
3.8 KiB
C++
159 lines
3.8 KiB
C++
#include <catch2/catch_test_macros.hpp>
|
|
#include "animation.hpp"
|
|
#include "textures.hpp"
|
|
#include "dinkyecs.hpp"
|
|
#include "config.hpp"
|
|
#include <iostream>
|
|
#include <memory>
|
|
|
|
using namespace components;
|
|
using namespace textures;
|
|
|
|
struct Sheet {
|
|
std::string texture_name;
|
|
int width;
|
|
int height;
|
|
int frame_width;
|
|
int frame_height;
|
|
};
|
|
|
|
struct Sequence {
|
|
size_t current_frame;
|
|
float subframe;
|
|
std::vector<size_t> frames;
|
|
std::vector<float> durations;
|
|
};
|
|
|
|
struct Transform {
|
|
// how to know when a transform ends?
|
|
float min_x = 1.0f;
|
|
float min_y = 1.0f;
|
|
float max_x = 1.0f;
|
|
float max_y = 1.0f;
|
|
bool simple = true;
|
|
bool flipped = false;
|
|
float ease_rate = 0.5f;
|
|
bool scaled = false;
|
|
bool stationary = false;
|
|
// these can handled by the onLoop, same as ganim8 does it
|
|
bool toggled = false;
|
|
bool looped = false;
|
|
|
|
std::shared_ptr<sf::Shader> shader = nullptr;
|
|
// change to using a callback function for these
|
|
ease::Style easing = ease::IN_OUT_BACK;
|
|
ease::Motion motion = ease::RUSH;
|
|
};
|
|
|
|
/* Gets the number of times it looped, and returns if it should stop. */
|
|
using OnLoopHandler = std::function<bool(int)>;
|
|
|
|
class Animate2 {
|
|
public:
|
|
Sheet& $sheet;
|
|
Sequence $sequence;
|
|
Transform $transform;
|
|
std::shared_ptr<sf::Sprite> $sprite = nullptr;
|
|
std::shared_ptr<sf::Texture> $texture = nullptr;
|
|
|
|
Animate2(Sheet sheet, Sequence seq, Transform trans) :
|
|
$sheet(sheet), $sequence(seq), $transform(trans)
|
|
{
|
|
auto st = textures::get_sprite($sheet.texture_name);
|
|
$sprite = st.sprite;
|
|
$texture = st.texture;
|
|
}
|
|
|
|
OnLoopHandler onLoop = nullptr;
|
|
};
|
|
|
|
|
|
/*
|
|
* Animation is a Sheet + Sequence + Transform.
|
|
*
|
|
* A Sheet is just a grid of images with a predefined size for each cell. Arbitrary sized cells not supported.
|
|
*
|
|
* A Sequence is a list of Sheet cells _in any order_. See https://github.com/yottahmd/ganim8-lib. Sequences have a timing element for the cells, possibly a list of durations or a single duration.
|
|
*
|
|
* A Transform is combinations of scale and/or position easing/motion, shader effects, and things like if it's looped or toggled.
|
|
*
|
|
* I like the ganim8 onLoop concept, just a callback that says what to do when the animation has looped.
|
|
*/
|
|
TEST_CASE("new animation system", "[animation-new]") {
|
|
textures::init();
|
|
|
|
Sheet sheet{
|
|
.texture_name{"rat_king_boss"},
|
|
.width{720*2},
|
|
.height{720},
|
|
.frame_width{720},
|
|
.frame_height{720},
|
|
};
|
|
|
|
Sequence sequence{
|
|
.current_frame{0},
|
|
.subframe{0.0f},
|
|
.frames{0,1},
|
|
.durations{0.1f,0.1f},
|
|
};
|
|
|
|
Transform transform{
|
|
.min_x{1.0f},
|
|
.min_y{1.0f},
|
|
.max_x{1.0f},
|
|
.max_y{1.0f},
|
|
.simple{true},
|
|
.flipped{false},
|
|
.ease_rate{0.5f},
|
|
.scaled{false},
|
|
.stationary{false},
|
|
.toggled{false},
|
|
.looped{false},
|
|
};
|
|
|
|
Animate2 anim{sheet, sequence, transform};
|
|
anim.onLoop = [](int loop_count) -> bool {
|
|
return loop_count < 2;
|
|
};
|
|
}
|
|
|
|
|
|
TEST_CASE("animation easing tests", "[animation]") {
|
|
Animation anim;
|
|
|
|
anim.easing = ease::NONE;
|
|
float res = anim.twitching();
|
|
REQUIRE(res == 0.0);
|
|
|
|
anim.easing = ease::SINE;
|
|
anim.subframe = 1.0f;
|
|
res = anim.twitching();
|
|
REQUIRE(!std::isnan(res));
|
|
|
|
anim.easing = ease::OUT_CIRC;
|
|
res = anim.twitching();
|
|
REQUIRE(!std::isnan(res));
|
|
|
|
anim.easing = ease::OUT_BOUNCE;
|
|
res = anim.twitching();
|
|
REQUIRE(!std::isnan(res));
|
|
|
|
anim.easing = ease::IN_OUT_BACK;
|
|
res = anim.twitching();
|
|
REQUIRE(!std::isnan(res));
|
|
}
|
|
|
|
|
|
TEST_CASE("animation utility API", "[animation]") {
|
|
textures::init();
|
|
animation::init();
|
|
|
|
auto blanket = textures::get_sprite("ritual_crafting_area");
|
|
auto anim = animation::load("ritual_crafting_area");
|
|
|
|
anim.play();
|
|
|
|
while(anim.apply(*blanket.sprite, {0,0})) {
|
|
fmt::println("animation: {}", anim.subframe);
|
|
}
|
|
}
|