summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2025-11-14 11:52:23 -0500
committerFreya Murphy <freya@freyacat.org>2025-11-14 11:52:23 -0500
commit8543609a95eca8b7cb22bbef5633730d50d7b737 (patch)
tree85ac9e4925030a9aae46703840a1a00ae30b8d90
parentRemove wildcard exports/imports (diff)
downloadDungeonCrawl-8543609a95eca8b7cb22bbef5633730d50d7b737.tar.gz
DungeonCrawl-8543609a95eca8b7cb22bbef5633730d50d7b737.tar.bz2
DungeonCrawl-8543609a95eca8b7cb22bbef5633730d50d7b737.zip
graphics: refactor timer
-rw-r--r--graphics/src/lib.rs2
-rw-r--r--graphics/src/render.rs6
-rw-r--r--graphics/src/timer.rs94
3 files changed, 53 insertions, 49 deletions
diff --git a/graphics/src/lib.rs b/graphics/src/lib.rs
index b42845c..d12eac0 100644
--- a/graphics/src/lib.rs
+++ b/graphics/src/lib.rs
@@ -203,7 +203,7 @@ impl Window {
}
/// Returns the per frame delta time
- pub fn delta_time(&self) -> Duration {
+ pub const fn delta_time(&self) -> Duration {
self.renderer.delta_time()
}
diff --git a/graphics/src/render.rs b/graphics/src/render.rs
index dff09df..ba6cf81 100644
--- a/graphics/src/render.rs
+++ b/graphics/src/render.rs
@@ -207,7 +207,7 @@ impl Renderer {
self.debug = !self.debug;
}
- pub fn delta_time(&self) -> Duration {
+ pub const fn delta_time(&self) -> Duration {
self.timer.delta_time()
}
@@ -654,7 +654,7 @@ impl Renderer {
let player = &dungeon.player;
// Draw FPS
- draw_text!(self, r, UI_COL1, UI_ROW1, "FPS {}", self.timer.get_fps());
+ draw_text!(self, r, UI_COL1, UI_ROW1, "FPS {}", self.timer.fps());
// Draw Player position
let (x, y) = &player.entity.pos.xy();
@@ -673,7 +673,7 @@ impl Renderer {
draw_text!(self, r, UI_COL2, UI_ROW2, "{hash:016X}");
// Draw current frame number
- let frame = self.timer.get_frame();
+ let frame = self.timer.frame();
draw_text!(self, r, UI_COL2, UI_ROW3, "FRAME {frame}");
}
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]
}
}