From cdd75000effac0216588766234cfa5b3e8e304d5 Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Wed, 8 Nov 2017 12:26:43 +0100 Subject: Frametime-independent dynamics. --- src/common.hpp | 15 ++++++++++----- src/game.cpp | 9 +++++---- src/interface.cpp | 4 ++-- src/main.cpp | 19 ++++++++++++++----- src/render.cpp | 5 +++-- 5 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/common.hpp b/src/common.hpp index f89ae08..df14f6f 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -175,7 +175,7 @@ namespace game { class unit_t; class state_t { - double now; + double now, dt; std::unordered_set units; std::unordered_set selected_units; @@ -185,7 +185,7 @@ namespace game { void start(void); void stop(void); - void tick(double now_); + void tick(double now_, double dt_); // These are called by the interface. void select(rectf_t rect); @@ -213,7 +213,7 @@ namespace interface { public: state_t(sf::RenderWindow *window_, game::state_t *game); - void tick(void); + void tick(double dt); void render_to(render::state_t *render); }; } @@ -264,10 +264,10 @@ namespace render { void drender_text(rectf_t rect, std::string str); void drender_entity(world::entity_t *ent); public: - double now; + double now, dt; state_t(sf::RenderWindow *window_); - void begin_frame(double time_); + void begin_frame(double time_, double dt_); void end_frame(void); void render(game::state_t *game); void render(animated_texture_t *anim, rectf_t bounds, bool mirror = false); @@ -333,3 +333,8 @@ T bilerp(T a, T b, T c, T d, T x, T y) cd = lerp(c, d, x); return lerp(ab, cd, y); } + +static inline float expfade(float a, float b, float l, float dt) +{ + return b + (a - b) * exp(-l * dt); +} diff --git a/src/game.cpp b/src/game.cpp index bfc698d..a3af9ed 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -73,7 +73,7 @@ public: link(world); } - void keep_moving(double now) + void keep_moving(double now, double dt) { float time; @@ -83,7 +83,7 @@ public: if (move.blocked && now < move.next_attempt) return; - time = 0.15; // FIXME + time = dt * 10; while (time > 0.0f) { v2f_t delta, next, x_new; @@ -241,12 +241,13 @@ void state_t::command(v2f_t x) unit->start_moving(x, now); } -void state_t::tick(double now_) +void state_t::tick(double now_, double dt_) { now = now_; + dt = dt_; for (unit_t *unit : units) - unit->keep_moving(now); + unit->keep_moving(now, dt); } } //namespace game diff --git a/src/interface.cpp b/src/interface.cpp index 11e297e..3a6a294 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -15,7 +15,7 @@ static sf::Vector2f compute_pan(sf::RenderWindow *window, sf::Vector2f pan_ref) return -(vmouse - pan_ref); } -void state_t::tick(void) +void state_t::tick(double dt) { sf::Vector2u size; sf::Event event; @@ -24,7 +24,7 @@ void state_t::tick(void) size = window->getSize(); - camera.zoom = (camera.zoom + camera.target_zoom) / 2; + camera.zoom = expfade(camera.zoom, camera.target_zoom, 15, dt); { float view_scale; diff --git a/src/main.cpp b/src/main.cpp index 1059cb6..f6a2de5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,6 +20,8 @@ int main() render::state_t render(&window); game::state_t game; interface::state_t interface(&window, &game); + size_t frame = 0; + double before = NAN; window.setVerticalSyncEnabled(false); @@ -29,21 +31,28 @@ int main() game.start(); while (1) { - double now = (nano_clock() - t0) * 1.0e-9; + double now = (nano_clock() - t0) * 1.0e-9, dt; - game.tick(now); - interface.tick(); + if (frame) + dt = now - before; + else + dt = 0.01; + + game.tick(now, dt); + interface.tick(dt); if (!window.isOpen()) break; window.clear(); - render.begin_frame(now); + render.begin_frame(now, dt); render.render(&game); interface.render_to(&render); render.end_frame(); + + before = now; + frame++; } game.stop(); - return 0; } diff --git a/src/render.cpp b/src/render.cpp index 259d898..d1b9752 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -65,9 +65,10 @@ state_t::state_t(sf::RenderWindow *window_) font.loadFromFile("assets/LiberationMono-Regular.ttf"); } -void state_t::begin_frame(double time_) +void state_t::begin_frame(double now_, double dt_) { - now = time_; + now = now_; + dt = dt_; window->clear(); } -- cgit