Now have a timer for animations that does ticks with deltatime...maybe it works.

This commit is contained in:
Zed A. Shaw 2026-01-27 12:52:33 -05:00
parent c0f69ed026
commit b7394f832d
5 changed files with 121 additions and 6 deletions

View file

@ -76,6 +76,38 @@ namespace animate2 {
$transform.lerp($sequence, pos, scale);
}
void Timer::start() {
clock.start();
}
void Timer::reset() {
clock.reset();
}
void Timer::restart() {
clock.restart();
}
sf::Time Timer::getElapsedTime() {
return clock.getElapsedTime();
}
void Timer::begin() {
prev_time = clock.getElapsedTime().asSeconds();
}
std::pair<int, double> Timer::commit() {
current_time = clock.getElapsedTime().asSeconds();
frame_duration = current_time - prev_time;
accumulator += frame_duration;
double tick_count = accumulator / DELTA;
double alpha = modf(tick_count, &tick_count);
accumulator -= tick_count * DELTA;
return {int(tick_count), alpha};
}
float Transform::twitching(Sequence& seq) {
float tick = 1 - std::powf(ease_rate, seq.subframe + 0.0001);
return easing(tick);

View file

@ -7,6 +7,7 @@
#include <SFML/System/Time.hpp>
#include <functional>
#include "ease2.hpp"
#include <fmt/core.h>
namespace animate2 {
struct Sheet {
@ -16,13 +17,30 @@ namespace animate2 {
int frame_height{0};
};
struct Timer {
double DELTA = 1.0/60.0;
double accumulator = 0.0;
double prev_time = 0.0;
double current_time = 0.0;
double frame_duration = 0.0;
double alpha = 0.0;
sf::Clock clock{};
void begin();
std::pair<int, double> commit();
void start();
void reset();
void restart();
sf::Time getElapsedTime();
};
struct Sequence {
std::vector<int> frames{};
std::vector<std::chrono::milliseconds> durations{};
size_t current{0};
int loop_count{0};
size_t frame_count{frames.size()};
sf::Clock timer{};
Timer timer{};
float subframe{0.0f};
};

View file

@ -5,7 +5,7 @@
#ifndef FSM_DEBUG
#define FSM_STATE(C, S, E, ...) case C::S: S(E, ##__VA_ARGS__); break
#else
int last_event=-1;
static int last_event=-1;
#define FSM_STATE(C, S, E, ...) case C::S: if(last_event != int(E)) { last_event = int(E); fmt::println(">> " #C " " #S " event={}, state={}", int(E), int($state));}; S(E, ##__VA_ARGS__); break
#endif

View file

@ -51,12 +51,16 @@ Animate2 crafter() {
return {sheet, sequence, transform};
}
void FAKE_RENDER() {
std::this_thread::sleep_for(Random::milliseconds(5, 32));
}
void PLAY_TEST(Animate2 &anim) {
anim.play();
while(anim.playing) {
anim.update();
std::this_thread::sleep_for(Random::milliseconds(1, 100));
FAKE_RENDER();
}
REQUIRE(anim.playing == false);
@ -114,6 +118,7 @@ TEST_CASE("new animation system", "[animation-new]") {
};
}
TEST_CASE("confirm frame sequencing works", "[animation-new]") {
textures::init();
animation::init();
@ -165,15 +170,37 @@ TEST_CASE("confirm transition changes work", "[animation-new]") {
anim.play();
sf::Clock clock;
clock.start();
sf::Time start;
sf::Time delta;
while(anim.playing) {
start = clock.getElapsedTime();
anim.update();
anim.motion(pos, scale);
std::this_thread::sleep_for(10ms);
fmt::println("POSITION: {},{}; SCALE: {},{}; current: {}; subframe: {}",
pos.x, pos.y, scale.x, scale.y, anim.$sequence.current, anim.$sequence.subframe);
delta = clock.getElapsedTime() - start;
fmt::println("FRAME RATE {}", 1.0f / delta.asSeconds());
}
REQUIRE(anim.playing == false);
REQUIRE(pos != sf::Vector2f{0,0});
REQUIRE(scale != sf::Vector2f{0,0});
}
TEST_CASE("playing with delta time", "[animation-new]") {
animate2::Timer timer;
for(int i = 0; i < 20; i++) {
timer.begin();
FAKE_RENDER();
auto [tick_count, alpha] = timer.commit();
fmt::println("tick: {}, alpha: {}", tick_count, alpha);
}
}

View file

@ -1,3 +1,4 @@
#define FSM_DEBUG 1
#include "sound.hpp"
#include "ai.hpp"
#include "animation.hpp"
@ -11,6 +12,9 @@
#include <guecs/ui.hpp>
#include "gui/event_router.hpp"
#include "gui/guecstra.hpp"
#include "animate2.hpp"
bool YES_SYNC=true;
namespace animator {
struct UI {
@ -53,6 +57,7 @@ namespace animator {
enum class State {
START=__LINE__,
ANIMATE=__LINE__,
END=__LINE__,
};
@ -63,20 +68,41 @@ namespace animator {
void init(const std::string &sprite_name) {
$ui.init(sprite_name);
$window.setVerticalSyncEnabled(VSYNC);
if(FRAME_LIMIT) $window.setFramerateLimit(FRAME_LIMIT);
if(YES_SYNC) {
$window.setVerticalSyncEnabled(VSYNC);
if(FRAME_LIMIT) $window.setFramerateLimit(FRAME_LIMIT);
}
$window.setPosition({0,0});
}
void event(game::Event ev, std::any data={}) {
switch($state) {
FSM_STATE(State, START, ev);
FSM_STATE(State, ANIMATE, ev);
FSM_STATE(State, END, ev);
}
}
void START(game::Event ev) {
state(State::START);
switch(ev) {
case game::Event::TICK:
state(State::ANIMATE);
break;
default:
state(State::START);
}
}
void ANIMATE(game::Event ev) {
switch(ev) {
case game::Event::TICK:
// stuff
break;
default:
state(State::START);
}
}
void END(game::Event ev) {
@ -132,8 +158,20 @@ int main(int argc, char* argv[]) {
animator::FSM main;
main.init(argv[1]);
animate2::Timer timer;
timer.start();
while(main.active()) {
timer.begin();
main.render();
auto [ticks, alpha] = timer.commit();
fmt::println("TICK: {}, alpha: {}", ticks, alpha);
for(int i = 0; i < ticks; i++) {
main.event(game::Event::TICK, {});
}
// do something with alpha....
main.handle_keyboard_mouse();
}