Tag Archives: delta timer

[ SDL2 – Part 9 ] No more delays

Getting rid of SDL_Delay


Up until now, we’ve been regulating movement by just setting a delay of 16 milliseconds at the end of each frame like so :

This would work if the frames always lasted less than 1 millisecond, but they don’t. There is absolutely no grantee that the each frame will last as long as the previous one. And when the duration of each frame differs, the animation will become choppy and not smooth like we want it to be. So how can we get smooth animation?

Method 1 – our current solution


We’ve set an aim for 60 frames per second. Since there is 1000 millisconds ( ms ) in a second, each frame should take 1000 ms / 60 frames = 16 ms.Since our code is very light, we’ve just assumed that each frame takes less than 1 ms, so we’ve added a 1ms delay.

Method 2 – using delta


Another, better way we could limit framerate is to calculate delta time and use that to set the delay. Delta time is the time between each frame ( or update. )

If a frame takes 3 ms, delta will be 3 ms. In method 1 we had a 16ms delay and ignore the delta time completely. This means there would always be a 16ms delay. If the frame took 3ms, the delay would still be 16ms. This means the entire frame would take 3ms + 16ms = 19ms. If this happened often, the duration of a frame would jump up and down, and the animation would be choppy.

Using delta time, though, we could simply subtract that from the 16ms to ensure that every frame lasted exactly 16ms. So if a frame lasts 3ms the delay would be 13ms for a total of 16.

Let’s create a simple example function that takes the delta time and does the delay :

This is a valid solution, and your game will run relatively smoothly in 60 fps. You can, of course change the framerate as you please simply by 1000ms by the desired framerate to get the delay amount :

This method will produce smooth animation, but the third method shows an even better method!

Method 3 – using delta, no delay


Method 1 and 2 has worked by limiting frame rate. But why limit it? We can just skip the delay altogether and just use the delta time to adjust animation. Most modern games works this way. Since we adjust movement with delta time, it doesn’t matter if we run in 60 fps or 6000 fps. For smooth animation, this method is superior to the ones above. Waiting 16 ms between frame can make objects jump a tiny bit. And having your game run at 200fps will make a difference, even though the human eye sees 24fps as smooth.

It’s also very simple, just multiply the movement with the delta time.

Implementation of method 3


Implementing frame independent movement is quite simple, but there are a few things you need to be aware of in order to get it right.

Delta time


Probably the most important point. In order to get animations right, the delta tie needs to be accurate. Very accurate, preferably with microsecond ( µs ), or nanoseconds ( ns )

There are various ways to do this.

  • The C way
    • – Confusing
      •   Functions takes a struct and fills it with time / date
    • – Not always accurate
    • – Hard to use correctly
    • – Platform dependent
      • No one way to do it in Linux and Winows
    • + No library needed,
    • + Doesn’t need C++11 support
  • Boost
    • – You’d need to download, and link with boost
    • – Adds and a dependency, just for time
    • – Syntax can be hard to understand
    • + Cross-platform
    • + Does everything you need easily
    • + Doesn’t need C++11 support
  • C++11

In this part, we’ll be using the chrono library. I suggest using it over the old C way. If you can’t compile C++11, you can use the boost version.

chorno


chrono is the new timing library in C++11. I covered this in my previous post, and I recommend that you read it before you read on. If you choose not to read it, I will give you the short version of the various part of the chrono library :

  • duration
    • Holds the amount of time between two points in time
    • Can be stored as any time unit ( seconds, millisconds, years, fortnights, .. )
    • Can use both double and int
  • time_point
    • Holds a point in time
    • Subtracting a time_point from another returns a duration
  • Clock
    • Three kinds: steady_clock, system_clock, high_resolution_clock
    • Used to get current time as a time_point

Getting the delta


So here’s the code for our simple delta timer :

Using delta to calculate movements


Now that the worst part is over, it’s time for some minor details on how to implement frame independent movement.

First of all, the animated objects needs to have speed. And for better precision, we use doubles. Let’s make a simple struct for holding the speed. Our speed will have values between -1.0 and 1.0.

We also need an Update( double delta ) functions that’s used to update the position of the object.

There’s a few things wrong with this, though. First of all, delta values will be really small, and our speed is between-1.0, and 1.0 so the resulting movement will be really small. We can solve this by multiplying with a constant.

But there is a second issue here : both speed and delta are likely to do decimal numbers. So the result of the multiplication will almost always be a decimal number as well. But we just put it into an int and this means we’ll loose the decimal precision. So if the result is 0.8, we’ll end up adding 0. And if the same things happen in the next frame, we’ve “lost” 1.6 worth of movement. A whole pixel! It might seem like a small thing, but it would make the movement really choppy. So instead we introduce two new member variables to our Texture struct to hold the result of the multiplication.

Final function


Here’s our final Update function:

In Texture :

Calling it :

Conclusion


That concludes the tutorial on delta timers. I’ve made a few updates, put things into different classes and other minor improvements. The full code is too big to include in this blog post, but you can find a full zip of it here.

I’ve added a new .cpp file, so you need to add that to the compilation string if you’re using clang or gcc

clang++ main.cpp Texture.cpp -std=c++11 -lSDL2 -lSDL2_image -o Game


Feel free to comment if you have anything to say or ask questions if anything is unclear. I always appreciate getting comments.

You can also email me : olevegard@headerphile.com
Share