gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Coding > Angles

#19579 - kinski - Thu Apr 22, 2004 9:48 am

Hello everybody, here is my first post.
I'd like to know the way to calculate in C the value of an angle between two sprite, as figured below:
[Images not permitted - Click here to view it]

Could someone help me? Thank you.

#19585 - Cearn - Thu Apr 22, 2004 1:40 pm

This is basic trigonometry.

If we use
(dx, dy) : the differences between the two objects in the x and y directions
dist : the distance between them dist= sqrt(dx^2 + dy^2)
theta : the angle you have in your picture

then

cos(theta)= dy/dist
sin(theta) = dx/dist
tan(theta) = sin(theta)/cos(theta) = dx/dy

These equations are a little different than the standard trig definitions because you chose the angle based on the y-axis instead of the x-axis. To get the actual angle, you need to use the inverses of these functions, arcsin, arccos and arctan. The C library <math.h> contains functions for these. You will have to be careful with minus signs, though, because the range of arccos, arcsin and arctan will only cover half a circle. You would have to check the signs of dx and dy for the full angle.

However, using these routines is bad idea on the GBA. As anyone here can tell you, the GBA doesn't have real floating point support so sqrt or any of the trigonometry functions are going to be dead slow. The same goes for division. You will want to put these in look-up tables instead.

Are you sure need the full angle by the way? If you just need a direction you can use the definitions for sin(theta) and cos(theta) without any need for the actual angle, which would save a good deal of calculation time.
There are also fast ways of calculating the distance that you need for this, but I can't recall it at this time. I'm sure one of the others can help you with that.

#19588 - kinski - Thu Apr 22, 2004 2:45 pm

Thank you a lot, Cearn.
In fact, I do not need the exact angle, just a direction... But I dont really understand this, since I have to use square root to calculate sin or cos:
Quote:

If you just need a direction you can use the definitions for sin(theta) and cos(theta) without any need for the actual angle, which would save a good deal of calculation time.

Could you explain?

Thanks again.

#19590 - Cearn - Thu Apr 22, 2004 3:10 pm

Quote:

Thank you a lot, Cearn.
In fact, I do not need the exact angle, just a direction... But I dont really understand this, since I have to use square root to calculate sin or cos:


Yes and no. The direction itself is actually simply given by (dx, dy), so if is really is just that, you're already done. But what you probably want is to shoot something off in that direction, right? In that case, you have to normalize the vector first and then multiply by the speed. Something like

vx= speed*dx/distance
vy= speed*dy/distance

Then, yes you would need the square root. In fact, you need to divide by the square root, so you have not one but two costly functions.

The GBA has BIOS routines that can do division and square roots, which are preferable to the standard C routines. For something on BIOS calls, search on the forum or look at http://user.chem.tue.nl/jakvijn/tonc/swi.htm or, even better,
libgba in the sample code of devkitARM, which has a nice way of dealing with these matters.

I am almost positive there is fast way of getting an approximation of 1/sqrt(x), but I can remember anymore. Does anyone else know?

EDIT: this thing's been covered already in http://forum.gbadev.org/viewtopic.php?t=2594. Seems that using arctan2 and a sin/cosine lut is the preferred solution.

#19597 - Miked0801 - Thu Apr 22, 2004 5:37 pm

How exactly do you need the direction represented - as a vector I assume? If so, what are you attempting to do with that angle? Depending on how you are going to use it, you can probably get away without a ArcTan/Sqrt and perhaps without the Div too. :)

#19671 - kinski - Fri Apr 23, 2004 8:34 am

In the image above, at the intersection of the two lines is a kind of "shooting tower" (in french, we call it a DCA) that should rotate in the direction of the main sprite (and then shoot at it).
Finally, I found a solution that is not based on angles but on the 8 main lines that have the tower as intersection. I just check if my main sprite is on one of these eight lines. It works fine.

Anyway, thanks a lot to the both of you for you help.
-> Cearn : it's quite funny, I was printing the content of your site (TONC) the day before starting this post. Impressive work!