use chrono;
use clock::{GameTime, GameClock};
use framerate::counter::FrameCount;
use step::TimeStep;
#[derive(Debug)]
pub struct FrameRunner<C: FrameCount> {
clock: GameClock,
counter: C,
}
impl<C> FrameRunner<C>
where
C: FrameCount,
{
pub fn new(clock: GameClock, counter: C) -> FrameRunner<C> {
FrameRunner { clock, counter }
}
pub fn clock(&self) -> &GameClock {
&self.clock
}
pub fn clock_mut(&mut self) -> &mut GameClock {
&mut self.clock
}
pub fn counter(&self) -> &C {
&self.counter
}
pub fn counter_mut(&mut self) -> &mut C {
&mut self.counter
}
pub fn tick<T: TimeStep>(&mut self, time_step: &T) -> GameTime {
let time = self.clock.tick(time_step);
self.counter.tick(&time);
time
}
pub fn tick_with_wall_time<T: TimeStep>(
&mut self,
time_step: &T,
frame_start: chrono::DateTime<chrono::Local>,
) -> GameTime {
let time = self.clock.tick_with_wall_time(time_step, frame_start);
self.counter.tick(&time);
time
}
pub fn do_frame<T, F>(&mut self, time_step: &T, frame_fn: F)
where
T: TimeStep,
F: FnOnce(GameTime),
{
let time = self.tick(time_step);
frame_fn(time);
self.clock.sleep_remaining(&self.counter);
}
}
#[cfg(test)]
mod tests {
use super::*;
use framerate::{counter, sample};
use step;
use float_duration::FloatDuration;
#[test]
fn test_runner() {
let clock = GameClock::new();
let count =
counter::FrameCounter::new(20.0, sample::RunningAverageSampler::with_max_samples(20));
let mut runner = FrameRunner::new(clock, count);
for i in 0..10 {
runner.do_frame(
&step::ConstantStep::new(FloatDuration::milliseconds(25.0)),
|time| {
assert_eq!(time.elapsed_game_time(), FloatDuration::milliseconds(25.0));
relative_eq!(
time.total_game_time(),
FloatDuration::milliseconds(25.0) * (i + 1) as f64,
epsilon = 1e-8
);
},
);
}
}
}