Skip to main content

game_toolkit_core/
time.rs

1use std::time::Duration;
2
3// `std::time::Instant::now` panics on wasm32-unknown-unknown; web-time re-exports std's
4// `Instant` on native and uses `performance.now()` in the browser.
5use web_time::Instant;
6
7/// Frame timing, as `ctx.time`.
8pub struct Time {
9    /// Time since startup.
10    pub elapsed: Duration,
11    /// Real time since the previous frame, uncapped. The `dt` passed to `Game::update` is
12    /// this capped at [`AppConfig::max_frame_time`](crate::AppConfig::max_frame_time) (or the
13    /// fixed step, with [`AppConfig::fixed_timestep`](crate::AppConfig::fixed_timestep)).
14    pub delta: Duration,
15    /// Frames since startup.
16    pub frame: u64,
17    /// Smoothed frames per second.
18    pub fps: f32,
19    /// With a fixed timestep: how far this frame is into the next step, in `0.0..1.0`. Draw
20    /// `previous + (current - previous) * alpha` in `render` for motion that's smooth at
21    /// display rates above the step rate. Always `0.0` without a fixed timestep.
22    pub alpha: f32,
23    start: Instant,
24    last_frame: Instant,
25    fps_accum: f32,
26}
27
28impl Time {
29    pub fn new() -> Self {
30        let now = Instant::now();
31        Self {
32            elapsed: Duration::ZERO,
33            delta: Duration::ZERO,
34            frame: 0,
35            fps: 0.0,
36            alpha: 0.0,
37            start: now,
38            last_frame: now,
39            fps_accum: 0.0,
40        }
41    }
42
43    pub fn tick(&mut self) {
44        let now = Instant::now();
45        self.delta = now - self.last_frame;
46        self.elapsed = now - self.start;
47        self.last_frame = now;
48        self.frame += 1;
49        let inst = 1.0 / self.delta.as_secs_f32().max(1e-6);
50        self.fps_accum = self.fps_accum * 0.95 + inst * 0.05;
51        self.fps = self.fps_accum;
52    }
53}
54
55impl Default for Time {
56    fn default() -> Self {
57        Self::new()
58    }
59}