Game Math Cookbook: Finding out where to move to through the Pythagorean theorem
It's been fifteen years since I had math in school, and even then trigonometry was barely just touched on. Every time I try to do game development though, I'm hitting a brick wall because people throw around concepts like tangents, radians and square roots of things like it's nothing and I completely forgot about all of that. Wikipedia isn't really that helpful because it explains the concepts from a math perspective which means it's dry, complicated, and doesn't answer the question "What would I use this mathematical concept for?". So for my own sake, I'm blogging about a game problem and how to solve it with math in a way that I can understand.
A note on Vectors: I use "vector" for a collection of 2 points (since I'm dealing with 2D here). In Mathematics, vector has very well defined meanings, but here it's just a X and Y value and a vector might both define a Point in space or an adjustment that's done over time.
Movement from A to B over time
Possibly the earliest (and easiest) problem is movement of something from A to B over time. I know that my object can move at 3 units per second (this is something I made up for the game, you'll have to figure out what speed you use in whatever game and coordinate system you use). I know where it is right now (A at 4,4) and where I want it to eventually be (B at 9,6), but how do I get there?
What we need is a movement vector, that is a set of X/Y values to add to A over time. What does this mean? Let's say that our movement vector is 0.6,0.4 just for the sake of the example. That means that after 1 second, A should be at 4.6,4.4. Then, a second later it would be at 5.2,4.8 and so on. The movement vector is called velocity because it doesn't describe a point in space but a magnitude of which a point gets shifted over time.
How do we find out the velocity? First, we need to know the difference between points A and B so that we know what we have to cross. Let's call this the difference vector, and it's calculated by B.X-A.X,B.Y-A.Y or in the example, 9-4,6-4 which results in 5,2. That's neat, but that's the complete distance I have to cross it doesn't tell me how much to move over time.
Here's the point I struggled with for a long time: Normalized Vectors. People call this the unit vector usually without going to deep into it. The textbook definition: A unit vector is a vector of length 1. What does that mean? For a long time, I thought that means that X + Y have to equal 1. The difference vector above seems to be 5+2 = 7. Why do I need to have a vector of length 1 and how to I turn my vector of 7 into a vector of 1? Just subtract X/Y by 7 to get 0.71,0.29?
First off, the length of the difference vector is not 7. This was a mistake I made for a long time. Rather, the length of the vector is the hypotenuse of a right triangle with origin 0,0 and points at the X and Y coordinates. Let's just quickly go over the parts of a right triangle (image courtesy of Wikipedia):
The Hypotenuse c is the longest side and is the one opposing the right angle. Side a is the adjacent while side b is the opposite. Angle B seems to be the source of the naming since side b sits adjacent to it while side a is on the opposite.
Point A is 0,0. Point B is my difference vector, 5,2. Point C is chosen by us to sit at 5,0 so that we get a right triangle like this:
This is where the pythagorean theorem comes in, which defines that a2 + b2 = c2. We want c, and we have a (2) and b (5). Let us calculate c2:
- a2 = 5 * 5 = 25
- b2 = 2 * 2 = 4
- c2 = 25 + 4 = 29
Getting c is now simply the square root of c2, which is 5.385164807134504 or 5.39 for short.
The length of the vector 5,2 is 5.39, not 7. Because it takes 5.39 units to cross the distance from 0,0 to 5,2 or from 4,4 to 9,6. Because if the length were 7 it means you would first walk the X-Axis for 5 units and then the Y-Axis for 2 Units, when you could just cross diagonally.
Quick recap:
- Source (A): 4,4
- Destination (B): 9,6
- Desired Speed: 3 units per second
- Difference: 5,2
- Length of Difference: 5.39
- Velocity: ???
So how do we get the velocity and what does this stuff have to do with normalized vectors? As said, a normalized vector is a vector of length 1, and we can get the normalized difference vector by dividing both 5 and 2 by 5.39 which gets us a vector of 0.93,0.37 (which, ignoring a rounding error for the sake of the blog post, has a length of 1 = sqrt(0.932 + 0.372)). We can now multiply this with the desired speed - 3 - to get the Velocity: 2.79,1.11 per second.
- Source (A): 4,4
- Destination (B): 9,6
- Desired Speed: 3 units per second
- Difference: 5,2
- Length of Difference: 5.39
- Normalized Difference: 0.93,0.37
- Velocity (=Change applied to A every second): 2.79,1.11
This would then be multiplied with the frame delta time to get the amount of movement in a frame (so in a 60 fps scenario you would multiply it by 1/60 = 0.016666...).
I still haven't explained the use of a normalized vector. I think that Gamedev.net has done a good job explaining it, but in my own understanding: The difference vector has a magnitude of it's own - with a length of 5.39 it would mean that my object would move 5.39 units per second. So normalizing a vector to me is an application of the rule of three. How do I get from 5.39 units per second to the desired 3 units per second? By going down to 1 unit per second:
- 5.39 = 5,2
- 1 = 5/5.39 , 2/5.39 = 0.93 , 0.37
- 3 = 3*0.93 , 3*0.37 = 2.79 , 1,11