It looks like a timer's value keeps updating even after it's been paused? I expected it to not change after :pause() was called, and to only begin incrementing again after calling :start()
I put together a minimal repro - if you press A and check the console output you will see the value incrementing normally, but if you press A again, wait for a couple of seconds, and press A once more, you will notice the value has jumped as though the timer was never paused.
local timer = playdate.timer.new(12000, 1, 1000)
timer.updateCallback = function ()
print('timer update', timer.value)
timer.timerEndedCallback = function ()
print('timer end', timer.value)
local isPlaying = false
if isPlaying then
isPlaying = false
isPlaying = true
For now, editing CoreLibs/timer.lua so that the :start() function sets the timer's _lastTime value back to nil seems to work:
self._lastTime = nil
self.paused = false
I'm working on a game and I have this issue but I am not 100% sure how to edit the core libs timer file. Can you expand on how to update the core libs timer file so the timers work correctly? I looked for other threads but I cannot find anything. Appreciate any help, I have come a long way on my project just from looking at threads like this. Timers are the bane of my existence right now so I would love to get this right, I have the pause code written perfectly but my timer always resets!
timer.paused is a very welcome addition in the new SDK, but checking it has no effect on this issue.
I've created a new example with a video of the result for everyone coming to this thread at a later time. It highlighting the differences between timer and frameTimer (which behaves as expected). In this, I'm initializing timers that should count from 0 to 100 over the span of 10 seconds. Pausing the timer after calling updateTimers() once, and then resuming it after 5 seconds of runtime shows it jumps ahead to a value of 50, where as frameTimer behaves as expected and starts counting from 0:
-- timer increasing value from 0 to 100 across 10 seconds
local timer = playdate.timer.new(10000, 0, 100)
-- trigger timer once, then pause
-- add frametimer for comparison (we're running at the default 30FPS)
local frameTimer = playdate.frameTimer.new(300, 0, 100)
local elapsedGameTime = playdate.getElapsedTime()
-- continue timer after 5 seconds runtime
if timer.paused and elapsedGameTime > 5 then
timer:start() -- timer value will jump to half way instead of continuing from ~0.
playdate.graphics.drawText("elapsed game time: " .. elapsedGameTime, 10, 10)
playdate.graphics.drawText("timer.currentTime: " .. timer.currentTime, 10, 50)
playdate.graphics.drawText(" timer.timeLeft: " .. timer.timeLeft, 10, 70)
playdate.graphics.drawText(" *timer.value: " .. math.floor(timer.value) .. "*", 10, 95)
playdate.graphics.drawText("frameTimer.frame: " .. frameTimer.frame, 10, 130)
playdate.graphics.drawText(" *frameTimer.value: " .. math.floor(frameTimer.value) .. "*", 10, 155)
In the video you can see how the timer jumps ahead when being started again after 5 seconds:
Setting self._lastTime = nil in playdate.timer:start() would fix this.
tbh the fact that there's a fix here means we don't feel as much pressure to fix it in the SDK, so it slips through the cracks when we're prioritizing fixes. It's also something that could potentially change existing behavior in unexpected ways, and we have to be very careful there.
That said, there's a prospective fix in the queue currently scheduled for 2.1.2. That adds a timer._lastTime = playdate.getCurrentTimeMilliseconds() call to timer:start() instead of setting it to nil, not sure what difference that makes and I don't have the time right now to look into it.
The difference of doing timer._lastTime = playdate.getCurrentTimeMilliseconds() vs timer._lastTime = nil will be very subtle (and I suspect in most cases not noticeable at all).
During timer.updateTimers(), if timer._lastTime is nil, the delta since the last update will default to 0.
So the prospective fix with playdate.getCurrentTimeMilliseconds() is technically more correct.