48 lines
1.6 KiB
Markdown
48 lines
1.6 KiB
Markdown
# Step 04 — AABB & the discrete overlap test
|
|
|
|
## Concept
|
|
|
|
**AABB** = **A**xis-**A**ligned **B**ounding **B**ox: 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`.
|
|
|
|
```sh
|
|
bun test workshop/steps/04-aabb
|
|
```
|