hello guys,
I want to fire the callback functions of my buttons at a certain FPS. The most clean solution for me, would be misusing tweens for this. But the tween doenst seem to even start. Why is that?
-- Long press handler
tween(.1, {}, {}, {loop = tween.loop.forever, easing = tween.easing.linear}, function()
if self.press_timer and self.press_timer < ElapsedTime then
self.callback()
end
end)
Complete code of the class
Button = class(Label)
function Button:init(params)
self.callback = params.callback
Label.init(self, params)
-- Long press handler
tween(.1, {}, {}, {loop = tween.loop.forever, easing = tween.easing.linear}, function()
if self.press_timer and self.press_timer < ElapsedTime then
self.callback()
end
end)
end
function Button:draw()
fill(47, 96, 156, 255)
rect(self.x, self.y, self.width, self.height)
fill(187, 159, 132, 255)
text(self.label, self.x, self.y)
end
function Button:touched(touch)
if touch.x > self.x - self.width*.5
and touch.x < self.x + self.width*.5
and touch.y > self.y - self.height*.5
and touch.y < self.y + self.height*.5 then
self.press_timer = self.press_timer or (ElapsedTime + .25)
if touch.state == ENDED then
self.press_timer = nil
self.callback()
end
else
self.press_timer = nil
end
end
I’m not really what this is meant to do. So when the button is pressed, you want the callback to fire once every frame for 0.25 seconds, is that right?
If so, I would get rid of the tween altogether and add something to the Button:draw method (or add a separate Button:update method if you want to keep drawing and logic separate), like this:
if self.press_timer then
if ElapsedTime > self.press_timer then
self.press_timer = nil
else
self.callback()
end
end
Callbacks only call once the tween has finished, so the callbacks of looping tweens (forever or pingpong) never fire (though it would be more useful if they fired at the end of each cycle)
not quite. if the button is ?tapped? I fire the callback once. But after .25 seconds the touch is considered to be a ?long press? in which case the callback must be fired every .5 seconds
I know i can solve it with timers only, but I wanted to have a clean draw function in this class…
@yojimbo2000 I assumed that callbacks are fired after each loop cycle… ahhh I see. good to know. thank you!
@Ignatz no I tried this long ago and it worked. The tween does not need any parameters to tween, actually.
here is the working code with timers for anyone interested in
Button = class(Label)
function Button:init(params)
self.callback = params.callback
self.frequency = .05
Label.init(self, params)
end
function Button:draw()
fill(47, 96, 156, 255)
rect(self.x, self.y, self.width, self.height)
fill(187, 159, 132, 255)
text(self.label, self.x, self.y)
-- Long press handler
if self.press_timer and self.press_timer < ElapsedTime then
if not self.cb_timer or (self.cb_timer and self.cb_timer < ElapsedTime) then
self.cb_timer = ElapsedTime + self.frequency
self.callback()
end
end
end
function Button:touched(touch)
if touch.x > self.x - self.width*.5
and touch.x < self.x + self.width*.5
and touch.y > self.y - self.height*.5
and touch.y < self.y + self.height*.5 then
self.press_timer = self.press_timer or (ElapsedTime + .25)
if touch.state == ENDED then
self.press_timer = nil
self.callback()
end
else
self.press_timer = nil
end
end
@se24vad , a looping timer is not difficult to implement with tweens: you just need to chain them together. Here is one possible implementation:
--# Main
-- Timer Demo
function setup()
print("START at: " .. os.date())
-- create a timer with 1.5 second delay
t1 = Timer(1.5, function()
print(ElapsedTime)
end)
t1:start({ loop = true, firstNoDelay = true })
-- use another timer to stop the first one
-- after 10 seconds
t2 = Timer(10, function()
t1:stop()
print("DONE at: " .. os.date())
end)
t2:start()
end
--# Timer
Timer = class()
function Timer:init(delay, callback)
self.delay = delay
self.callback = callback
end
function Timer:start(options)
local f
f = function()
self.callback()
if options and options.loop then
self.t = tween.delay(self.delay, f)
end
end
if options and options.firstNoDelay then
f()
else
self.t = tween.delay(self.delay, f)
end
end
function Timer:stop()
if self.t then
tween.stop(self.t)
self.t = nil
end
end
I did some progress on my app and wanted to share my exitement with you (code fallows shortly in a separate thread)
The idea was to make animations with #procreate and quickly use them as assets inside #codea games. But procreate doesn’t have any animation tools. - This app allows you to import your procreate artwork and project animation frames onto it. When you are done refining your artwork and satisfied with the animation, you can simply export a clean spritesheet and use it inside your game engine.