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
use std::collections::VecDeque;
use std::time::{Duration, Instant};
use crate::Context;
pub(crate) struct TimeContext {
tick_rate: Duration,
fps_tracker: VecDeque<f64>,
last_time: Instant,
lag: Duration,
}
impl TimeContext {
pub(crate) fn new(tick_rate: f64) -> TimeContext {
let mut fps_tracker = VecDeque::with_capacity(200);
fps_tracker.resize(200, 1.0 / 60.0);
TimeContext {
tick_rate: f64_to_duration(tick_rate),
fps_tracker,
last_time: Instant::now(),
lag: Duration::from_secs(0),
}
}
}
pub(crate) fn reset(ctx: &mut Context) {
ctx.time.last_time = Instant::now();
ctx.time.lag = Duration::from_secs(0);
}
pub(crate) fn tick(ctx: &mut Context) {
let current_time = Instant::now();
let elapsed = current_time - ctx.time.last_time;
ctx.time.last_time = current_time;
ctx.time.lag += elapsed;
ctx.time.fps_tracker.pop_front();
ctx.time.fps_tracker.push_back(duration_to_f64(elapsed));
}
pub(crate) fn is_tick_ready(ctx: &Context) -> bool {
ctx.time.lag >= ctx.time.tick_rate
}
pub(crate) fn consume_tick(ctx: &mut Context) {
ctx.time.lag -= ctx.time.tick_rate;
}
pub(crate) fn get_alpha(ctx: &Context) -> f64 {
duration_to_f64(ctx.time.lag) / duration_to_f64(ctx.time.tick_rate)
}
pub fn duration_to_f64(duration: Duration) -> f64 {
let seconds = duration.as_secs() as f64;
let nanos = f64::from(duration.subsec_nanos()) * 1e-9;
seconds + nanos
}
pub fn f64_to_duration(duration: f64) -> Duration {
debug_assert!(duration >= 0.0);
let seconds = duration.trunc() as u64;
let nanos = (duration.fract() * 1e9) as u32;
Duration::new(seconds, nanos)
}
pub fn get_tick_rate(ctx: &Context) -> f64 {
1.0 / duration_to_f64(ctx.time.tick_rate)
}
pub fn set_tick_rate(ctx: &mut Context, tick_rate: f64) {
ctx.time.tick_rate = f64_to_duration(1.0 / tick_rate);
}
pub fn get_fps(ctx: &Context) -> f64 {
1.0 / (ctx.time.fps_tracker.iter().sum::<f64>() / ctx.time.fps_tracker.len() as f64)
}