Imagine you're making a game or a simulation. You want things to move smoothly, right? Computers run your code in tiny steps called "frames". How many frames happen each second is the "Frame Rate" or FPS (Frames Per Second).
Here's the catch: not all computers are the same! A powerful gaming PC might run at 120 FPS or more, while an older laptop might struggle at 30 FPS.
The simplest way to make something move seems obvious: tell it to move a small, fixed amount every frame.
For example, you might write code like this:
// Inside the game loop (runs every frame)
object.positionX = object.positionX + 2; // Move 2 pixels to the right
But this is where the problem starts!
2 pixels/frame * 120 frames/second = 240 pixels/second.
2 pixels/frame * 30 frames/second = 60 pixels/second.
The object's speed is completely tied to the computer's performance! This leads to unfair gameplay (players with better PCs move faster) and unpredictable simulations.
Below, the RED square uses the naive "move fixed amount per frame" method. The GREEN square uses the correct method (explained next). Adjust the "Simulated FPS" slider and see what happens!
// Runs ~FPS times per second
// moveAmount = 2 (fixed)
naivePos.x += moveAmount;
Speed depends entirely on how often this runs (FPS).
// Runs ~FPS times per second
// speed = 150 (pixels/sec)
// dt = time since last frame (secs)
correctPos.x += speed * dt;
Movement scales with time passed, keeping speed consistent.
Instead of counting frames, we need to measure *how much real time*
has passed between one frame and the next. This duration is called
Delta Time, often abbreviated as dt.
dt ≈ 0.0167 seconds.
dt ≈ 0.0333 seconds.
Now that we have dt (the time elapsed since the last
frame), we can define movement based on a desired *speed* (e.g.,
pixels *per second*) instead of a fixed amount per frame.
The core formula becomes:
movement_this_frame = speed_per_second * delta_time
Let's revisit our example with a target speed of 150 pixels per second:
dt ≈ 1/120 ≈ 0.0083s. Move
150 * 0.0083 ≈ 1.25 pixels this frame.
dt ≈ 1/30 ≈ 0.0333s. Move
150 * 0.0333 ≈ 5 pixels this frame.
Notice how the object moves *less* per frame on the fast computer and *more* per frame on the slow computer. This precisely compensates for the difference in frame rates!
The result: The object travels 150 pixels every *real second*, no matter the FPS. Watch the GREEN square in the simulation – its perceived speed stays consistent!
// Inside the game loop (runs every frame)
// speed = 150 (pixels per second)
// dt = time elapsed since last frame (in seconds)
object.positionX = object.positionX + (speed * dt);
The key takeaway is simple: Don't base movement or logic updates on *how many frames* have passed. Base them on *how much time* has passed.
Use Delta Time (dt) to multiply your rates (speed,
rotation speed, etc.), and you'll achieve smooth, consistent behavior
across all sorts of different hardware.
Experiment with the simulation above to solidify your understanding!