Game math: atan

Hm, I wanted to shoot an arrow, in the direction in which a sprite is dragged, using the touchscreen of course.
So the arrow sprite has to be rotated, and we have the x distance and the y distance of the dragging.
To get the angle, normally the atan or atan2 is used (this even works in Second Life!!!)
First possibility:

atan gives an error….. not found in devkitpro???

if this happens take a look at your makefile:

#———————————————————————————
# any extra libraries we wish to link with the project
#———————————————————————————
LIBS    := -lmm9 -lnds9 -lm

this last -lm tells the compiler to include mathematical libraries. Sometimes in example makefiles it is left out.

Ok the atan function is found, how to work with it?

By the way without a library you have two possibilities:

  • working with approximations
  • working with tables

Working with approximations

If you want to do math without the math library you can always use approximations, which are quite good: I wrote about this in another blog: http://nds-homebrew-hslleiden.blogspot.com/2008/06/nds-and-atan.html

Approximations can be found on the internet, for sin, cos, tan, atan, and of course other math functions.

Working with tables: LUT look up table

When working on smaller or slower devices, you dont use complicated functions like sin, atan, you use tables. At the start you generate an array with the values you need for your functions, probably, also because the screen is small, only 255 for a whole 360 degrees. This costs a bit of memory space, but looking up something in this table is much faster than calculating the function.

An example:

float sinTable[255];

u8 x = 0;

for(x=0;x<255;x++)

sinTable[x] = sin( 360 /255 * x * 2 * PI );

you do this once at the beginning of your app and after that:

you just ask the value of your  array for 180 degrees: sinTable[128]

You can even do better because of the symmetry of the sin:

When over 180 degrees you use the negative value of the x-180, saving half of the mem space needed for the table. The cosTable can also be minimized, the cos having the same shape and being “in front” 90 degrees.

cos ( x ) = sin ( x + 90 degrees)

be careful with negative x or x bigger than 360. (360 degrees = 255 u8)

ok: not working with floats? multiply the value by say 1000 and use the int:

int sinTable[255];

u8 x = 0;

for(x=0;x<255;x++)

sinTable[x] = (int)(1000* sin( 360 /255 * x * 2 * PI ));

later on you divide by 1000 needing a value of the LUT: sinTable[128]/1000

saving lots of space!
Remark: say you dont have a sin function. You are not able to calculate your table. Then you calculate the list in another IDE and import this prepared LUT as a textfile using libfat.

(found this picture somewhere 🙂

Working with atan or atan2:

Of course the x and y on the screen are different from our normal thinking y being positive while going downwards.

atan( x/y ) (one arguments)  is only defined on -90 to 90 degrees so you have to be careful about the quadrants:

atan( 65 / 45 ) = 45.001327 // using atan( 65 / 45 )/PI*180 to get degrees
atan( -65 / 45 )= -45.001327
atan( 65 / -45 )=  -45.001327  //this is  a quadrant repeated
atan( -65 / -45 )= 45.001327  //this is  a quadrant repeated

The trick is simple: if y (in atan (x / y) is negative add 180 or PI.

atan2(x, y) (two arguments)  is defined on the whole 360 degrees:

atan2( 65 / 45 ) = 55.306478 // using atan2( 65 , 45 )/PI*180 to get degrees
atan2( -65 / 45 )= -55.306478
atan2( 65 / -45 ) = 124.698831
atan2( -65 / -45 )= -124.698831

all is done without worrying about the quadrants

Rotation using a matrix will b explained in another blog.

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: