#include #include "graphics/textures.hpp" #include "algos/dinkyecs.hpp" #include "game/config.hpp" #include #include #include #include #include "algos/rand.hpp" #include "graphics/animation.hpp" #include "game/sound.hpp" #include "game/components.hpp" using namespace components; using namespace textures; using namespace std::chrono_literals; using namespace animation; Animation load_animation(const string& name) { auto anim = animation::load("assets/animation.json", "rat_king_boss"); anim.set_form("attack"); anim.transform.looped = false; for(size_t i = 0; i < anim.sequence.durations.size(); i++) { anim.sequence.durations[i] = Random::uniform(1, 5); } return anim; } void FAKE_RENDER() { std::this_thread::sleep_for(Random::milliseconds(5, 32)); } void PLAY_TEST(Animation &anim) { REQUIRE(anim.transform.looped == false); anim.play(); while(anim.playing) { anim.update(); FAKE_RENDER(); } REQUIRE(anim.playing == false); } // /* // * 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(); // sound::init(); // sound::mute(true); // // auto anim = load_animation("rat_king_boss"); // PLAY_TEST(anim); // // // test that toggled works // anim.transform.toggled = true; // PLAY_TEST(anim); // REQUIRE(anim.sequence.current == anim.sequence.frames.size() - 1); // anim.transform.toggled = false; // // bool onLoop_ran = false; // anim.onLoop = [&](auto& seq, auto& tr) -> bool { // seq.current = 0; // onLoop_ran = true; // return tr.looped; // }; // // 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; // } // }; // // PLAY_TEST(anim); // REQUIRE(anim.sequence.loop_count == 2); // } // // // TEST_CASE("confirm frame sequencing works", "[animation-new]") { // textures::init(); // sound::init(); // sound::mute(true); // // auto anim = load_animation("rat_king_boss"); // // auto boss = textures::get_sprite("rat_king_boss"); // sf::IntRect init_rect{{0,0}, {anim.sheet.frame_width, anim.sheet.frame_height}}; // // anim.play(); // bool loop_ran = false; // // // this will check that it moved to the next frame // anim.onLoop = [&](auto& seq, auto& tr) -> bool { // seq.current = 0; // loop_ran = true; // return false; // }; // // anim.onFrame = [&](){ // anim.apply(*boss.sprite); // }; // // while(anim.playing) { // anim.update(); // FAKE_RENDER(); // } // // REQUIRE(loop_ran == true); // REQUIRE(anim.playing == false); // } // // TEST_CASE("confirm transition changes work", "[animation-new]") { // textures::init(); // sound::init(); // sound::mute(true); // // auto sprite = *textures::get_sprite("rat_king_boss").sprite; // sf::Vector2f pos{100,100}; // sprite.setPosition(pos); // auto scale = sprite.getScale(); // auto anim = load_animation("rat_king_boss"); // // // also testing that onFrame being null means it's not run // REQUIRE(anim.onFrame == nullptr); // // anim.play(); // REQUIRE(anim.playing == true); // // while(anim.playing) { // anim.update(); // anim.motion(sprite, pos, scale); // FAKE_RENDER(); // } // // REQUIRE(anim.playing == false); // REQUIRE(pos == sf::Vector2f{100, 100}); // REQUIRE(scale != sf::Vector2f{0,0}); // } TEST_CASE("playing with delta time", "[animation-new]") { animation::Timer timer; timer.start(); for(int i = 0; i < 20; i++) { FAKE_RENDER(); auto [tick_count, alpha] = timer.commit(); // fmt::println("tick: {}, alpha: {}", tick_count, alpha); } }