117 lines
2.5 KiB
C++
117 lines
2.5 KiB
C++
#include <catch2/catch_test_macros.hpp>
|
|
#include <fmt/core.h>
|
|
#include <string>
|
|
#include <coroutine>
|
|
#include <chrono>
|
|
#include "rand.hpp"
|
|
#include <thread>
|
|
#include <vector>
|
|
#include "components.hpp"
|
|
#include <iostream>
|
|
#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<TheClock>;
|
|
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<AnimationState> 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());
|
|
}
|