From 7f216f815537a4e3f9fe6636643cd929fed5ac81 Mon Sep 17 00:00:00 2001 From: LLLL Colonq Date: Sat, 26 Jul 2025 17:42:01 -0400 Subject: WIP timestep --- crates/teleia/src/state.rs | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) (limited to 'crates') diff --git a/crates/teleia/src/state.rs b/crates/teleia/src/state.rs index 763f302..99e5e0b 100644 --- a/crates/teleia/src/state.rs +++ b/crates/teleia/src/state.rs @@ -6,7 +6,7 @@ use serde::{Serialize, Deserialize}; use crate::{audio, context, framebuffer, shader, utils}; -const DELTA_TIME: f64 = 1.0 / 60.0; +const DELTA_TIME: f64 = 1.0 / 61.0; // todo pub struct WinitWaker {} impl WinitWaker { @@ -163,9 +163,11 @@ impl<'de> Deserialize<'de> for Keycode { } pub struct State { - pub acc: f64, - pub last: Timestamp, pub tick: u64, + pub nextframe: Timestamp, + pub fps: u32, + pub frames_this_second: u32, + pub start_this_second: Timestamp, pub rebinding: Option, pub keybindings: BiHashMap, @@ -250,16 +252,18 @@ impl State { let cwaker = Box::leak(Box::new(waker.into())); let waker_ctx = std::task::Context::from_waker(cwaker); - let acc = 0.0; - let last = now(ctx); + let nextframe = now(ctx); Self { - acc, - last, // we initialize the tick to 1000, which allows us to use "0" as the default time for // various animation starts on entities without having them all play at game start tick: 1000, + nextframe, + fps: 0, + frames_this_second: 0, + start_this_second: nextframe, + rebinding: None, keybindings: default_keybindings(), keys: Keys::new(), @@ -520,18 +524,18 @@ impl State { pub fn run_update(&mut self, ctx: &context::Context, game: &mut G) -> utils::Erm<()> where G: Game { let now = now(ctx); - let diff = now - self.last; - - // skip update if not enough time has accumulated since last update - // we truncate to below the target framerate, which is pretty gross - // the intention here is to allow vsync to dictate the framerate most of the time - // however, we need some way to limit the framerate on monitors with >60Hz - // so we use this to skip frames. in general this should be tested more on faster monitors - if diff >= DELTA_TIME.trunc() as f64 { - self.last = now; + if now > self.nextframe { + while self.nextframe < now { // find the next target frame that isn't in the past + self.nextframe = self.nextframe + DELTA_TIME; + } self.tick += 1; + self.frames_this_second += 1; game.update(ctx, self)?; - self.acc = 0.0; + } + if now - self.start_this_second > 1.0 { // track FPS + self.start_this_second = now; + self.fps = self.frames_this_second; + self.frames_this_second = 0; } Ok(()) } -- cgit v1.2.3