Files
gen1recomp/tests/engine/fast_forward_rate_bug2471.lua

92 lines
3.2 KiB
Lua

package.path = "./?.lua;./?/init.lua;" .. package.path
local T = require("tests.harness")
local check, eq = T.check, T.eq
love = love or require("tests.love_stub")
local FixedStep = require("src.core.FixedStep")
local GameSpeed = require("src.core.GameSpeed")
local STEP = FixedStep.STEP
local function run(speed, fps, frames, clock, period)
local now = 0
local steps, maxPerFrame, maxAccum = 0, 0, 0
FixedStep.refreshPeriod = period
FixedStep:init(function()
steps = steps + 1
if clock == "ms" then now = now + 0.001 end
end)
FixedStep.clock = function() return now end
local dt = 1 / fps
for _ = 1, frames do
local before = steps
FixedStep.maxAccum = FixedStep.catchupLimit(speed, dt)
FixedStep:update(dt, speed)
if clock == "ms" then now = now + 0.004 end
if steps - before > maxPerFrame then maxPerFrame = steps - before end
if FixedStep.accum > maxAccum then maxAccum = FixedStep.accum end
end
FixedStep.clock = nil
FixedStep.refreshPeriod = nil
return steps, maxPerFrame, maxAccum
end
for _, speed in ipairs(GameSpeed.LEVELS) do
local steps = run(speed, 60, 60, "frozen")
check(math.abs(steps - 60 * speed) <= 1,
("%dX at 60fps: %d logic steps a second (want %d)"):format(speed, steps, 60 * speed))
local slow = run(speed, 30, 30, "frozen")
check(math.abs(slow - 60 * speed) <= 1,
("%dX at 30fps: %d logic steps a second (want %d)"):format(speed, slow, 60 * speed))
local mid = run(speed, 45, 45, "frozen")
check(math.abs(mid - 60 * speed) <= 1,
("%dX at 45fps: %d logic steps a second (want %d)"):format(speed, mid, 60 * speed))
end
local fast = run(200, 60, 60, "frozen")
local ten = run(10, 60, 60, "frozen")
check(fast >= ten * 15,
("200X runs far more logic than 10X on a fast frame (%d vs %d)"):format(fast, ten))
local steps, perFrame, carried = run(200, 60, 60, "ms", 1 / 60)
check(perFrame >= 11 and perFrame <= 14,
("200X on a slow device stops at the frame budget (%d steps a frame)"):format(perFrame))
check(carried < STEP,
("the unpaid debt is dropped, not carried (max accum %.4f)"):format(carried))
check(steps >= 60 * 11,
("and still runs as fast as the device allows (%d steps)"):format(steps))
local oneX = run(1, 60, 60, "ms", 1 / 60)
eq(oneX, 60, "1X ignores the work budget")
local function hitchBurst(speed, hitch)
local n = 0
FixedStep.refreshPeriod = nil
FixedStep.clock = function() return 0 end
FixedStep:init(function() n = n + 1 end)
for _ = 1, 30 do
FixedStep.maxAccum = FixedStep.catchupLimit(speed, 1 / 60)
FixedStep:update(1 / 60, speed)
end
n = 0
FixedStep.maxAccum = FixedStep.catchupLimit(speed, hitch)
FixedStep:update(hitch, speed)
FixedStep.clock = nil
return n
end
for _, speed in ipairs({ 1, 2, 4, 10 }) do
local cap = math.max(2, math.floor(speed * 1.5 + 1e-9))
for _, hitch in ipairs({ 0.05, 0.1, 0.25, 1.0 }) do
local n = hitchBurst(speed, hitch)
check(n <= cap,
("%dX: a %.0fms hitch is not repaid as a burst (%d steps, max %d)"):format(speed, hitch * 1000, n, cap))
end
end
eq(hitchBurst(1, 0.25), 2, "1X after a 250ms hitch runs 2 steps, like before the budget")
FixedStep:init(function() end)
FixedStep.maxAccum = FixedStep.MAX_ACCUM
T.finish("fast forward rate bug 2471")