Game math: moving and colliding

Play this lesson

Where is everything?

Every frame, a game answers two questions: where is everything now, and is anything touching? Both answers are plain arithmetic.

A screen is a grid of pixels. A position is two numbers: x counts pixels from the left edge, and y counts pixels from the top. The top-left corner is (0, 0).

Watch out: in maths class, y goes up. On screens, y goes down. Old TV screens drew their picture line by line from the top, like reading a page, and computers kept that habit.

Quick check

The Hyper Shards ship is at x = 180, y = 600. The player pushes up. What happens to its numbers?

  1. y gets smaller
  2. y gets bigger
  3. x gets smaller
Show the answer

y gets smaller

On screens, y counts down from the top edge. Moving up means getting closer to the top, so y shrinks, for example from 600 to 590.

Velocity

Velocity is speed with a direction. Games store it as two numbers: vx, pixels per second across, and vy, pixels per second down.

A Hyper Shards laser has vx = 0 and vy = -900: it flies straight up, 900 pixels every second. An alien drifting down and left might have vx = -60 and vy = 120.

Each frame, the game adds a slice of the velocity to the position. How big a slice? See the next card.

Delta time

Frames are not all the same length. Many laptops show 60 frames a second, lots of phones show 120, and a busy moment can slow any device down.

If the ship moves 5 pixels every frame, it flies twice as fast on a 120 Hz phone. So games measure delta time, or dt: the seconds since the last frame, about 0.0167 at 60 FPS. Then they write x += vx * dt, and the ship covers the same distance per second on every screen. This is frame-rate independent movement.

Bug hunt

loop.js
let last = performance.now();function loop(now) { // now: time in milliseconds  const dt = (now - last) / 1000; // in seconds  last = now;  laser.y += laser.vy; // vy is -900  draw();  requestAnimationFrame(loop);}requestAnimationFrame(loop);

Lasers vanish off the top almost instantly, and even faster on a 120 Hz phone. Which line is the bug?

  1. Line 1
  2. Line 3
  3. Line 5
  4. Line 7
Show the answer

Line 5

Line 5 moves the laser 900 pixels every frame, which is 54,000 pixels a second at 60 FPS. It should be laser.y += laser.vy * dt, so the laser moves 900 pixels per second on any screen.

Gravity

Acceleration changes velocity, the same way velocity changes position. Gravity is a steady acceleration downward.

When a pest pops in Garden Defense, a coin jumps out with vy = -400 (negative means up, because y goes down). Every frame:

coin.vy += 1200 * dt;
coin.y += coin.vy * dt;

The coin rises about 67 pixels in a third of a second, stops for an instant, then falls faster and faster. That curve is a parabola, the same path a thrown ball takes.

Distance and circles

To find the distance between two points, work out how far apart they are across (dx) and down (dy). Those are two sides of a right-angled triangle, so Pythagoras' theorem gives the third side: Math.hypot(dx, dy), the square root of dx times dx plus dy times dy.

Two circles touch when the distance between their centres is less than their two radii (the plural of radius) added together. That one check is how Hyper Shards knows a bullet hit the ship.

Bolt says: Pros often skip the square root and compare dx * dx + dy * dy with (r1 + r2) * (r1 + r2). Same answer, a little less work, which adds up with 300 bullets.

Boxes: AABB

Many things are closer to rectangles: Garden Defense tiles, Sprig, a wall. Games check them as an AABB, an axis-aligned bounding box: a rectangle that is never tilted, stored as x, y (its top-left corner), width w and height h.

Two boxes overlap only if they overlap across and down. Across means A's left edge is left of B's right edge, and A's right edge is right of B's left edge. Down is the same check with top and bottom edges. Any gap means no touch.

Bug hunt

collide.js
// x, y is the top-left corner of each boxfunction overlap(a, b) {  return a.x < b.x + b.w &&         a.x + a.w > b.x &&         a.y < b.y + b.h &&         a.y + a.h > b.x;}

Beetles sometimes hurt Sprig while they are still far above Sprig. Which line is the bug?

  1. Line 3
  2. Line 4
  3. Line 5
  4. Line 6
Show the answer

Line 6

Line 6 compares a bottom edge (a.y + a.h) with b.x, a left edge. It should be b.y. Mixing up x and y is one of the most common collision bugs.

Too fast to hit

One last trap. A laser moving 900 pixels a second jumps 15 pixels each frame at 60 FPS. A thin alien, 10 pixels tall, can fit between two jumps, so the laser skips straight past it. This is called tunnelling.

Fixes: make hitboxes a bit bigger, split each frame's move into smaller steps and check each one, or check the whole line the laser travelled. A hitbox is the invisible shape used for these checks, and it does not have to match the picture.

Bolt says: Next lesson: game loops and state machines, the shape that every game's code runs in.

Fact-checked 9 October 2026