aboutsummaryrefslogtreecommitdiff
path: root/simloop/src/simloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'simloop/src/simloop.c')
-rw-r--r--simloop/src/simloop.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/simloop/src/simloop.c b/simloop/src/simloop.c
new file mode 100644
index 0000000..11f4d6d
--- /dev/null
+++ b/simloop/src/simloop.c
@@ -0,0 +1,68 @@
1#include <simloop.h>
2
3#include <assert.h>
4
5static uint64_t ddt_from_fps(int fps) {
6 static constexpr double NANOSECONDS = 1e9;
7 return (fps == 0) ? 0 : (uint64_t)(NANOSECONDS / (double)fps);
8}
9
10Simloop simloop_make(const SimloopArgs* args) {
11 assert(args);
12 assert(args->update_fps > 0);
13
14 return (Simloop){
15 .frame = 0,
16 .update = (SimloopTimeline){.ddt = ddt_from_fps(args->update_fps),
17 .last_step = args->timer->start_time},
18 .render = (SimloopTimeline){ .ddt = ddt_from_fps(args->max_render_fps),
19 .last_step = args->timer->start_time},
20 .timer = args->timer,
21 };
22}
23
24static time_delta time_elapsed(const Simloop* sim, time_point t) {
25 assert(sim);
26 return time_diff(sim->timer->start_time, t);
27}
28
29static int step_update(const Simloop* sim, SimloopTimeline* timeline) {
30 assert(sim);
31 assert(timeline);
32 assert(timeline->ddt > 0);
33
34 const time_delta dt = time_diff(timeline->last_step, sim->timer->last_tick);
35 const time_delta steps = dt / timeline->ddt;
36 timeline->last_step = time_add(timeline->last_step, dt);
37 return (int)steps;
38}
39
40static bool step_render(const Simloop* sim, SimloopTimeline* timeline) {
41 assert(sim);
42 assert(timeline);
43
44 bool render = false;
45 if (timeline->ddt > 0) {
46 render = step_update(sim, timeline) > 0;
47 } else {
48 timeline->last_step = sim->timer->last_tick;
49 render = true;
50 }
51 return render;
52}
53
54void simloop_update(Simloop* sim, SimloopOut* out) {
55 assert(sim);
56 assert(out);
57
58 const int new_frames = step_update(sim, &sim->update);
59 out->updates_pending = new_frames;
60 out->should_render =
61 step_render(sim, &sim->render) ||
62 (sim->frame == 0); // Trigger an initial render on the first frame.
63 sim->frame += new_frames;
64 out->frame = sim->frame;
65 out->render_elapsed = time_elapsed(sim, sim->render.last_step);
66 out->update_elapsed = time_elapsed(sim, sim->update.last_step);
67 out->update_dt = sim->update.ddt;
68}