fps_controller/
lib.rs

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    /// Create a default struct for 60 fps.
14    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(); // 0 ~ 999
37        let time_as_secs = time.as_secs(); // 0 ~
38        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}