Page 1 of 1

Timer - a timer expiration lib

Posted: Sat Jun 27, 2015 4:31 pm
by Almia
Hello :D

I'm a bit newbie in this game engine and lua and I wanted to create a game, though it made it harder for me because of the love.update() function which I have to add functions on my every single lib that needs periodic execution. Because of this I created a small library that allows you to create "timers" that periodically executes or executes delayed functions.

Code:

Code: Select all

--[[

timer.lua by Almia

a library that handles periodic or delayed execution of functions
via virtual timers.

Timers has a minimum of 32 executions per second.
--------------------------------------------

	API
	
	timer.start(timeout, doReset, handler)
		- starts a timer
			*timeout - how often the timer executes handlers
			*doReset - does the timer executes again?
			*handler - the initial handling function that
						is executed every time the timer expires.
	
	timer:pause()
		- pauses the timer
	
	timer:resume()
		- resumes the timer
		
	timer:setTimeout(timeout)
		- changes/sets the timer's timeout
		
	timer.update(dt)
		- must be put inside the love.update, also having the love.update's dt
]]--
MIN_TIMEOUT = 0.031250000 -- 32 frames
timer = {}
timer.__index = timer
local timers = {}

function timer.start(timeout, doReset, handler)
	if type(timeout) == "number" then
		if timeout <= MIN_TIMEOUT then
			timeout = MIN_TIMEOUT
		end
	else
		timeout = MIN_TIMEOUT
	end
	
	local new = {active = true,
				 timeout = timeout,
				 doReset = doReset,
				 handler = handler,
				 prev = love.timer.getTime()}
	table.insert(timers, new)
	setmetatable(new, timer)
	return new
end

function timer:pause()
	self.active = false
end

function timer:resume()
	self.active = true
end

function timer:setTimeout(timeout)
	if timeout <= MIN_TIMEOUT then
		timeout = MIN_TIMEOUT
	end
	if self.active then
		self.prev = love.timer.getTime()
	end
	self.timeout = timeout
end

function timer.update()
	dt = love.timer.getTime()
	for k, t in ipairs(timers) do
		if t.active then
			if dt - t.prev >= t.timeout then
				t.handler()
				if t.doReset then
					t.prev = dt
				else
					t.pause()
				end
			end
		end
	end
end
Sample code:

Code: Select all

require "timer"
function love.load()
	local t = 0.031250000
	text = {}
	for i = 1,32 do
		text[i] = 0
		timer.start(t, true, function ()
			text[i] = text[i] + 1
		end)
		t = t + MIN_TIMEOUT
	end
end

function love.update()
	timer.update()
end

function love.draw()
	local y = 0
	local yg = 600/32
	for i = 1, 32 do
		love.graphics.print((33 - i).." frames : "..text[i], 100, y)
		y  = y + yg
	end
end
If you have any suggestions, I would appreciate it :D

[edit]
Update 1.1
- Merged .start with .new
- Timers now handles only single functions
- added .resume function
- (Misc) improved demo

Re: Timer - a timer expiration lib

Posted: Sat Jun 27, 2015 8:16 pm
by airstruck
Looks pretty good. A few thoughts:
  • Use "local" to declare local variables so they don't pollute the global scope.
  • Some identifiers use camelCase and others use snake_case, try to be consistent.
  • The name "timer_stack" seems a little stange, it doesn't really have stack-like qualities. Just "timers" might be better.
  • If you pass dt to the update function, you can probably get rid of love.timer.getTime(), making the code framework-agnostic.
  • Having multiple callbacks associated with individual timers seems odd, it doesn't seem like that should be the timer's responsibility.
  • Having two separate steps to create and start timers feels a little cumbersome. Starting them on creation could simplify the API.
  • If you like having two steps anyway, consider moving the parameters from "start" into "new." Those feel more like initialization parameters.

Re: Timer - a timer expiration lib

Posted: Sun Jun 28, 2015 3:19 am
by Almia
Thank you :D

I have updated all of it except for the "dt" thing. It seems that it doesn't work because all of the timers doesn't tick or maybe i'm just missing something that i didn't know with the "dt" (perhaps the value "dt" contains)

Re: Timer - a timer expiration lib

Posted: Sun Jun 28, 2015 7:04 am
by T-Bone
The variable name "dt" is typically used for delta-time (the time between the previous frame and the current one). You seem to use it for the time since the "epoch" instead, which is probably the source of the confusion.

Re: Timer - a timer expiration lib

Posted: Sun Jun 28, 2015 10:57 am
by airstruck
T-Bone wrote:You seem to use it for the time since the "epoch" instead, which is probably the source of the confusion.
I don't think it was there in the first version. Sorry for the confusion, I meant you could pass the dt parameter from love.update on to timer.update, then you wouldn't need getTime.

Code: Select all

function love.update (dt)
   timer.update(dt)
end

Re: Timer - a timer expiration lib

Posted: Sun Jun 28, 2015 12:04 pm
by Almia
That's what i did. Though i think dt returns the time between the last update and the current update, whereas Timer uses the time since the program is run.

Re: Timer - a timer expiration lib

Posted: Mon Jun 29, 2015 5:32 am
by T-Bone
time thief wrote:
T-Bone wrote:You seem to use it for the time since the "epoch" instead, which is probably the source of the confusion.
I don't think it was there in the first version. Sorry for the confusion, I meant you could pass the dt parameter from love.update on to timer.update, then you wouldn't need getTime.

Code: Select all

function love.update (dt)
   timer.update(dt)
end
My post was directed to OP, not you. But yeah :)



What I was specifically refering to was this line:

Code: Select all

dt = love.timer.getTime()
According to the documentation, getTime returns the time since the epoch, not a time difference.