The single most important distinction in game math hides behind two things that look
identical on screen: both are just a list of numbers like
Confuse them and the bugs are baroque: a "velocity" that drifts when you move the world's origin, an enemy that teleports when you reparent it. Keep them straight and the algebra itself tells you what is legal.
Write points as
Step 1 — point minus point is a vector. Subtract two locations and the
"where" cancels; what survives is the trip from one to the other — its direction and length.
This is the workhorse: the displacement from
Step 2 — point plus vector is a point. Start at a location and apply a
displacement: you land at a new location. This is how everything moves — the player
each frame is
Step 3 — vector plus vector is a vector. Two displacements done in sequence are one combined displacement — "east two, then up one" is a single arrow.
Step 4 — point plus point is meaningless. Add two locations and ask what you get. "The chest plus the door" is nonsense, and worse, the answer changes if you move the origin — so it cannot describe anything physical. The operation is simply not defined.
(The honourable exception is an average: the midpoint
You could police all this by hand — or you could let the numbers do it for you. In
Step 5 — watch the w-component do the policing. Add or subtract component-wise and just read the last slot:
Point minus point lands on
The distinction is not pedantry — it is how you store a game world. A character's position is a point (where it stands). Its velocity is a vector (how fast and which way it heads), and the update is the canonical point-plus-vector,
When the AI asks "which way is the enemy?", it never adds the two positions — it
subtracts them, point minus point, to get the displacement
A point and a vector are usually stored as exactly the same kind of triple — a
Vector3 or (x, y, z) struct doesn't know or care which one it
holds. That is convenient right up until it hides a bug: the compiler happily accepts
playerPos + enemyPos because, syntactically, "triple plus triple" always
type-checks — even though semantically you just added two locations, which is the
one operation the maths forbids.
The code runs. It produces a number. It just isn't a meaningful location — and worse, it
silently depends on where the world's origin happens to sit, so it can look "close enough"
in one scene and wildly wrong in the next. A classic version of the mistake: computing a
midpoint as a + b instead of the affine average
pos + otherPos when you
meant pos + velocity. Nothing crashes; the character just drifts to a place
that makes no sense. The fix isn't a runtime check — it's naming your types (or at least
your variables) so a point can never masquerade as a vector in the first place.