home *** CD-ROM | disk | FTP | other *** search
/ The Amiga Game Guide / AmigaGameGuide_CD.iso / Amiga / PD-Games / DogFight! / Sources.lha / DogFight!_class9.cpp < prev    next >
C/C++ Source or Header  |  1994-05-21  |  18KB  |  493 lines

  1. /********************************************************************
  2. ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
  3. ##
  4. ##      DogFight!_class.h
  5. ##
  6. ## Defines Fighters, Shots, Coords, and functions on these objects.
  7. ##
  8. ## V0.6  01-MAR-94
  9. ##       03-Mar-94   Moving to real data abstraction (seperating
  10. ##                   the .h from the .c for this file.
  11. ##       21-May-94   Converted to SAS/C
  12. ##
  13. ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
  14. *********************************************************************/
  15.  
  16. #include "DogFight!_class9.h"
  17. #include "sound.h"
  18.  
  19. // why are all math functions in radians??  Who thinks in radians?!?
  20.  
  21. const float rad_inc     =       (TWO_PI / 360.0);
  22. const float ri135               =       (TWO_PI/360) * 135.0;
  23. const float ri225               =       (TWO_PI/360) * 225.0;
  24. const float RADS                =       (rad_inc* 1.5);
  25.  
  26. /******************************************
  27. ×××××××××××××××××××××××××××××××××××××××××××
  28.  
  29.         The following code was taken from
  30.         the ASwarm module of the
  31.         GarshneBlanker sourcecodes.
  32.  
  33. ×××××××××××××××××××××××××××××××××××××××××××
  34. ******************************************/
  35.  
  36. BYTE sqrt_tab[256] = {
  37.         0,1,1,1,2,2,2,2,2,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,
  38.         7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10,10,
  39.         10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
  40.         11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,
  41.         13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,
  42.         14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
  43.         15,15,15,15,15,15,15,15,15,15,15,15
  44. };
  45.  
  46. LONG FastSQRT( LONG x )
  47. {
  48.         LONG sr = 1L;
  49.  
  50.         while( x > 255L ) {
  51.                 x /= 4L;
  52.                 sr *= 2L;
  53.         }
  54.  
  55.         return( sr * (LONG)sqrt_tab[x] );
  56. }
  57.  
  58. /********************************************************************
  59. ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
  60.         The COORD class handles all of our
  61.         screen positioning, and is screen
  62.         size sensitive (assuming we set the
  63.         correct variables in the DogFight!.h)
  64.         It handles inc/decrementing (movement),
  65.         wraparound, and keeps track of the
  66.         position in floating point.
  67. ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
  68. *********************************************************************/
  69.  
  70. COORD::COORD() {
  71.         x=y=0;
  72.         fx=fy=0.0;
  73.         xinc=yinc=0.0;
  74. }
  75.  
  76. void COORD::set_f(float a, float b) {
  77.         fx = a;
  78.         fy = b;
  79.         x=int(fx);
  80.         y=int(fy);
  81. }
  82.  
  83.  
  84. /******************************************
  85. ×××××××××××××××××××××××××××××××××××××××××××
  86.         Increment the coords and check for
  87.         wraparound.
  88. ×××××××××××××××××××××××××××××××××××××××××××
  89. ******************************************/
  90.  
  91. void COORD::inc()  {
  92.         fx += xinc;
  93.         fy += yinc;
  94.         if (fx < scrn_left) {
  95.                 fx = float(scrn_left) - fx;
  96.                 fx = float(scrn_right) - fx;
  97.         }
  98.         else if (fx > (float)scrn_right) {
  99.                 fx -= float(scrn_right);
  100.                 fx += float(scrn_left);
  101.         }
  102.  
  103.         if (fy < (float)scrn_top) {
  104.                 fy = float(scrn_top) - fy;
  105.                 fy = float(scrn_bottom) - fy;
  106.         }
  107.         else if (fy > (float)scrn_bottom) {
  108.                 fy -= float(scrn_bottom);
  109.                 fy += float(scrn_top);
  110.         }
  111.         x = int(fx);
  112.         y = int(fy);
  113. }
  114.  
  115. /******************************************
  116. ×××××××××××××××××××××××××××××××××××××××××××
  117.         Returns the distance between itself
  118.         and the supplied coordinate.
  119. ×××××××××××××××××××××××××××××××××××××××××××
  120. ******************************************/
  121.  
  122. int COORD::dist(COORD a)        {
  123.         static int k, l;
  124.         k = a.x-x;
  125.         l = a.y-y;
  126.         return int(FastSQRT((k*k) + (l*l)));
  127. }
  128.  
  129. /********************************************************************
  130. ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
  131.         Our SHOT class.  Since Jets don't
  132.         collide, this is the only way to shoot
  133.         down enemy craft =-).
  134. ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
  135. *********************************************************************/
  136.  
  137. void SHOT::stop() {underway = FALSE;}
  138.  
  139. SHOT::SHOT() {  underway = FALSE;}
  140.  
  141. void SHOT::bang(COORD co, float d, int pla) {
  142.         if (!underway) {
  143.                 dir = d;
  144.                 c = co;
  145.                 underway = TRUE;
  146.                 dist = 0;
  147.                 c.xinc = SPSin(dir) * shotspeed[game_speed];
  148.                 c.yinc = SPCos(dir) * -shotspeed[game_speed];
  149.                 shoot(pla);
  150.         }
  151. }
  152.  
  153. /******************************************
  154. ×××××××××××××××××××××××××××××××××××××××××××
  155.         Check for collision with the supplied
  156.         coordinate.  This might be better if
  157.         we can actually check to see if we're
  158.         _inside_ a Jet, but those calculations
  159.         slow the game down too much, and
  160.         checking by pixel is unreliable.
  161.         Returns TRUE if collision, and if so,
  162.         stops shot.
  163. ×××××××××××××××××××××××××××××××××××××××××××
  164. ******************************************/
  165.  
  166. BOOL SHOT::collide(COORD b) {
  167.         if (underway) {
  168.                 if (b.dist(c) < 10) {
  169.                         underway = FALSE;
  170.                         return TRUE;
  171.                 }
  172.         }
  173.         return FALSE;
  174. }
  175.  
  176. /******************************************
  177. ×××××××××××××××××××××××××××××××××××××××××××
  178.         Responsible for erasing, repositioning,
  179.         and redrawing the shot, as well
  180.         as checking to see if the shot has moved
  181.         it's maximum range.
  182.         See FIGHTER::move().
  183. ×××××××××××××××××××××××××××××××××××××××××××
  184. ******************************************/
  185.  
  186. void SHOT::move(struct RastPort *rp) {
  187.         if (underway) {
  188.                 erase(rp);
  189.                 old_c = c;
  190.                 if (dist < 280) {
  191.                         dist += shotspeed[game_speed];
  192.                         c.inc();
  193.                         draw(rp);
  194.                         }
  195.                 else {
  196.                         underway = FALSE;
  197.                         }
  198.         }
  199.         else if (dist) {
  200.                         erase(rp);
  201.                         dist = 0;
  202.                 }
  203.  
  204. }
  205.  
  206. /******************************************
  207. ×××××××××××××××××××××××××××××××××××××××××××
  208.         Draw the shot
  209. ×××××××××××××××××××××××××××××××××××××××××××
  210. ******************************************/
  211.  
  212. void SHOT::draw(struct RastPort * rp) {
  213.         SetAPen(rp, 5);
  214.         Move(rp, c.x, c.y);
  215.         Draw(rp, c.x + int(SPSin(dir)*4), c.y + int(SPCos(dir)*-4));
  216. }
  217.  
  218. /******************************************
  219. ×××××××××××××××××××××××××××××××××××××××××××
  220.         Erase the shot.  See FIGHTER::erase()
  221. ×××××××××××××××××××××××××××××××××××××××××××
  222. ******************************************/
  223.  
  224. void SHOT::erase(struct RastPort * rp) {
  225.         SetAPen(rp, 0);
  226.         RectFill(rp, old_c.x - 4, old_c.y - 4,
  227.                                          old_c.x + 4, old_c.y + 4);
  228. }
  229.  
  230. /********************************************************************
  231. ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
  232.         The Jet class.
  233.         We have:
  234.         * 3 coordinates for double-
  235.         buffering (to remember where we _were_),
  236.         * dir for direction, in rads (bleh!)
  237.         * turnrad for rate of turn
  238.         * 2 flags (rf&lf) for remembering in
  239.         which direction we're turning
  240.         * explosions for how big and long we
  241.         explode
  242.         * color to identify the Jet
  243.         * speed for how fast the Jet is
  244.         * deadtime to keep track of how long
  245.         we have to go before we're resurected
  246.         * txt for our Jet identification number.
  247.         * alive for whether we've been shot
  248.         * in_play to tell if the Jet is being
  249.         used
  250.         * killscore for how many jets we've
  251.         shot down
  252.         * and our very own SHOT.
  253. ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
  254. *********************************************************************/
  255.  
  256. void FIGHTER::right() {
  257.         if (!lf) rf = TRUE;
  258.         lf = FALSE;
  259.         shootable = TRUE;
  260. }
  261.  
  262. void FIGHTER::left() {
  263.         if (!rf) lf = TRUE;
  264.         rf = FALSE;
  265.         shootable = TRUE;
  266. }
  267.  
  268. void FIGHTER::fire() {
  269.         if (alive & shootable) {
  270.                 shot.bang(c, dir, color);
  271.                 shootable = TRUE;
  272.         }
  273. }
  274.  
  275. /******************************************
  276. ×××××××××××××××××××××××××××××××××××××××××××
  277.         Keeps the Jet out of play for a
  278.         certain amount of time (deadtime loops),
  279.         and then starts him up again.
  280. ×××××××××××××××××××××××××××××××××××××××××××
  281. ******************************************/
  282.  
  283. void FIGHTER::resurect(int p, int perf) {
  284.         if (deadtime)
  285.                 deadtime--;
  286.         else {
  287.                 init(p, perf);
  288.                 start(p+1);
  289.         }
  290. }
  291.  
  292. /******************************************
  293. ×××××××××××××××××××××××××××××××××××××××××××
  294.         Checks to see if the Jet has collided
  295.         with the supplied SHOT.
  296. ×××××××××××××××××××××××××××××××××××××××××××
  297. ******************************************/
  298.  
  299. BOOL FIGHTER::collide(SHOT *s) {
  300.         if (alive && shootable) 
  301.                 if (s->collide(c)) {
  302.                         alive = FALSE;
  303.                         explode(color);
  304.                         return TRUE;
  305.                 }
  306.  
  307.         return FALSE;
  308. }
  309.  
  310. /******************************************
  311. ×××××××××××××××××××××××××××××××××××××××××××
  312.         Set up Jet values.
  313.         - 'a' is the player number, 
  314.         - 'perf' is the Jet type option set in
  315.         the prefs window.
  316.         Player1 (a=0) starts in the upperleft
  317.         screen corner, Player2 (a=1) in the
  318.         upperright, etc.
  319.         perf=0 means the Jet is not in play,
  320.         perf=1 is a compromise Jet, etc.
  321. ×××××××××××××××××××××××××××××××××××××××××××
  322. ******************************************/
  323.         
  324. void FIGHTER::init(int a, int perf)     {
  325.  
  326.         lf = rf = FALSE;                // moving straight
  327.         alive = TRUE;                   // not dead yet
  328.         explosions = 15;                // each explosion lasts 15 program loops
  329.         color = a+1;
  330.         txt = &(PLT[a]);                        // see DogFight!4.h
  331.         deadtime = 500;         // each death lasts 500 program loops
  332.         in_play=TRUE;                   // assume the Jet is in play...
  333.         shootable=vulnerability;
  334.         shot.stop();
  335.         
  336.         switch(perf) {
  337.                 case 0:                         // ... because we just take it out of
  338.                         in_play=FALSE;  // play if perf is 0
  339.                         break;
  340.                 case 1:                                                                 // this is the compromise Jet
  341.                         speed = medium[game_speed];
  342.                         turnrad = 1.7 * float(rad_inc);
  343.                         break;
  344.                 case 2:                                                                 // the fast (Speed) Jet
  345.                         speed = fast[game_speed];               
  346.                         turnrad = 1.2 * float(rad_inc);
  347.                         break;
  348.                 default:                                                                                // the only other option is
  349.                         speed = slow[game_speed];                       // the maneuverable (slow)
  350.                         turnrad = 2.2 * float(rad_inc); // Jet
  351.                         break;
  352.         }
  353.         
  354.         switch(a)       {
  355.                 case 0:
  356.                         c.set_f((int)scrn_left, (int)scrn_top); // put him in the upper left
  357.                         dir = float(rad_inc) * 135.0;                                   // aim him SE
  358.                         break;
  359.                 case 1:
  360.                         c.set_f((int)scrn_right, (int)scrn_top);        // upper right
  361.                         dir = float(rad_inc) * 225.0;                                   // headed SW
  362.                         break;
  363.                 case 2:
  364.                         c.set_f((int)scrn_left, (int)scrn_bottom);      // lower left
  365.                         dir = float(rad_inc) * 45.0;                                            // headed NE
  366.                         break;
  367.                 case 3:
  368.                         c.set_f((int)scrn_right, (int)scrn_bottom);     // lower right
  369.                         dir = float(rad_inc) * 315.0;                                           // headed NW
  370.                         break;
  371.                 default:
  372.                         break;
  373.         }
  374.         c.xinc = SPSin(dir);                    // start 'em out slow & steady in the initial
  375.         c.yinc = -SPCos(dir);                   // direction.
  376. }
  377.  
  378. /******************************************
  379. ×××××××××××××××××××××××××××××××××××××××××××
  380.         Responsible for erasing, calculating
  381.         the new position, and drawing the Jet
  382.         in the supplied RastPort.  Assumes that
  383.         we're double buffered; IE, that we're
  384.         drawing on exactly two screens (hence
  385.         the c, old_c, and oold_c coordinates).
  386.         Also calls the explosion routines if
  387.         the Jet is in the process of dying.
  388. ×××××××××××××××××××××××××××××××××××××××××××
  389. ******************************************/
  390.  
  391. void FIGHTER::move(struct RastPort * rp)        {
  392.         
  393.         shot.move(rp);                  // let the missile move if it wants to
  394.  
  395.         if (alive) {                    // if we're alive...
  396.                 if (rf | lf) {          // if we get a turn signal
  397.                         if (rf) {               // if the signal is right
  398.                                 dir = (float)dir + (float)turnrad;              // turn clockwise
  399.                                 if (dir > float(TWO_PI)) dir = 0.0;     // IE, if dir > 360°
  400.                         }                                                                                       // we set it to 0.
  401.                         else    {
  402.                                 dir = (float)dir - (float)turnrad;              // else turn counterclockwise
  403.                                 if (dir < 0.0)  dir = float(TWO_PI);            // and complete a circle
  404.                         }
  405.                                 
  406.                         c.xinc = SPSin(dir) * speed;            // set the incs for the new dir
  407.                         c.yinc = SPCos(dir) * -speed;
  408.                 }
  409.  
  410.                 c.inc();                                // calculate the new coordinates
  411.  
  412.                 draw(rp);                       // draw the Jet.
  413.         }
  414.         else if (explosions>1)  // not alive?!? still exploding?
  415.                         draw_explode(rp);       // then draw explosion
  416. }
  417.  
  418. /******************************************
  419. ×××××××××××××××××××××××××××××××××××××××××××
  420.         Draws a fighter in the supplied
  421.         RasterPort, and plops the text in the
  422.         middle.
  423. ×××××××××××××××××××××××××××××××××××××××××××
  424. ******************************************/
  425.  
  426. void FIGHTER::draw(struct RastPort * rp) {
  427.         static float first;             // So we don't have to calculate them twice 
  428.         static float second;    // every time.
  429.         static WORD xy[6];              // The array for the endpoints in the Jet
  430.  
  431.         first = (float)dir + (float)ri135;                      // down right
  432.         second= (float)dir + (float)ri225;                      // down left
  433.         xy[0] = c.x + int( SPSin(dir)    *  13.0 );
  434.         xy[1] = c.y + int( SPCos(dir)    * -13.0 );
  435.         xy[2] = c.x + int( SPSin(first)  *   8.0 );
  436.         xy[3] = c.y + int( SPCos(first)  *  -8.0 );
  437.         xy[4] = c.x + int( SPSin(second) *   8.0 );
  438.         xy[5] = c.y + int( SPCos(second) *  -8.0 );
  439.         
  440.         SetAPen(rp, color);
  441.         txt->FrontPen = color;
  442.         PrintIText(rp, txt, c.x-3, c.y-3);
  443.         Move(rp, xy[4], xy[5]);
  444.         PolyDraw(rp, 3, xy);
  445. }
  446.  
  447. /******************************************
  448. ×××××××××××××××××××××××××××××××××××××××××××
  449.         Quick erase of the fighter shape.
  450.         It would be better to erase just the
  451.         shape instead of a block fill, but
  452.         it takes too long.
  453. ×××××××××××××××××××××××××××××××××××××××××××
  454. ******************************************/
  455.  
  456. void FIGHTER::erase(struct RastPort * rp) {
  457.         SetAPen(rp, 0);
  458.  
  459.         if (alive)      {                                                                                       // if alive, erase Jet
  460.                 RectFill(rp, old_c.x - 13, old_c.y - 13,
  461.                                                  old_c.x + 13, old_c.y + 13);
  462.                 RectFill(rp, old_c.x-3, old_c.y-3, old_c.x + 8, old_c.y + 9);
  463.                 old_c = c;
  464.         }
  465.         else if (explosions) {                                                          // otherwise, erase
  466.                         explosions--;                                                                   // explosions
  467.                         RectFill(rp, c.x - (explosions + 2),
  468.                                                          c.y - (explosions + 2),
  469.                                                          c.x + (explosions + 2),
  470.                                                          c.y + (explosions + 2));
  471.                 }
  472. }
  473.  
  474. /******************************************
  475. ×××××××××××××××××××××××××××××××××××××××××××
  476.         Draws a simple explosion with a
  477.         radius of 'explosions' in the supplied
  478.         RasterPort.
  479. ×××××××××××××××××××××××××××××××××××××××××××
  480. ******************************************/
  481.  
  482. void FIGHTER::draw_explode(struct RastPort * rp) {
  483.         float i;
  484.         
  485.         SetAPen(rp, color);
  486.         
  487.         for (i = 0; i < TWO_PI; i = (float)i + (float)(PI/5)) {
  488.                 Move(rp, c.x, c.y);
  489.                 Draw(rp, c.x + int(SPSin(i) * explosions),
  490.                                    c.y + int(SPCos(i) * explosions));
  491.         }
  492. }
  493.