Use chrono::duration for animation frame durations.

This commit is contained in:
Zed A. Shaw 2026-01-19 11:50:00 -05:00
parent d81e127686
commit 5b509c277a
4 changed files with 53 additions and 12 deletions

View file

@ -3,4 +3,11 @@
namespace Random { namespace Random {
std::random_device RNG; std::random_device RNG;
std::mt19937 GENERATOR(RNG()); std::mt19937 GENERATOR(RNG());
std::chrono::milliseconds milliseconds(int from, int to) {
int tick = Random::uniform_real(float(from), float(to));
return std::chrono::milliseconds{tick};
}
} }

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <random> #include <random>
#include <chrono>
namespace Random { namespace Random {
@ -25,4 +26,6 @@ namespace Random {
return rand(GENERATOR); return rand(GENERATOR);
} }
std::chrono::milliseconds milliseconds(int from, int to);
} }

View file

@ -5,9 +5,13 @@
#include "config.hpp" #include "config.hpp"
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <chrono>
#include <thread>
#include "rand.hpp"
using namespace components; using namespace components;
using namespace textures; using namespace textures;
using namespace std::chrono_literals;
struct Sheet { struct Sheet {
int width{0}; int width{0};
@ -18,7 +22,7 @@ struct Sheet {
struct Sequence { struct Sequence {
std::vector<size_t> frames{}; std::vector<size_t> frames{};
std::vector<float> durations{}; std::vector<std::chrono::milliseconds> durations{};
size_t current{0}; size_t current{0};
int loop_count{0}; int loop_count{0};
size_t frame_count{frames.size()}; size_t frame_count{frames.size()};
@ -80,14 +84,13 @@ class Animate2 {
} }
// replaces step // replaces step
void update() { void update_frame() {
dbc::check(playing, "attempt to update animation that's not playing"); 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()"); 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]; auto duration = $sequence.durations[$sequence.current];
if(secs >= duration) { if($sequence.timer.getElapsedTime() >= duration) {
$sequence.timer.restart(); $sequence.timer.restart();
$sequence.current++; $sequence.current++;
} }
@ -99,6 +102,10 @@ class Animate2 {
dbc::check($sequence.current < $sequence.frame_count, "current frame out of frames.size()"); dbc::check($sequence.current < $sequence.frame_count, "current frame out of frames.size()");
} }
void update() {
update_frame();
}
}; };
Animate2 crafter() { Animate2 crafter() {
@ -111,7 +118,7 @@ Animate2 crafter() {
Sequence sequence{ Sequence sequence{
.frames{0,1}, .frames{0,1},
.durations{0.01f,0.03f} .durations{Random::milliseconds(1, 100), Random::milliseconds(1, 100)}
}; };
REQUIRE(sequence.frame_count == sequence.frames.size()); REQUIRE(sequence.frame_count == sequence.frames.size());
@ -136,9 +143,12 @@ Animate2 crafter() {
void PLAY_TEST(Animate2 &anim) { void PLAY_TEST(Animate2 &anim) {
anim.play(); anim.play();
while(anim.playing) { while(anim.playing) {
anim.update(); anim.update();
std::this_thread::sleep_for(Random::milliseconds(1, 100));
} }
REQUIRE(anim.playing == false); REQUIRE(anim.playing == false);
} }
@ -194,10 +204,29 @@ TEST_CASE("new animation system", "[animation-new]") {
}; };
} }
TEST_CASE("easing functions in animate2", "[animation-new]") { TEST_CASE("apply animation works", "[animation-new]") {
return;
textures::init();
animation::init();
auto blanket = textures::get_sprite("ritual_crafting_area");
sf::Vector2f pos{0,0};
auto anim = crafter(); auto anim = crafter();
anim.play();
while(anim.playing) {
anim.update();
anim.apply(*blanket.sprite, pos);
}
REQUIRE(anim.playing == false);
REQUIRE(blanket.sprite->getPosition() != sf::Vector2f{0,0});
REQUIRE(pos != sf::Vector2f{0,0});
} }
TEST_CASE("animation easing tests", "[animation]") { TEST_CASE("animation easing tests", "[animation]") {
Animation anim; Animation anim;

View file

@ -10,10 +10,7 @@
#include "constants.hpp" #include "constants.hpp"
#include <guecs/ui.hpp> #include <guecs/ui.hpp>
#include "gui/event_router.hpp" #include "gui/event_router.hpp"
#include <chrono> #include "gui/guecstra.hpp"
#include <thread>
using namespace std::chrono_literals;
namespace animator { namespace animator {
struct UI { struct UI {
@ -22,8 +19,10 @@ namespace animator {
void init(const std::string& sprite_name) { void init(const std::string& sprite_name) {
$ui.position(0,0, SCREEN_WIDTH, SCREEN_HEIGHT); $ui.position(0,0, SCREEN_WIDTH, SCREEN_HEIGHT);
$ui.layout( $ui.layout(
"[*%(100,200)data|*%=(300,200)viewer|_|_]" "[play|*%=(300,400)viewer|_|_]"
"[_|_|_|_]"); "[stop|_|_|_]"
"[next|_|_|_]"
"[prev|_|_|_]");
for(auto& [name, cell] : $ui.cells()) { for(auto& [name, cell] : $ui.cells()) {
auto comp = $ui.entity(name); auto comp = $ui.entity(name);
@ -34,6 +33,9 @@ namespace animator {
$ui.set<guecs::Rectangle>(comp, {}); $ui.set<guecs::Rectangle>(comp, {});
$ui.set<guecs::Text>(comp, {guecs::to_wstring(name)}); $ui.set<guecs::Text>(comp, {guecs::to_wstring(name)});
$ui.set<guecs::Effect>(comp, {}); $ui.set<guecs::Effect>(comp, {});
$ui.set<guecs::Clickable>(comp, {[](auto){
fmt::println("I don't know what to do here.");
}});
} }
} }