#![no_std]
#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
#![warn(missing_docs)]
use core::time::Duration;
#[derive(Clone, Debug)]
pub struct GameLoop {
target_frame_time: Duration,
max_frame_time: Duration,
accumulated_time: Duration,
total_num_updates: u64,
total_time_passed: Duration,
}
impl GameLoop {
#[inline]
pub fn new(target_frame_time: Duration, max_frame_time: Duration) -> Self {
Self {
target_frame_time,
max_frame_time,
accumulated_time: Duration::ZERO,
total_num_updates: 0,
total_time_passed: Duration::ZERO,
}
}
#[inline]
pub fn new_with_fps(fps: u32, max_frame_time: Duration) -> Self {
Self::new(Duration::from_secs_f64(1. / fps as f64), max_frame_time)
}
#[inline]
pub fn set_target_frame_time(&mut self, time: Duration) {
self.target_frame_time = time;
}
#[inline]
pub fn set_fps(&mut self, fps: u32) {
self.target_frame_time = Duration::from_secs_f64(1. / fps as f64);
}
#[inline]
pub fn set_max_frame_time(&mut self, time: Duration) {
self.max_frame_time = time;
}
pub fn update(&mut self, elapsed: Duration) -> UpdateResult {
self.total_time_passed += elapsed;
self.accumulated_time += if elapsed > self.max_frame_time {
self.max_frame_time
} else {
elapsed
};
let mut num_updates = 0;
while self.accumulated_time >= self.target_frame_time {
self.accumulated_time -= self.target_frame_time;
num_updates += 1;
}
self.total_num_updates += num_updates;
let blending_factor =
self.accumulated_time.as_secs_f64() / self.target_frame_time.as_secs_f64();
UpdateResult {
num_updates,
total_num_updates: self.total_num_updates,
frame_time: self.target_frame_time,
blending_factor,
total_time_passed: self.total_time_passed,
exit: false,
}
}
}
#[derive(Clone, Debug)]
pub struct UpdateResult {
pub num_updates: u64,
pub total_num_updates: u64,
pub frame_time: Duration,
pub blending_factor: f64,
pub total_time_passed: Duration,
pub exit: bool,
}
impl UpdateResult {
#[inline]
pub fn run<F>(mut self, mut func: F) -> Self
where
F: FnMut(&mut Self),
{
for _i in 0..self.num_updates {
(func)(&mut self);
if self.exit {
break;
}
}
self
}
#[inline]
pub fn run_result<F, E>(mut self, mut func: F) -> Result<Self, E>
where
F: FnMut(&mut Self) -> Result<(), E>,
{
for _i in 0..self.num_updates {
(func)(&mut self)?;
if self.exit {
break;
}
}
Ok(self)
}
}