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 {
std::random_device 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
#include <random>
#include <chrono>
namespace Random {
@ -25,4 +26,6 @@ namespace Random {
return rand(GENERATOR);
}
std::chrono::milliseconds milliseconds(int from, int to);
}

View file

@ -5,9 +5,13 @@
#include "config.hpp"
#include <iostream>
#include <memory>
#include <chrono>
#include <thread>
#include "rand.hpp"
using namespace components;
using namespace textures;
using namespace std::chrono_literals;
struct Sheet {
int width{0};
@ -18,7 +22,7 @@ struct Sheet {
struct Sequence {
std::vector<size_t> frames{};
std::vector<float> durations{};
std::vector<std::chrono::milliseconds> durations{};
size_t current{0};
int loop_count{0};
size_t frame_count{frames.size()};
@ -80,14 +84,13 @@ class Animate2 {
}
// replaces step
void update() {
void update_frame() {
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) {
if($sequence.timer.getElapsedTime() >= duration) {
$sequence.timer.restart();
$sequence.current++;
}
@ -99,6 +102,10 @@ class Animate2 {
dbc::check($sequence.current < $sequence.frame_count, "current frame out of frames.size()");
}
void update() {
update_frame();
}
};
Animate2 crafter() {
@ -111,7 +118,7 @@ Animate2 crafter() {
Sequence sequence{
.frames{0,1},
.durations{0.01f,0.03f}
.durations{Random::milliseconds(1, 100), Random::milliseconds(1, 100)}
};
REQUIRE(sequence.frame_count == sequence.frames.size());
@ -136,9 +143,12 @@ Animate2 crafter() {
void PLAY_TEST(Animate2 &anim) {
anim.play();
while(anim.playing) {
anim.update();
std::this_thread::sleep_for(Random::milliseconds(1, 100));
}
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();
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]") {
Animation anim;

View file

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