1use std::time::{Instant, Duration};
2use std::thread::sleep;
3
4pub struct FPSController {
5 fps: f64,
6 frame_time: f64,
7 frame_count: u64,
8 time: Instant,
9 extra_time: f64,
10}
11
12impl FPSController {
13 pub fn new() -> Self {
15 Self::from_fps(60)
16 }
17
18 pub fn from_fps(fps: u64) -> Self {
19 let fps = fps as f64;
20 FPSController {
21 fps,
22 frame_time: 1.0 / fps,
23 frame_count: 0,
24 time: Instant::now(),
25 extra_time: 0.0
26 }
27 }
28
29 pub fn tick(&mut self) -> u64 {
30 self.frame_count += 1;
31 self.frame_count
32 }
33
34 pub fn run<F: FnMut(u64)>(&mut self, mut update: F) -> f64 {
35 let time = self.time.elapsed();
36 let time_as_millis = time.subsec_millis(); let time_as_secs = time.as_secs(); let current_time = time_as_secs as f64 + time_as_millis as f64 / 1000.0;
39 let true_time = self.frame_count as f64 / self.fps as f64;
40 let sleep_time = true_time - current_time;
41 if sleep_time >= 0.0 {
42 if sleep_time > self.extra_time {
43 let sleep_time = sleep_time - self.extra_time;
44 self.extra_time = 0.0;
45 sleep(Duration::from_millis((sleep_time * 1000.0) as u64));
46 } else {
47 self.extra_time -= sleep_time;
48 }
49 } else {
50 self.extra_time += -sleep_time;
51 while self.extra_time >= self.frame_time {
52 self.frame_count += 1;
53 update(self.frame_count);
54 self.extra_time -= self.frame_time;
55 }
56 }
57 let time = self.time.elapsed();
58 let time_as_secs = time.as_secs() as f64 + time.subsec_millis() as f64 / 1000.0;
59 let fps = self.frame_count as f64 / time_as_secs;
60 fps
61 }
62}