Game Loop
Run a loop that continuously reads input, advances state, and renders output at a controlled cadence for the entire active lifetime of a program - the opposite of waiting idle for the next request.
The problem
Game.onKeyPress() moves the player and redraws. It looks complete until anything needs to
move on its own: a thrown projectile, a patrolling enemy, a countdown timer. None of those
have a key to press. Between two key presses, time effectively stands still - nothing in the
world advances unless the player caused it directly.
Request/response thinking (wait for input, react, wait again) has no room for "keep happening regardless of input." A world with physics, AI, or timers needs to advance on its own schedule, not the player's.
The solution
Wrap the whole active lifetime of the program in one loop that repeats a fixed sequence:
read whatever input arrived, advance every piece of state by however much time actually
passed, then draw the result. Nothing in that sequence requires a key press - update()
runs every tick, whether or not processInput() found anything to drain.
The loop itself stays deliberately dumb: it does not know what a player or an enemy is, it just calls three methods in order, on a schedule. All actual game logic lives in the object it drives, which is what keeps the loop reusable across entirely different games.
- 1Once the game starts, control never returns to normal request/response code until the game ends.
- 2Every iteration starts by measuring time, because how much state advances depends on how long the last tick actually took.
- 3The world drains whatever input arrived since the last tick - a key press does not get its own separate event handler.
- 4State advances by exactly as much time as really passed, so gameplay speed does not depend on hardware speed.
- 5Only after state is fully advanced does anything get drawn - never mid-update, or the frame would show a half-updated world.
- 6If the tick finished early, the loop waits out the remainder instead of burning the CPU redrawing the same frame needlessly.
- 7The whole sequence repeats, tens of times a second, for as long as the game is active.
Structure
GameLoop has no relationship to InputSource at all in this diagram - only GameWorld
does. The loop drives the cadence; the world decides what the cadence means.
Code
Same example three ways: a loop driving a world with a player and patrolling enemies.
When to use it
- State needs to advance continuously - physics, AI, timers, animation - independent of whether the user did anything this instant.
- The program has one clear "active" phase (a game in progress, a live simulation) where driving forward at a controlled cadence matters more than minimizing idle CPU use.
Pitfalls
- Physics tied to frame rate. Advancing state by a fixed amount per frame instead of by
real elapsed time makes gameplay run faster on faster hardware -
deltaTimeexists specifically to prevent this. - Unbounded variable timestep. If a slow frame produces a huge
deltaTimein one jump (say, after the OS paused the process), physics can tunnel through walls or behave wildly. Clamping the maximumdeltaTimeper tick is the usual guard. - Burning CPU for no reason. A loop with no sleep/wait at the end of a fast tick will spin at 100% CPU rendering identical frames. The wait step is not an optimization - it is part of a correctly behaved loop.
Don't confuse it with
- Template Method. The loop's own
run()is frequently implemented as a template method - a fixed skeleton calling overridableprocessInput/update/rendersteps - but Game Loop names the runtime cadence pattern; Template Method names the class-structuring technique one implementation of it happens to use. - Observer / event-driven architecture. Event-driven code does nothing until an event
fires. Game Loop advances unconditionally every tick. The two commonly coexist: input
events get queued by an Observer-style listener and drained once per tick inside
processInput(). - A simple
whilepolling loop. Polling for one condition until it becomes true is not this pattern by itself - Game Loop specifically names the three-phase cadence (input, update, render) sustained for the program's whole active lifetime, not an arbitrary loop that happens to repeat.
Check yourself
What is the correct order of the three phases inside one tick of a game loop?