diff options
Diffstat (limited to 'graphics/src/timer.rs')
| -rw-r--r-- | graphics/src/timer.rs | 94 |
1 files changed, 49 insertions, 45 deletions
diff --git a/graphics/src/timer.rs b/graphics/src/timer.rs index a8317c7..e2209c7 100644 --- a/graphics/src/timer.rs +++ b/graphics/src/timer.rs @@ -1,67 +1,71 @@ -use std::{ - ops::{Add, Div, Mul}, - time::{Duration, Instant}, -}; +use std::time::{Duration, Instant}; -/// How often to update the fps interval on screen -const FPS_INTERVAL: Duration = Duration::from_millis(250); - -/// How much to smooth he `delta_avg` amount (`AVG_RATIO`:1) -const AVG_RATIO: u32 = 10; +/// Number of fps samples to store +const MAX_SAMPLES: usize = 100; /// Keeps track of frame intervals and FPS pub struct Timer { - /// Last time updated previous: Instant, - /// Current time - now: Instant, - /// Rolling delta time average - delta_avg: Duration, - /// Computed fps - fps: f64, - /// Last time the fps was updated - fps_time: Instant, - /// Frame count - count: u32, + tick_index: usize, + tick_sum: Duration, + tick_list: Box<[Duration; MAX_SAMPLES]>, + frame: u32, } impl Timer { pub fn new() -> Self { - let now = Instant::now(); + let previous = Instant::now(); + let tick_index = 0usize; + let tick_sum = Duration::ZERO; + let tick_list = Box::new([tick_sum; MAX_SAMPLES]); + let frame = 0u32; + Self { - previous: now, - now, - delta_avg: Duration::ZERO, - fps: 0.0, - fps_time: now, - count: 0, + previous, + tick_index, + tick_sum, + tick_list, + frame, } } pub fn update(&mut self) { - self.previous = self.now; - self.now = Instant::now(); - self.delta_avg = self - .delta_avg - .mul(AVG_RATIO) - .add(self.delta_time()) - .div(AVG_RATIO + 1); - if (self.now - self.fps_time) > FPS_INTERVAL { - self.fps = 1.0 / self.delta_avg.as_secs_f64(); - self.fps_time = self.now; - } - self.count += 1; + let time = self.previous.elapsed(); + self.previous = Instant::now(); + + // caculate average tick + self.tick_index += 1; + self.tick_index %= MAX_SAMPLES; + self.tick_sum -= self.tick_list[self.tick_index]; + self.tick_sum += time; + self.tick_list[self.tick_index] = time; + + // update frame frame + self.frame += 1; } - pub const fn get_frame(&self) -> u32 { - self.count + pub const fn frame(&self) -> u32 { + self.frame } #[expect(clippy::cast_possible_truncation)] - pub fn get_fps(&self) -> u32 { - self.fps.ceil() as u32 + pub const fn fps(&self) -> u32 { + match self.frame_time().as_nanos() { + 0 => u32::MAX, + // fps can never be bigger than u32::MAX since we're + // computing in nanoseconds + nanos => 1_000_000_000u128.div_ceil(nanos) as u32, + } + } + + #[expect(clippy::cast_possible_truncation)] + pub const fn frame_time(&self) -> Duration { + match self.tick_sum.checked_div(MAX_SAMPLES as u32) { + Some(duration) => duration, + None => Duration::ZERO, + } } - pub fn delta_time(&self) -> Duration { - self.now - self.previous + pub const fn delta_time(&self) -> Duration { + self.tick_list[self.tick_index] } } |