It seems that when using the AButtonDown with a keyRepeat timer produces odd results when a limit is already reached. It means a code can be fired twice instead of once.
It may be hard to describe but obvious when you see it:
In this video, you see the PAUSE text being fired twice when the limit (10) is already reached.
Here is the github repository for reference: GitHub - Schyzophrenic/testKeyRepeatTimer
For information, this is run on SDK 2.0.1 on Windows Simulator
The code is as below:
local counter = 0
local keyTimer = nil
sprPause = nil
local sprCounter = gfx.sprite.spriteWithText("Counter - " .. counter, 300, 50)
sprCounter:moveTo(200, 120)
sprCounter:add()
function createPauseSpr()
local spr = gfx.sprite.spriteWithText("PAUSE", 300, 50)
spr:moveTo(math.random(350),math.random(220))
spr:add()
return spr
end
function pd.AButtonDown()
print("In A Down, adding counter")
local function incrementCounter()
print(string.format("A Down, counter at %d", counter))
print(keyTimer)
if counter >= 10 then
-- Let's stop the repeat and show the pause sprite
if keyTimer ~= nil then
print("Kill Timer in Down")
keyTimer:remove()
keyTimer = nil
end
sprPause = createPauseSpr()
else
counter += 1
end
print ("End incrementCounter")
end
keyTimer = pd.timer.keyRepeatTimer(incrementCounter)
end
function pd.AButtonUp()
if keyTimer ~= nil then
print("Kill Timer in Up")
keyTimer:remove()
keyTimer = nil
end
end
function pd.BButtonDown()
-- We get out of pause
-- counter = 0
if sprPause ~= nil then
sprPause:remove()
sprPause = nil
end
end
function pd.update()
local img = gfx.imageWithText("Counter - " .. counter, 300, 50)
sprCounter:setImage(img)
gfx.sprite.update()
pd.timer.updateTimers()
end
I am not sure if this is a bug or me misunderstanding some of the SDK functions. Thank you
I think it's working as expected. The reason it seems weird might just be because your keyRepeatTimer calls incrementCounter() once immediately, before it returns and assigns a value to your keyTimer variable. So in that first immediate call to incrementCounter() execution does not enter the if keyTimer ~= nil then block. On the first repeat call to incrementCounter() it does, so the timer is removed then.
Maybe it would make sense to add a counter check before calling keyTimer = pd.timer.keyRepeatTimer(incrementCounter) if you don't want it to fire in that case?
That indeed works because it prevents the creation of the timer and then execution of the code inside the callback.
Doubling the limit test in AButtonDown does the trick:
if counter < 10 then
keyTimer = pd.timer.keyRepeatTimer(incrementCounter)
else
sprPause = createPauseSpr()
end
That being said, when press A and my counter is already at the limit the callback is called once but the timer is not yet created. Wouldn't it make sense to have the callback called only once the timer is running?
I agree, it would still mean the code would then need to be executed in AButtonDown as well but it would seem more logical to have something like:
function pd.AButtonDown()
doAction()
keyTimer = pd.timer.keyRepeatTimer(doAction)
end
I see your point for sure... I almost want to say it used to work that way but my memories are foggy. Might be too late to change it now in any case, since people are already using it with the current behavior.
Since this is all implemented in CoreLibs/timer.lua you could always modify it to work that way if it makes more sense for your project!
I would rather not change the SDK lib, that would come and bite me later on:D
I totally get your point though, it really is a detail and we should not changed this behavior.
Maybe adding a note in the doc would be helpful? I spent quite a bit of time trying to understand what was wrong here haha