Trigonometry for Gamers - Lesson 1

Post your own tutorials, guides and demos.

Post » Wed Jul 28, 2010 12:21 am

[size=150:eofm602j]Part 1 - Distance[/size:eofm602j]

Trigonometry is, unsurprisingly, the study of triangles. A triangle is defined by any three points in space not on a line and, despite its seeming simplicity, can lead to a lot of pain.

The most useful triangles, at least for our purposes, are right triangles - figures in which one angle is permanently set at 90 degrees. Given that Construct operates in a predefined 2d plane, a little trigonometry can go a long way towards helping objects relate to each other.

One important application of trigonometry is finding the distance between two arbitrary points: by drawing a right triangle whose hypotenuse (the longest arm of a right triangle) is defined by the two points you want to learn the distance between, you can deduce the length of this line with the formula

c^2 = a^2 * b^2

or, to refine it for our use:

dist = sqrt((x2-x1)^2 + (y2-y1)^2).



Fortunately, Construct's developers have included a system expression to do exactly this for us:

distance(x1,y1,x2,y2)

See Pyth.cap for a demonstration.

[size=150:eofm602j]Part 2 - Sines and Cosines[/size:eofm602j]

First, a verbal mnemonic device:

SOH-CAH-TOA.

It stands for:
Sine = Opposite / Hypotenuse
Cosine = Adjacent / Hypotenuse
Tangent = Opposite / Adjacent

These values (sin, cos and tan, although we won't be using tan today) represent the length ratios of the arms listed above. No matter how large the triangle is, the sine of x degrees is the sine of x degrees, and so on.

Observe the following diagram of unknown angle Theta:



Notice that the hypotenuse of our imaginary triangle connects the two points (X1,Y1) and (X2,Y2). We construct this triangle anchored on the X axis because angles in Construct are measured in degrees from that point. This effectively makes the X axis our Adjacent arm (because it is adjacent to angle Theta), and the Y axis our Opposite (because ditto).

Since both Sine and Cosine rely on the value of the hypotenuse, the only remaining choice when calculating offset is which arm to use, and once we anchor our triangle properly it becomes clear - the Cosine value, because it is calculated with the Adjacent arm (which we've ascertained is the same as the X component) becomes our X offset modifier, and the Sine value (Opposite arm, parallel and equal to the Y component) becomes our Y offset modifier.

Because these values are always between -1 and 1, they'll need to be multiplied by another number, which we'll call Magnitude, to get more than ~1 pixel away from the object at the origin of our system.
B
2
S
1
G
2
Posts: 35
Reputation: 870

Post » Wed Jul 28, 2010 12:21 am

[size=150:dxi541tu]Part 3 - Application[/size:dxi541tu]

In response to Kiloku's question:

[quote:dxi541tu]I need a small sprite to always stay in front of the main character. This sprite is kind of a targeting reticule, so it should always keep the same distance away from the character's sprite and always in it's front.[/quote:dxi541tu]

Arcticus wrote:

[quote:dxi541tu]I think what you want is something like

Always set Reticle position to:

X: Player.X + cos(Player.Angle) * Desired distance from player
Y: Player.Y + sin(Player.Angle) * Desired distance from player[/quote:dxi541tu]

The previous sections of this article should provide enough information to properly decode these lines. Player.X,Player.Y indicates the position of the origin (in this case, the player). The cosine of the character's angle corresponds to the X axis offset (remember, adjacent = x axis) and the sine to the character's Y offset (again, opposite = y axis).

'Desired distance from player' directly corresponds to Magnitude as mentioned above - this changes the length of our theoretical hypotenuse and thus the distance the two objects are from each other.

See reticle.cap for a demonstration.

This method can be adapted fairly easily to power any behavior that requires an object to maintain a static distance and orientation from another object. For instance, if we want to make one object orbit another, the same formula can be used, except that the object serving as the Origin would be rotated behaviorally rather than by user input.

We could also remove the Origin entirely and have our satellite orbit empty space by replacing the references to the central object with values we calculate on our own.

See orbit.cap for a demonstration.

One last point - a circle is nothing but an ellipse with equal X and Y offsets. If you set the Magnitude stronger in one axis than the other then you can have your object describe an ellipse around your origin.

See ellipse.cap for a demonstration.

Combine a very large planet with some event-based Z axis movement and you can have it pass in front of or behind your planet as needed.

As far as I can tell, this article should be free of any enormous embarrassing flaws, but it's the product of my effort to teach myself trigonometry so please submit corrections if you notice any big errors.

I hope it was helpful!
B
2
S
1
G
2
Posts: 35
Reputation: 870

Post » Fri Jul 30, 2010 8:51 am

i remember using SOHCAHTOA in high school :D

look like a ninja scream :lol:

SOHCAHTOOAAAAAAAAAAAAAA ! (with the bruce lee pose) :lol:
B
3
S
2
G
2
Posts: 136
Reputation: 1,347

Post » Fri Jul 30, 2010 10:28 pm

Nice tutorial, it's very useful

Could I translate it into Polish and place at Polish Construct blog?
B
6
S
3
G
7
Posts: 138
Reputation: 3,547

Post » Sat Jul 31, 2010 2:39 am

Go for it!
B
2
S
1
G
2
Posts: 35
Reputation: 870


Return to Your tutorials & example files

Who is online

Users browsing this forum: No registered users and 0 guests