Page 1 of 2

Change dt or use another timeformat?

Posted: Wed Oct 05, 2011 9:16 am
by TheEmperorOfLulz
Hello all LÖVE users,

I recently started with LÖVE and i want to create a program that counts. However, i need it to not count in dt, but for every second instead. Is there a way i can change the duration of dt? Or do i use another timeformat in this case?

Thanks:)

TehEmperorOfLulz

Re: Change dt or use another timeformat?

Posted: Wed Oct 05, 2011 11:21 am
by kikito
Hi there, welcome!

There are several ways to do this.

One option is manually storing "how much time has passed" since the last dt, and trigger the proper action when a second has passed.

Another option is using my library, cron.lua, which basically does the "manual accumulation in a variable" for you.

For example, let's say we have a troll whose energy increases 1 point per second:

Code: Select all

cron = require 'cron'

function love.update(dt)
  cron.update(dt) -- you must do this once inside love.update
  ...
  trollClock = cron.every(1, function()
    troll.energy = troll.energy + 1
  end)
  ...
  cron.cancel(trollClock) -- this stops the clock, for example when the troll dies
  
end
If you need things to happen every second, then probably 1 clock is enough for you. But you can create as many clocks as you need. The first parameter of cron.every controls the amount of seconds. You can create an action that happens every 60 seconds, or every 0.5 seconds, if you need to.

In addition to periodic actions, cron also allows to program actions that happens some time in the future, but only once. You can do that with cron.after .

Re: Change dt or use another timeformat?

Posted: Wed Oct 05, 2011 12:05 pm
by thelinx
dt is in seconds. It's just a very short amount of time between each update.

Re: Change dt or use another timeformat?

Posted: Wed Oct 05, 2011 1:57 pm
by Taehl
This may be useful to you:

Code: Select all

function love.update(dt)
	local wholeSeconds = math.floor(love.timer.getTime())
end

Re: Change dt or use another timeformat?

Posted: Wed Oct 05, 2011 4:13 pm
by T-Bone
I usually do something like this

Code: Select all

function love.load()
    time = 0
end

function love.update(dt)
   time = time + dt
   if time > 1 then
       --do something
       time = 0
   end
end

Re: Change dt or use another timeformat?

Posted: Wed Oct 05, 2011 4:45 pm
by Boolsheet
T-Bone wrote:I usually do something like this

Code: Select all

function love.load()
    time = 0
end

function love.update(dt)
   time = time + dt
   if time > 1 then
       --do something
       time = 0
   end
end
You'll lose a few milliseconds with that approach. time could be 1.009 and you set it back to 0. To stay accurate subtract your limit from time.

Re: Change dt or use another timeformat?

Posted: Thu Oct 06, 2011 2:10 pm
by tentus
T-Bone wrote:I usually do something like this

Code: Select all

function love.load()
    time = 0
end

function love.update(dt)
   time = time + dt
   if time > 1 then
       --do something
       time = 0
   end
end
Like Boolsheet said, that can be inaccurate. Suppose your app is struggling and running just barely faster than 3 frames per second. The following code will keep you from losing ~ one third of a second every second.

Code: Select all

function love.update(dt)
   time = time + dt
   if time > 1 then
       time = time - 1
   end
end

Re: Change dt or use another timeformat?

Posted: Fri Oct 07, 2011 5:41 am
by TheEmperorOfLulz
kikito wrote:

Code: Select all

cron = require 'cron'

function love.update(dt)
  cron.update(dt) -- you must do this once inside love.update
  ...
  trollClock = cron.every(1, function()
    troll.energy = troll.energy + 1
  end)
  ...
  cron.cancel(trollClock) -- this stops the clock, for example when the troll dies
  
end
That all looks awesome. There's just one problem... How do i install it? I really don't know how to do that:)

Also, in the code, you say

Code: Select all

trollClock = cron.every(1, function()
To me, it looks like you let out a parenthesis. Is that an error, or did you do it on purpose?

TheEmperorOfLulz

Re: Change dt or use another timeformat?

Posted: Fri Oct 07, 2011 6:31 am
by kikito
TheEmperorOfLulz wrote: There's just one problem... How do i install it? I really don't know how to do that:)
Just download this file and put it next to your main.lua file (same dir): https://raw.github.com/kikito/cron.lua/master/cron.lua

Then you can include it in main by doing this:

Code: Select all

cron = require 'cron'
And that's it. You are ready to use cron.every, cron.after, etc.
TheEmperorOfLulz wrote: Also, in the code, you say

Code: Select all

trollClock = cron.every(1, function()
To me, it looks like you let out a parenthesis. Is that an error, or did you do it on purpose?
It's on purpose. Ignoring the troll.health line, the code is like this:

Code: Select all

trollClock = cron.every(1, function()
  ...
end)
As you can see, the function() part gets "closed" by the "end" on the third line. That function() ... end structure is called "anonymous function" (because it doesn't have a name). Anonymous functions are very used in Lua, for places where you need a function in one place, but you know you are not going to use it in any other places.

If you have difficulties figuring it out, this code is equivalent to the one on my first post:

Code: Select all

cron = require 'cron'

function increaseTrollEnergy()
  troll.energy = troll.energy + 1
end

function love.update(dt)
  cron.update(dt) -- you must do this once inside love.update
  ...
  trollClock = cron.every(1, increaseTrollEnergy)
  ...
  cron.cancel(trollClock) -- this stops the clock, for example when the troll dies
end
In this case, I've replaced the anonymous function by a regular function called increaseTrollEnergy. The only difference is that there is a global function called increaseTrollEnergy now - since I only needed to use it in one place, it didn't seem necesary.

Well, this is not entirely true; the code is equivalent only if the troll variable is available in both increaseTrollEnergy and love.update. If it was a local variable created inside love.update, then you would have to pass it as a parameter - like this:

Code: Select all

cron = require 'cron'

function increaseTrollEnergy(troll)
  troll.energy = troll.energy + 1
end

function love.update(dt)
  cron.update(dt) -- you must do this once inside love.update
  ...
  local troll = something() -- troll is a local variable created inside love.update
  ...
  trollClock = cron.every(1, increaseTrollEnergy, troll) -- we pass it as a parameter
  ...
  cron.cancel(trollClock) -- this stops the clock, for example when the troll dies
end
I don't know if this helps you or makes it more difficult to understand :) . Let me know if you have more questions.

Re: Change dt or use another timeformat?

Posted: Fri Oct 07, 2011 8:25 am
by TheEmperorOfLulz
Still doesn't work:(

Heres my code:

Code: Select all


function love.load()
	a = 1
end
cron = require 'cron'

function love.update(dt)
  cron.update(dt) -- you must do this once inside love.update

	trollClock = cron.every(1, function()
		a = a + 1
  end)

function love.draw()
	love.graphics.print(a, 200, 200)
end

end
I added the print function, just to see if it works. But it only works for one second, and then it start counting with dt again, going crazy fast! Where's the error?