use super::*;
pub struct TickLoopState {
start: Instant,
ticks_per_second: u32,
tick_duration: Duration,
tock_duration: Duration,
max_frameskip: i32,
loops: i32,
next_game_tick: Instant,
next_game_tock: Instant,
last_tick_time: Instant,
last_tock_time: Instant,
tick_count: u32,
total_ticks: u64,
total_tocks: u64,
}
#[derive(Debug)]
pub struct TickLoopEvent {
pub target_tickrate: u32,
pub time: Instant,
pub duration: Duration,
pub ticks: u64,
}
#[derive(Debug)]
pub struct TockLoopEvent {
pub target_tickrate: u32,
pub time: Instant,
pub duration: Duration,
pub ticks: u64,
pub tocks: u64,
pub last_tock: Instant,
pub average_tickrate: f64,
}
impl TickLoopState {
pub fn new(ticks_per_second: u32) -> Self {
Self {
start: Instant::now(),
ticks_per_second,
tick_duration: Duration::from_secs(1) / ticks_per_second,
tock_duration: Duration::from_secs(1),
max_frameskip: 1,
loops: 0,
next_game_tick: Instant::now(),
next_game_tock: Instant::now(),
last_tick_time: Instant::now(),
last_tock_time: Instant::now(),
tick_count: 0,
total_ticks: 0,
total_tocks: 0,
}
}
pub fn pre(&mut self) {
self.loops = 0;
}
pub fn tick<F: FnOnce(&mut TickLoopEvent)>(&mut self, current_time: Instant, function: F) -> bool {
if (current_time > self.next_game_tick) && (self.loops < self.max_frameskip) {
function(&mut TickLoopEvent {
target_tickrate: self.ticks_per_second,
time: current_time,
duration: self.tick_duration,
ticks: self.total_ticks,
});
self.last_tick_time = current_time;
self.next_game_tick += self.tick_duration;
self.loops += 1;
self.tick_count += 1;
self.total_ticks += 1;
return true;
}
false
}
pub fn tock<F: FnOnce(&mut TockLoopEvent)>(&mut self, current_time: Instant, function: F) -> bool {
let time_since_tock = current_time.duration_since(self.last_tock_time).as_secs_f64();
if self.next_game_tock <= current_time {
let hertz_avg = self.tick_count as f64 / time_since_tock;
function(&mut TockLoopEvent {
target_tickrate: self.ticks_per_second,
time: current_time,
duration: self.tick_duration,
last_tock: self.last_tock_time,
average_tickrate: hertz_avg,
ticks: self.total_ticks,
tocks: self.total_tocks,
});
self.tick_count = 0;
self.total_tocks += 1;
self.last_tock_time = current_time;
self.next_game_tock = current_time + self.tock_duration;
return true;
}
false
}
pub fn interpolation(&self, current_time: Instant) -> f64 {
let delta = current_time - self.next_game_tick;
(delta + self.tick_duration).as_secs_f64() / self.tick_duration.as_secs_f64()
}
pub fn get_minimum_tick_duration(&self) -> Duration {
self.tick_duration
}
pub fn get_start(&self) -> Instant {
self.start
}
}