I've neglected this thread for far too long and it could really use a bit of a rewrite. Thanks for catching that Seravy I don't know what I was thinking when I wrote that section.

Anyways I've written up a fairly detailed explanation of common trigonometric functions, hopefully there's one person who won't tl;dr it.

If you want to understand how sine, cosine, and tangent work you need to understand a few fundamental things about circles and triangles.

Consider a whole circle. The circumference is PI * 2 * radius. For the sake of this explanation we will use what is a called a unit circle, which is a circle with radius 1

Which means our circumference is simply PI * 2. We also have a unit of angle measurements called radians, which are simply relating angles to the length of an arc on our unit circle. That is to say 360 degrees (a full circle) is equal to 2*PI radians.

In mugen, sin, cos, and tan use radians as parameters, not degrees. Therefore, before you do any calculation you must remember to use the correct conversion.

**What are sin, cos, and tan?**

These are ratios of the sides of a right triangle. As long as we know the angles of a triangle, and one angle on that triangle is 90 degrees (PI/2 radians) we can know for certain the ratios of the lengths of all three sides of the triangle.

For example, if we have a triangle with two angles of 45 degrees and one angle of 90 degrees (your Geometry teacher will call this a 45/45/90 triangle) then the two sides near the right angle will be X and the hypotenuse will be of length X * square root of 2. It doesn't matter how big the triangle is, those ratios will be constant as long as the angles don't change.

So how are these ratios defined?

Most people in school will learn SOHCAHTOA

Say it repeatedly until you remember it.

SOH = Sine, Opposite over Hypotenuse

CAH = Cosine, Adjacent over Hypotenuse

TOA = Tangent, Opposite over Adjacent

Naturally in a right triangle, the hypotenuse refers to the side directly opposite of the right angle. So in our 45/45/90 example, we can take the sine of one of the 45 degree angles, and that'll give us 1/sqrt(2)

Plug in sin(45) in a calculator and you'll get that answer.

If you know the lengths of a right triangle, but you don't know the other two angles, you can use inverse trigonometry and input your ratio in order to get the angle, asin, acos, and atan.

**I still don't get it.**

If you want to imagine sin and cos graphically, imagine the unit circle in your head. You know, the circle with radius 1. Now imagine that circle is on a graph, with the center at 0,0. That means that 0 degrees on the circle (furthest right) is at point 1,0

If you want to know the position of any point in the circle, the X coordinate is cos and the Y coordinate is sin. So sin(0) is 0 and cos(0) is 1. At the top of the circle, 90 degrees, the circle is at 0,1. So sin(90) = 1 and cos(90) = 0. Looking at it this way, you can observe a few interesting things about sin and cos

- Because the unit circle only has a radius of 1, sin and cos will only go from -1 to 1

- sin and cos repeat themselves after going a full 360 degrees (2*PI) this is also called the period of the function.

- cosine is just a sine that's been shifted by 90 degrees (PI / 2)

**But what about Tan?**

tan is simply sin/cos.

**How is this useful?**

As I mentioned before you can find the coordinates of any point of a circle using sin and cos, provided you have the angle. In a unit circle, we know the radius is going to be 1, but we can use the same formulas to find coordinates for a circle of any size just by multiplying the radius. So if we want the coordinates at 30 degrees 20 feet away from the center, we use 20*cos(30) for the x axis and 20*sin(30) for the y axis.

**Show me how this fancy math works.**

Ok, here's a video I made recently.

http://www.youtube.com/watch?v=7nZQu9rrLFA

And here's the code that makes it work.

[State 3150, Fulcrum] ; Spawn the center of our "circle"

type = Helper

trigger1 = anim = 3150

trigger1 = animelemno(0) = 2

name = "Fulcrum"

ID = 3150

pos = 250, -400

stateno = 3151

ownpal = 1

persistent = 0

[State 3150, Arm] ; The arm is a seperate object from the body

type = Helper

trigger1 = anim = 3150

trigger1 = animelemno(0) = 2

name = "Arm"

ID = 3151

pos = 0,-120

stateno = 3152

ownpal = 0

persistent = 0

[State 3150, Wire] ; The string that shoots out is also its own object

type = Helper

trigger1 = anim = 3150

trigger1 = animelemno(0) = 2

name = "Wire"

ID = 3152

pos = 0,-120

stateno = 3153

ownpal = 0

persistent = 0

[State 3150, Clone] ; The body we see is actually a helper, the real character will be invisible

type = Helper

trigger1 = anim = 3151

trigger1 = animelemno(0) = 2

name = "Clone"

ID = 3154

pos = 0,0

stateno = 3155

ownpal = 0

persistent = 0

[State 3150, Blade] ; The part that attacks just spins around on its own.

type = Helper

trigger1 = anim = 3151

trigger1 = animelemno(0) = 2

name = "Blade"

ID = 3153

pos = 0,-120

stateno = 3154

ownpal = 0

persistent = 0

[State 3150, Distance Calculate] ; Here we use the pythagorean theorem to find the initial distance between the character and the fulcrum

type = varset

trigger1 = anim = 3151

trigger1 = animelemno(0) = 2

fvar(0) = (((helper(3150), Pos Y)-(Pos Y-120))**2 + ((helper(3150), Pos X)-(Pos X))**2)**.5

persistent = 0

[State 3150, Angle Calculate] ; Calculate the angle of the character relative to the fulcrum. Remember it slows down near the ends.

type = varset

trigger1 = anim = 3151

fvar(1) = -1* sin((time+12)*pi/70.0)

[State 3150, Position Set] ; Here's where we actually figure out where the character needs to be

type = posset

trigger1 = anim = 3151

trigger1 = animelemno(0) >= 2

x = (helper(3150), Pos X) + facing*fvar(0)*cos(fvar(1)*pi/2 - pi/2)

y = (helper(3150), Pos Y) - fvar(0)*sin(fvar(1)*pi/2 - pi/2) + 120

[State 3150, Invisible]

type = assertspecial

trigger1 = anim = 3151

trigger1 = animelemno(0) >= 2

flag = invisible

[State 3150, Screenbound]

type = Screenbound

trigger1 = anim = 3151

trigger1 = animelemno(0) >= 2

value = 0

movecamera = 0,1

[State 3150, End]

type = ChangeState

trigger1 = time = 90+140*var(5)

trigger2 = anim = 3151

trigger2 = animelemno(0) >= 2

trigger2 = command = "a"

value = 50

ctrl = 1

;Arm

[Statedef 3152]

type = A

physics = N

movetype = I

ctrl = 0

anim = 3152

[State 3152, Screenbound]

type = Screenbound

trigger1 = 1

value = 0

movecamera = 0,0

[State 3152, Bind] ; Attach the arm to the body

type = BindToParent

trigger1 = 1

time = 1

pos = 0,-120

[State 3152, AngleSet] ; Remember where we attached the arm, set the angle based on that.

type = AngleSet

trigger1 = ((helper(3150), Pos X)-Pos X) != 0

value = -1* facing * 180.0*atan(((helper(3150), Pos Y)-Pos Y)/((helper(3150), Pos X)-Pos X))/pi

[State 3152, Flip] ; We have to make a correction here depending on if we're on the left or right side of the swing.

type = AngleAdd

trigger1 = ((helper(3150), Pos X)-Pos X) < 0

value = 180

[State 3152, Flip Again] ; We have to make a correction here if we're facing left or right.

type = AngleAdd

trigger1 = facing < 0

value = 180

[State 3152, AngleSet]

type = AngleSet

trigger1 = ((helper(3150), Pos X)-Pos X) = 0

value = 90

[State 3152, AngleDraw]

type = AngleDraw

trigger1 = 1

[State 3152, Destroy]

type = destroyself

triggerall = IsHelper

trigger1 = Root, Stateno != 3150

;Wire

[Statedef 3153]

type = A

physics = N

movetype = I

ctrl = 0

anim = 3154

[State 3153, Screenbound]

type = Screenbound

trigger1 = 1

value = 0

movecamera = 0,0

[State 3153, Extend]

type = varset

trigger1 = time < 7

fvar(0) = time/6.0

[State 3153, Bind]

type = BindToParent

trigger1 = 1

time = 1

pos = 0,-120

[State 3153, AngleSet] ; This code is the same as the arm

type = AngleSet

trigger1 = ((helper(3150), Pos X)-Pos X) != 0

value = -1 * facing * 180.0*atan(1.0*((helper(3150), Pos Y)-Pos Y)/((helper(3150), Pos X)-Pos X))/pi

[State 3153, Flip]

type = AngleAdd

trigger1 = ((helper(3150), Pos X)-Pos X) < 0

value = 180

[State 3153, Flip Again]

type = AngleAdd

trigger1 = facing < 0

value = 180

[State 3153, AngleSet]

type = AngleSet

trigger1 = ((helper(3150), Pos X)-Pos X) = 0

value = 90

[State 3153, AngleDraw]

type = AngleDraw

trigger1 = 1

scale = 4.2*fvar(0),1

[State 3153, Destroy]

type = destroyself

triggerall = IsHelper

trigger1 = Root, Stateno != 3150

;Blade

[Statedef 3154]

type = A

physics = N

movetype = I

ctrl = 0

anim = 3155

sprpriority = 3

[State 3154, Screenbound]

type = Screenbound

trigger1 = 1

value = 0

movecamera = 0,0

[State 3154, Bind]

type = BindToParent

trigger1 = 1

time = 1

pos = 0,-120

[State 3154, AngleSet] ; This blade just spins on its own, but it has a precise timing to it. It spins once completely every 32 frames.

type = AngleSet

trigger1 = 1

value = -time*45.0/4.0

[State 3154, AngleDraw]

type = AngleDraw

trigger1 = 1

[State 3154, Destroy]

type = destroyself

triggerall = IsHelper

trigger1 = Root, Stateno != 3150

;Clone

[Statedef 3155] ; This is the body we see. on the back swing it just hangs upright, but at the front it starts angling backwards.

type = A

physics = N

movetype = I

ctrl = 0

anim = 3156

sprpriority = 2

[State 3155, Screenbound]

type = Screenbound

trigger1 = 1

value = 0

movecamera = 0,0

[State 3155, Bind]

type = BindToParent

trigger1 = 1

time = 1

pos = 0,0

[State 3155, Angle Calculate] ; Find the angle, same code as the main body

type = varset

trigger1 = 1

fvar(1) = -1* sin((time+52)*pi/70.0)

[State 3155, AngleSet] ; Find the angle, slightly different code because the axis is off by 120

type = varset

trigger1 = 1

fvar(2) = -1 * facing * 180.0*atan(((helper(3150), Pos Y)-(Pos Y-120))/((helper(3150), Pos X)-Pos X))/pi + 90

[State 3155, Offset] ; Make a position correction based on the angle, since the axis is wrong this is actually complicated.

type = offset

trigger1 = cos(fvar(1)*pi/2 - pi/2) > .01

x = facing*120*cos(fvar(2)*pi/180.0-pi/2.0)

y = -120*sin(fvar(2)*pi/180.0) + 48*sin(fvar(2)*pi/90.0)

[State 3155, Angle] ; Set the angle, but only at the front of our swing.

type = AngleSet

trigger1 = cos(fvar(1)*pi/2 - pi/2) > .01

value = fvar(2)

[State 3155, Angle]

type = AngleDraw

trigger1 = cos(fvar(1)*pi/2 - pi/2) > .01

[State 3155, Destroy]

type = destroyself

triggerall = IsHelper

trigger1 = Root, Stateno != 3150