I have a Class that contains an imagetable with "numbers" and I want to update the numbers while I keep pressing a button. However, the numbers change too fast... pressing the button just half a second will call the update method several times. I tried to play with timers but I couldn't improve this behaviour.
How could I do it? For example, for a screen in which you have to select a number.
main.lua
import "CoreLibs/object"
import "CoreLibs/graphics"
import "CoreLibs/sprites"
import "CoreLibs/timer"
local pd <const> = playdate
local gfx <const> = pd.graphics
import "number"
local number = Number(pd.display.getWidth() / 4, pd.display.getHeight() / 1.75)
local function initialize()
number:add()
end
initialize()
function pd.update()
gfx.sprite.update()
pd.timer.updateTimers()
end
number.lua
import "CoreLibs/sprites"
local pd <const> = playdate
local gfx <const> = pd.graphics
class('Number').extends(gfx.sprite)
function Number:init(x, y)
Number.super.init(self)
-- image table is 7 wide by 3 tall, each cell is 48x48 pixels
self.swimImages = gfx.imagetable.new('images/numbers')
self.tableWidth = 7
self.tableColumn = 1
self.tableRow = 0
self.positionX = x
self.positionY = y
self:reset()
self:addSprite()
end
function Number:reset()
self:updateFrame();
self:moveTo(self.positionX, self.positionY)
end
function Number:updateFrame()
self:setImage(self.swimImages[self.tableColumn + self.tableWidth * self.tableRow])
end
function Number:update()
if pd.buttonIsPressed(pd.kButtonUp) then
self:increaseNumber()
end
pd.timer.updateTimers()
end
function Number:increaseNumber()
-- local function timerCallback()
-- print('increase number')
-- if self.tableColumn + 1 <= 7 then
-- self.tableColumn = self.tableColumn + 1
-- else
-- self.tableColumn = 1
-- end
-- print('increase number: ', self.tableColumn)
-- self:updateFrame()
-- end
-- pd.timer.performAfterDelay(1000, timerCallback)
if self.tableColumn + 1 <= 7 then
self.tableColumn = self.tableColumn + 1
else
self.tableColumn = 1
end
print('increase number: ', self.tableColumn)
self:updateFrame()
end
Thank you and sorry for my English as it's not my first language.
I just found the solution. I was mistaking adding delay for a timer.
local playTimer = nil
local playTime = 1000
local function resetTimer()
playTimer = playdate.timer.new(playTime, playTime, 0, pd.easingFunctions.linear)
end
function Number:init(x, y)
...
...
resetTimer()
end
function Number:update()
if playTimer.value == 0 then
if pd.buttonIsPressed(pd.kButtonUp) then
self:increaseNumber()
resetTimer()
end
end
pd.timer.updateTimers()
end
Depending on what behavior you want, you can also use pd.buttonJustPressed instead of pd.buttonIsPressed. That way, a single press of the button will only increase your number once, and you have to release the button and press it again. Here's the documentation.
And if you want to be able to keep the button pressed, but just want to slow things down, you can use a separate counter and only increase the number on every n'th frame.
For example, this allows you to press-and-hold, but it will only increase the number ever 15 frames (i.e. twice a second):
-- start at -1 so that the very first time causes an immediate number increase
local count = -1
function Number:update()
if pd.buttonIsPressed(pd.kButtonUp) then
count = (count + 1) % 15
if count == 0 then self:increaseNumber() end
else
-- reset the count when the user releases the button
count = -1
end
pd.timer.updateTimers()
end
Personally I think I'd go with a counter because to me it feels clearer (you have to do less mental juggling of timer behavior). And I guess technically your current implementation creates a lot of timer objects (but I assume it wouldn't be so many that GC pressure will become a major issue).
On the other hand, one advantage of your approach is that the speed is mostly independent of the framerate (but, if it matters, you could get the same from the counter approach if you don't increment by 1, but by a measure of "time passed since the last frame").
Also consider keyRepeatTimer() which can optionally have a little longer delay after the first action, and then go into fast repeating (imitating what happens when you hold a key on a computer keyboard).
EDIT: I don't know why the forum keeps stripping the last part of the docs link: