home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / apilot.lha / APilot / APilot_Opt / ships.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-12  |  11.0 KB  |  400 lines

  1. /****************************************************************************
  2.  *
  3.  * Ships.c -- Functions used for calculations and displaying of ships.
  4.  *
  5.  *-------------------------------------------------------------------------
  6.  * Authors: Casper Gripenberg  (casper@alpha.hut.fi)
  7.  *          Kjetil Jacobsen  (kjetilja@stud.cs.uit.no)
  8.  *
  9.  */
  10.  
  11. #include <stdlib.h>
  12. #include <math.h>
  13. #include <exec/types.h>             /* The Amiga data types file.         */
  14. #include <libraries/dos.h>          /* Official return codes defined here */
  15.  
  16. #include <proto/intuition.h>
  17. #include <proto/graphics.h>
  18.  
  19. #include "main_protos.h"
  20. #include "points_protos.h"
  21. #include "ships_protos.h"
  22. #include "lists_protos.h"
  23. #include "fuelpod_protos.h"
  24.  
  25. #include "common.h"
  26. #include "defs.h"
  27. #include "map.h"
  28. #include "prefs.h"
  29. #include "ships.h"
  30.  
  31. /*---------------------------------------------------------------------------*/
  32.  
  33. extern int sina[];
  34. extern int cosa[];
  35.  
  36. extern AWorld World;
  37.  
  38. struct Coordinates triangle[] = {
  39.   { 0,-11},
  40.   { 7,  7},
  41.   {-7,  7},
  42.   {0, -11}
  43. };
  44.  
  45. static int animno = 0; /* Need this for shield animation */
  46.  
  47. /*---------------------------------------------------------------------------*/
  48.  
  49. /*
  50.  * init_ship -- Inizialize ship parameterers. (May be changed to accept
  51.  *              parameters as function arguments later...)
  52.  *
  53.  */
  54.  
  55. void
  56. init_ship( AShip *aShip )
  57. {
  58.   int i, j;
  59.   ABase *shipbase;
  60.  
  61.   shipbase = get_base();
  62.   /*
  63.    * Should be made to handle out-of-bases situations more gracefully
  64.    * in the future.
  65.    */ 
  66.   if (shipbase == NULL)
  67.     cleanExit( RETURN_WARN, "** Out of bases for new ship." );
  68.  
  69.   shipbase->owner = aShip;
  70.   aShip->base.x = shipbase->mapos.x * MAP_BLOCKSIZE + MAP_BLOCKSIZE/2;
  71.   aShip->base.y = shipbase->mapos.y * MAP_BLOCKSIZE + MAP_BLOCKSIZE/2;
  72.  
  73.   aShip->shape     = triangle;  
  74.   aShip->shapesize = sizeof(triangle)/sizeof(struct Coordinates);
  75.   aShip->mass      = SHP_MASS;
  76.   aShip->draw_it   = FALSE;
  77.   aShip->fueling   = FALSE;
  78.   aShip->fuel      = MAXFUEL/5;
  79.   aShip->fuelcount = 0;
  80.  
  81.   for (i = 0; i < MY_BUFFERS; i++) {
  82.     aShip->s_drawn[i] = FALSE;
  83.     aShip->f_drawn[i] = FALSE;
  84.   }
  85.  
  86.   aShip->pos.x     = aShip->base.x;
  87.   aShip->pos.y     = aShip->base.y;
  88.   aShip->xvel      = aShip->yvel   = 0;
  89.   aShip->xcount    = aShip->ycount = 0;
  90.   aShip->status    = 0;
  91.   aShip->shields   = TRUE;
  92.   aShip->power     = THR_POWER * PRECS;
  93.   aShip->exhcount  = EXH_COUNT; 
  94.   aShip->exhwidth  = EXH_WIDTH;
  95.   aShip->exhdist   = EXH_DIST;
  96.   aShip->exhlife   = 25;   /* 50 = one second on 50fps */
  97.   aShip->rotspeed  = ROT_SPEED;
  98.   aShip->angle     = 0;
  99.   aShip->local     = TRUE;
  100.   aShip->fireing   = FALSE;
  101.   aShip->buldist   = BUL_DIST;
  102.   aShip->bul_life  = BUL_LIFE;
  103.   aShip->fw_nbul   = 3;
  104.   aShip->bw_nbul   = 1;
  105.   aShip->thrusting = FALSE;
  106.  
  107.   aShip->currc     = (struct Coordinates *) 
  108.                       malloc( aShip->shapesize * sizeof(struct Coordinates) );
  109.   if (aShip->currc == NULL)
  110.     cleanExit( RETURN_WARN, "** Unable to allocate space for ship structure.\n" );
  111.  
  112.   aShip->prevc     = (struct Coordinates **)
  113.                       malloc( MY_BUFFERS * sizeof(struct Coordinates) );
  114.   if (aShip->prevc == NULL)
  115.     cleanExit( RETURN_WARN, "** Unable to allocate space for ship structure.\n" );
  116.  
  117.   for (i = 0; i < MY_BUFFERS; i++) {
  118.     if ( (aShip->prevc[i] = 
  119.           (struct Coordinates *)
  120.            malloc( aShip->shapesize * sizeof(struct Coordinates) )) == NULL )
  121.       cleanExit( RETURN_WARN, "** Unable to allocate space for ship structure.\n" );
  122.   }     
  123.  
  124.   /* Copy the shape into current coordinates */
  125.   for(i = 0; i < aShip->shapesize; i++) {
  126.     aShip->currc[i].x = aShip->shape[i].x;
  127.     aShip->currc[i].y = aShip->shape[i].y;
  128.   }
  129.   for(i = 0; i < MY_BUFFERS; i++) {
  130.     aShip->p_pos[i].x = aShip->p_pos[i].y = 0;
  131.     for(j = 0; j < aShip->shapesize; j++) {
  132.       aShip->prevc[i][j].x = aShip->shape[j].x;
  133.       aShip->prevc[i][j].y = aShip->shape[j].y;
  134.     }
  135.   }
  136.  
  137. }
  138.  
  139. /*---------------------------------------------------------------------------*/
  140.  
  141. /*
  142.  * landing -- Returns TRUE if the ship is in a landing configuration,
  143.  *            ie. nose up, slow speed.
  144.  *
  145.  */
  146. BOOL
  147. landing( AShip *ship )
  148. {
  149.   if (ship->angle < 15 || ship->angle > 345)
  150.     if (ship->yvel <= PRECS && ship->yvel >= 0)
  151.       return TRUE;
  152.  
  153.   return FALSE;
  154. }
  155.  
  156. /*---------------------------------------------------------------------------*/
  157.  
  158. /*
  159.  * update_ship -- Updates the ship position, angle, fireing and exhaust. Checks
  160.  *                for ship out of window range etc. etc..
  161.  */
  162. void
  163. update_ship( AShip *aShip, UWORD buf, UWORD nframes )
  164. {
  165.   int i;
  166.   int isin, icos;
  167.  
  168.   /*
  169.    * Check if ship exploded 
  170.    */
  171.   if (aShip->status > 0)
  172.     return;
  173.  
  174.   if (aShip->turning != NO || aShip->thrusting || aShip->fireing) {
  175.  
  176.     if (aShip->turning == RIGHT) {
  177.       aShip->angle = (aShip->angle + aShip->rotspeed * nframes) % 360;
  178.     } else if (aShip->turning == LEFT) {
  179.       aShip->angle = (aShip->angle - aShip->rotspeed * nframes) % 360;
  180.      }
  181.  
  182.     if (aShip->angle < 0)
  183.       aShip->angle = 360 + aShip->angle;
  184.  
  185.     isin = sina[aShip->angle];
  186.     icos = cosa[aShip->angle];
  187.  
  188.     if (aShip->turning != NO) {
  189.       if (aShip->turning == YES) aShip->turning = NO;
  190.       /* Rotate the points */
  191.       for(i = 0; i < aShip->shapesize; i++) {
  192.         aShip->currc[i].x = (aShip->shape[i].x * icos - aShip->shape[i].y * isin) >> SHFTPR;
  193.         aShip->currc[i].y = (aShip->shape[i].x * isin + aShip->shape[i].y * icos) >> SHFTPR;
  194.       }
  195.     }
  196.   }
  197.  
  198.   for (i = nframes; i > 0; i--) {
  199.     if (aShip->thrusting && aShip->fuel > 0) {
  200.       aShip->xvel += (isin * aShip->power) >> SHFTPR;
  201.       aShip->yvel -= (icos * aShip->power) >> SHFTPR;
  202.     }
  203.     aShip->yvel += World.gravity;
  204.     aShip->xcount += aShip->xvel;
  205.     aShip->ycount += aShip->yvel;
  206.   }
  207.  
  208.   /* Store old positions 
  209.   aShip->p_pos[buf].x = aShip->pos.x;
  210.   aShip->p_pos[buf].y = aShip->pos.y;
  211.   */
  212.  
  213.   /* Move ship */
  214.   aShip->pos.x  += (aShip->xcount < 0) ? -((-aShip->xcount) >> SHFTPR) : (aShip->xcount >> SHFTPR);
  215.   aShip->xcount  = aShip->xcount % PRECS;
  216.   aShip->pos.y  += (aShip->ycount < 0) ? -((-aShip->ycount) >> SHFTPR) : (aShip->ycount >> SHFTPR);
  217.   aShip->ycount  = aShip->ycount % PRECS;
  218.  
  219.   if (aShip->thrusting && aShip->fuel > 0) {
  220.     add_exhaust(aShip, isin, icos, nframes);
  221.     aShip->fuelcount += 2*nframes;
  222.   }
  223.  
  224.   if (aShip->fireing) {
  225.     aShip->fireing = FALSE;
  226.     if (!aShip->shields && aShip->fuel > 0) {
  227.       /* Every bullet grabs one fuel */
  228.       aShip->fuel -= aShip->fw_nbul + aShip->bw_nbul;
  229.       add_bullets(aShip, isin, icos);
  230.     }
  231.   }
  232.  
  233.   if (aShip->shields)
  234.     aShip->fuelcount += nframes;
  235.   if (aShip->fuelcount >= 50) {
  236.     aShip->fuelcount = 0;
  237.     aShip->fuel--;
  238.   }
  239.   if (aShip->fuel <= 0) {
  240.     aShip->shields = FALSE;
  241.     aShip->fuel = 0;
  242.   }
  243.  
  244.   if (aShip->fueling)
  245.     fuel_ship(aShip);
  246.  
  247.   if (aShip->pos.x >= MAP_BLOCKSIZE*World.Width) {
  248.     aShip->pos.x = MAP_BLOCKSIZE*World.Width-1;
  249.     aShip->xvel  = -(aShip->xvel >> 1);
  250.   } else if (aShip->pos.x < 0) {
  251.     aShip->pos.x = 0;
  252.     aShip->xvel  = -(aShip->xvel >> 1);
  253.   }
  254.   if (aShip->pos.y >= MAP_BLOCKSIZE*World.Height) {
  255.     aShip->pos.y = MAP_BLOCKSIZE*World.Height-1;
  256.     aShip->yvel  = -(aShip->yvel >> 1);
  257.   } else if (aShip->pos.y < 0) {
  258.     aShip->pos.y = 0;
  259.     aShip->yvel  = -(aShip->yvel >> 1);
  260.   }
  261. }
  262.  
  263. /*---------------------------------------------------------------------------*/
  264.  
  265. /*
  266.  * draw_ship.c -- Draws a ship on the display
  267.  *
  268.  */
  269. void
  270. draw_ship( AShip *aShip, struct RastPort *rp, UWORD buf )
  271. {
  272.   int bp_x, bp_y, i;
  273.   int pos_x, pos_y;
  274.   struct Coordinates *prevc;
  275.   struct Coordinates *currc;
  276.  
  277.   prevc = aShip->prevc[buf];
  278.   currc = aShip->currc;
  279.  
  280.   SetWriteMask(rp, 3l);
  281.   SetAPen(rp, 0);
  282.  
  283.   /* Remove ship */
  284.   if (aShip->local) {
  285.     Move(rp, LOCL_X+prevc[0].x, LOCL_Y+prevc[0].y);
  286.     for (i = 1; i < aShip->shapesize; i++) {
  287.       Draw(rp, LOCL_X+prevc[i].x, LOCL_Y+prevc[i].y);
  288.       /* Store new coordinates */
  289.       prevc[i].x = currc[i].x;
  290.       prevc[i].y = currc[i].y;
  291.     }
  292.     prevc[0].x = currc[0].x;
  293.     prevc[0].y = currc[0].y;
  294.    
  295.     /*
  296.      * Last shield image is the circle-mask for clearing.
  297.      * Should try to find some condition where this clearing
  298.      * is not necessary. As it is now, some CPU might get wasted...
  299.      */
  300.     BltBitMap(World.shld_bm, (SHL_SIZE*2+1)*(SHL_ANIM-1), 0, rp->BitMap, 
  301.           LOCL_X-SHL_SIZE, LOCL_Y-SHL_SIZE,
  302.           SHL_SIZE*2+1, SHL_SIZE*2+1, 0x22, 0x03, NULL);
  303.     
  304.     if (aShip->f_drawn[buf]) {
  305.       aShip->f_drawn[buf] = FALSE;  
  306.       Move(rp, LOCL_X, LOCL_Y);
  307.       Draw(rp, aShip->fuell[buf].x, aShip->fuell[buf].y);
  308.     }
  309.   } else { 
  310.     if (aShip->s_drawn[buf]) {
  311.       pos_x = aShip->p_pos[buf].x;
  312.       pos_y = aShip->p_pos[buf].y;
  313.       
  314.       Move(rp, pos_x+prevc[0].x, pos_y+prevc[0].y);
  315.       for (i = 1; i < aShip->shapesize; i++) {
  316.         Draw(rp, pos_x+prevc[i].x, pos_y+prevc[i].y);
  317.       }
  318.  
  319.       aShip->s_drawn[buf] = FALSE;
  320.     }      
  321.   }
  322.  
  323.   /*
  324.    * Check if our ship is dead
  325.    */
  326.   if (aShip->status > 0) {
  327.     aShip->status -= (World.framerate * 2);
  328.     if (aShip->status <= 0) {
  329.       /*
  330.        * Been dead long enough, restore default values...
  331.        */
  332.       if (aShip->local)
  333.         World.hudon = TRUE;
  334.       aShip->fuel    = MAXFUEL/5;
  335.       aShip->fueling = FALSE;
  336.       aShip->fpod    = NULL;
  337.       /* ** Only during testing ** */
  338.       if (aShip->local)
  339.         aShip->shields = TRUE;
  340.       aShip->angle   = 0;
  341.       aShip->turning = YES;
  342.       aShip->pos.x = aShip->base.x;
  343.       aShip->pos.y = aShip->base.y;
  344.       aShip->xvel = aShip->xcount = 0;
  345.       aShip->yvel = aShip->ycount = 0;
  346.     }
  347.     return;
  348.   }
  349.  
  350.   SetAPen(rp, 3);
  351.  
  352.   /* Draw ship */
  353.   if (aShip->local) {
  354.     if (aShip->shields) {
  355.  
  356.       /* Animate the shield */
  357.       if (animno >= SHL_ANIM-1)
  358.         animno -= SHL_ANIM-1;
  359.       BltBitMap(World.shld_bm, (SHL_SIZE*2+1)*animno, 0, rp->BitMap, 
  360.                 LOCL_X-SHL_SIZE, LOCL_Y-SHL_SIZE,
  361.                 SHL_SIZE*2+1, SHL_SIZE*2+1, 0xEE, 0x03, NULL);
  362.       animno +=  World.framerate; 
  363.     }
  364.     if (aShip->fueling) {
  365.       bp_x = World.local_ship->pos.x-(SCR_WIDTH+MAP_BLOCKSIZE*2)/2;
  366.       bp_y = World.local_ship->pos.y-(SCR_HEIGHT+MAP_BLOCKSIZE*2)/2;
  367.       Move(rp, LOCL_X, LOCL_Y);
  368.       aShip->fuell[buf].x = aShip->fpod->pos.x-bp_x;
  369.       aShip->fuell[buf].y = aShip->fpod->pos.y-bp_y;
  370.       Draw(rp, aShip->fuell[buf].x, aShip->fuell[buf].y);
  371.       aShip->f_drawn[buf] = TRUE;
  372.     }
  373.  
  374.     Move(rp, LOCL_X+currc[0].x, LOCL_Y+currc[0].y);
  375.     for (i = 1; i < aShip->shapesize; i++)
  376.       Draw(rp, LOCL_X+currc[i].x, LOCL_Y+currc[i].y);
  377.   } else {
  378.     if (aShip->draw_it) {
  379.       bp_x = World.local_ship->pos.x-(SCR_WIDTH+MAP_BLOCKSIZE*2)/2;
  380.       bp_y = World.local_ship->pos.y-(SCR_HEIGHT+MAP_BLOCKSIZE*2)/2;
  381.       pos_x = aShip->pos.x-bp_x;
  382.       pos_y = aShip->pos.y-bp_y;
  383.  
  384.       aShip->p_pos[buf].x = pos_x;
  385.       aShip->p_pos[buf].y = pos_y;
  386.  
  387.       Move(rp, pos_x+currc[0].x, pos_y+currc[0].y);
  388.       for (i = 1; i < aShip->shapesize; i++) {
  389.         Draw(rp, pos_x+currc[i].x, pos_y+currc[i].y);
  390.         prevc[i].x = currc[i].x;
  391.         prevc[i].y = currc[i].y;
  392.       }
  393.       prevc[0].x = currc[0].x;
  394.       prevc[0].y = currc[0].y;
  395.  
  396.       aShip->s_drawn[buf] = TRUE;
  397.     }
  398.   }
  399. }
  400.