62 lines
2.2 KiB
Markdown
62 lines
2.2 KiB
Markdown
# Step 09 — Slide (this is what `dot` was for)
|
|
|
|
Back in step 02 you implemented `dot` and I said "you'll see later." This is
|
|
later. Sliding is the difference between a game that feels good and one where
|
|
you stick to every wall like glue.
|
|
|
|
## The problem
|
|
|
|
You're moving with velocity `v` and you hit a wall whose outward normal is `n`.
|
|
If you just _stop_ (velocity → 0), the player jams against the wall — press into
|
|
a wall diagonally and all motion dies, even the part that was parallel to the
|
|
wall and perfectly fine. What we actually want: **cancel only the part of `v`
|
|
that pushes _into_ the wall, and keep the part that runs _along_ it.** That's a
|
|
slide.
|
|
|
|
## The math (projection)
|
|
|
|
Any velocity `v` can be split into two pieces relative to the wall:
|
|
|
|
- the part **along the normal** (into/out of the wall) — this is what the wall
|
|
forbids,
|
|
- the part **along the wall surface** (perpendicular to the normal) — this is
|
|
fine.
|
|
|
|
Because `n` is a **unit vector**, the amount of `v` pointing along `n` is
|
|
exactly `dot(v, n)`. That single number is "how much of `v` goes straight into
|
|
the wall." The vector piece pointing into the wall is `n * dot(v, n)`. Subtract
|
|
it off:
|
|
|
|
```
|
|
vSlide = v - n * dot(v, n)
|
|
```
|
|
|
|
What's left has **zero** component along the normal — it lies flat against the
|
|
wall. (That's the geometric meaning of `dot`: it measures how much two vectors
|
|
share a direction. Subtract the shared-with-the-normal part, and nothing
|
|
pointing into the wall survives.)
|
|
|
|
### Feel it with numbers
|
|
|
|
Move `v = (10, 5)` into a wall whose normal is `n = (-1, 0)` (a vertical wall on
|
|
your right, pushing you left):
|
|
|
|
- `dot(v, n) = 10*(-1) + 5*0 = -10`
|
|
- `n * dot = (-1,0) * -10 = (10, 0)`
|
|
- `vSlide = (10,5) - (10,0) = (0, 5)`
|
|
|
|
The rightward motion (10) is gone — that was driving you into the wall — but the
|
|
downward motion (5) survives untouched. You slide down the wall. Exactly right.
|
|
|
|
This is the very last line of your engine's `moveAndSlide`:
|
|
`velocity -= normal * (velocity · normal)`.
|
|
|
|
## Task
|
|
|
|
Implement `slide(v, normal)` in `slide.ts` using `dot`, `scale`, and `sub` (all
|
|
in `given.ts`). Return the velocity with its into-the-wall component removed.
|
|
|
|
```sh
|
|
bun test workshop/steps/09-slide
|
|
```
|