I recently started reusing a couple of timers for UI animations, and noticed that they started breaking in strange ways. I peeked inside the CoreLibs and found the following:
When calling :pause()
on any timer, it sets the pauseOffset
for every timer, and no combination of :reset()
or :start()
restores this. This can cause timers to complete immediately (and skip over the entire UI animation in a single frame), including for example the timerX and timerY used in GridView.
I managed to fix this issue by changing the pauseOffset
into an instance property, and setting it back to 0
when calling :reset()
. Included a diff below for reference.
(btw this doesn't seem to be a recent change, traced it back to SDK 2.4.2 at least)
CoreLibs/timer.lua
--- CoreLibs/timer.lua 2025-05-22 00:22:32
+++ CoreLibs/timer-fix.lua 2025-05-25 16:16:41
@@ -86,6 +86,7 @@
o._endValue = endValue or 0
o._currentTime = 0
+ o._pauseOffset = 0
o.value = o._startValue
o.active = true
o.delay = 0
@@ -203,22 +204,19 @@
return playdate.timer.keyRepeatTimerWithDelay(300, 100, func, ...)
end
-
-local pauseOffset = 0
-
function playdate.timer:pause()
self.paused = true
if self._lastTime ~= nil and self.active == true then
- pauseOffset = playdate.getCurrentTimeMilliseconds() - self._lastTime
+ self._pauseOffset = playdate.getCurrentTimeMilliseconds() - self._lastTime
else
- pauseOffset = 0
+ self._pauseOffset = 0
end
end
function playdate.timer:start()
self.paused = false
- self._lastTime = playdate.getCurrentTimeMilliseconds() - pauseOffset
+ self._lastTime = playdate.getCurrentTimeMilliseconds() - self._pauseOffset
end
function playdate.timer:reset()
@@ -226,6 +224,7 @@
self._endValue = self.originalValues.endValue
self._easingFunction = self.originalValues.easingFunction
self._currentTime = 0
+ self._pauseOffset = 0
self._lastTime = nil
self.active = true
self.hasReversed = false