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!!!)
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.
u8 x = 0;
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
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:
u8 x = 0;
sinTable[x] = (int)(1000* sin( 360 /255 * x * 2 * PI ));
later on you divide by 1000 needing a value of the LUT: sinTable/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.
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.