#include #include #include #include #include #include "rand.hpp" #include #include #include "components.hpp" #include #include "stats.hpp" #include "simplefsm.hpp" #include "textures.hpp" #include "animation.hpp" using namespace std::chrono_literals; using components::Animation; using TheClock = std::chrono::steady_clock; using TimeDelta = TheClock::duration; using TimePoint = std::chrono::time_point; const TimeDelta MIN_TICK = 200ms; struct AnimationState { Animation anim; TimeDelta wait = 1s; sf::Vector2f scale{1.0, 1.0}; sf::Vector2f pos{0.0, 0.0}; sf::IntRect rect{{0, 0}, {300, 300}}; void step() { anim.step(scale, pos, rect); } void apply(textures::SpriteTexture& st) { animation::apply(anim, *st.sprite, pos); } }; struct AnimationQueue { std::vector active; TimePoint last_tick; TimeDelta wait_for = MIN_TICK; size_t in_queue = 0; size_t chunk = 1000; TimeDelta delta() { return TheClock::now() - last_tick; } void tick() { last_tick = TheClock::now(); } size_t add(Animation& anim, int initial_wait) { active.emplace_back(anim, TheClock::duration(initial_wait)); return active.size() - 1; } AnimationState& get(size_t id) { return active.at(id); } void render() { wait_for = MIN_TICK; auto dt = delta(); for(size_t i = 0; i < chunk; i++) { in_queue++; auto& a = active[in_queue % active.size()]; if(!a.anim.playing) continue; if(a.wait < wait_for) { wait_for = a.wait; } if(a.wait < dt) { // fmt::println("play animation: {} total ", active.size()); a.step(); } } } }; TEST_CASE("simple coroutine animation test", "[coro]") { AnimationQueue queue; Animation anim; anim.play(); for(int i = 0; i < 100; i++) { int time = Random::uniform(16, 32); size_t id = queue.add(anim, time); auto& what = queue.get(id); REQUIRE(what.wait == TheClock::duration(time)); } dbc::check(queue.active.size() > 0, "zero size queue after adding is impossible."); queue.tick(); Stats stats; for(int i = 0; i < 10000; i++) { auto start = stats.time_start(); auto delta = queue.delta(); queue.render(); if(delta > queue.wait_for) { queue.add(anim, Random::uniform(100, 5000)); queue.tick(); } stats.sample_time(start); } fmt::print("stdev: {}, mean: {}\r", stats.stddev(), stats.mean()); }