GP32 Calculate Angle Beetween 2 Sprites


JyCet

Member
Joined
Feb 23, 2004
Messages
469
Age
118
Location
France
Website
Visit site
Ok,

Here a topic to ask how to calculate the angle A beetween 2 sprites (SPR0 & SPR1).
The only thing I know is DX and DY (spr0.x-spr1.x=DX & spr0.y-spr1.y=DY):
calcul_angle.gif


It’s really interesting for shoot em up enemy bullets, but I don’t know how calculate this angle A.

I hope someone can help me.

JYCET
 
You need to use atan2 like this:

angle = -atan2( dy, dx );

This will return the angle in RADIANS!!!

If you want to move a bullet a certain amount of pixels, given an angle, you use this:

bulletx = bulletx + sin(angle)*pixelsToMove;
bulletx = bulletx + cos(angle)*pixelsToMove;

If this doesn't work, swap the cos and sin, I may have got them around the wrong way.

EDIT:
Remember that if you calculate dx and dy like this:
dx = sprite1-sprite0;
Then the angle is towards sprite1 from sprite0
If you do it like this (which is incorrect):
dx = sprite0-sprite1;
Then the angle is towards sprite0 from sprite1

HIH
Pea
 
@Splinter:
I think you write a joke :D
It's only a example picture, all sprites move and sure their angle change ;)

@pea:
Thank you for your guide.
Today, I know how to move a sprite with sin or cos (see Aka Noid :)) and I use only 256 angle not 360, it's simpler in fact 1bit = 1.4° , it's very nice solution for 2d game and with 320*240 resolution screen ;)

I see:
tan A = DY/DX
first pb division is not good for arm9 so I can use
DXi=1/DX =========> need to convert in fixed point
tan A = DY*DXi
second pb convert RADIAN to DEGREE:
DEGREE = 180 * (RADIAN) / pi ========> another division :(

Finally I think i'll precalutate all possibility, there're some very easy:
0° is when DY=0 & DX>0
45° DY=DX
90° DX=0 & DY>0
135° DY=-DX & DX<0
180° DY=0 & DX<0
225° DX=DY & DX<0 & DY<0
270° DX=0 & DY<0
315° DX=-DY & DY <0
360°=0°
 
For this job, trigonometry is far too much work :)

Look up Bresenham's line drawing algorithm instead. It's simple and extremely fast (it's all integer-based) and will give you exactly what you need to get your enemy bullet going towards your hero :)

Here's a link, although google has many more :D
 
Personally, I would still use trig, just because it would be easier to follow...

I would look at the allegro libraries which are a free c library for game development. These have fixed point routines that you can use almost out of the box that calculate atan2, atan, cos, sin etc and all in 256 step angles like you say, using look-up tables for speed.

Bresenham might be faster, but the trig solution would be neater :)

EDIT: On a side note:

when you convert degrees to radians (or vv) you don't need to divide. This is because:
DEGREE = 180*RADIAN/PI;
Multiplications and divisions can be placed in any order, so this is the same:
DEGREE = 180/PI * RADIAN;
Now all you need to do is have a pre-calculated value for 180/PI:
#define CONVERTRAD 57.29578
And do this:
DEGREE = CONVERTRAD * RADIAN;
 
JyCet: Your thinking too much. The rule of "The simplest is normally the best and quickest to implement.". Follow that rule, and then (and only then) if you find your game is too slow, profile it and optimize the slow parts. You may be suprised and find it's not your trig functions or floating point.

It's pointless spending a day or so optimizing a routine, and then finding out that it wasn't where the bottleness was.
 
precalculate a 2d array for 256 angle with 1.4°:

unsigned char pre_angle[240][320];

for (y=0;y<239;++y)
for (x=0;x<319;++x)
pre_angle[y][x]=((atan2(y,x)*180/PI)*256/360);



Of course it's only to calculate angle 0° to 90° (0 to 64 for me :))
for the negative dx or dy it's easy and faster to add 180° or anything.

BUT i dont arrive to calculate only ONE correct angle ! :blink:
I really dont understand why it doesn't work


edit:
If I test with:
unsigned char angle;

angle=((atan2(10,0)*180.0/PI)*256/360);

sprintf((char*)g_string, "%d",angle);
put_string10(g_string,2,230);
GpTextOut(NULL,&gpDraw[nflip],2,200,g_string,BLANC);

display bad angle :(
 
JyCet posted on May 3 2005 at 08:39 PM said:
[...]
sprintf((char*)g_string, "%d",angle);
[...]

When you want to display a float, you must change the format in sprintf, use f:

Code:
sprintf((char*)g_string, "%f",angle);
 
Last edited by a moderator:
Don't run your loops from 0!

when x=0 the angle=0,
when y=0 the angle=90 and tan(90) = infinity and is bad to atan too!

Just add these into your aray as constants seperately and calculate the rest
 
@Oankali
Ok it work better to see float, but angle calculation is always bad.

@gp32rich
Yes i see the pb with borland bcc32 in the loop when x=y=0 and i see another pb i need to put (char) before (atan2....)

unsigned char pre_angle[240][320];

for (y=0;y<239;++y)
for (x=0;x<319;++x)
if (y!=0 && x!=0)
pre_angle[y][x]=(char)((atan2(y,x)*180/PI)*256/360);


@all
But test yourself:
double angle2;
angle2 =atan2 (40,40);
sprintf((char*)g_string, "%f",angle2);
put_string10(g_string,64,230);

on display I've angle2=1,570796
Normaly the correct result should be 0,785398
 
I've tried with VC++ and I get the good result, but with GCC I get the wrong result. Strange...
And why don't you prepare your table in you source file and include it when you need it?

Here you have for example my sin and cos tables I have prepared for my tests.

maths.h
Code:
#ifndef __maths_h__
#define __maths_h__

#ifdef __cplusplus
extern "C" {
#endif


// Constants
#ifndef PI
#define PI 3.14159265
#endif
  
// Global variables
extern signed short cosinus[360], sinus[360];


#ifdef __cplusplus
  }
#endif

#endif /*__maths_h__*/


maths.c:
Code:
#include "maths.h"


//*** Public global variables
// Cosinus table * 1000 every degree
signed short cosinus[360] = {
 1000,  999,  999,  998,  997,  996,  994,  992,  990,  987,  984,  981,  978,  974,  970,
  965,  961,  956,  951,  945,  939,  933,  927,  920,  913,  906,  898,  891,  882,  874,
  866,  857,  848,  838,  829,  819,  809,  798,  788,  777,  766,  754,  743,  731,  719,
  707,  694,  681,  669,  656,  642,  629,  615,  601,  587,  573,  559,  544,  529,  515,
  500,  484,  469,  453,  438,  422,  406,  390,  374,  358,  342,  325,  309,  292,  275,
  258,  241,  224,  207,  190,  173,  156,  139,  121,  104,   87,   69,   52,   34,   17,
    0,  -18,  -35,  -53,  -70,  -88, -105, -122, -140, -157, -174, -191, -208, -225, -242,
 -259, -276, -293, -310, -326, -343, -359, -375, -391, -407, -423, -439, -454, -470, -485,
 -500, -516, -530, -545, -560, -574, -588, -602, -616, -630, -643, -657, -670, -682, -695,
 -708, -720, -732, -744, -755, -767, -778, -789, -799, -810, -820, -830, -839, -849, -858,
 -867, -875, -883, -892, -899, -907, -914, -921, -928, -934, -940, -946, -952, -957, -962,
 -966, -971, -975, -979, -982, -985, -988, -991, -993, -995, -997, -998, -999,-1000,-1000,
-1000,-1000,-1000, -999, -998, -997, -995, -993, -991, -988, -985, -982, -979, -975, -971,
 -966, -962, -957, -952, -946, -940, -934, -928, -921, -914, -907, -899, -892, -883, -875,
 -867, -858, -849, -839, -830, -820, -810, -799, -789, -778, -767, -755, -744, -732, -720,
 -708, -695, -682, -670, -657, -643, -630, -616, -602, -588, -574, -560, -545, -530, -516,
 -501, -485, -470, -454, -439, -423, -407, -391, -375, -359, -343, -326, -310, -293, -276,
 -259, -242, -225, -208, -191, -174, -157, -140, -122, -105,  -88,  -70,  -53,  -35,  -18,
   -1,   17,   34,   52,   69,   87,  104,  121,  139,  156,  173,  190,  207,  224,  241,
  258,  275,  292,  309,  325,  342,  358,  374,  390,  406,  422,  438,  453,  469,  484,
  499,  515,  529,  544,  559,  573,  587,  601,  615,  629,  642,  656,  669,  681,  694,
  707,  719,  731,  743,  754,  766,  777,  788,  798,  809,  819,  829,  838,  848,  857,
  866,  874,  882,  891,  898,  906,  913,  920,  927,  933,  939,  945,  951,  956,  961,
  965,  970,  974,  978,  981,  984,  987,  990,  992,  994,  996,  997,  998,  999,  999,
};

// Sinus table * 1000 every degree
signed short sinus[360] = {
    0,   17,   34,   52,   69,   87,  104,  121,  139,  156,  173,  190,  207,  224,  241,
  258,  275,  292,  309,  325,  342,  358,  374,  390,  406,  422,  438,  453,  469,  484,
  499,  515,  529,  544,  559,  573,  587,  601,  615,  629,  642,  656,  669,  681,  694,
  707,  719,  731,  743,  754,  766,  777,  788,  798,  809,  819,  829,  838,  848,  857,
  866,  874,  882,  891,  898,  906,  913,  920,  927,  933,  939,  945,  951,  956,  961,
  965,  970,  974,  978,  981,  984,  987,  990,  992,  994,  996,  997,  998,  999,  999,
 1000,  999,  999,  998,  997,  996,  994,  992,  990,  987,  984,  981,  978,  974,  970,
  965,  961,  956,  951,  945,  939,  933,  927,  920,  913,  906,  898,  891,  882,  874,
  866,  857,  848,  838,  829,  819,  809,  798,  788,  777,  766,  754,  743,  731,  719,
  707,  694,  681,  669,  656,  642,  629,  615,  601,  587,  573,  559,  544,  529,  515,
  500,  484,  469,  453,  438,  422,  406,  390,  374,  358,  342,  325,  309,  292,  275,
  258,  241,  224,  207,  190,  173,  156,  139,  121,  104,   87,   69,   52,   34,   17,
    0,  -18,  -35,  -53,  -70,  -88, -105, -122, -140, -157, -174, -191, -208, -225, -242,
 -259, -276, -293, -310, -326, -343, -359, -375, -391, -407, -423, -439, -454, -470, -485,
 -500, -516, -530, -545, -560, -574, -588, -602, -616, -630, -643, -657, -670, -682, -695,
 -708, -720, -732, -744, -755, -767, -778, -789, -799, -810, -820, -830, -839, -849, -858,
 -867, -875, -883, -892, -899, -907, -914, -921, -928, -934, -940, -946, -952, -957, -962,
 -966, -971, -975, -979, -982, -985, -988, -991, -993, -995, -997, -998, -999,-1000,-1000,
-1000,-1000,-1000, -999, -998, -997, -995, -993, -991, -988, -985, -982, -979, -975, -971,
 -966, -962, -957, -952, -946, -940, -934, -928, -921, -914, -907, -899, -892, -883, -875,
 -867, -858, -849, -839, -830, -820, -810, -799, -789, -778, -767, -755, -744, -732, -720,
 -708, -695, -682, -670, -657, -643, -630, -616, -602, -588, -574, -560, -545, -530, -516,
 -501, -485, -470, -454, -439, -423, -407, -391, -375, -359, -343, -326, -310, -293, -276,
 -259, -242, -225, -208, -191, -174, -157, -140, -122, -105,  -88,  -70,  -53,  -35,  -18,
};
 
I've build a pre-calculate 2d table and formated it in C with Borland bcc32.
It's fast and IT WORK :D

I really dont understand why it doesn't work with GCC :(

Thank at all for all your help !

JYCET
 
Back
Top