home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / MacWT 0.9 / wt Source / collision.c next >
Encoding:
C/C++ Source or Header  |  1995-10-23  |  5.3 KB  |  244 lines  |  [TEXT/CWIE]

  1. /*
  2. **  MacWT -- a 3d game engine for the Macintosh
  3. **  © 1995, Bill Hayden and Nikol Software
  4. **  Free for non-commercial use - address questions to the e-mail address below
  5. **
  6. **  Mail:           afn28988@freenet.ufl.edu (Bill Hayden)
  7. **    MacWT FTP site: ftp.circa.ufl.edu/pub/software/ufmug/mirrors/LocalSW/Hayden/
  8. **  WWW Page:       http://grove.ufl.edu:80/~nikolsw
  9. **
  10. **    All of the above addresses are due to changes sometime in 1996, so stay tuned
  11. **
  12. **  based on wt, by Chris Laurel
  13. **
  14. **  This program is distributed in the hope that it will be useful,
  15. **  but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. */
  18.  
  19.  
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <math.h>
  24.  
  25. #include "wt.h"
  26. #include "fixed.h"
  27. #include "table.h"
  28. #include "view.h"
  29. #include "framebuf.h"
  30. #include "list.h"
  31. #include "world.h"
  32. #include "object.h"
  33. #include "collision.h"
  34.  
  35. static double LineDistance( double cx, double cy, double ax, double ay, double bx, double by, Boolean *corner );
  36. static void get_vector_xy( double *vx, double *vy, Wall *wall );
  37.  
  38. static Wall   *s_wall = NULL;
  39.  
  40.  
  41.  
  42. /*
  43.     LineDistance returns the distance between a point c, and a line a-b.
  44. */
  45.  
  46. static double LineDistance( double cx, double cy, double ax, double ay, double bx, double by, Boolean *corner )
  47. {
  48.     double    delta_x = bx-ax;
  49.     double    delta_y = by-ay;
  50.     double    line_len, r, s;
  51.     
  52.  
  53.     /* the length of the line in **2 */
  54.     line_len = delta_x * delta_x + delta_y * delta_y;
  55.  
  56.     r = ( (ay-cy)*(-delta_y) - (ax-cx)*delta_x ) / line_len;
  57.  
  58. #if 0
  59.     if ( r > 1.0 || r < 0.0)
  60.           s = sqrt(fabs(ax - cx) + fabs(ay - cy));
  61.       else if ( r < 0.0 )
  62.           s = sqrt(fabs(bx - cx) + fabs(by - cy));
  63.     else
  64.         s = ((ay-cy)*(delta_x)-(ax-cx)*delta_y) / sqrt( line_len );
  65. #endif
  66.  
  67.     if ( r > 1.0 )
  68.         {
  69.         s = sqrt( (bx - cx)*(bx - cx) + (by - cy)*(by - cy) );
  70.         *corner = true;
  71.         }
  72.       else if ( r < 0.0 )
  73.           {
  74.           s = sqrt( (ax - cx)*(ax - cx) + (ay - cy)*(ay - cy) );
  75.           *corner = true;
  76.           }
  77.     else
  78.         {
  79.         s = ((ay-cy)*(delta_x)-(ax-cx)*delta_y) / sqrt( line_len );
  80.         *corner = false;
  81.         }
  82.  
  83.     return s;
  84. }
  85.  
  86.  
  87.  
  88.  
  89. static void get_vector_xy( double *vx, double *vy, Wall *wall )
  90. {
  91.     double dx, dy, line_len;
  92.     
  93.  
  94.     dx = (double)FIXED_TO_FLOAT(wall->vertex2->x - wall->vertex1->x);
  95.     dy = (double)FIXED_TO_FLOAT(wall->vertex2->y - wall->vertex1->y);
  96.  
  97.     line_len = sqrt( dx*dx + dy*dy );
  98.  
  99.     *vx = dx / line_len;
  100.     *vy = dy / line_len;
  101. }
  102.  
  103.  
  104. /*
  105.   Check how MacWT should behave when an object slides against a wall. 
  106. */
  107.  
  108. static void slide_wall( double *x, double *y, double x2, double y2,
  109.                           double dist_old, double dist_new )
  110. {
  111.     double percent, line_len;
  112.     double vector_x, vector_y;
  113.     double dx = x2-*x;
  114.     double dy = y2-*y;
  115.     double suck1, suck2;
  116.  
  117.  
  118.     line_len = sqrt( dx*dx + dy*dy );
  119.  
  120.     /* (dist_old-dist_new) becomes one side in a triangle. */
  121.     /* percent cannot be over 1.0. */
  122.     /* How long is the distance towards the line compared to the line_length. */
  123.     percent = (1.0 - fabs( dist_old - dist_new ) / line_len);
  124.  
  125.     get_vector_xy( &vector_x, &vector_y, s_wall );
  126.  
  127.     /* in what direction are the vectors compared to the walk ? */
  128.     suck1 = (vector_x + dx)*(vector_x + dx) + (vector_y + dy)*(vector_y + dy);
  129.     suck2 = (vector_x - dx)*(vector_x - dx) + (vector_y - dy)*(vector_y - dy);
  130.  
  131.     if ( suck1 > suck2 )
  132.         {
  133.         *x += percent * line_len * vector_x;
  134.         *y += percent * line_len * vector_y;
  135.         }
  136.     else
  137.         {
  138.         *x -= percent * line_len * vector_x;
  139.         *y -= percent * line_len * vector_y;
  140.         }
  141.  
  142. }
  143.  
  144.  
  145. void CheckCollision( Object *o )
  146. {
  147.     Wall   *wall = (Wall *) o->world->walls->table, *mem_wall;
  148.     double  tmp, min = 512.0;
  149.     short i;
  150.     //List *l;
  151.     static double    side    = 0.0,
  152.                     x       = 0.0,
  153.                     y       = 0.0;
  154.     Boolean        corner, tmpCorner;
  155.  
  156.     if ( o->x == x && o->y == y )
  157.         return;
  158.     
  159. #if 0
  160.     for (l = o->world->objects; l->next != NULL; l = l->next)
  161.         {
  162.         Object *obj = LIST_NODE(l, Object *);
  163.         
  164.         if (o == obj)
  165.             continue;
  166.             
  167.         if ( (fabs(o->x - obj->x) < (o->xsize + obj->xsize)) ||
  168.                 (fabs(o->y - obj->y) < (o->ysize + obj->ysize)) )
  169.                 o->z = 2;
  170.         }
  171. #endif
  172.  
  173.     for (i = 0; i < TABLE_SIZE(o->world->walls); i++, wall++ )
  174.         {
  175.  
  176.         /* Check Distance */
  177.         tmp = LineDistance( o->x, o->y, FIXED_TO_FLOAT(wall->vertex1->x ), 
  178.                                         FIXED_TO_FLOAT(wall->vertex1->y ), 
  179.                                         FIXED_TO_FLOAT(wall->vertex2->x ), 
  180.                                         FIXED_TO_FLOAT(wall->vertex2->y ),
  181.                                         &corner );
  182.  
  183.         if ( fabs(tmp) < fabs( min ) )
  184.             {
  185.             min = tmp;
  186.             mem_wall = wall;
  187.             tmpCorner = corner;
  188.             }
  189.  
  190.         }
  191.  
  192.         /* is there any point in checking further. */
  193.     if ( fabs( min ) < o->xsize )    // Note that objects are assumed to be round
  194.         {
  195.         /* start by examining the wall */
  196.         fixed floor;
  197.         fixed ceiling;
  198.         
  199.         /* Check the other side of the object */
  200.         if ( min > 0.0 )
  201.             {
  202.             floor      = mem_wall->front->floor;
  203.             ceiling    = mem_wall->front->ceiling;
  204.             }
  205.         else
  206.             {
  207.             floor      = mem_wall->back->floor;
  208.             ceiling    = mem_wall->back->ceiling;
  209.             }
  210.  
  211.           if ( (min < o->xsize) && tmpCorner )    // object entering positive corner
  212.              {
  213.              o->x -= o->dx;
  214.              o->y -= o->dy;
  215.             o->dx = 0.0;
  216.             o->dy = 0.0;
  217.             }
  218.              
  219.       /* if the wall is less than the object height and the object has room */
  220.  
  221.         if ( FIXED_TO_FLOAT(floor) > (o->z + o->height) && fabs( min ) < fabs( side ))
  222.             {
  223.             s_wall = mem_wall;
  224.                 slide_wall( &x, &y, o->x, o->y, side, min );
  225.  
  226.             o->x = x;
  227.             o->y = y;
  228.  
  229.             return;
  230.             }
  231.         else
  232.             {
  233.             o->z = FIXED_TO_FLOAT(floor);
  234.             o->dz = 0.0;
  235.             }
  236.         }
  237.  
  238.     side = min;
  239.     x    = o->x;
  240.     y    = o->y;
  241.  
  242.     return;
  243. }
  244.