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}