home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / audio / bz / bzcollide.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  10.2 KB  |  482 lines

  1. /*
  2.  * Copyright (C) 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /***************************************************************************
  18.  *
  19.  * BZ - Multiplayer tank game - collision routines.
  20.  *
  21.  * $Id: bzcollide.c,v 1.4 1993/08/11 19:46:01 adele Exp $
  22.  *
  23.  *                    Chris Fouts - Silicon Graphics, Inc.
  24.  *                    October, 1991
  25.  **************************************************************************/
  26. #include <stdio.h>
  27. #include <math.h>
  28. #include "bz.h"
  29. #include "bzcollide.h"
  30.  
  31. /* BEGIN PROTOTYPES -S bzcollide.c */
  32. static int  check_rect_to_rect( float self[4][2], float obstacle[4][2] ) ;
  33. /* END PROTOTYPES -S bzcollide.c */
  34.  
  35. extern unsigned            number_players ;
  36. extern struct BzMember    player[MAXPLAYERS] ;
  37. extern float            obst_x[TOTALOBSTS] ;
  38. extern float            obst_y[TOTALOBSTS] ;
  39. extern float            last_msl_x[] ;
  40. extern float            last_msl_y[] ;
  41. extern float            mine_x ;
  42. extern float            mine_y ;
  43.  
  44. #define MAX_TANK_COL_DIST    25.0f
  45. #define MAX_OBST_COL_DIST    30.0f
  46.  
  47. static char    *version_id = "$Id: bzcollide.c,v 1.4 1993/08/11 19:46:01 adele Exp $" ;
  48.  
  49.  
  50. /*------------------------------------------------------------------------------
  51.  * INTERSECTION_CHECK - checks for the intersection of two lines.  One line
  52.  *  is defined by the points r0 and r1; the other line is defined by the
  53.  *  points r2 and r3.
  54.  *
  55.  *  Line 1 is defined by:    Pt = r0 + s * ( r1 - r0 ) ;    0 <= s <= 1
  56.  *  Line 2 is defined by:    Pt = r2 + t * ( r3 - r2 ) ;    0 <= t <= 1
  57.  *
  58.  *  Set the two equal, solve for s and t.  If s and t are both between
  59.  *  0 and 1 (inclusive), the lines intersect.  Return 1 if the lines
  60.  *  intersect, 0 otherwise.
  61.  *----------------------------------------------------------------------------*/
  62. int intersection_check(
  63.     float r0[2],
  64.     float r1[2],
  65.     float r2[2],
  66.     float r3[2],
  67.     float *s
  68.     )
  69. {
  70.     float    denom ;
  71.     float    denom1 ;
  72.     float    denom2 ;
  73.     float    ns, nt ;
  74.     float    dx10, dy10 ;
  75.     float    dx20, dy20 ;
  76.     float    dx32, dy32 ;
  77.  
  78.     dx10 = r1[0] - r0[0] ;
  79.     dy10 = r1[1] - r0[1] ;
  80.  
  81.     dx20 = r2[0] - r0[0] ;
  82.     dy20 = r2[1] - r0[1] ;
  83.  
  84.     dx32 = r3[0] - r2[0] ;
  85.     dy32 = r3[1] - r2[1] ;
  86.  
  87.     denom1 = dy10 * dx32 ;
  88.     denom2 = dx10 * dy32 ;
  89.  
  90.     /*
  91.      * Fail if lines are parallel.
  92.      */
  93.     if( denom1 == denom2 )
  94.         return( 0 ) ;
  95.  
  96.     denom = denom1 - denom2 ;
  97.  
  98.     ns = dx32 * dy20 - dy32 * dx20 ;
  99.     nt = dx10 * dy20 - dy10 * dx20 ;
  100.  
  101.     /*
  102.      * Fail if s or t will be greater than 1 (s = ns/denom ; t = nt/denom).
  103.     if( ns > denom || nt > denom )
  104.         return( 0 ) ;
  105.      */
  106.  
  107.     /*
  108.      * Fail if s or t are less than 0 (negative, which happens if ns or nt
  109.      * are of different signs than denom) or greater than 1 (if abs(ns) or
  110.      * abs(nt) are greater than abs(denom) ).
  111.      */
  112.     if( denom < 0 ) {
  113.         if( ns > 0 || nt > 0 || ns < denom || nt < denom ) {
  114.             return( 0 ) ;
  115.             }
  116.         }
  117.     else {
  118.         if( ns < 0 || nt < 0 || ns > denom || nt > denom ) {
  119.             return( 0 ) ;
  120.             }
  121.         }
  122.  
  123.     *s = ns / denom ;
  124.  
  125.     return( 1 ) ;
  126. }
  127.  
  128.  
  129.  
  130. int check_missile_hit(
  131.     int tank_id,
  132.     unsigned int *obst_id,
  133.     int *side
  134.     )
  135. {
  136.     int                tank ;
  137.     int                obst ;
  138.     float            self[2][2] ;
  139.     float            obstacle[4][2] ;
  140.  
  141.     /*
  142.      * Get missile points.
  143.      */
  144.     self[0][0] = last_msl_x[tank_id] ;
  145.     self[0][1] = last_msl_y[tank_id] ;
  146.     self[1][0] = player[tank_id].msl_x ;
  147.     self[1][1] = player[tank_id].msl_y ;
  148.  
  149.     /*
  150.      * Compare against other tanks.
  151.      */
  152.     for( tank = SELF ; tank < number_players ; tank++ ) {
  153.         if( IS_ALIVE( player[tank] ) ) {
  154.             locate_tank_corner_points( tank, obstacle ) ;
  155.             if( ( *side = check_line_to_rect( self, obstacle, 0 ) ) != 0 ) {
  156.                 *obst_id = tank ;
  157.                 return( 1 ) ;
  158.                 }
  159.             }
  160.         }
  161.  
  162.     /*
  163.      * Compare against obstacles.
  164.      */
  165.     for( obst = CONES ; obst < CUBES ; obst++ ) {
  166.         locate_obstacle_corner_points( obst, obstacle, CONE_COLLISION_INSET ) ;
  167.         if( ( *side = check_line_to_rect( self, obstacle, 1 ) ) != 0 ) {
  168.             *obst_id = obst ;
  169.             return( 2 ) ;
  170.             }
  171.         }
  172.     for( obst = CUBES ; obst < TOTALOBSTS ; obst++ ) {
  173.         locate_obstacle_corner_points( obst, obstacle, 1.0f ) ;
  174.         if( ( *side = check_line_to_rect( self, obstacle, 1 ) ) != 0 ) {
  175.             *obst_id = obst ;
  176.             return( 2 ) ;
  177.             }
  178.         }
  179.  
  180.     return( 0 ) ;
  181. }
  182.  
  183.  
  184.  
  185. int check_tank_collision(
  186.     unsigned int tank_id,
  187.     unsigned int *obst_id
  188.     )
  189. {
  190.     int        tank ;
  191.     int        obst ;
  192.     float    self[4][2] ;
  193.     float    obstacle[4][2] ;
  194.  
  195.     /*
  196.      * Get self corner points.
  197.      */
  198.     locate_tank_corner_points( tank_id, self ) ;
  199.  
  200.     /*
  201.      * Compare against other tanks.
  202.      */
  203.     for( tank = SELF ; tank < number_players ; tank++ ) {
  204.         if( tank != tank_id && IS_ALIVE( player[tank] ) &&
  205.             fabsf( player[tank_id].x - player[tank].x ) < MAX_TANK_COL_DIST &&
  206.             fabsf( player[tank_id].y - player[tank].y ) < MAX_TANK_COL_DIST ) {
  207.             locate_tank_corner_points( tank, obstacle ) ;
  208.             if( check_rect_to_rect( self, obstacle ) ) {
  209.                 *obst_id = tank ;
  210.                 return( 1 ) ;
  211.                 }
  212.             }
  213.         }
  214.  
  215.     /*
  216.      * Compare against obstacles.
  217.      */
  218.     for( obst = CONES ; obst < CUBES ; obst++ ) {
  219.         if( fabsf( player[tank_id].x - obst_x[obst] ) < MAX_OBST_COL_DIST &&
  220.             fabsf( player[tank_id].y - obst_y[obst] ) < MAX_OBST_COL_DIST ) {
  221.             locate_obstacle_corner_points( obst, obstacle, 1.0f ) ;
  222.             if( check_rect_to_rect( self, obstacle ) ) {
  223.                 *obst_id = obst ;
  224.                 return( 2 ) ;
  225.                 }
  226.             }
  227.         }
  228.     for( obst = CUBES ; obst < TOTALOBSTS ; obst++ ) {
  229.         if( fabsf( player[tank_id].x - obst_x[obst] ) < MAX_OBST_COL_DIST &&
  230.             fabsf( player[tank_id].y - obst_y[obst] ) < MAX_OBST_COL_DIST ) {
  231.             locate_obstacle_corner_points( obst, obstacle, 1.0f ) ;
  232.             if( check_rect_to_rect( self, obstacle ) ) {
  233.                 *obst_id = obst ;
  234.                 return( 2 ) ;
  235.                 }
  236.             }
  237.         }
  238.  
  239.     return( 0 ) ;
  240. }
  241.  
  242.  
  243.  
  244. void locate_tank_corner_points(
  245.     int tank_id,
  246.     float pt[4][2]
  247.     )
  248. {
  249.     float    x ;
  250.     float    y ;
  251.     float    w ;
  252.     float    l ;
  253.     float    wc ;
  254.     float    ws ;
  255.     float    lc ;
  256.     float    ls ;
  257.  
  258.     x = player[tank_id].x ;
  259.     y = player[tank_id].y ;
  260.     w =  5.0f ;
  261.     l = 10.0f ;
  262.  
  263.     wc =  COSINE( player[tank_id].head ) ;
  264.     ws =    SINE( player[tank_id].head ) ;
  265.     lc =  l * wc ;
  266.     ls =  l * ws ;
  267.     wc *= w ;
  268.     ws *= -w ;
  269.  
  270.     pt[0][0] = x + wc + ls ;
  271.     pt[0][1] = y + ws + lc ;
  272.  
  273.     pt[1][0] = x - wc + ls ;
  274.     pt[1][1] = y - ws + lc ;
  275.  
  276.     pt[2][0] = x - wc - ls ;
  277.     pt[2][1] = y - ws - lc ;
  278.  
  279.     pt[3][0] = x + wc - ls ;
  280.     pt[3][1] = y + ws - lc ;
  281. }
  282.  
  283.  
  284.  
  285. void locate_obstacle_corner_points(
  286.     int obst_id,
  287.     float pt[4][2],
  288.     float scaling
  289.     )
  290. {
  291.     float    x ;
  292.     float    y ;
  293.     float    dx ;
  294.     float    dy ;
  295.  
  296.     x  = obst_x[obst_id] ;
  297.     y  = obst_y[obst_id] ;
  298.  
  299.     /*
  300.      * Scaling factor in order to model slope of cones at missile height.
  301.      */
  302.     dx = 10.0f * scaling ;
  303.     dy = 10.0f * scaling ;
  304.  
  305.     pt[0][0] = x - dx ;
  306.     pt[0][1] = y + dy ;
  307.  
  308.     pt[1][0] = x + dx ;
  309.     pt[1][1] = y + dy ;
  310.  
  311.     pt[2][0] = x + dx ;
  312.     pt[2][1] = y - dy ;
  313.  
  314.     pt[3][0] = x - dx ;
  315.     pt[3][1] = y - dy ;
  316. }
  317.  
  318.  
  319.  
  320. static int check_rect_to_rect(
  321.     float self[4][2],
  322.     float obstacle[4][2]
  323.     )
  324. {
  325.     int        s0 ;
  326.     int        s1 ;
  327.     int        o0 ;
  328.     int        o1 ;
  329.     float    s ;
  330.  
  331.     for( s0 = 0 ; s0 < 4 ; s0++ ) {
  332.         s1 = ( s0 + 1 ) % 4 ;
  333.         for( o0 = 0 ; o0 < 4 ; o0++ ) {
  334.             o1 = ( o0 + 1 ) % 4 ;
  335.             if( intersection_check( self[s0], self[s1],
  336.                                     obstacle[o0], obstacle[o1], &s ) )
  337.                 return( 1 ) ;
  338.             }
  339.         }
  340.  
  341.     return( 0 ) ;
  342. }
  343.  
  344.  
  345.  
  346. int check_line_to_rect(
  347.     float self[2][2],
  348.     float obstacle[4][2],
  349.     int closest
  350.     )
  351. {
  352.     int        o0 ;
  353.     int        o1 ;
  354.     int        jmin = 0 ;
  355.     float    s ;
  356.     float    smin ;
  357.  
  358.     for( o0 = 0 ; o0 < 4 ; o0++ ) {
  359.         o1 = ( o0 + 1 ) % 4 ;
  360.         if( intersection_check( self[0], self[1],
  361.                                 obstacle[o0], obstacle[o1], &s ) )
  362.             if( !closest ) {
  363.                 return( o0 + 1 ) ;
  364.                 }
  365.             else if( jmin == 0 ) {
  366.                 jmin = o0 + 1 ;
  367.                 smin = s ;
  368.                 }
  369.             else if( s < smin ) {
  370.                 jmin = o0 + 1 ;
  371.                 }
  372.         }
  373.  
  374.     return( jmin ) ;
  375. }
  376.  
  377.  
  378.  
  379. int check_mine_hit(
  380.     unsigned int *enemy_id,
  381.     float radius_2
  382.     )
  383. {
  384.     int                tank ;
  385.     float            dx ;
  386.     float            dy ;
  387.  
  388.     for( tank = ENEMY ; tank < number_players ; tank++ ) {
  389.         if( player[tank].team == NEUTRAL_TEAM ||
  390.             player[tank].team != player[SELF].team ) {
  391.             dx = mine_x - player[tank].x ;
  392.             dy = mine_y - player[tank].y ;
  393.             if( dx*dx + dy*dy < radius_2 ) {
  394.                 *enemy_id = tank ;
  395.                 return( 1 ) ;
  396.                 }
  397.             }
  398.         }
  399.  
  400.     dx = mine_x - player[SELF].x ;
  401.     dy = mine_y - player[SELF].y ;
  402.     if( dx*dy + dy*dy < radius_2 ) {
  403.         *enemy_id = SELF ;
  404.         return( 1 ) ;
  405.         }
  406.  
  407.     return( 0 ) ;
  408. }
  409.  
  410.  
  411.  
  412. int id_tank( void )
  413. {
  414.     int                tank ;
  415.     int                obst ;
  416.     int                closest_tank = 0 ;
  417.     float            self[2][2] ;
  418.     float            obstacle[4][2] ;
  419.     float            dist ;
  420.     float            min_dist = 1.e30f ;
  421.  
  422.     /*
  423.      * Get line representing line o' sight.
  424.      */
  425.     self[0][0] = player[SELF].x ;
  426.     self[0][1] = player[SELF].y ;
  427.     self[1][0] = player[SELF].x + 100000.f *   SINE( player[SELF].head ) ;
  428.     self[1][1] = player[SELF].x + 100000.f * COSINE( player[SELF].head ) ;
  429.  
  430.     /*
  431.      * Compare against other tanks.
  432.      */
  433.     for( tank = ENEMY ; tank < number_players ; tank++ ) {
  434.         if( IS_ALIVE( player[tank] ) ) {
  435.             locate_tank_corner_points( tank, obstacle ) ;
  436.             if( check_line_to_rect( self, obstacle, 0 ) ) {
  437.                 dist = ( player[tank].x - player[SELF].x ) *
  438.                        ( player[tank].x - player[SELF].x ) +
  439.                        ( player[tank].y - player[SELF].y ) *
  440.                        ( player[tank].y - player[SELF].y ) ;
  441.                 if( dist < min_dist ) {
  442.                     min_dist = dist ;
  443.                     closest_tank = tank ;
  444.                     }
  445.                 }
  446.             }
  447.         }
  448.  
  449.     /*
  450.      * Compare against obstacles.
  451.      */
  452.     for( obst = CONES ; obst < CUBES ; obst++ ) {
  453.         locate_obstacle_corner_points( obst, obstacle, 0.8375f ) ;
  454.         if( check_line_to_rect( self, obstacle, 0 ) ) {
  455.             dist = ( obst_x[obst] - player[SELF].x ) *
  456.                    ( obst_x[obst] - player[SELF].x ) +
  457.                    ( obst_y[obst] - player[SELF].y ) *
  458.                    ( obst_y[obst] - player[SELF].y ) ;
  459.             if( dist < min_dist ) {
  460.                 return( 0 ) ;
  461.                 }
  462.             }
  463.         }
  464.     for( obst = CUBES ; obst < TOTALOBSTS ; obst++ ) {
  465.         locate_obstacle_corner_points( obst, obstacle, 1.0f ) ;
  466.         if( check_line_to_rect( self, obstacle, 0 ) ) {
  467.             dist = ( obst_x[obst] - player[SELF].x ) *
  468.                    ( obst_x[obst] - player[SELF].x ) +
  469.                    ( obst_y[obst] - player[SELF].y ) *
  470.                    ( obst_y[obst] - player[SELF].y ) ;
  471.             if( dist < min_dist ) {
  472.                 return( 0 ) ;
  473.                 }
  474.             }
  475.         }
  476.  
  477.     return( closest_tank ) ;
  478. }
  479.  
  480.  
  481.  
  482.