use core::ops::*;
use idem::Zero;
use time;
pub struct Simulator<State> {
tick: time::Span,
then: time::Point,
cumul: time::Span,
total: time::Span,
prior_state: State,
}
impl<State: Clone> Simulator<State> {
pub fn new(tick: time::Span, state: State) -> Self { Simulator {
tick: tick,
then: time::Point::now(),
cumul: Zero::zero,
total: Zero::zero,
prior_state: state,
} }
pub fn go<A, Step, Interpolate>(&mut self, state: &mut State,
step: Step, interpolate: Interpolate) -> A
where Step: Fn(&mut State),
Interpolate: Fn(f64, &State, &State) -> A {
{
let now = time::Point::now();
let elapsed = now - self.then;
debug_assert!(elapsed >= Zero::zero);
self.then = now;
self.cumul += elapsed;
self.total += elapsed;
}
while self.cumul > Zero::zero {
self.cumul -= self.tick;
if self.cumul < Zero::zero {
self.prior_state.clone_from(state);
}
step(state);
}
interpolate((self.cumul.to_ns() as f64 / self.tick.to_ns() as f64).neg(),
&state, &self.prior_state)
}
}