Reference: More 2d Vector Operations

The journey of a thousand miles begins with a single step

We covered using vectors for position and velocity, which is great for controlling entities by their speed and direction. However, vectors can also help us with interactions between entities, like facing and shooting. I mean, giving encouraging gifts.

Vector subtraction is mechanically just like addition, and it allows us to determine a path from one position to another. As you'd expect, subtraction is just the inverse of addition, and you just subtract the x and y components just like you added them. Quite simply, for positions p1 and p2 and a path between them:

p1 + path = p2
p2 - p1 = path

Now say you wanted to move from p1 to p2, perhaps because the player clicked at p2 (or send a rocket flying from you to p2, which is just moving a different entity). First, you calculate the path:

path = p2 - p1

Now, if you update your position like this:

p1 = p1 + path

You'll simply teleport to p2, which you could have done more easily by just setting p1 = p2. What you want to do is move along that path at a reasonable speed, perhaps constant or perhaps using acceleration. To do this, we'll use a number of vector operations that should be part of any good vector class.

First, we need the magnitude of the vector. Pythagorean theorem! I'll figure you can google that if you're rusty.

Second, we need to normalize the vector. That means to convert it to a vector with the same direction, but unit magnitude (magnitude of 1). We want the pure direction to go in, without any commitment to a distance. Turns out this is quite a simple thing to do:

Both the original vector p and the normalized vector pn have the same theta angle. Remember trigonometry? This means that:

cos(theta) = p.y / magnitude(p)
cos(theta) = pn.y / magnitude(pn)

Fortunately, we don't have to calculate the cosine, because we're just going to take advantage of the equality, and the fact that the whole goal here is for magnitude(pn) = 1.

p.y / magnitude(p) = pn.y / magniude(pn)
p.y / magnitude(p) = pn.y / 1
p.y / magnitude(p) = pn.y

Put more nicely and applied to x as well, you normalize a vector by simply dividing both x and y by the magnitude.

pn.x = p.x / magnitude(p)
pn.y = p.y / magnitude(p)

So returning to our path problem, we normalize the path down to a direction just by dividing it.

pathn = path / magnitude(path)

And now that we have the normalized direction to travel in, we can scale it by the distance we want to travel each frame (the constant SPEED). For the same reason as explained above, you can simply multiple x and y by a scale factor and the magnitude of the resulting vector will be equal to that scale factor. This gives us an appropriate velocity vector for Euler integration.

p1 = p1 + (pathn * SPEED * delta)

It's a pretty simple extension to use the path as acceleration instead of velocity, when you get to cooler movement.