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
|
#include <simloop.h>
#include <test.h>
#include <timer.h>
/// At time/frame 0:
/// 1. An initial render is always triggered.
/// 2. No update is triggered (not enough time passed).
TEST_CASE(simloop_initial_render) {
Timer timer = {};
Simloop simloop = simloop_make(
&(SimloopArgs){.update_fps = 10, .max_render_fps = 0, .timer = &timer});
SimloopOut simout;
simloop_update(&simloop, &simout);
TEST_TRUE(simout.should_render);
TEST_TRUE(!simout.should_update);
TEST_EQUAL(simout.frame, 0);
}
/// The initial render is not re-triggered if there is a render frame rate cap
/// and time does not advance.
TEST_CASE(simloop_initial_render_not_retriggered) {
Timer timer = {};
Simloop simloop = simloop_make(
&(SimloopArgs){.update_fps = 10, .max_render_fps = 10, .timer = &timer});
SimloopOut simout;
simloop_update(&simloop, &simout);
TEST_TRUE(simout.should_render);
TEST_TRUE(!simout.should_update);
TEST_EQUAL(simout.frame, 0);
for (int i = 0; i < 10; i++) {
// Note that time does not advance.
simloop_update(&simloop, &simout);
TEST_TRUE(!simout.should_render);
TEST_TRUE(!simout.should_update);
TEST_EQUAL(simout.frame, 0);
}
}
/// A simulation loop with no render frame cap:
/// 1. Updates based on the desired update frame rate.
/// 2. Renders at every loop.
TEST_CASE(simloop_no_render_frame_cap) {
constexpr int UPDATE_FPS = 10;
const time_delta EXPECT_UPDATE = sec_to_time_delta(1.0 / (double)UPDATE_FPS);
const time_delta STEP = sec_to_time_delta(1);
const time_delta SIM_TIME_SEC = sec_to_time_delta(30);
Timer timer = {};
Simloop simloop = simloop_make(&(SimloopArgs){
.update_fps = UPDATE_FPS, .max_render_fps = 0, .timer = &timer});
SimloopOut simout;
for (time_delta t = 0; t < SIM_TIME_SEC; t += STEP) {
timer_advance(&timer, t);
simloop_update(&simloop, &simout);
TEST_TRUE(simout.should_render);
TEST_EQUAL((t > 0) && ((t % EXPECT_UPDATE) == 0), simout.should_update);
}
}
/// A simulation loop with a render frame cap:
/// 1. Updates based on the desired update frame rate.
/// 2. Renders based on the desired render frame rate.
TEST_CASE(simloop_with_render_frame_cap) {
constexpr int UPDATE_FPS = 10;
constexpr int RENDER_FPS = 5;
const time_delta EXPECT_UPDATE = sec_to_time_delta(1.0 / (double)UPDATE_FPS);
const time_delta EXPECT_RENDER = sec_to_time_delta(1.0 / (double)RENDER_FPS);
const time_delta STEP = sec_to_time_delta(0.1);
const time_delta SIM_TIME_SEC = sec_to_time_delta(30);
Timer timer = {};
Simloop simloop = simloop_make(&(SimloopArgs){
.update_fps = UPDATE_FPS, .max_render_fps = RENDER_FPS, .timer = &timer});
SimloopOut simout;
for (time_delta t = 0; t < SIM_TIME_SEC; t += STEP) {
timer_advance(&timer, t);
simloop_update(&simloop, &simout);
// Also expecting initial render at t=0.
TEST_EQUAL((t % EXPECT_RENDER) == 0, simout.should_render);
TEST_EQUAL((t > 0) && ((t % EXPECT_UPDATE) == 0), simout.should_update);
}
}
int main() { return 0; }
|