SnutiToday’s guest tutorial comes to you courtesy of Christer Eckermann, the co-founder of Snuti, a small Norway-based indie game start-up. Snuti consists of two University graduates, Clare Falconer and Christer Eckermann, trying to make their independent game development dream come true. They will release their first commercial game this summer and are hoping to deliver a cute and unique experience. You can follow Snuti on Facebook and Twitter.


Making Games Run Smoothly With Delta Time

One method of animating, moving, and timing things in games is to programmatically change certain values on each frame update. However, if you update with a specific value every frame, for example, moving an object down one pixel every frame, then, with fluctuating frame rates, the speed of this action may seem inconsistent to the player. In that case, the player will experience both a choppy frame rate and a fluctuating game speed.

But if your game already runs smoothly, so why should you worry about it? Well, even if it does run smoothly, there are constant small changes in the frame rate. To compensate for this, you can use delta time. This helps ensure that your game runs more stable on older devices.  More significantly, frame rate often drops noticeably when the device is displaying notifications or when your game is processing something heavy.

In my opinion, all games should use delta time, no matter the size and depth, if you want the game speed to appear consistent.


What is Delta Time?

The word delta means “change,” and thus delta time means “change in time.”

In games, delta time is a compensation value. In practical use, the delta time value is multiplied by values that are affected by time. When the frame rate is lower, affected values increase to compensate for the time gap, or decrease for fast frame rates. If your frame rate is consistently 60 frames per second, then the delta time value is 1.0, effectively enacting no change. If the frame rate drops to 30 fps, then the delta time increases to 2.0, making all values twice the size to compensate for the slower frame rate.


Where to Use Delta Time

  • For a moving object which changes position, rotation, or scale.
  • Manual countdowns in the frame update, as you may want these countdowns to reflect time instead of how many frames have passed.
  • Most values which are changed over time.

The Delta Time Function

The function below calculates the delta time value which you can use in your frame update function. Corona games can run at two different frames-per-second rates: 30 and 60. The function below is set up for 60 fps, but you can adjust it for a 30 fps game by changing (1000/60) to (1000/30).

local runtime = 0

local function getDeltaTime()
   local temp = system.getTimer()  --Get current game time in ms
   local dt = (temp-runtime) / (1000/60)  --60fps or 30fps as base
   runtime = temp  --Store game time
   return dt
end

If you print out the delta time value for each frame, it will look something like this:

0.95916, 1.00638, 0.924, 0.9667, ...

The value will be very close to 1.0 when the game runs at 59-61 frames a second, but it will change more significantly if the frame rate fluctuates more severely.


Implementing Delta Time

Assuming you have the above function in your game code, implementing delta time shouldn’t change your existing code too much. However, just be careful to only multiply it by changing values, not the entire value, as illustrated in the code below.

--A box object
local box = display.newRect( 50, 0, 100, 100 )

--Frame update function
local function frameUpdate()

   --Delta Time value
     local dt = getDeltaTime()

   --Move your box, 5 pixels with delta compensation
     box:translate( 0, 5.0*dt )

   --For rotation...
   --INCORRECT: do not multiply with the entire value!
   --box.rotation = (box.rotation+1) * dt
   --CORRECT: only multiply with the changing value:
     box.rotation = box.rotation + (1*dt)

   --Same goes for scaling...
   --INCORRECT: 1.0 and 0.01 have to be separated, as 1.0 represents the current scale:
   --box:scale( 1.01*dt, 1.01*dt )
   --CORRECT: only affect the changing value
     local scale = 1 + (0.01*dt)
     box:scale( scale, scale )
end

--Frame update listener
Runtime:addEventListener( "enterFrame", frameUpdate )

Testing Delta Time

To confirm that your setup is working properly and that your game has become “framerate independent,” just change the fps value in config.lua to 30 and 60, back and forth over several tests. Your game should appear to run at the exact same speed, except that the 30 fps tests will likely seem a bit “choppy.”

application = {
   content = {
      fps = 60  --Switch between 30 and 60 over several tests
   }
}

That’s it! Your game should now appear to run at the same speed no matter what the frame rate is. This technique can be used for all types of delta-related processes, so feel free to expand its functionality to suit your needs.

  1. Just one quick thing that might be useful. In getDeltaTime(), instead of hard coding the base framerate you could use

    local dt = (temp-runtime) / (1000/display.fps)

    I believe that display.fps returns the ideal fps value (from config.lua), and not the currrent frame rate.
    Just saves you having to adjust it later in the code if you change your base rate to 30 for some reason.

    • That’s a very good idea, didn’t cross my mind. That would indeed be a more flexible solution.

      But it would cause problems if you decided to test if your game have become “framerate independant”, using the config.lua technique (changing the fps between 30 and 60 in the config.lua file). As that value in the delta time function should not be changed while testing, it would cause your game to run in slow motion or super speed while testing, defeating the purpose of the test.

    • To save a little extra CPU time, you could also percale this at the start, to avoid calculating it every frame…

      fpsFraction = 1000/display.fps

  2. That’s a really nice advice, I’ve used that in some games aswell.
    Also make sure to use that correctly with transitions – you could use it this way:
    transition.to(obj, {time=1000/dt,…}
    The only downside to this is that the transition won’t change it’s speed corresponding to your FPS. Best way would be to move everything manually.

  3. Hi

    The first i think is that would be practical not having to do for each frame 1000/fps and use a local variable with the result of this fixed calc. And because i want to use the delta time in diferente “classes” at the same time, i prefer to give its own enterframe event and use a get method only for recover the current/last delta value.

    Here my class that maybe can help someone.

    module ( …, package.seeall )

    function new ( _fps )

    local o = {}

    ———————————————
    ———— ** ATRIBUTOS ** ————
    ———————————————

    local delta = 0
    local lastTime = 0
    local divisor = 1000 / _fps — 60 or 30 fps

    ———————————————
    ————- ** METODOS ** ————
    ———————————————

    function o:getCurrent () return delta end

    ———————————————
    ————— ** LOOP ** —————-
    ———————————————

    local function eLoop ( event )
    local time = system.getTimer () — Tiempo actual en milisegundos
    delta = ( time – lastTime ) / divisor
    lastTime = time
    end

    ———————————————
    —————- ** INICIO ** ————–
    ———————————————

    Runtime:addEventListener( “enterFrame”, eLoop )

    return o
    end

  4. long time coming this post. I always remember a piece of code called super timer when doing flash that took this even further. Nice tip for newcomers and key to smooth pixel movement without transitions.

  5. Hmmm I have been testing this kind of method already. There is one problem I have with my programming style. Often I will do custom invserse log type animations and I’m wondering how to implement delta time. It seems easy to implement for speeds etc, but not so much ratios? e.g:
    ———————————————–
    local xTarget = 100
    object.x = 0

    function enterFrame()
    object.x = object.x + (xTarget – object.x)*0.5
    end
    ———————————————–

    Every frame the object will move half again the distance between it and the xTarget. I know there is an elegant mathematical solution to time and log curves… but my brain just aint connecting the dots right now.

    • If you have a target to move to with a given time, then I often find that the transition.to() function works well, you need no delta time with that.

      But if the target position is constantly changing, I usually do this using velocity, it’s not based on ratio. But if I understand you correctly this might do what your looking for, I’ve written a blog post on it in the past, see the headline: “Example use: 2D Rubber Band Movement”: http://ecker00.tumblr.com/post/51964198092/

      But if your not looking for a rubber band effect, but rather a perfect ratio movement, maybe this will work. In the blog post above there is an “Influence” function described, which is essentially a ratio method, but to do a ratio movement you need to know your start position.

      function influence( val1, val2, inf )
      local aInf = 1 – inf
      return (val1*aInf) + (val2*inf)
      end

      local object = display.newRect( 10, 10, 10, 10 )
      object.start = {x=10, y=10}
      object.target = {x=200, y=200}
      object.transition = 0.0
      object.speed = 0.01

      function enterFrame()
      local dt = getDeltaTime()
      object.x = influence( object.start.x, object.target.x, object.transition )
      object.y = influence( object.start.y, object.target.y, object.transition )
      object.transition = object.transition + (object.speed * dt)
      if object.transition > 1 then object.transition = 1 end
      end

      Multiply the transition speed with the delta time, should do the trick.

  6. Thank you for the post! Wasn’t until final testing and noticing significant differences between Android and iOS devices additive object movement inside my main game loop. I think this will help keep everyone closer to the same precision and ensure a more consistent experience across platforms.

  7. Guys….
    When I do this my players movement becomes super choppy….
    Not sure if I am doing it wrong. I have the ‘getDeltaTime()’ function at the top, then I have the ‘movePlayer()’ just under….

    [lua]
    ———————————————————————— Delta Time
    local getDeltaTime = function()
    local temp = system.getTimer() –Get current game time in ms
    local dt = (temp-runtime) / (1000/60) –60fps or 30fps as base
    runtime = temp –Store game time
    return dt
    end
    ———————————————————————— Move Player
    local movePlayer = function()
    local dt = getDeltaTime()
    player1.x = player1.x + (motion*dt)
    print(display.fps)
    end
    [/lua]
    Am I doing it right?

    Thanks for this btw, I was looking for a tutorial on this :)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>