Step 04 — AABB & the discrete overlap test
Concept
AABB = Axis-Aligned Bounding Box: a rectangle whose sides are parallel to the x and y axes (never rotated). They're cheap to test, which is why almost every 2D engine — including yours — uses them as the base collision shape.
We represent one as a corner plus a size:
type AABB = { x, y, w, h } // (x,y) = top-left corner, w = width, h = height
So the box spans x .. x+w horizontally and y .. y+h vertically.
Two boxes overlap when they overlap on BOTH axes
This is the key insight you'll reuse for the rest of the workshop. Think of each box as a shadow on the x-axis and a shadow on the y-axis. Two boxes intersect only if both pairs of shadows intersect:
overlapX: a.x < b.x + b.w AND b.x < a.x + a.w
overlapY: a.y < b.y + b.h AND b.y < a.y + a.h
overlap = overlapX AND overlapY
Hold onto "collision = the AND of two 1D tests." In a few steps you'll do the exact same thing, but with time instead of space, and that's the whole trick behind swept collision.
The discrete trap (why this test alone isn't enough)
aabbOverlap only answers "are they overlapping right now?" If a fast object
jumps from one side of a thin wall to the other in a single frame, it never
overlaps the wall at any sampled instant — so this test says "no collision" and
the object tunnels straight through. Steps 05+ fix that by testing the path,
not the endpoints. Feel the gap here first; it's why everything after exists.
Task
Implement pointInAABB and aabbOverlap in aabb.ts.
bun test workshop/steps/04-aabb