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 > ArcTan2

#60623 - Orion - Sun Nov 13, 2005 1:38 am

hello

I have some code like this:

Code:
arctan2(obj_x - player_x, player_y - object_y)


Where that macro is deifned as:

Code:
#define arctan(x, y)   bios_arctan2(x, y) * 0.0054932478828107118333714808880771


extern __attribute__ ((long_call)) u16 bios_arctan2(s16 x, s16 y);


The number is worked out like this: 1 / (65535 / 360). It's the return value for 360 degrees, divided by 360 degrees, and reciprocated so you multiply to get the angle.

My problem is that if I double object_y, the angle the object moves to meet the player halves instead of doubling - so it completely misses and fires off elsewhere. If object_y and object_x are in ratio, though (32 and 32, or 16 and 16, or 64 and 64) then it works fine, with the object moving at the expected angle.

Can you help? Is it something to do with how I am dealing with ArcTan2?

Thank you

#60627 - tepples - Sun Nov 13, 2005 2:36 am

This won't solve your problem, but it's something to think about:

First of all, whenever you multiply by a number with a decimal point, you bring in the floating point emulator. The GBA's CPU has no dedicated floating point hardware, so it has to emulate it using hundreds of ARM CPU instructions. If you use any floating point code in a loop, it will run very slowly.

Another thing you could try is designing your data structures around the unit "brads" instead of "degrees". There are 256 brads in a circle, or 64 brads in a right angle. I know that at least the BASIC Stamp uses brads, and so does the Allegro library. Then you can use the values returned from BIOS ArcTan2 directly.

One thing you could do is make a loop that steps through each direction from 0 to 359 (or 255 once you make the switch to brads) and shoots once to make sure that it's not exchanging the axes or anything.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.


Last edited by tepples on Sun Nov 13, 2005 4:24 am; edited 1 time in total

#60628 - Orion - Sun Nov 13, 2005 2:46 am

Using brads sounds like a good idea cause then I could use & to loop my sin lookups as well... Hmm. thanks.

And trying that, I found that I have to actually use ArcTan2(y,x)... but I've never seen any implementation have to do this before. Think this is specific to the way I'm doing things?

Another question... would I be better doing a bios divide or a multiply by 0.005495 (for speed)?

#60631 - DekuTree64 - Sun Nov 13, 2005 3:06 am

Orion wrote:
Code:
arctan2(obj_x - player_x, player_y - object_y)

Hmm, this may just be a typo, but shouldn't it be object_y - player_y, not the other way around? I think that could cause the backwardness from what you're expecting when you double object_y...

Also, there's an old thread with an atan2 implementation using ARM-friendly integer math, and written in assembly. Might want to try that out if you switch your angles to brads. Looks like it uses a 512 degree circle though, so you'd want to divide the angle it returns by 2 to convert to brads.
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku

#60633 - Orion - Sun Nov 13, 2005 3:27 am

Well, the thing was, before I had that odd thing in there it made my object move in a perfect quarter-circle around the obejct I wanted it to move to o_O

#60635 - LOst? - Sun Nov 13, 2005 4:17 am

brads?

Is that the official name for 256 circle radian?

Any official name for 512 circle radian?
_________________
Exceptions are fun

#60636 - tepples - Sun Nov 13, 2005 4:28 am

LOst? wrote:
brads?

Is that the official name for 256 circle radian?

Don't know if the unit of Pi/128 radians is recognized by any standards body, but in addition to the Stamp, at least FutureBASIC for Mac has used the term, explaining it as b for binary, rad for radian.

Quote:
Any official name for 512 circle radian?

Easy: "Brads in 8.1 fixed point."
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#60639 - LOst? - Sun Nov 13, 2005 5:01 am

[quote="tepples"]
LOst? wrote:
explaining it as b for binary, rad for radian.


Great! I love that name. I use 256 circle radian all over my engines. In DS I am using 512 because it fits the hardware better.
_________________
Exceptions are fun

#60654 - poslundc - Sun Nov 13, 2005 10:03 am

Orion wrote:
Another question... would I be better doing a bios divide or a multiply by 0.005495 (for speed)?


If you convert the number to fixed point, multiplication will be much, much faster.

If you leave it as floating point, there's a good chance it will be slower.

Used fixed point. Everywhere, all the time.

Dan.

#60659 - sgeos - Sun Nov 13, 2005 1:35 pm

poslundc wrote:
Used fixed point. Everywhere, all the time.

Unless you have access to an FPU.

-Brendan