While creating games it is hard to avoid using vector math, however they are not commonly taught in schools. While they are fairly intuitive once you get used to them, learning about vector math for the first time can be a bit difficult, therefore this tutorial.
Vectors are a way to describe a point or direction in space. This space can have any number of dimensions, but for this tutorial we will focus on 2D just because it is easier to draw. All of these concepts also apply to higher dimension vectors though!
Usually a vector will be represented as
(x, y), which you can either interpret as:
Point with coordinates (x, y)
Movement from (0, 0) to point (x, y)
When using vectors as a movement they only describe a movement TO somewhere, originating from the origin (0, 0). If you want to describe a movement that also has a FROM part, you need a second vector to describe the initial position.
So let's look at how we would think about and vizualize two vectors:
A: (3, 2) and
B: (-1, 3):
Note: vectors have no origin and always originate from (0, 0). If you consider vectors as movements from origin to a point, you can also calculate their length, denoted by l_A and l_B.
So let's say you consider vectors as movements, you can simply add two vectors to get the result of doing both movements. For example if you have a vector
A (xa, ya) and
B (xb, yb) indicating two movements, what is the result of doing both
B? This is visualized like so:
Note: Moving by vector A first and then by B will result in the same vector as moving by B first followed by A. (This is why visualizing vector addition always results in this parallelogram).
You can use calculate things like offsets or knockbacks using addition, i.e where does a unit end after getting knocked back in some direction?
Now let's say we want to know the inverse question to the previous one: Assuming I have two vector positions
B, what movement do I have to do to get from
B? The answer to this is a vector subtraction:
C = B - A. Note that this works exactly like regular math, so doing
A + C = B:
Note: Just like when subtracting regular numbers, order matters!
B - A gives the vector from
A - B gives the opposite vector, from
You can use vector subtraction to calculate the difference in position between two units, and get for example the distance between them:
The last 'basic' vector operation I want to go over is multiplication with a number (NOT with another vector).
When multiplying a vector with a number it retains its direction, but its length is multiplied by this number:
You can use vector multiplication to rescale vectors to a certain length. For example when you have a unit or normal vector (length 1), multiplying with a number will make it that length.
As seen before, vectors look very much like a direction to somewhere. This makes them very useful for representing the orientation of something instead of using an angle (because angles make calculating much more difficult).
To do so, orientation is often expressed as vectors of length 1. This is because of the special relation vectors have with angles: For an angle
(cos(a), sin(a)) is a vector of length 1, pointing in the direction of angle
You might be wondering what the point of this is, for an application if why storing orientation as vectors of length 1 see section 'Spawning an item in front of the player'.
The final vector concept for this tutorial is the 'dot product' of two vectors. Simply put, this dot product gives you a measure of 'how much vectors are pointing in the same direction'. If two vectors (of length 1) point in exactly the same direction, the dot product is 1. If two vectors (of length 1) point in exactly the opposite direction the dot product is -1. If the two vectors are at a 90 degree angle, the dot product is 0:
dot(A, B) = length(A) * length(B) * cos(angle), so watch out when calculating the dot product of non-length-1 vectors: they will no longer range from -1 to 1.
As mentioned shown above it is often very useful to have vectors of length 1 (only the direction, not the distance). This is so common there is a standard procedure to calculate this: Normalization. When normalizing a vector you simply divide it by its length (or multiply with 1/length). This will always give you a vector of length 1.
Vectors with length 1 are referred to as 'Normal' or 'Unit' vectors.
Let's say we want to spawn an item 100 units in front of a player hero, how do we calculate this location
We can visualize this question like this:
Referencing this visualization it is obvious we can calculate this A as follows:
Another common question is how can we calculate if my unit is facing a specific point on the map.
We visualize this problem like this:
So looking at the visualization, when does a unit face point P? Well it looks like this happens when their forward vector (the orange one) aligns with the vector from the unit to the point (the purple one). So capturing this in code would look a little like this:
This question is similar to the previous question, only now there are two units facing in different ways:
Looking at this drawing it becomes obvious that the forward vector of unit 2 (F2) actually does not matter. What matters is the angle (dot product) between the forward vector of the unit getting attacked, and the where the attack is coming from (the vector from unit 2 to unit 1:
P1 - P2)
Consider the case where you want multiple things to happen evenly spaced in a circle around the player character. We can visualize it as follows:
By now it should be obvious we need to add the green vectors to the player position, the question is however how do you calculate these green vectors?
What we can simply do is divide the full circle radius (2 * pi) by the number of points we want to use, and then for each angle calculate the unit vector from the angle, multiply it with the desired length and add it to the player position:
As you have seen vector math is quite powerful and can be used to express positional and movement concepts in simple statements. In this final example I will show how to a simple 'physics' simulation to create a homing projectile.
We will express the projectile using two vectors:
velocity. This makes the projectile unable to instantly change its direction, but suffer some inertia: it will home in on the player on every tick, but it cannot easily slow down or change direction:
To achieve this effect we simply 'accelerate' the velocity of the projectile towards the player on every update, so the velocity turns towards the player a little bit every update. We then simply update the position based on the current velocity: