58 lines
No EOL
1.7 KiB
Lua
58 lines
No EOL
1.7 KiB
Lua
--!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 |