diff --git a/tests/animation.cpp b/tests/animation.cpp index 9d197d8..2ce30be 100644 --- a/tests/animation.cpp +++ b/tests/animation.cpp @@ -10,63 +10,137 @@ using namespace components; using namespace textures; struct Sheet { - std::string texture_name; - int width; - int height; - int frame_width; - int frame_height; + int width{0}; + int height{0}; + int frame_width{0}; + int frame_height{0}; }; struct Sequence { - size_t current_frame; - float subframe; - std::vector frames; - std::vector durations; + std::vector frames{}; + std::vector durations{}; + size_t current{0}; + int loop_count{0}; + size_t frame_count{frames.size()}; + sf::Clock timer{}; }; 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; + 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 shader = nullptr; - // change to using a callback function for these - ease::Style easing = ease::IN_OUT_BACK; - ease::Motion motion = ease::RUSH; + std::shared_ptr 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; +using OnLoopHandler = std::function; + +bool DefaultOnLoop(Sequence& seq, Transform& tr) { + seq.current = 0; + return tr.looped; +} class Animate2 { public: - Sheet& $sheet; + Sheet $sheet; Sequence $sequence; Transform $transform; - std::shared_ptr $sprite = nullptr; - std::shared_ptr $texture = nullptr; + OnLoopHandler onLoop = DefaultOnLoop; + bool playing = false; - 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; + void play() { + dbc::check(!playing, "can't call play while playing?"); + $sequence.current = 0; + $sequence.loop_count = 0; + playing = true; + $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. @@ -82,42 +156,46 @@ class Animate2 { 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}, + auto anim = crafter(); + PLAY_TEST(anim); + + bool onLoop_ran = false; + anim.onLoop = [&](auto& seq, auto &tr) -> bool { + seq.current = 0; + onLoop_ran = true; + return tr.looped; }; - Sequence sequence{ - .current_frame{0}, - .subframe{0.0f}, - .frames{0,1}, - .durations{0.1f,0.1f}, + PLAY_TEST(anim); + REQUIRE(onLoop_ran == true); + + // only runs twice + 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{ - .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}, - }; + PLAY_TEST(anim); + REQUIRE(anim.$sequence.loop_count == 2); - Animate2 anim{sheet, sequence, transform}; - anim.onLoop = [](int loop_count) -> bool { - return loop_count < 2; + // stops at end + anim.onLoop = [](auto &seq, auto &tr) -> bool { + if(seq.loop_count == 1) { + seq.current = seq.frame_count - 1; + return false; + } else { + return true; + } }; } + TEST_CASE("animation easing tests", "[animation]") { Animation anim;