home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / roids / rocks.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  8.4 KB  |  344 lines

  1. /*
  2.  * Copyright 1989 Digital Equipment Corporation
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software and its
  5.  * documentation for any purpose and without fee is hereby granted,
  6.  * provided that the above copyright notice appear in all copies and that
  7.  * both that copyright notice and this permission notice appear in
  8.  * supporting documentation, and that the name of Digital Equipment
  9.  * Corporation not be used in advertising or publicity pertaining to
  10.  * distribution of the software without specific, written prior
  11.  * permission.  Digital Equipment Corporation makes no representations
  12.  * about the suitability of this software for any purpose.  It is
  13.  * provided "as is" without express or implied warranty.
  14.  *
  15.  * DIGITAL EQUIPMENT CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO
  16.  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17.  * FITNESS, IN NO EVENT SHALL DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR
  18.  * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  20.  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  21.  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  *
  23.  * Author:  Terry Weissman
  24.  *          weissman@decwrl.dec.com
  25.  */
  26.  
  27. /* rocks.c - handle movement, etc. of the rocks. */
  28.  
  29. #include "roids.h"
  30.  
  31.  
  32.  
  33. #define NUMTYPES    3    /* How many types of rocks there are. */
  34. #define MAXPOINTS    10    /* Maximum number of points in a rock. */
  35.  
  36. #define MAXROCKS    256    /* Maximum rocks we'll have at one time. */
  37.  
  38.  
  39. static int numtocreate = 4;    /* How many rocks to create each round. */
  40.  
  41.  
  42. #define DIAMONDDATA(size)    \
  43. {0, size},            \
  44. {size, 0},            \
  45. {0, -size},            \
  46. {-size, 0},
  47.  
  48.  
  49.  
  50.  
  51.  
  52. static int smallshape[][2] = {
  53.     DIAMONDDATA(10)
  54.     };
  55. static int mediumshape[][2] = {
  56.     DIAMONDDATA(15)
  57.     };
  58. static int largeshape[][2] = {
  59.     DIAMONDDATA(20)
  60.     };
  61.  
  62.  
  63. static int ***shapes;
  64.  
  65.  
  66. static int numpoints[NUMTYPES] = {XtNumber(largeshape), XtNumber(mediumshape),
  67.                       XtNumber(smallshape)};
  68.  
  69. int radius[NUMTYPES];
  70.  
  71. extern double sx, sy;        /* Ship location. */
  72.  
  73. typedef struct _RockRec {
  74.     double x, y;        /* Location. */
  75.     double vx, vy;        /* Velocity. */
  76.     int radius;            /* Radius of this rock. */
  77.     int **shape;        /* Pointer to shape record. */
  78.     int numpoints;        /* Number of points in shape record. */
  79. } RockRec, *Rock;
  80.  
  81. RockRec rocks[MAXROCKS+2];
  82.  
  83. int numrocks = 0;        /* Number of rocks existing. */
  84.  
  85.  
  86. #define RockNearBox(rock, minx, maxx, miny, maxy)    \
  87.     (rint((rock)->x) - (rock)->radius <= (maxx) &&        \
  88.      rint((rock)->y) - (rock)->radius <= (maxy) &&        \
  89.      rint((rock)->x) + (rock)->radius >= (minx) &&        \
  90.      rint((rock)->y) + (rock)->radius >= (miny))
  91.  
  92.  
  93. #define RandomSpeed()    (maxrockspeed * (random() % 2000 - 1000) / 1000.0)
  94.  
  95. Boolean AreaForShipIsClear()
  96. {
  97.     int minx, maxx, miny, maxy, i;
  98.     Rock rock;
  99.     minx = sx - 5 * shipradius;
  100.     maxx = sx + 5 * shipradius;
  101.     miny = sy - 5 * shipradius;
  102.     maxy = sy + 5 * shipradius;
  103.     for (i=0, rock = rocks ; i<numrocks ; i++, rock++) {
  104.     if (RockNearBox(rock, minx, maxx, miny, maxy))
  105.         return FALSE;
  106.     }
  107.     return TRUE;
  108. }
  109.  
  110.  
  111.  
  112. static void ConfigureRock(rock, x, y, vx, vy, shape, numpoints, radius)
  113. Rock rock;
  114. double x, y, vx, vy;
  115. int **shape;
  116. int numpoints, radius;
  117. {
  118.     rock->x = x;
  119.     rock->y = y;
  120.     rock->vx = vx;
  121.     rock->vy = vy;
  122.     rock->shape = shape;
  123.     rock->numpoints = numpoints;
  124.     rock->radius = radius;
  125. }
  126.  
  127.  
  128.  
  129. static void PaintRock(rock, gc)
  130. Rock rock;
  131. GC gc;
  132. {
  133.     register int x = rock->x;
  134.     register int y = rock->y;
  135.     register int i;
  136.     for (i=0 ; i<rock->numpoints ; i++)
  137.     AddLine(x + rock->shape[i][0], y + rock->shape[i][1],
  138.         x + rock->shape[i+1][0], y + rock->shape[i+1][1],
  139.         gc);
  140. }
  141.  
  142.  
  143.  
  144. /*
  145.  * Destroy rock #i.  Often, this means creating two rocks in its place.  The
  146.  * point given is used to determine the direction of the destroying influence,
  147.  * and thus which direction the two rocks should go.
  148.  */
  149.  
  150. static void DestroyRock(i, x, y)
  151. int i, x, y;
  152. {
  153.     int num, value;
  154.     Rock rock = rocks + i;
  155.     double oldx = rock->x;
  156.     double oldy = rock->y;
  157.     PaintRock(rock, backgc);
  158.     value = 50;
  159.     for (num = 0 ; num < NUMTYPES ; num++)
  160.     if (rock->shape == shapes[num]) break;
  161.     else value *= 2;
  162.     if (num >= NUMTYPES)
  163.     Punt("Couldn't find shape in DestroyRock!");
  164.     score += value;
  165.     PaintScore();
  166.     numrocks--;
  167.     rocks[i] = rocks[numrocks];
  168.     num++;
  169.     if (num < NUMTYPES) {
  170.     for (i=numrocks ; i<MIN(MAXROCKS, numrocks+2) ; i++) {
  171.         ConfigureRock(rocks + i, oldx, oldy, RandomSpeed(), RandomSpeed(),
  172.               shapes[num], numpoints[num], radius[num]);
  173.     }
  174.     numrocks = MIN(MAXROCKS, numrocks + 2);
  175.     }
  176. }
  177.  
  178.  
  179.     
  180. Boolean LineHitsRock(ax, ay, bx, by)
  181. int ax, ay, bx, by;
  182. {
  183.     register Rock rock;
  184.     int i, j, x, y;
  185.     register int minx, miny, maxx, maxy;
  186.     int **shape;
  187.     minx = MIN(ax, bx);
  188.     maxx = MAX(ax, bx);
  189.     miny = MIN(ay, by);
  190.     maxy = MAX(ay, by);
  191.     for (i=0, rock = rocks ; i<numrocks ; i++, rock++) {
  192.     if (RockNearBox(rock, minx, maxx,  miny, maxy)) {
  193.         shape = rock->shape;
  194.         x = rock->x;
  195.         y = rock->y;
  196.         for (j=0 ; j<rock->numpoints ; j++) {
  197.         if (CheckIntersects(ax, ay, bx, by,
  198.                     shape[j][0] + x, shape[j][1] + y,
  199.                     shape[j+1][0] + x, shape[j+1][1] + y)) {
  200.             DestroyRock(i, ax, ay);
  201.             return TRUE;
  202.         }
  203.         }
  204.     }
  205.     }
  206.     return FALSE;
  207. }
  208.         
  209.     
  210.  
  211. /* 
  212.  * Carefully check if the given rock has hit the ship.  If so, destroy the
  213.  * rock (creating new rocks as necessary), and return TRUE.  This does not
  214.  * touch the ship; that is left to the calling routine.
  215.  */
  216.  
  217. static Boolean CheckForCrash(rock)
  218. Rock rock;
  219. {
  220.     extern int px[], py[];
  221.     int i, j, ax, ay, bx, by;
  222.     int **shape = rock->shape;
  223.     int x = rock->x;
  224.     int y = rock->y;
  225.     if (shipdestroyed) return FALSE;
  226.     for (i=0 ; i < NPOINTS ; i++) {
  227.     ax = px[i];
  228.     ay = py[i];
  229.     bx = px[(i+1) % NPOINTS];
  230.     by = py[(i+1) % NPOINTS];
  231.     for (j=0 ; j<rock->numpoints ; j++) {
  232.         if (CheckIntersects(ax, ay, bx, by,
  233.                 shape[j][0] + x, shape[j][1] + y,
  234.                 shape[j+1][0] + x, shape[j+1][1] + y)) {
  235.         DestroyRock(rock - rocks, rint(sx), rint(sy));
  236.         return TRUE;
  237.         }
  238.     }
  239.     }
  240.     return FALSE;
  241. }
  242.  
  243.  
  244. Boolean CheckIfShipHitRocks()
  245. {
  246.     int i, minx, miny, maxx, maxy;
  247.     Rock rock;
  248.     minx = sx - shipradius;
  249.     miny = sy - shipradius;
  250.     maxx = sx + shipradius;
  251.     maxy = sy + shipradius;
  252.     for (i=0, rock = rocks ; i < numrocks ; i++, rock++) {
  253.     if (RockNearBox(rock, minx, maxx, miny, maxy)) {
  254.         if (CheckForCrash(rock))
  255.         return TRUE;
  256.     }
  257.     }
  258.     return FALSE;
  259. }
  260.  
  261.  
  262.  
  263. void PaintAllRocks()
  264. {
  265.     int i;
  266.     for (i=0 ; i<numrocks ; i++)
  267.     PaintRock(rocks + i, rockgc);
  268. }
  269.  
  270. void MoveRocks(closure, id)
  271. Opaque closure;
  272. XtIntervalId id;
  273. {
  274.     register Rock rock;
  275.     register int i;
  276.     int minx, miny, maxx, maxy;
  277.     if (closure != (Opaque) MoveRocks) return;
  278.     rocktimerid = XtAddTimeOut(rockwait, MoveRocks, (Opaque) MoveRocks);
  279.     if (numrocks == 0) {
  280.     numrocks = MIN(numtocreate, MAXROCKS);
  281.     numtocreate += 2;
  282.     for (i=0 ; i<numrocks ; i++) {
  283.         ConfigureRock(rocks + i, 0.0, 0.0,
  284.               RandomSpeed(), RandomSpeed(),
  285.               shapes[0], numpoints[0], radius[0]);
  286.     }
  287.     }
  288.     minx = sx - shipradius;
  289.     miny = sy - shipradius;
  290.     maxx = sx + shipradius;
  291.     maxy = sy + shipradius;
  292.     for (i=0 ; i<numrocks ; i++) {
  293.     rock = rocks + i;
  294.     PaintRock(rock, backgc);
  295.     rock->x += rock->vx;
  296.     rock->y += rock->vy;
  297.     rock->x = (rock->x < 0) ? rock->x + gamewidth :
  298.         ((rock->x > gamewidth) ? rock->x - gamewidth : rock->x);
  299.     rock->y = (rock->y < 0) ? rock->y + gameheight :
  300.         ((rock->y > gameheight)? rock->y - gameheight: rock->y);
  301.     PaintRock(rock, rockgc);
  302.     if (RockNearBox(rock, minx, maxx, miny, maxy)) {
  303.         if (CheckForCrash(rock))
  304.         DestroyShip();
  305.     }
  306.     }
  307. }
  308.     
  309.     
  310.  
  311. static void SetIt(shape, init, num)
  312. int **shape;
  313. int init[][2];
  314. int num;
  315. {
  316.     int i, j;
  317.     for (i=0 ; i<num+1 ; i++) {
  318.     shape[i] = (int *) XtMalloc(sizeof(int) * 2);
  319.     for (j=0 ; j<2 ; j++)
  320.         shape[i][j] = init[i%num][j];
  321.     }
  322. }
  323.  
  324. void InitRocks()
  325. {
  326.     int i, j, m;
  327.     rocktimerid = NULL;
  328.     shapes = (int ***) XtMalloc(sizeof(int **) * NUMTYPES);
  329.     for (i=0 ; i<NUMTYPES ; i++) {
  330.     shapes[i] = (int **) XtMalloc(sizeof(int *) * (numpoints[i] + 1));
  331.     }
  332.     SetIt(shapes[0], largeshape, numpoints[0]);
  333.     SetIt(shapes[1], mediumshape, numpoints[1]);
  334.     SetIt(shapes[2], smallshape, numpoints[2]);
  335.     for (i=0 ; i<NUMTYPES ; i++) {
  336.     m = -1;
  337.     for (j=0 ; j<numpoints[i] ; j++) {
  338.         m = MAX(m, shapes[i][j][0]);
  339.         m = MAX(m, shapes[i][j][1]);
  340.     }
  341.     radius[i] = m;
  342.     }
  343. }
  344.