Game math: atan

28/12/2009

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.


Math functions like random and sin

27/12/2009

Sometimes you need a random number.

Strange enough: this math function is  found in the stdlib.h: rand() with datatype int

http://www.cs.cf.ac.uk/Dave/C/node16.html#SECTION001600000000000000000

Other math functions are found in the math.h:

like abs, cos, sin, tan, atan

http://en.wikipedia.org/wiki/Math.h

you use the libs like this:

<stdio.h>

<stdlib.h>

<math.h>

int main(){

printf( “this is a random number between 0 and 10 %d \n”, rand() % 10 );

printf( “this is a sin %f \n”, sin(.157) );

while(1) {}

}

Also in the makefile -lm should be added, if it isn’t. You get funny bugs if it isn’t.


Mathematical scripts

26/12/2009

Sometimes you need a small algorithm for a game, for instance a test if a point is inside or outside a triangle defined by three other points.

You can make and test your own solution which will certainly be very instructive, but other very dedicated people have come up with clever solutions and these are very tested!

a good link is: http://www.gmlscripts.com/

for instance, for the problem mentioned above you type triangle in the search field and it comes up with the solution in a readable format:

http://www.gmlscripts.com/script/point_in_triangle

it is easily translated in c for our nds purposes!