First idea for the new animation api.
This commit is contained in:
parent
acadf3ca31
commit
7d08e60537
1 changed files with 141 additions and 63 deletions
|
|
@ -10,63 +10,137 @@ using namespace components;
|
||||||
using namespace textures;
|
using namespace textures;
|
||||||
|
|
||||||
struct Sheet {
|
struct Sheet {
|
||||||
std::string texture_name;
|
int width{0};
|
||||||
int width;
|
int height{0};
|
||||||
int height;
|
int frame_width{0};
|
||||||
int frame_width;
|
int frame_height{0};
|
||||||
int frame_height;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Sequence {
|
struct Sequence {
|
||||||
size_t current_frame;
|
std::vector<size_t> frames{};
|
||||||
float subframe;
|
std::vector<float> durations{};
|
||||||
std::vector<size_t> frames;
|
size_t current{0};
|
||||||
std::vector<float> durations;
|
int loop_count{0};
|
||||||
|
size_t frame_count{frames.size()};
|
||||||
|
sf::Clock timer{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Transform {
|
struct Transform {
|
||||||
// how to know when a transform ends?
|
// how to know when a transform ends?
|
||||||
float min_x = 1.0f;
|
float min_x{1.0f};
|
||||||
float min_y = 1.0f;
|
float min_y{1.0f};
|
||||||
float max_x = 1.0f;
|
float max_x{1.0f};
|
||||||
float max_y = 1.0f;
|
float max_y{1.0f};
|
||||||
bool simple = true;
|
bool simple{true};
|
||||||
bool flipped = false;
|
bool flipped{false};
|
||||||
float ease_rate = 0.5f;
|
float ease_rate{0.5f};
|
||||||
bool scaled = false;
|
bool scaled{false};
|
||||||
bool stationary = false;
|
bool stationary{false};
|
||||||
// these can handled by the onLoop, same as ganim8 does it
|
// these can handled by the onLoop, same as ganim8 does it
|
||||||
bool toggled = false;
|
bool toggled{false};
|
||||||
bool looped = false;
|
bool looped{false};
|
||||||
|
|
||||||
std::shared_ptr<sf::Shader> shader = nullptr;
|
std::shared_ptr<sf::Shader> shader{nullptr};
|
||||||
// change to using a callback function for these
|
// change to using a callback function for these
|
||||||
ease::Style easing = ease::IN_OUT_BACK;
|
ease::Style easing = ease::IN_OUT_BACK;
|
||||||
ease::Motion motion = ease::RUSH;
|
ease::Motion motion = ease::RUSH;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Gets the number of times it looped, and returns if it should stop. */
|
/* Gets the number of times it looped, and returns if it should stop. */
|
||||||
using OnLoopHandler = std::function<bool(int)>;
|
using OnLoopHandler = std::function<bool(Sequence& seq, Transform& tr)>;
|
||||||
|
|
||||||
|
bool DefaultOnLoop(Sequence& seq, Transform& tr) {
|
||||||
|
seq.current = 0;
|
||||||
|
return tr.looped;
|
||||||
|
}
|
||||||
|
|
||||||
class Animate2 {
|
class Animate2 {
|
||||||
public:
|
public:
|
||||||
Sheet& $sheet;
|
Sheet $sheet;
|
||||||
Sequence $sequence;
|
Sequence $sequence;
|
||||||
Transform $transform;
|
Transform $transform;
|
||||||
std::shared_ptr<sf::Sprite> $sprite = nullptr;
|
OnLoopHandler onLoop = DefaultOnLoop;
|
||||||
std::shared_ptr<sf::Texture> $texture = nullptr;
|
bool playing = false;
|
||||||
|
|
||||||
Animate2(Sheet sheet, Sequence seq, Transform trans) :
|
void play() {
|
||||||
$sheet(sheet), $sequence(seq), $transform(trans)
|
dbc::check(!playing, "can't call play while playing?");
|
||||||
{
|
$sequence.current = 0;
|
||||||
auto st = textures::get_sprite($sheet.texture_name);
|
$sequence.loop_count = 0;
|
||||||
$sprite = st.sprite;
|
playing = true;
|
||||||
$texture = st.texture;
|
$sequence.timer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
OnLoopHandler onLoop = nullptr;
|
void stop() {
|
||||||
|
playing = false;
|
||||||
|
$sequence.timer.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// need one for each kind of thing to animate
|
||||||
|
void apply(sf::Sprite& sprite, sf::Vector2f pos) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// replaces step
|
||||||
|
void update() {
|
||||||
|
dbc::check(playing, "attempt to update animation that's not playing");
|
||||||
|
dbc::check($sequence.frame_count == $sequence.frames.size(), "frame_count doesn't match frame.size()");
|
||||||
|
|
||||||
|
auto secs = $sequence.timer.getElapsedTime().asSeconds();
|
||||||
|
auto duration = $sequence.durations[$sequence.current];
|
||||||
|
|
||||||
|
if(secs >= duration) {
|
||||||
|
$sequence.timer.restart();
|
||||||
|
$sequence.current++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($sequence.current >= $sequence.frame_count) {
|
||||||
|
$sequence.loop_count++;
|
||||||
|
playing = onLoop($sequence, $transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbc::check($sequence.current < $sequence.frame_count, "current frame out of frames.size()");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Animate2 crafter() {
|
||||||
|
Sheet sheet{
|
||||||
|
.width{720*2},
|
||||||
|
.height{720},
|
||||||
|
.frame_width{720},
|
||||||
|
.frame_height{720},
|
||||||
|
};
|
||||||
|
|
||||||
|
Sequence sequence{
|
||||||
|
.frames{0,1},
|
||||||
|
.durations{0.01f,0.03f}
|
||||||
|
};
|
||||||
|
|
||||||
|
REQUIRE(sequence.frame_count == sequence.frames.size());
|
||||||
|
REQUIRE(sequence.frame_count == sequence.durations.size());
|
||||||
|
|
||||||
|
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},
|
||||||
|
};
|
||||||
|
|
||||||
|
return {sheet, sequence, transform};
|
||||||
|
}
|
||||||
|
|
||||||
|
void PLAY_TEST(Animate2 &anim) {
|
||||||
|
anim.play();
|
||||||
|
while(anim.playing) {
|
||||||
|
anim.update();
|
||||||
|
}
|
||||||
|
REQUIRE(anim.playing == false);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Animation is a Sheet + Sequence + Transform.
|
* Animation is a Sheet + Sequence + Transform.
|
||||||
|
|
@ -82,42 +156,46 @@ class Animate2 {
|
||||||
TEST_CASE("new animation system", "[animation-new]") {
|
TEST_CASE("new animation system", "[animation-new]") {
|
||||||
textures::init();
|
textures::init();
|
||||||
|
|
||||||
Sheet sheet{
|
auto anim = crafter();
|
||||||
.texture_name{"rat_king_boss"},
|
PLAY_TEST(anim);
|
||||||
.width{720*2},
|
|
||||||
.height{720},
|
bool onLoop_ran = false;
|
||||||
.frame_width{720},
|
anim.onLoop = [&](auto& seq, auto &tr) -> bool {
|
||||||
.frame_height{720},
|
seq.current = 0;
|
||||||
|
onLoop_ran = true;
|
||||||
|
return tr.looped;
|
||||||
};
|
};
|
||||||
|
|
||||||
Sequence sequence{
|
PLAY_TEST(anim);
|
||||||
.current_frame{0},
|
REQUIRE(onLoop_ran == true);
|
||||||
.subframe{0.0f},
|
|
||||||
.frames{0,1},
|
// only runs twice
|
||||||
.durations{0.1f,0.1f},
|
anim.onLoop = [](auto &seq, auto &tr) -> bool {
|
||||||
|
if(seq.loop_count == 2) {
|
||||||
|
seq.current = 0;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
seq.current = seq.current % seq.frame_count;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Transform transform{
|
PLAY_TEST(anim);
|
||||||
.min_x{1.0f},
|
REQUIRE(anim.$sequence.loop_count == 2);
|
||||||
.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};
|
// stops at end
|
||||||
anim.onLoop = [](int loop_count) -> bool {
|
anim.onLoop = [](auto &seq, auto &tr) -> bool {
|
||||||
return loop_count < 2;
|
if(seq.loop_count == 1) {
|
||||||
|
seq.current = seq.frame_count - 1;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("animation easing tests", "[animation]") {
|
TEST_CASE("animation easing tests", "[animation]") {
|
||||||
Animation anim;
|
Animation anim;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue