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.

DS development > How to detect an enemy

#60780 - jandujar - Mon Nov 14, 2005 8:15 pm

Hello people,

I'm getting stark mad.
I don't know how to detect if I have an enemy in front of my player.

I move my player and I have his coordinates in (x,y), for example (x1,y1).
My player moves arround itself 360 degrees, and I have the point touched with stylus (x2,y2).

So my player points at the direction of the line
R = (x1,y1) + t(x2-x1,y2-y1)

The cpu's player has coordinates (a,b).

To know if my player are pointing the cpu, I calcule the distance between the cpu and the line and then I look if this distance is less than a value r(radius of the cpu's body) (i calcule the distance^2 to reduce calculations)

d(P,r)= |Ax+By+C|
---------
sqrt(A^2 + B^2)

Where A=1/(x2-x1)
B=-1/(y2-y1)
C=y1/(y2-y1) -x1/(x2,x1)

This is the code:


Code:

s32 CSDS_distancia_recta_punto(u8 x1,u8 y1,u8 x2,u8 y2,u8 a,u8 b){
   s32 A,B,C,arriba,abajo,resultado;
   PA_OutputSimpleText(1,0,1,"                                    ");
   PA_OutputSimpleText(1,0,2,"                                    ");
   
   if(x2-x1!=0 && y2-y1!=0){
      A=1/(x2-x1);
      B=-1/(y2-y1);
      C=(-y1*B) - (x1*A);
      arriba=(A*a)+(B*b) +(C);
      arriba=arriba^2;
      abajo=(A^2)+(B^2);
      resultado=arriba/abajo;
   PA_OutputText(1,0,1,"(%d,%d) (%d,%d) (%d,%d)",x1,y1,x2,y2,a,b);
   PA_OutputText(1,0,2,"A = %d, B= %d, C=%d, resultado=%d",A,B,C,resultado);
   if(resultado<0){PA_OutputText(1,0,2,"Es -"); return 80000;}
   return resultado;
   }else{
      PA_OutputSimpleText(1,0,0,"es 0                                    ");
      return 8000;
   }
}


But this code make incorrects values.
What I'm making bad?

Note: Sorry for my english.

You can view a java applet to show you the distance between point and a line http://www.pntic.mec.es/Descartes/Bach_CNST_1/Geometria_afin_analitica_plano_lugares_geome[url]tricos/Geometria4.htm

Please, help me. I have 2 weeks working on this.
_________________
http://jandujar.homelinux.com
http://www.dsrobot.com

#60781 - natrium42 - Mon Nov 14, 2005 8:41 pm

Ugh, you know that you are using integer variables, right? They don't have enough "precision" for the kind of calculations you are doing, by briefly looking at your code.

For example:
Code:
A=1/(x2-x1);


where A, x1, x2 are integers will give you A=0 most of the time and sometimes A=1, because of rounding... A will never have any other values.
_________________
www.natrium42.com

#60783 - Foxy - Mon Nov 14, 2005 8:49 pm

BTW with C/C++, A ^ B doesn't mean A power B, but A XOR B.

#60785 - Frz - Mon Nov 14, 2005 9:10 pm

Actually in integer divison there is no rounding. So 999/1000 is still 0 in integer division

only the value 1 could work
(1/1 = 1 :))

#60789 - jandujar - Mon Nov 14, 2005 9:29 pm

I haved change the code and still does not work. :(

Code:

s32 CSDS_distancia_recta_punto(u8 x1,u8 y1,u8 x2,u8 y2,u8 a,u8 b){
   float A,B,C,arriba,abajo,resultado;
   PA_OutputSimpleText(1,0,1,"                                    ");
   PA_OutputSimpleText(1,0,2,"                                    ");
   
   if(x2-x1!=0 && y2-y1!=0){
      A=1/(x2-x1);
      B=-1/(y2-y1);
      C=(-y1*B) - (x1*A);
      arriba=(A*a)+(B*b) +(C);
      arriba=arriba*arriba;
      abajo=(A*A)+(B*B);
      resultado=arriba/abajo;
   PA_OutputText(1,0,1,"(%d,%d) (%d,%d) (%d,%d)",x1,y1,x2,y2,a,b);
   PA_OutputText(1,0,2,"A = %d, B= %d, C=%d, resultado=%d",A,B,C,resultado);
   if(resultado<0){PA_OutputText(1,0,2,"Es -"); return 80000;}
   return resultado;
   }else{
      PA_OutputSimpleText(1,0,0,"es 0                                    ");
      return 8000;
   }
}

_________________
http://jandujar.homelinux.com
http://www.dsrobot.com

#60790 - Mighty Max - Mon Nov 14, 2005 9:43 pm

It will still calc (i.e.)

A=1/(x2-x1);

in int and then convert to float, as the implizit conversation will only be made when needed.

you should try

A = 1/((float)x2-x1) ;

That way the compiler is forced to do the conversation to float prior to any calculation.
_________________
GBAMP Multiboot

#60791 - jandujar - Mon Nov 14, 2005 9:49 pm

Thanks a lot, I finally fount the solution:

Code:

s32 CSDS_distancia_recta_punto(u8 x1,u8 y1,u8 x2,u8 y2,u8 a,u8 b){
   float A,B,C,arriba,abajo,resultado;
   PA_OutputSimpleText(1,0,1,"                                    ");
   PA_OutputSimpleText(1,0,2,"                                    ");
   
   if(x2-x1!=0 && y2-y1!=0){
      A=1/((float)x2-(float)x1);
      B=-1/((float)y2-(float)y1);
      C=(-(float)y1*(float)B) - ((float)x1*(float)A);
      arriba=((float)A*(float)a)+((float)B*(float)b) +((float)C);
      arriba=(float)arriba*(float)arriba;
      abajo=((float)A*(float)A)+((float)B*(float)B);
      resultado=(float)arriba/(float)abajo;
   PA_OutputText(1,0,1,"(%d,%d) (%d,%d) (%d,%d)",x1,y1,x2,y2,a,b);
   PA_OutputText(1,0,2,"A = %f, B= %f, C=%f, resultado=%f",A,B,C,resultado);
   if(resultado<0){PA_OutputText(1,0,2,"Es -"); return 80000;}
   return resultado;
   }else{
      PA_OutputSimpleText(1,0,0,"es 0                                    ");
      return 8000;
   }
}

_________________
http://jandujar.homelinux.com
http://www.dsrobot.com

#60824 - LOst? - Tue Nov 15, 2005 4:25 am

jandujar wrote:
Thanks a lot, I finally fount the solution:

Code:

s32 CSDS_distancia_recta_punto(u8 x1,u8 y1,u8 x2,u8 y2,u8 a,u8 b){
   float A,B,C,arriba,abajo,resultado;
   PA_OutputSimpleText(1,0,1,"                                    ");
   PA_OutputSimpleText(1,0,2,"                                    ");
   
   if(x2-x1!=0 && y2-y1!=0){
      A=1/((float)x2-(float)x1);
      B=-1/((float)y2-(float)y1);
      C=(-(float)y1*(float)B) - ((float)x1*(float)A);
      arriba=((float)A*(float)a)+((float)B*(float)b) +((float)C);
      arriba=(float)arriba*(float)arriba;
      abajo=((float)A*(float)A)+((float)B*(float)B);
      resultado=(float)arriba/(float)abajo;
   PA_OutputText(1,0,1,"(%d,%d) (%d,%d) (%d,%d)",x1,y1,x2,y2,a,b);
   PA_OutputText(1,0,2,"A = %f, B= %f, C=%f, resultado=%f",A,B,C,resultado);
   if(resultado<0){PA_OutputText(1,0,2,"Es -"); return 80000;}
   return resultado;
   }else{
      PA_OutputSimpleText(1,0,0,"es 0                                    ");
      return 8000;
   }
}


Now double your working time and convert all floats to use integer fixed point for speed. .... Yea I was evil now. Sorry.
_________________
Exceptions are fun