Page 1 of 1

How to handle multiple timers

Posted: Mon Mar 27, 2017 3:28 am
by mtdev
Playing around with an idea that has multiple bases. Player starts with 1 base and has a timer that increases units for it. My question is how should I handle the timer(s) for the npc bases? Have considered tracking the timer within the table for each base as they may need to differ from each other in the future.

Code: Select all

bases[id].timer = some float
Guess the question would be if that is the "normal" way to handle it?

Also, if anyone has any suggestions for how to draw the map, it would be helpful. Left click an NPC base to claim it and you will see what I am trying to solution. Current thought is to lock onto the player's starting base to start (as it does now) and then maybe have any right mouse clicks re-center the map. Thoughts?

Thanks for looking

Re: How to handle multiple timers

Posted: Tue Mar 28, 2017 3:44 pm
by Lucyy
The best way to do this is, like you said, by keeping track of the timers within the instances of your base object aka the table.

Your table would look something like:

Code: Select all

Base = {}
Base.Timer = 0
Base.createUnit = function()
    -- create your unit here
end
function Base:update(dt)
    this.Timer = this.Timer + dt

    if this.Timer >= 5 then
        this.createUnit()
        this.Timer = 0
    end
end
return Base
In this example the createUnit function would get called every 5 seconds for every instance of Base.

Re: How to handle multiple timers

Posted: Tue Mar 28, 2017 5:00 pm
by zorg
Lucyy wrote: Tue Mar 28, 2017 3:44 pm <Code snippet Snip>
if you define the parameter to :update as dt then you should use it as dt, not DT; lua is case-sensitive.

Re: How to handle multiple timers

Posted: Tue Mar 28, 2017 6:01 pm
by Lucyy
zorg wrote: Tue Mar 28, 2017 5:00 pm if you define the parameter to :update as dt then you should use it as dt, not DT; lua is case-sensitive.
My bad, typed it on my phone xD I didn't notice it auto-corrected it

Re: How to handle multiple timers

Posted: Wed Mar 29, 2017 3:48 am
by mtdev
Thank you Lucyy

I was thinking I might need every base to be on a different timer or probably in 1 of say 4 groups.

something like

Code: Select all

function love:update(dt)
	for _,base in pairs(bases)
		base.timer = base.timer - dt
		if base.timer <= 0 then
			createUnit(blah, blah)
			base.timer = base.defaultTimer (could be 1, 2, etc... - different for various bases)
		end
	end		
end
There would be at least 40 of these and perhaps more. Any gotchas come to mind? Thanks again!

Re: How to handle multiple timers

Posted: Wed Mar 29, 2017 4:37 am
by Lucyy
That seems about right ;o though you'd probably reset your timer to 0, no reason to start counting at 1.

And I recommend moving the code within your loop into an update function in your base object. And then change the loop to be like:

Code: Select all

for _, base in ipairs(bases) do
    base:update(dt)
end
This way your love.update will look a bit cleaner

Re: How to handle multiple timers

Posted: Wed Mar 29, 2017 3:32 pm
by s-ol
Lucyy wrote: Wed Mar 29, 2017 4:37 am That seems about right ;o though you'd probably reset your timer to 0, no reason to start counting at 1.

And I recommend moving the code within your loop into an update function in your base object. And then change the loop to be like:

Code: Select all

for _, base in ipairs(bases) do
    base:update(dt)
end
This way your love.update will look a bit cleaner
In the last example he doesn't start counting at 1, he starts counting at the duration and decrements to 0, which is the proper way to do it IMO.
mtdev wrote: Wed Mar 29, 2017 3:48 am There would be at least 40 of these and perhaps more. Any gotchas come to mind? Thanks again!
That's far from a problematic amount of 'things of this complexity' to handle, and it's perfectly usual to keep this many seperate timers running :)

Lucyy is right that it may get easier to manage lots of different types of objects if you start encapsulating them OOP-style like in his example, but don't feel urged to do it if you don't see the need (yet) or it makes the project less simple to read in your opinion.

Re: How to handle multiple timers

Posted: Wed Mar 29, 2017 4:19 pm
by zorg
s-ol wrote: Wed Mar 29, 2017 3:32 pm In the last example he doesn't start counting at 1, he starts counting at the duration and decrements to 0, which is the proper way to do it IMO.
If not the proper way, i do agree that it's easier to code if a variable used as a counter going from someVal down to zero, since wherever you want to implement the check, you only need to compare the counter with 0, not any stored value.

Re: How to handle multiple timers

Posted: Wed Mar 29, 2017 4:28 pm
by s-ol
zorg wrote: Wed Mar 29, 2017 4:19 pm
s-ol wrote: Wed Mar 29, 2017 3:32 pm In the last example he doesn't start counting at 1, he starts counting at the duration and decrements to 0, which is the proper way to do it IMO.
If not the proper way, i do agree that it's easier to code if a variable used as a counter going from someVal down to zero, since wherever you want to implement the check, you only need to compare the counter with 0, not any stored value.
Lucyy just asked about my reasoning in a PM and I already wanted to come back and change the wording too. When I have the choice to use either (because the limit is constant, see below) I go with this way and I consider it slightly superior because of what you said - it's cleaner when the limit is only read on reset, because it groups the action taken and the time to get there in your code visually. Someone might disagree here, and I guess it is personal choice.

However both ways definitely have their own reasons to be used, consider:

Code: Select all

local timer = 0

function love.update(dt)
  maxTimer = love.mouse.isDown(1) and 4 or 2
  if timer > maxTimer then
    timer = 0
    -- do something
  end
end
and

Code: Select all

local timer = 2

function love.update(dt)
  maxTimer = love.mouse.isDown(1) and 4 or 2
  if timer < 0 then
    timer = timer + maxTimer
    -- do something
  end
end
these two timers will have different behavior when the mouse is pressed and depressed anytime else than right on a timer reset.
This actual logic difference of course matters and the right one should be chosen (there are other ways to produce both behaviors, but these are the simplest I think).