1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
use sdl2::Sdl; #[derive(Clone, Copy, Debug)] pub struct Tick { pub total_time: f64, pub dt: f32, pub frame: u64, } pub struct Timer { dt: f64, freq: f64, max_frame: f64, total_time: f64, accumulator: f64, current_time: f64, frame: u64, subsystem: sdl2::TimerSubsystem, } impl Timer { pub fn new(context: &Sdl, dt: f64, max_frame: f64) -> Result<Self, String> { let subsystem = context.timer()?; let freq = subsystem.performance_frequency() as f64; let current_time = subsystem.performance_counter() as f64 / freq; Ok(Self { dt, freq, max_frame, total_time: 0., accumulator: 0., current_time, frame: 0, subsystem, }) } fn get_time(&self) -> f64 { (self.subsystem.performance_counter() as f64) / self.freq } pub fn begin_frame<'a>(&'a mut self) -> TimeIter<'a> { let new_time = self.get_time(); let frame_time = (new_time - self.current_time).min(self.max_frame); self.current_time = new_time; self.accumulator += frame_time; TimeIter { timer: self } } pub const fn get_tick(&self) -> Tick { Tick { total_time: self.total_time, dt: self.dt as f32, frame: self.frame, } } fn has_accumulator_remaining(&self) -> bool { self.accumulator >= self.dt } fn reduce_accumulator(&mut self) { self.accumulator -= self.dt; self.total_time += self.dt; } #[allow(dead_code)] pub const fn dt(&self) -> f32 { self.dt as f32 } #[allow(dead_code)] pub const fn total_time(&self) -> f32 { self.total_time as f32 } } pub struct TimeIter<'a> { timer: &'a mut Timer, } impl<'a> Iterator for TimeIter<'a> { type Item = Tick; fn next(&mut self) -> Option<Self::Item> { let timer = &mut self.timer; if timer.has_accumulator_remaining() { timer.frame += 1; let tick = timer.get_tick(); timer.reduce_accumulator(); return Some(tick); } None } }