diff --git a/ModuleScripts/MergeTables.lua b/ModuleScripts/MergeTables.lua new file mode 100644 index 0000000..6a3b77a --- /dev/null +++ b/ModuleScripts/MergeTables.lua @@ -0,0 +1,58 @@ +--!strict + +-- A simple fixed step system scheduler +-- Fixed updates can happen multiple times per frame +-- Variable updates will happen after all fixed updates complete + +local FIXED_DELTA = (1 / 60) +local MAXIMUM_DELTA = (1 / 5) + +export type System = { + --> variable delta_time update, used for rendering + --> blend used for interpolation of simulation state + update: ((delta_time: number, blend: number) -> ())?, + --> fixed delta_time update, used for simulation + fixed_update: ((delta_time: number, frame: number) -> ())?, +} + +local function create(systems: {System}): (number) -> () + local frame = 0 + local accumulator = 0 + + return function(delta_time: number) + delta_time = math.min(delta_time, MAXIMUM_DELTA) + accumulator += delta_time + + local steps = 0 + local previous_frame = frame + + if (accumulator > 0) then + --> typically done with a while accumulator >= fixed_rate but this way is 35x faster + steps = accumulator // FIXED_DELTA + frame += steps + accumulator -= (steps * FIXED_DELTA) + end + + for step = 1, steps do + local step_frame = previous_frame + step + for _, system in systems do + if system.fixed_update == nil then + continue + end + + system.fixed_update(FIXED_DELTA, step_frame) + end + end + + local blend = accumulator / FIXED_DELTA + for _, system in systems do + if system.update == nil then + continue + end + + system.update(delta_time, blend) + end + end +end + +return create \ No newline at end of file