Execute a function on a repeating timer (SOLVED)


#1

I have seen and used the timer module provided by britzl (thanks for that btw).

Is there a similar module or modification that will make it repeatable? I have a particular moment function that I would like to put on repeat about every 2-5 seconds.

Thanks.


Implement Gamedistribution ads using webview
Alarms/Wait function? (SOLVED)
#2

You could just repeatedly call timer.seconds() or add it as another function on the timer module:

function M.repeat_seconds(seconds, callback)
	M.seconds(seconds, function()
		callback()
		M.repeat_seconds(seconds, callback)
	end)
end

And in some script:

local timer = require "timer"

function init(self)
	timer.repeat_seconds(3, function()
		print("yay")
	end)
end

function final(self)
	timer.cancel_all()
end

function update(self, dt)
	timer.update(dt)
end

#3

This works perfectly, thank you!


#4

This variant will be better if user need to cancel timers by callback (your variant create timer after callback, and timer continue working):

function M.repeat_seconds(seconds, callback)
	M.seconds(seconds, function()
		M.repeat_seconds(seconds, callback)
		callback() -- callback call after create a new repeat
	end)
end

Delay functions?
Defold Timer - The native timer extension
#5

I’m attempting to use your M.repeat_seconds() example for my game.

Where do I specify how many seconds for the repeating code, and where do I put the code to repeat?


#6

The callback argument is supposed to be a function that you wish to get repeated calls to. Like this:

local timer = require "timer"

timer.repeat_seconds(10, function()
    print("I will be called every 10 seconds")
end)

#7

Is it possible to call the callback function with some additional arguments?

I need to refer to some global properties that I created in the init() function and they are stored inside “self”. But I can’t access to self because the timer module does not allow to pass any argument.

function init(self)
    self.start_x_position = go.get_position().x
    timer.seconds( 2 , respawn)
end

function update(self, dt)
    timer.update(dt)
end

function respawn()
    -- can't access to self because I can't pass it as an argument to the function
    print self.start_x_position
end

Thanks in advance :slight_smile:


#8

Since you setup the timer from the init() function you also have access to self from within the callback function. Try something like this:

local function respawn(self)
    print self.start_x_position
end

function init(self)
    self.start_x_position = go.get_position().x
    timer.seconds( 2 , function()
        respawn(self)
    end)
end

function update(self, dt)
    timer.update(dt)
end

#9

Yup, it seems like working. Thanks a lot! :slight_smile:


#10

Have a new problem with the timer script :frowning:
When I run the project locally, everything looks fine.
When I run it on an iPhone 6 with last iOS version, it still works fine but I have the following error message in the console when the timer is completed:

ERROR:SCRIPT: invalid key to 'next’
stack traceback:
[C]: in function '(for generator)'
main.timer:45: in function 'update’
laser/laser_controller.script:111: in function <laser/laser_controller.script:110>

The update function of my script has only this:

function update(self, dt)
    timer.update(dt)
end

If I run the game on older devices with iOS 7, they freeze in that same moment (when I get the error log on other devices).

Any idea?
Don’t know if it can help, but I’m using two timers (the second starts when the first one is done) and I get this error message when the second timer is done (and that point, the first timer should start again).


#11

It seems like there’s a problem with the timer callback function. What if you replace all of that code with a simple print() or something?


#12

I found out what was the problem :slight_smile:
Since the function was generating some random numbers, I thought that creating a new seed for every call, it would have improved the randomness. But I was using this line of code:

math.randomseed( os.time() - os.clock() * 1000 * self.start_time)

So it was probably something with os.time() or os.clock() inside the looped timer that creating some problems.


#13

How to get the time? I want to display that on GUI node.


#14

Check out os.date() and os.time().

https://www.lua.org/pil/22.1.html


#15

I am sorry what i mean get number of second from timer above.


#16

Are you using the timer module I published as a Gist? I would suggest that you perhaps return the Lua table that is inserted into the list of timers here:

https://gist.github.com/britzl/0f6291990b0b11f92775#file-timer-lua-L23 And then read the seconds/frames value.


#17

Thx, I add getSec() function on module like this :

function M.getSec()
  for k,timer in pairs(timers) do
	return math.ceil(timer.seconds)
  end	
end

#18

Ok, but that would return the time left for one timer (and maybe not even their first one). You could potentially have many timers running at the same time. That is why I think it’s better if you return something when you create the timer and then directly read from that data or use it to look up the time left.


#19

You are right, i am tested create second timer instance, it show same number even if i make different parameter,
can you give me example how to implement it in code?
I am really confuse.


#20

I’ve updated the Gist: https://gist.github.com/britzl/0f6291990b0b11f92775 Now you can do like this:

local timer = require "timer"

function init(self)
    self.t1 = timer.seconds(10, function() print("time's up!") end)
    self.t2 = timer.seconds(5, function() print("time's up!") end)
    self.t3 = timer.frames(10, function() print("time's up!") end)
end

function update(self, dt)
	timer.update(dt)
	print("Time left on timer 1:", timer.time_left(self.t1))
	print("Time left on timer 2:", timer.time_left(self.t2))
	print("Time left on timer 3:", timer.time_left(self.t3))
end