COLLISIO.CPP
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:8k
源码类别:

游戏

开发平台:

Visual C++

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include "sign.h"
  5. #include "ray.h"
  6. #include "fixed.h"
  7. #include "globals.h"
  8. #include "collisio.h"
  9. #include "isect.h"
  10. #include "blockmap.h"
  11. #include "message.h"
  12. #include "abs.h"
  13. #include "ground.h"
  14. #define COLLINEAR         2
  15. #define FIXED_TO_FLOAT(x) (((float)(x))/ONE)
  16. #define FLOAT_TO_FIXED(x) (long)((float)(x)*ONE)
  17. #define FIXED_ONE_QUARTER (16)
  18. #define MAN_SIZE          (64)
  19. #define WALL_PASSABLE 8
  20. static plinedef s_wall = NULL;
  21. #define VECTOR_LEN  15
  22. /*
  23. -- ----------------------------------------------------------------------
  24. -  Function    : LineDistance
  25. -
  26. -  Parameters  :
  27. -
  28. -  Result      :
  29. -
  30. -  Description :
  31. -    Returns the distance between point c, and the line a-b.
  32. -- ----------------------------------------------------------------------
  33. */
  34. MYFIXED
  35. LineDistance( MYFIXED cx, MYFIXED cy, long ax, long ay, long bx, long by, long line_len )
  36. {
  37.   long delta_x = ax-bx;
  38.   long delta_y = ay-by;
  39.   MYFIXED s;
  40.   /* If s becomes negative we are facing the line clockwise */
  41.   fixedmult64(cy-(by<<SHIFT), delta_x);
  42.   fixedma64((bx<<SHIFT)-cx, delta_y);
  43.   s=fixeddiv64(line_len);
  44. /*
  45.   printf( "R = %f S = %fn", r, s );
  46. */
  47.   return s;
  48. }
  49. BOOL
  50. On_Line( MYFIXED cx, MYFIXED cy, long ax, long ay, long bx, long by )
  51. {
  52.   long delta_x = ax-bx;
  53.   long delta_y = ay-by;
  54.   long line_len;
  55.   MYFIXED r;
  56.   /* the lenght of the line in **2 */
  57.   line_len = delta_x*delta_x+delta_y*delta_y;
  58.   fixedmult64((ay<<SHIFT)-cy, delta_y);
  59.   fixedma64((ax<<SHIFT)-cx, delta_x);
  60.   r=fixeddiv64(line_len);
  61.   if ( r < 0 || r > ONE)
  62.   return FALSE;
  63.   else return TRUE;
  64. }
  65. void
  66. get_vector_xy( MYFIXED *vx, MYFIXED *vy, plinedef wall )
  67. {
  68.   long dx, dy, line_len;
  69.   dx = Vector_List[wall->v[0]].x - Vector_List[wall->v[1]].x;
  70.   dy = Vector_List[wall->v[0]].y - Vector_List[wall->v[1]].y;
  71.  
  72.   line_len = wall->distance;
  73.   *vx = fixeddiv(dx,line_len);
  74.   *vy = fixeddiv(dy,line_len);
  75. /*
  76.   printf( "line_len %f, dx %f, dy %fn", 
  77.  line_len, dx, dy );
  78. */
  79. }
  80. /*
  81.   Check how it should behave when you sliding agains a wall. 
  82. */
  83. void
  84. slide_wall( MYFIXED *x, MYFIXED *y, MYFIXED x2, MYFIXED y2,
  85.   MYFIXED dist_old, MYFIXED dist_new )
  86. {
  87.   MYFIXED vector_x, vector_y;
  88.  
  89.   // get percent moves in x & y per move in unit of distance along line
  90.   get_vector_xy( &vector_x, &vector_y, s_wall );
  91.   // move along perpendicular to line, which to the best of my knowledge _always_ works
  92.   // for sliding
  93. *x  = x2+fixedmult(dist_old-dist_new,-vector_y);
  94. *y  = y2+fixedmult(dist_old-dist_new, vector_x);
  95.   
  96. }
  97. void Find_Closest_Line_In_List(MYFIXED x1, MYFIXED y1, plinedef * close_line,
  98. MYFIXED * cur_min, pline_list search_list) {
  99. if (search_list==NULL)
  100. return;
  101. plinedef wall;
  102. MYFIXED tmp;
  103. int i; 
  104. for (i = 0; i < search_list->line_count; i++) {
  105.  wall=search_list->lines[i];
  106.  /* Check Distance */
  107.  if (On_Line(x1, y1,
  108.  (Vector_List[wall->v[0]].x ),
  109.  (Vector_List[wall->v[0]].y ),
  110.  (Vector_List[wall->v[1]].x ),
  111.  (Vector_List[wall->v[1]].y)) ) {
  112.  tmp = LineDistance( x1, y1, 
  113.  (Vector_List[wall->v[0]].x ),
  114.  (Vector_List[wall->v[0]].y ),
  115.  (Vector_List[wall->v[1]].x ),
  116.  (Vector_List[wall->v[1]].y),
  117.   wall->distance);
  118.  } else {
  119.  tmp=MAXMYFIXED;
  120.  }
  121.  if ( ABS(tmp) < ABS( *(cur_min) ) )
  122. {
  123. *(cur_min)      = tmp;
  124. *(close_line) = wall; 
  125. }
  126.   }
  127. }
  128. void
  129. checkwalls(pwall_collision_info the_collision)
  130. {
  131. MYFIXED  side   = 0,
  132. x   = 0,
  133. y   = 0;
  134.   plinedef mem_wall;
  135.   MYFIXED  x1, y1, dest, min = MAXMYFIXED;
  136.   // we never want an object with 2*speed of a wall, or it may get through
  137.   long cur_speed=(the_collision->move_obj->type->stats.base_speed*2)<<SHIFT;
  138.   MYFIXED dest_x, dest_y;
  139.   USHORT block_x, block_y;
  140.   x = the_collision->move_obj->x;
  141.   y = the_collision->move_obj->y;
  142.   x1 = x+the_collision->delta_vec->x;
  143.   y1 = y+the_collision->delta_vec->y;
  144.   if ( x1 == x && y1 == y ) {
  145.  the_collision->found_collision=FALSE;
  146.  return;
  147.   }
  148.   mem_wall=NULL;
  149.   
  150.   dest_x=x1;
  151.   dest_y=y1;
  152.   block_x=Block_X(dest_x);
  153.   block_y=Block_Y(dest_y);
  154.   
  155.   Find_Closest_Line_In_List(x1, y1, &mem_wall, &min, 
  156.   Get_Block_Line_List(block_x, block_y));
  157.   // check surrounding blocks
  158.   if (dest_y-Block_Bottom_Line(dest_y)<(cur_speed)) {
  159.  Find_Closest_Line_In_List(x1,y1,&mem_wall, &min,
  160.  Get_Block_Line_List(block_x, block_y-1));
  161.  if (dest_x-Block_Left_Line(dest_x)<(cur_speed)) {
  162.  Find_Closest_Line_In_List(x1,y1,&mem_wall, &min,
  163.  Get_Block_Line_List(block_x-1, block_y-1));
  164.  }
  165.  if (dest_x-Block_Right_Line(dest_x)>(-cur_speed)) {
  166.  Find_Closest_Line_In_List(x1,y1,&mem_wall, &min,
  167.  Get_Block_Line_List(block_x+1, block_y-1));
  168.  }
  169.   } else if (dest_y-Block_Top_Line(dest_y)>(-cur_speed)) {
  170.  Find_Closest_Line_In_List(x1,y1,&mem_wall, &min,
  171.  Get_Block_Line_List(block_x, block_y+1));
  172.  if (dest_x-Block_Left_Line(dest_x)<(cur_speed)) {
  173.  Find_Closest_Line_In_List(x1,y1,&mem_wall, &min,
  174.  Get_Block_Line_List(block_x-1, block_y+1));
  175.  }
  176.  if (dest_x-Block_Right_Line(dest_x)>(-cur_speed)) {
  177.  Find_Closest_Line_In_List(x1,y1,&mem_wall, &min,
  178.  Get_Block_Line_List(block_x+1, block_y+1));
  179.  }
  180.   } else if (dest_x-Block_Left_Line(dest_x)<(cur_speed)) {
  181.   Find_Closest_Line_In_List(x1,y1,&mem_wall, &min,
  182.   Get_Block_Line_List(block_x-1, block_y));
  183.   } else if (dest_x-Block_Right_Line(dest_x)>(-cur_speed)) {
  184.   Find_Closest_Line_In_List(x1,y1,&mem_wall, &min,
  185.   Get_Block_Line_List(block_x+1, block_y));
  186.   }
  187. the_collision->wall=mem_wall;
  188. the_collision->dis_from_line=min;
  189. if ( (mem_wall!=NULL) && (ABS( min ) < cur_speed) ) {
  190. the_collision->found_collision=TRUE;
  191. } else {
  192. the_collision->found_collision=FALSE;
  193. }
  194. }
  195. BOOL Intersect_Abs(pvector2 sv1, pvector2 dv1, pvector2 sv2, pvector2 dv2) {
  196. long sv1d, dv1d, sv2d, dv2d;
  197. sv1d=(sv2->x-dv2->x)*(sv1->y-dv2->y)-(sv2->y-dv2->y)*(sv1->x-dv2->x);
  198. dv1d=(sv2->x-dv2->x)*(dv1->y-dv2->y)-(sv2->y-dv2->y)*(dv1->x-dv2->x);
  199. sv1d=(sv1->x-dv1->x)*(sv2->y-dv1->y)-(sv1->y-dv1->y)*(sv2->x-dv1->x);
  200. sv1d=(sv1->x-dv1->x)*(dv2->y-dv1->y)-(sv1->y-dv1->y)*(dv2->x-dv1->x);
  201. if ( (SIGN(sv1d)!=SIGN(dv1d)) && (SIGN(sv2d)!=SIGN(dv2d)) ) {
  202. return TRUE;
  203. } else {
  204. return FALSE;
  205. }
  206. }
  207. BOOL Passable_Wall(plinedef wall, pobject the_obj, MYFIXED dest_x,
  208. MYFIXED dest_y, psector sec2) {
  209. if (!(wall->attributes & WALL_PASSABLE)) 
  210. return FALSE; 
  211. if (the_obj->z+the_obj->type->height>(sec2->ceil_height-
  212. Ground_Height_XY(dest_x, dest_y, sec2))) 
  213. return FALSE;
  214. if (Ground_Height(the_obj)+the_obj->type->stepping_height+the_obj->z < 
  215. Ground_Height_XY(dest_x, dest_y, sec2))
  216. return FALSE;
  217. return TRUE;
  218. }
  219. ULONG Do_Slide_Wall(pobject the_obj, pwall_collision_info the_collision) {
  220.   psector sec1, sec2;
  221.   plinedef wall;
  222.   MYFIXED min, side, cur_speed, dest;
  223.   MYFIXED source_x, source_y, dest_x, dest_y;
  224.   source_x=the_obj->x;
  225.   source_y=the_obj->y;
  226.   dest_x=source_x+the_collision->delta_vec->x;
  227.   dest_y=source_y+the_collision->delta_vec->y;
  228.   wall=the_collision->wall;
  229.   min=the_collision->dis_from_line;
  230.   cur_speed=(the_obj->type->stats.base_speed*2) <<SHIFT;
  231.   /* is there any point in checking further. */
  232.   side=LineDistance(source_x,source_y,       
  233.  (Vector_List[wall->v[0]].x ),
  234.  (Vector_List[wall->v[0]].y ),
  235.  (Vector_List[wall->v[1]].x ),
  236.  (Vector_List[wall->v[1]].y),
  237. wall->distance);
  238.   if (side<0) {
  239.   sec1=wall->s[1]->sec;
  240.   sec2=wall->s[0]->sec;
  241.   } else {
  242.   sec1=wall->s[0]->sec;
  243.   sec2=wall->s[1]->sec;
  244.   }
  245. ULONG message_res;
  246. BOOL impassible;
  247. /* can we pass the wall */
  248. if (Passable_Wall(wall, the_obj, dest_x, dest_y, sec2))
  249. {
  250. dest=-SIGN(side)*cur_speed;
  251. impassible=FALSE;
  252. } else {
  253. dest=SIGN(side)*cur_speed;
  254. impassible=TRUE;
  255. }
  256. message_res=Send_Specific_Message(NULL, the_obj, 
  257. WALL_SLIDE_CONFIRM, (pdata)&impassible); 
  258. if (message_res==STOP_SLIDE) {
  259. return NORMAL_MESSAGE;
  260. }
  261. if (message_res!=NORMAL_MESSAGE) {
  262. return message_res;
  263. }
  264. s_wall = wall;
  265. slide_wall( &source_x, &source_y, dest_x, dest_y, dest, min );
  266. the_collision->delta_vec->x   =  source_x-the_obj->x ;
  267. the_collision->delta_vec->y   = source_y-the_obj->y ;
  268. return NORMAL_MESSAGE;
  269. }