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
use amethyst_core::{ECSBundle, Result};
use amethyst_core::timing::{duration_to_nanos, Time};
use circular_buffer::CircularBuffer;
use specs::{DispatcherBuilder, Fetch, FetchMut, System, World};
pub struct FPSCounter {
buf: CircularBuffer<u64>,
sum: u64,
}
impl FPSCounter {
pub fn new(samplesize: usize) -> FPSCounter {
FPSCounter {
buf: CircularBuffer::<u64>::new(samplesize),
sum: 0,
}
}
pub fn push(&mut self, elem: u64) {
self.sum += elem;
if let Some(front) = self.buf.push(elem) {
self.sum -= front;
}
}
pub fn frame_fps(&self) -> f32 {
if let Some(back) = self.buf.queue().back() {
return 1.0e9 / *back as f32;
}
0.0
}
pub fn sampled_fps(&self) -> f32 {
if self.sum == 0 || self.buf.queue().len() == 0 {
return 0.0;
}
1.0e9 * self.buf.queue().len() as f32 / self.sum as f32
}
}
pub struct FPSCounterSystem;
impl<'a> System<'a> for FPSCounterSystem {
type SystemData = (Fetch<'a, Time>, FetchMut<'a, FPSCounter>);
fn run(&mut self, (time, mut counter): Self::SystemData) {
counter.push(duration_to_nanos(time.delta_real_time()));
}
}
pub struct FPSCounterBundle {
samplesize: usize,
}
impl FPSCounterBundle {
pub fn new(samplesize: usize) -> Self {
Self { samplesize }
}
}
impl Default for FPSCounterBundle {
fn default() -> Self {
Self::new(20)
}
}
impl<'a, 'b> ECSBundle<'a, 'b> for FPSCounterBundle {
fn build(
self,
world: &mut World,
builder: DispatcherBuilder<'a, 'b>,
) -> Result<DispatcherBuilder<'a, 'b>> {
world.add_resource(FPSCounter::new(self.samplesize));
Ok(builder.add(FPSCounterSystem, "fps_counter_system", &[]))
}
}