| How a Game Loop Works |
|
|
| Written by Markus Ewald | |
| Monday, October 09 2006 20:30 | |
|
At the core of all games, a permanent loop is running which repeatedly gathers data from the input devices, moves all active objects in the game world and then generates the visual and audible representation of that world on the screen and on your speakers. Time to examine this game loop then! This article will explain different designs of game loops and why time stepping is a good idea even in single player games. A Naive Game LoopA naive implementation of a game loop could not like this: Now we are about to encounter one of the most basic problems game programmers have had to cope with from the beginning: Not all PCs are equally fast, some will take longer to update the positions of your game's objects, others will not be able to render them quite as fast. Performance might even change during the game because the number of things on the screen will vary greatly. With the above game loop, the game would simply run slower, since the objects' positions will be updated less often than on a faster PC. On the other side, if the game is run on a faster machine, it might run faster than you expected and is likely to become unplayable. The next chapter will show you how to avoid that. Time-Scaled Game LoopIn order to make a game independent of how fast the PC can run the game loop, we need to scale the amount by which objects are moved by the time the previous iteration of the game loop took. In other words, measure how much time has passed since the last time your objects were updated, calculate the up-to-date positions of all objects based on that time and render another frame.
For example, consider a bullet that's moving through the game world at a desired speed of
1 unit per second: Sounds nice. But wait! This game loop still has major problems! Take above game loop which updates objects sequentially based on the time that has passed since the last loop iteration. Now assume you were programming a racing game and two cars were headed towards each other for a big frontal crash. Both cars are moving at 10 units per second and are 10 units apart (so after half a second, they will both have moved by 5 units towards each other, reducing their distance to zero - bang!). Let's observe this scene with on two different computers! John's ComputerJohn's computer is rather slow and is running your game at a breathtaking 1 frame per second, so each iteration of the game loop takes 1 second. At the beginning of the update, both cars are still 10 units apart:
Now the first car's position will be updated. Since 1 second has passed from when the last iteration was performed, the car will be moved by a full 10 units:
Bang! The updated car has reached its opponent before he even had the chance to be updated. But weren't they supposed to meet in the middle? Rick's ComputerRick's computer is a real performance monster. It is running your game at no less than 4 frames per second, making each iteration of the game loop take 0.25 seconds. Here, the collision will occur like this: We'll start with both cars 10 units apart from each other as before:
Now the first car's position is updated. Since only 0.25 seconds have passed from when the last iteration of the game loop took place, the car will be moved by 2.5 units only:
Then the second car's position is updated, moving the car by 2.5 units as well:
Nothing happened yet. So the game will render another frame and, 0.25 seconds later, we will be in the update phase once more. Again, the first car is moved another 2.5 units:
Then the second car is also moved another 2.5 units:
Bang! In Rick's computer, the cars have hit each other in the middle. ConclusionNow assume John and Rick were playing a multiplayer game and continued driving to the finish line after their accident. The game would be in a different state on each computer and slowly drift even further apart. If you're thinking that this problem could be solved with math, you're right (keyword swept collision detection). But even then, due to the different steps by which both PCs update the game world, you would still have different rounding errors on each PC, causing the game states to drift apart nevertheless. The next chapter will present a solution to all this which also happens to make the implementation of the game loop easier! Time-Stepped Game LoopIn the previous chapter, we watches a performance-scaled time loop fail to achieve a uniform outcome on two computers with different performance. Now we will look at a game loop that solves this problem and is easier to implement at the same time. That solution is to advance the game in fixed time steps. You will still have rounding errors and inaccuracies like the one demonstrated above, but at least they will be the same on all computers, allowing your game to record replays, have a multiplayer mode and in-game cut scenes with predictable outcome. Here's one method to achieve this:
The next section will discuss more reasons why we want to seperate the update phase from
the drawing phase and draw the connection to the Advanced Game LoopsIn the previous sections, we have separated the game loop's update phase and drawing phase from each other. This not only makes sense when we want to use fixed time steps, but also:
All this causes our updating and drawing code to becoming much, much more complicated once we
go from pong and tetris clones to intermediate games. Therefore it's wise to extract all this
code into seperate methods which we'll call Game Loops in the XNA Framework
By chance, the XNA Framework's
This base class is contained in the Now that you know how to set up a game loop, your next topic should be how to use the XNA framework to display 2D or 3D graphics on the screen!
|

