This article takes a high-level but hopefully useful look and some common trigonometric functions with the aim of clarifying how they can be used as solutions in our game coding to create some cool movement and drawing effects. As this article is aimed at beginners in game coding it makes no assumptions about the readers mathematical knowledge either. In this article Calculating heading in 2D games: Using trigonometric functions part 1 we will explore how to calculate heading but let’s have a quick look at what else these mystical functions can achieve for us that we will cover in the future articles of this series.
Introduction to trigonometric functions
Trigonometric functions like sine (sin) and cosine (cos) are often used in game programming for a number of tasks. For example, rotating a spaceship or determining horizontal and vertical velocity based upon the angle the character/ball/missile is moving, moving a non-player-character in a more pleasing way than simply left, right, up, down or diagonal (think about the deadly swooping of a Galaxians enemy). And what about a ripple effect; perhaps an explosion or pebble-splash, starting from a centre point and radiating outwards at an increasing radius.
There are no end of uses for these trigonometric functions but the key to understanding how to use them in all of these situations is to understand a bit more about the functions themselves. We don’t actually need to understand the math contained in the function but we should be able to understand the range of results returned by a function. But before we go into it, what exactly is a trigonometric function?
What is a trigonometric function
A function is simply a calculation, a sum or algorithm. The point is that we use the function by giving it an input (a number) and the function gives us back an output, an answer. A trigonometric function is just a function used in the field of trigonometry, which loosely put is the study of triangles. So they are functions (designed usually by a mathematical genius or two) which we can use to get a result to a problem that would otherwise have been significantly more challenging.
As an example of what’s inside a trigonometric function here is how to find the sine of an angle WITHOUT using the sine button on the calculator. We don’t need to understand anything on that page to make games but it is kind of fun to see how complex this stuff is. Perhaps even more interesting is the history of trigonometry. The previous link and its out-links start with the Egyptians and eventually arrives at early microprocessors and B58 bombers and is truly fascinating. But back to games, how do we make use of these functions.
Calculating heading with trigonometric functions
The programming languages and API’s provide the complex math wrapped up in a simple method/function call. For example, in Java, we could use this code snippet to control the horizontal and vertical velocity of say a spaceship to make sure it travelled in precisely the same direction that it was facing.
// facingAngle can be any angle between 1 and 360 degrees // the Math.toRadians method simply converts the more conventional // degree measurements to radians which are required by the cos and sin methods. horizontalVelocity = speed * Math.cos(Math.toRadians(facingAngle)); verticalVelocity = speed * Math.sin(Math.toRadians(facingAngle));
As we see in the code snippet we used the cosine of an angle to get the horizontal velocity and the Sine for the vertical.
Very similar code would work in all the other major languages. As example projects are completed over the coming months I will link out to them from the header of this article under the “Projects that demonstrate these concepts” heading. If you are happy that this works and that is all you care about, that is fine, copy the code and close this article. If you want to know why it works and get an insight into using sine and cosine for other game programming solutions then read on.
However, the code snippet in itself doesn’t really explain why it works. We will go into some depth with the spaceship’s heading example and look a bit deeper into the values returned by the sine and cosine functions, then we will be able to move on, in future articles to work out how to achieve the other game coding tasks mentioned in the introduction.
Take a look at this next diagram.
For simplicities sake, let’s say we always move 1 pixel each time we update our spaceship’s coordinates. The spaceship is the orange circle. Assuming we have a simple Cartesian coordinate system where y increases as we go up the screen and x increases as we go to the right. Then as shown in the diagram, if we want to go up we increase y by 1, right we increase x by 1, down we decrease y by 1 etc. Furthermoreh the slightly more awkward 45-degree angles can also be fairly simply catered for. If we want to go 45 degrees to the right and up we add 1 to both x and y. If we wanted to go 45 degrees down and to the left we would subtract 1 from both x and y.
But of course a real vehicle can travel at any angle it wants to and our games will be a whole lot more satisfying if they let the player do the same. What the problem can be simplified to is this. We need to find the ratio of the distance travelled on the x-axis compared to the y-axis. Once we have this ratio we can multiply by any factor we like (as long as we multiply both sides of the ratio by the same amount) to vary the speed at which we travel. Enter sine and cosine.
Sine and Cosine
We have one minor stumbling block before we can start testing numbers on a calculator to see how we can set the heading of our spaceship at all those awkward angles. Remember the snippet of Java code earlier? It was two method calls wrapped up together.
... horizontalVelocity = speed* Math.cos(Math.toRadians(facingAngle)); ...
We are passing the result of converting the facingAngle converted into radians, into the cos/sin function/method. This is because sin and cos work with radians, not degrees. Radians are simply another measurement for angles. But if we are going to understand how we can calculate our spaceship’s horizontal and vertical ratio we need to take a quick look at radians.
A radian is a measurement of an arc of a circle. A radian is roughly 57.3 degrees. This might seem arbitrary and invented but it is really degrees that are arbitrary and invented, but we have become used to dealing with them. A radian is precisely the arc of a circle measured to the same length of that circle’s radius.
There are pi (3.14…) radians in 180 degrees and therefore 2 pi (6.28…) radians in a circle. From this, we can work out that pi divided by 180 multiplied by the angle the spaceship is facing is the number of radians we need to send into the sin or cos function.
cos or sin(pi / 180 * facingAngle)
Now if we experiment using a few angles that our spaceship might be heading and analyse the results. Let’s use the angles we already know the answers for.
Perhaps ironically, most simple personal calculators expect DEGREES as an input to sin and cos. If you are unsure what your calculator uses or get different results to those in the table try these neat online calculators for sine and cosine where you can specify degrees or radians (choose radians).
|facingAngle||Convert to radians||Radians||Sin||Cos||Approximate ratio sin:cos|
|45||pi / 180 * 45||0.78||0.70||0.71||1:1|
|180||pi / 180 * 180||3.14||0.00||-0.99||0:-1|
|225||pi / 180 * 225||3.92||-0.70||-0.71||-1:-1|
|270||pi / 180 * 270||4.71||-1.0||0||-1:0|
Remember that the important thing about the answers is not just the actual value but the ratio between the two values returned by sin and cos. So that when we multiply by our spaceship’s xVeloxity and yVelocity variables by a speed variable the heading will be the same as facingAngle. Bearing in mind that 0 degrees means facing 3 o’clock/east/right; let’s look at a few of the results in the table.
As a quick aside, zero degrees returns zero from both sin and cos. This is not a problem because of course, 360 degrees is the same heading as zero degrees.
The first value in the table is when facingAngle = 45 degrees (pointing up to the right/North East). We can see that the value of sin is 0.70 and cos is 0.71. and excluding the discrepancy of 1 one hundredth, if we assigned the value from sin to verticalVelocity and cos to horizontalVelocity would have our ship headed in exactly the intended direction.
The next row in the table is 180 degrees. If we refer back to the diagram we can see that the horizontal velocity should be -1 and the vertical velocity should be 0. We compare our expectations to the values of sin and cos and see that indeed they are exactly correct. Cos is near-as-exactly -1 and sin equals 0.
We can go on and check the rest of the values in the table but what would be more interesting is to try and demonstrate the effectiveness of the method on some more awkward angles.
Consider the following:
- 1 degree in radians = 0.017
- 360 degrees in radians = 6.28
Considering the above two facts, let’s plot a graph with every value between and including those values for the values of sine and cosine. The actual values of sine and cosine are not shown in the image below but their relationship to each other and the uniform, constrained and extremely useful extents of those values are. Almost certainly you will have seen these before. They are the sine and cosine waves.
So we can see that we can rely on the values returned by the cosine function to give us a velocity for horizontal movement based on the angle our spaceship is facing as long as we plug that same value into Sine and use it for the vertical velocity.
We can also use sine and cosine for orienting (rotating) graphics; because what is the point in heading in the exact angle as calculated above if we are looking the other way? But that is a topic for part 2 of this series.