Allow skipping frames

This commit is contained in:
Rico Riedel 2022-07-04 19:38:27 +02:00
parent 94888dcc7d
commit 7500e5af1b
No known key found for this signature in database
GPG Key ID: 75AC868575DE7B18
2 changed files with 31 additions and 15 deletions

View File

@ -5,8 +5,8 @@ use crate::timer::Timer;
/// Periodically calls [Renderer::render] and [Renderer::present]. /// Periodically calls [Renderer::render] and [Renderer::present].
pub struct Runner<TTimer, TRenderer> { pub struct Runner<TTimer, TRenderer> {
duration: Duration,
timer: TTimer, timer: TTimer,
ticks: u128,
renderer: TRenderer, renderer: TRenderer,
} }
@ -14,19 +14,23 @@ impl<T1: Timer, T2: Renderer> Runner<T1, T2> {
pub fn new(duration: Duration, pub fn new(duration: Duration,
timer: T1, timer: T1,
renderer: T2) -> Self { renderer: T2) -> Self {
let ticks = duration.as_nanos() / timer.delay().as_nanos();
Self { timer, ticks, renderer } Self { duration, timer, renderer }
} }
pub fn run(mut self) -> Result<(), Error> { pub fn run(mut self) -> Result<(), Error> {
for i in 0..=self.ticks { self.timer.set();
let step = i as f32 / self.ticks as f32;
while self.timer.elapsed() < self.duration {
let step = self.timer.elapsed().as_secs_f32() / self.duration.as_secs_f32();
self.renderer.render(step); self.renderer.render(step);
self.renderer.present()?; self.renderer.present()?;
self.timer.sleep(); self.timer.sleep();
} }
self.renderer.render(1.0);
self.renderer.present()?;
Ok(()) Ok(())
} }
} }
@ -46,19 +50,21 @@ mod test {
let mut renderer = MockRenderer::new(); let mut renderer = MockRenderer::new();
let seq = &mut Sequence::new(); let seq = &mut Sequence::new();
timer.expect_delay().return_const(Duration::from_secs(2)); timer.expect_set().once().in_sequence(seq).return_const(());
timer.expect_elapsed().times(2).in_sequence(seq).return_const(Duration::from_secs(0));
renderer.expect_render().once().with(eq(0.0)).in_sequence(seq).return_const(()); renderer.expect_render().once().with(eq(0.0)).in_sequence(seq).return_const(());
renderer.expect_present().once().in_sequence(seq).returning(|| Ok(())); renderer.expect_present().once().in_sequence(seq).returning(|| Ok(()));
timer.expect_sleep().once().in_sequence(seq).return_const(()); timer.expect_sleep().once().in_sequence(seq).return_const(());
timer.expect_elapsed().times(2).in_sequence(seq).return_const(Duration::from_secs(2));
renderer.expect_render().once().with(eq(0.5)).in_sequence(seq).return_const(()); renderer.expect_render().once().with(eq(0.5)).in_sequence(seq).return_const(());
renderer.expect_present().once().in_sequence(seq).returning(|| Ok(())); renderer.expect_present().once().in_sequence(seq).returning(|| Ok(()));
timer.expect_sleep().once().in_sequence(seq).return_const(()); timer.expect_sleep().once().in_sequence(seq).return_const(());
timer.expect_elapsed().times(1).in_sequence(seq).return_const(Duration::from_secs(4));
renderer.expect_render().once().with(eq(1.0)).in_sequence(seq).return_const(()); renderer.expect_render().once().with(eq(1.0)).in_sequence(seq).return_const(());
renderer.expect_present().once().in_sequence(seq).returning(|| Ok(())); renderer.expect_present().once().in_sequence(seq).returning(|| Ok(()));
timer.expect_sleep().once().in_sequence(seq).return_const(());
let runner = Runner::new(Duration::from_secs(4), timer, renderer); let runner = Runner::new(Duration::from_secs(4), timer, renderer);

View File

@ -7,29 +7,43 @@ use mockall::automock;
/// Allows for periodic execution of code. /// Allows for periodic execution of code.
#[cfg_attr(test, automock)] #[cfg_attr(test, automock)]
pub trait Timer { pub trait Timer {
/// Set the start time of the timer.
fn set(&mut self);
/// Get the elapsed time since calling [Timer::set].
fn elapsed(&self) -> Duration;
/// Sleep until the next tick starts. /// Sleep until the next tick starts.
fn sleep(&mut self); fn sleep(&mut self);
/// Get the delay between ticks.
fn delay(&self) -> Duration;
} }
/// A simple [Timer] based on the system clock. /// A simple [Timer] based on the system clock.
pub struct SimpleTimer { pub struct SimpleTimer {
delay: Duration, delay: Duration,
start: Instant,
last: Instant last: Instant
} }
impl SimpleTimer { impl SimpleTimer {
pub fn new(delay: Duration) -> Self { pub fn new(delay: Duration) -> Self {
Self { Self {
last: Instant::now(),
delay, delay,
start: Instant::now(),
last: Instant::now(),
} }
} }
} }
impl Timer for SimpleTimer { impl Timer for SimpleTimer {
fn set(&mut self) {
self.start = Instant::now();
self.last = self.start;
}
fn elapsed(&self) -> Duration {
Instant::now() - self.start
}
fn sleep(&mut self) { fn sleep(&mut self) {
let now = Instant::now(); let now = Instant::now();
@ -38,8 +52,4 @@ impl Timer for SimpleTimer {
} }
self.last = Instant::now(); self.last = Instant::now();
} }
fn delay(&self) -> Duration {
self.delay
}
} }