From 5458f3db7b08bf06c1f5c99a5851f6b270126b92 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sun, 5 Apr 2026 14:48:01 -0700 Subject: Initial simloop module --- simloop/src/simloop.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 simloop/src/simloop.c (limited to 'simloop/src') 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 @@ +#include + +#include + +static uint64_t ddt_from_fps(int fps) { + static constexpr double NANOSECONDS = 1e9; + return (fps == 0) ? 0 : (uint64_t)(NANOSECONDS / (double)fps); +} + +Simloop simloop_make(const SimloopArgs* args) { + assert(args); + assert(args->update_fps > 0); + + return (Simloop){ + .frame = 0, + .update = (SimloopTimeline){.ddt = ddt_from_fps(args->update_fps), + .last_step = args->timer->start_time}, + .render = (SimloopTimeline){ .ddt = ddt_from_fps(args->max_render_fps), + .last_step = args->timer->start_time}, + .timer = args->timer, + }; +} + +static time_delta time_elapsed(const Simloop* sim, time_point t) { + assert(sim); + return time_diff(sim->timer->start_time, t); +} + +static int step_update(const Simloop* sim, SimloopTimeline* timeline) { + assert(sim); + assert(timeline); + assert(timeline->ddt > 0); + + const time_delta dt = time_diff(timeline->last_step, sim->timer->last_tick); + const time_delta steps = dt / timeline->ddt; + timeline->last_step = time_add(timeline->last_step, dt); + return (int)steps; +} + +static bool step_render(const Simloop* sim, SimloopTimeline* timeline) { + assert(sim); + assert(timeline); + + bool render = false; + if (timeline->ddt > 0) { + render = step_update(sim, timeline) > 0; + } else { + timeline->last_step = sim->timer->last_tick; + render = true; + } + return render; +} + +void simloop_update(Simloop* sim, SimloopOut* out) { + assert(sim); + assert(out); + + const int new_frames = step_update(sim, &sim->update); + out->updates_pending = new_frames; + out->should_render = + step_render(sim, &sim->render) || + (sim->frame == 0); // Trigger an initial render on the first frame. + sim->frame += new_frames; + out->frame = sim->frame; + out->render_elapsed = time_elapsed(sim, sim->render.last_step); + out->update_elapsed = time_elapsed(sim, sim->update.last_step); + out->update_dt = sim->update.ddt; +} -- cgit v1.2.3