diff --git a/src/lib.rs b/src/lib.rs index 30e3216..f0feb08 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -631,6 +631,24 @@ impl Window { } } + /// Returns the current fps of the window + /// + /// # Examples + /// + /// ```no_run + /// # use minifb::*; + /// # let mut window = Window::new("Test", 640, 400, WindowOptions::default()).unwrap(); + /// let fps = window.get_fps(); + /// println!("fps {}", fps); + /// ``` + #[inline] + pub fn get_fps(&mut self) -> usize { + match self.0.get_delta_time() { + Some(rate) => (1.0 / rate.as_secs_f32()) as usize, + _ => 0, + } + } + /// Returns the current size of the window /// /// # Examples diff --git a/src/os/macos/mod.rs b/src/os/macos/mod.rs index 84a8b49..cf488d0 100644 --- a/src/os/macos/mod.rs +++ b/src/os/macos/mod.rs @@ -344,6 +344,11 @@ impl Window { self.update_rate.set_rate(rate); } + #[inline] + pub fn get_delta_time(&self) -> Option { + self.update_rate.get_delta_time() + } + #[inline] pub fn update_rate(&mut self) { self.update_rate.update(); diff --git a/src/os/posix/mod.rs b/src/os/posix/mod.rs index 716b71b..6ce36ce 100644 --- a/src/os/posix/mod.rs +++ b/src/os/posix/mod.rs @@ -225,6 +225,15 @@ impl Window { } } + pub fn get_delta_time(&self) -> Option { + match self { + #[cfg(feature = "x11")] + Window::X11(w) => w.get_delta_time(), + #[cfg(feature = "wayland")] + Window::Wayland(w) => w.get_delta_time(), + } + } + pub fn update_rate(&mut self) { match self { #[cfg(feature = "x11")] diff --git a/src/os/posix/wayland.rs b/src/os/posix/wayland.rs index 51ef6c3..6722330 100644 --- a/src/os/posix/wayland.rs +++ b/src/os/posix/wayland.rs @@ -672,6 +672,11 @@ impl Window { self.update_rate.set_rate(rate); } + #[inline] + pub fn get_delta_time(&self) -> Option { + self.update_rate.get_delta_time() + } + #[inline] pub fn set_key_repeat_rate(&mut self, rate: f32) { self.key_handler.set_key_repeat_delay(rate); diff --git a/src/os/posix/x11.rs b/src/os/posix/x11.rs index bcbb386..f744409 100644 --- a/src/os/posix/x11.rs +++ b/src/os/posix/x11.rs @@ -769,6 +769,11 @@ impl Window { self.update_rate.set_rate(rate); } + #[inline] + pub fn get_delta_time(&self) -> Option { + self.update_rate.get_delta_time() + } + #[inline] pub fn update_rate(&mut self) { self.update_rate.update(); diff --git a/src/os/wasm/mod.rs b/src/os/wasm/mod.rs index 8a81cb1..a2d2879 100644 --- a/src/os/wasm/mod.rs +++ b/src/os/wasm/mod.rs @@ -228,6 +228,11 @@ impl Window { #[inline] pub fn set_rate(&mut self, _rate: Option) {} + #[inline] + pub fn get_delta_time(&self) -> Option { + None + } + #[inline] pub fn update_rate(&mut self) {} diff --git a/src/os/windows/mod.rs b/src/os/windows/mod.rs index 304cd2e..86932bb 100644 --- a/src/os/windows/mod.rs +++ b/src/os/windows/mod.rs @@ -870,6 +870,11 @@ impl Window { self.update_rate.set_rate(rate); } + #[inline] + pub fn get_delta_time(&self) -> Option { + self.update_rate.get_delta_time() + } + #[inline] pub fn update_rate(&mut self) { self.update_rate.update(); diff --git a/src/rate.rs b/src/rate.rs index 39ef936..f44a49b 100644 --- a/src/rate.rs +++ b/src/rate.rs @@ -9,34 +9,45 @@ use std::time::{Duration, Instant}; pub struct UpdateRate { target_rate: Option, prev_time: Instant, + delta: Option, } #[cfg_attr(target_arch = "wasm32", allow(unused))] impl UpdateRate { - pub fn new() -> UpdateRate { - UpdateRate { - // Default limit to 4 ms + pub fn new() -> Self { + Self { + // Default target rate: 4 ms per frame (~250 FPS) target_rate: Some(Duration::from_millis(4)), prev_time: Instant::now(), + delta: None, } } #[inline] pub fn set_rate(&mut self, rate: Option) { - self.target_rate = rate + self.target_rate = rate; } pub fn update(&mut self) { - if let Some(target_rate) = self.target_rate { - let delta = self.prev_time.elapsed(); + let now = Instant::now(); + let elapsed = now.duration_since(self.prev_time); - if delta < target_rate { - let sleep_time = target_rate - delta; - //eprintln!("sleeping {} ms", sleep_time.as_secs_f64() * 1000.); + // If a target rate is set, sleep to match it + if let Some(target_rate) = self.target_rate { + if elapsed < target_rate { + let sleep_time = target_rate - elapsed; std::thread::sleep(sleep_time); } - - self.prev_time = Instant::now(); } + + // Now mark the new frame time and compute total delta (including sleep) + let now = Instant::now(); + self.delta = Some(now.duration_since(self.prev_time)); + self.prev_time = now; + } + + #[inline] + pub fn get_delta_time(&self) -> Option { + self.delta } }