YesNoOk
avatar

Math for the Algebraically Challenged (Read 11926 times)

Started by Bronko, November 20, 2005, 04:19:10 pm
Share this topic:
Re: Math for the Algebraically Challenged
#21  November 22, 2009, 05:54:50 pm
  • avatar
  • ***
  • Why can't I upload a Profile Pic?!
Re: Math for the Algebraically Challenged
#22  November 25, 2009, 03:29:47 pm
  • ******
  • Just a butcher on a mission.
    • www.justnopoint.com/lbends
Heh, I completely forgot about this thread.
For now I'm going to see if I can find the images again and re-upload.
Re: Math for the Algebraically Challenged
#23  October 21, 2011, 01:17:24 am
  • ****
    • Hungary
    • seravy.x10.mx/Wordpress
There is a mistake around here :
Quote
Time^2 is just another notation for Time*Time. The bigger the exponent, the faster the graph curves upward.  And just as the inverse of multiplication is division, the inverse of an exponent is a logarithm.
Logarithm base 2 would be the inverse of 2^Time, not Time^2.
Time^2 is the square of Time, and the inverse of that is Square Root, so the graph below is Sqrt(time) and not log(2,time).

For comparison,
log(2,64)=6 (because 2^6=2*2*2*2*2*2=64)
log(2,1024)=10  (because 2^10=2*2*2*2*2*2*2*2*2*2=1024)
log(2,65536)=16 (because 2^16=65536)
sqrt(64)=8 (because 8^2=8*8=64)
sqrt(1024)=32. (because 32^2=32*32=1024)
sqrt(65536)=256. (because 256^2=256*256=65536)

As you can see, logarithm grows a lot slower than square root does.
Other than that, nice guide, math is indeed often useful when coding things in Mugen, and there are way too many people not using it.
Re: Math for the Algebraically Challenged
#24  March 08, 2012, 09:27:32 pm
  • ******
  • Just a butcher on a mission.
    • www.justnopoint.com/lbends
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.
Code:
[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