home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 543a.lha / Nebula / source.LZH / source / main3d.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-10  |  18.1 KB  |  980 lines

  1. /*
  2.  
  3. ------------------------------------------------------------------
  4.  
  5. Black Nebula
  6.  
  7. File :                main3d.c
  8. Programmer:        Colin Adams
  9. Date:                29/3/91
  10. Last Modified :    10/6/91
  11.  
  12. Description:
  13.  
  14. Controls the main loop of the player's ship.
  15.  
  16. ------------------------------------------------------------------
  17.  
  18. */
  19.  
  20. #define AMIGA_INCLUDES
  21. #include "3d.h"
  22.  
  23. #define FIRE   1
  24. #define RIGHT  2
  25. #define LEFT   4
  26. #define DOWN   8
  27. #define UP    16
  28.  
  29. #define DELAY_TIME 2
  30.  
  31.  
  32. /*    ------------------------------------------------------------------
  33.         External Variables
  34.         ------------------------------------------------------------------
  35. */
  36.  
  37. extern short swapflag;
  38. extern object myship;
  39. extern int player_score, player_scale;
  40. extern struct RastPort my_rast_port, back_rast_port;
  41. extern struct View my_view, back_view;
  42. extern struct ViewPort my_view_port, back_view_port;
  43. extern struct BitMap my_bit_map;
  44. extern struct BitMap back_bit_map;
  45. extern void AddNewObject(short, short, short, short);
  46. extern void SpinObjCentres(void);
  47. extern int GetPointAngle(int *, short, short);
  48.  
  49. /*    ------------------------------------------------------------------
  50.         Variables
  51.         ------------------------------------------------------------------
  52. */
  53.  
  54. static int last_draw = 0;
  55. int player_missiles;
  56. short U_rot = 270, W_rot = 180;
  57. short View2_Angle;
  58. int cos_angle[360], sin_angle[360];
  59. char rotate[4];
  60.  
  61. /* pointers to bitmaps for console update */
  62.  
  63. PLANEPTR front_alt[4], back_alt[4];
  64. PLANEPTR front_sp[4], back_sp[4];
  65.  
  66. PLANEPTR front_radar[66][4];
  67. PLANEPTR back_radar[66][4];
  68.  
  69. char colour_mask[16][4];
  70. UBYTE on_pat[8], off_pat[8];
  71.  
  72. /*    ------------------------------------------------------------------
  73.         Routines
  74.         ------------------------------------------------------------------
  75. */
  76.  
  77. void SetUpConsole(void)
  78. /* precalculation of bitmap pointers for fast drawing */
  79. {
  80.     unsigned char i, j;
  81.     
  82.     for(i=0; i<16; i++)
  83.     {
  84.         colour_mask[i][0] = i & 1;
  85.         colour_mask[i][1] = i & 2;
  86.         colour_mask[i][2] = i & 4;
  87.         colour_mask[i][3] = i & 8;
  88.     }
  89.     
  90.     for(i=0; i<DEPTH; i++)
  91.     {
  92.         front_alt[i] = my_bit_map.Planes[i] + (G/8) * 225;
  93.         front_sp[i] = my_bit_map.Planes[i] + (G/8) * 245;
  94.         
  95.         back_alt[i] = back_bit_map.Planes[i] + (G/8) * 225;
  96.         back_sp[i] = back_bit_map.Planes[i] + (G/8) * 245;    
  97.         
  98.         for(j=0; j<66; j++)
  99.         {
  100.             front_radar[j][i] = my_bit_map.Planes[i] + (G/8) * (182+j) + 16;
  101.             back_radar[j][i] = back_bit_map.Planes[i] + (G/8) * (182+j) + 16;
  102.         }
  103.     }
  104.     
  105.     on_pat[0] = 1;
  106.     off_pat[0] = ~1;
  107.     
  108.     on_pat[1] = 2;
  109.     off_pat[1] = ~2;
  110.     
  111.     on_pat[2] = 4;
  112.     off_pat[2] = ~4;
  113.     
  114.     on_pat[3] = 8;
  115.     off_pat[3] = ~8;
  116.     
  117.     on_pat[4] = 16;
  118.     off_pat[4] = ~16;
  119.     
  120.     on_pat[5] = 32;
  121.     off_pat[5] = ~32;
  122.     
  123.     on_pat[6] = 64;
  124.     off_pat[6] = ~64;
  125.     
  126.     on_pat[7] = 128;
  127.     off_pat[7] = ~128;
  128.     
  129. }
  130.  
  131. void UpdateAlt(void)
  132. /* updates the altmeter on the user display */
  133. {
  134.     int byte = ey / (MAX_WORLD_Y/9);
  135.     unsigned int i;
  136.         
  137.     for(i=0; i<DEPTH; i++)
  138.     {
  139.         register PLANEPTR temp, temp2;
  140.         register unsigned int j;
  141.         
  142.         temp = front_alt[i] + byte;
  143.         temp2 = back_alt[i] + byte;
  144.         
  145.         for(j=1; j<=9; j++)
  146.         {
  147.             register unsigned int colour;
  148.             
  149.             if(byte)
  150.             {
  151.                 if(j>5)
  152.                     colour = j + 4;
  153.                 else
  154.                     colour = 13 - j;
  155.         
  156.                 if(colour_mask[colour][i])
  157.                 {
  158.                     *temp2 = 255; /* fill byte with colour */
  159.                     *temp = 255;
  160.                 }
  161.                 else
  162.                 {
  163.                     *temp2 = 0; /* set to background colour */
  164.                     *temp = 0;
  165.                 }
  166.             }
  167.             
  168.             if(byte<9)
  169.             {
  170.                 *(temp + 1) = 0; /* clear to right side */
  171.                 *(temp2 + 1) = 0;
  172.             }
  173.             
  174.             temp += G/8;
  175.             temp2 += G/8;
  176.         }
  177.     }
  178. }
  179.  
  180. void UpdateSpeed(void)
  181. /* 
  182. Updates the speed meter on the user display.  For some strange
  183. reason this code doesn't work on an Amiga 3000 the way it does on
  184. a 2000.  ie. bugs
  185. */
  186. {
  187.     unsigned int i;
  188.         
  189.     for(i=0; i<DEPTH; i++)
  190.     {
  191.         register PLANEPTR temp, temp2;
  192.         register unsigned int j;
  193.         
  194.         temp = front_sp[i] + velocity;
  195.         temp2 = back_sp[i] + velocity;
  196.         
  197.         for(j=1; j<=9; j++)
  198.         {
  199.             register unsigned int colour;
  200.             
  201.             if(velocity)
  202.             {
  203.                 if(j>5)
  204.                     colour = j + 4;
  205.                 else
  206.                     colour = 13 - j;
  207.             
  208.                 if(colour_mask[colour][i])
  209.                 {
  210.                     *temp2 = 255; /* fill byte with colour */
  211.                     *temp = 255;
  212.                 }
  213.                 else
  214.                 {
  215.                     *temp2 = 0; /* set to background colour */
  216.                     *temp = 0;
  217.                 }
  218.             }
  219.             
  220.             if(velocity<9)
  221.             {
  222.                 *(temp + 1) = 0; /* clear to right side */
  223.                 *(temp2 + 1) = 0;
  224.             }
  225.             
  226.             temp += G/8;
  227.             temp2 += G/8;
  228.         }
  229.     }
  230. }
  231.  
  232. void UpdateRadar(void)
  233. /* updates the radar on the user display */
  234. {
  235.  
  236.     static PLANEPTR last_bytes_front[TOTAL_MAX_OBJECTS][DEPTH];
  237.     static PLANEPTR last_bytes_back[TOTAL_MAX_OBJECTS][DEPTH];
  238.     
  239.     unsigned int i, loop;
  240.     object *obj;
  241.     
  242.     for(loop=0; loop<last_draw; loop++)
  243.     {
  244.         for(i=0; i<DEPTH; i++)
  245.         {
  246.             *last_bytes_front[loop][i] = 0;
  247.             *last_bytes_back[loop][i] = 0;
  248.         }
  249.     }
  250.     
  251.     last_draw = no_objects + 1;
  252.     
  253.     for(loop=0; loop<=no_objects; loop++)
  254.     {
  255.         register int y, byte, offset, colour, x;
  256.         
  257.         if(loop!=no_objects)
  258.         {
  259.             obj = active_list[loop];
  260.             
  261.             x = obj->trans_x;
  262.             y = obj->trans_z / (MAX_WORLD_Z/65);
  263.             
  264.             switch(obj->type)
  265.             {
  266.                 case FIXED: colour = 9; break;
  267.                 case ENEMYMISSILE: colour = 10; break;
  268.                 case MYMISSILE: colour = 1; break;
  269.                 case SHUTTLE: colour = 14; break;
  270.                 case KRAIT: colour = 12; break;
  271.                 case GECKO: colour = 15; break;
  272.                 case THARGOID: colour = 11; break;
  273.                 case MAMBA: colour = 8; break;
  274.                 case GUIDEDMISSILE: colour = 3; break;
  275.                 case EXPLOSION: colour = 0; break;
  276.             }
  277.         }
  278.         else
  279.         {
  280.             x = ex;
  281.             y = ez / (MAX_WORLD_Z/65);
  282.             colour = 8;
  283.         }
  284.         
  285.         byte = x/(MAX_WORLD_X/7); /* get byte number */
  286.         offset = x- (byte*(MAX_WORLD_X/7)); /* get bit offset */
  287.         offset = 7 - (offset/((MAX_WORLD_X/7)/7));
  288.         
  289.         for(i=0; i<DEPTH; i++)
  290.         {
  291.             register PLANEPTR temp, temp2;
  292.             register UBYTE s_read;
  293.             
  294.             temp = front_radar[y][i] + byte;
  295.             temp2 = back_radar[y][i] + byte;
  296.         
  297.             last_bytes_front[loop][i] = temp;
  298.             last_bytes_back[loop][i] = temp2;
  299.             
  300.             if(colour_mask[colour][i]) /* set bit in this plane */
  301.             {
  302.                 s_read = *temp2;
  303.                 s_read |= on_pat[offset];
  304.                 *temp2 = s_read;
  305.                 
  306.                 s_read = *temp;
  307.                 s_read |= on_pat[offset];
  308.                 *temp = s_read;
  309.             }
  310.             else /* have to clear the bit in this plane */
  311.             {
  312.                 s_read = *temp2;
  313.                 s_read &= off_pat[offset];
  314.                 *temp2 = s_read;
  315.                 
  316.                 s_read = *temp;
  317.                 s_read &= off_pat[offset];
  318.                 *temp = s_read;
  319.             }
  320.         }
  321.     }
  322. }
  323.     
  324. void Setupangles(void)
  325. {
  326.     FILE *fp;
  327.     int i, j;
  328.     double d;
  329.     
  330.     if(!(fp=fopen("moretrig.pre","r")))
  331.     {
  332.         printf("Calculating fixed point sin/cos\n");
  333.         
  334.         for(i=0; i<=359; i++)
  335.         {
  336.             d = sin(deg(i))*1000;
  337.             j = d;
  338.         
  339.             sin_angle[i] = -j;
  340.         
  341.             d = cos(deg(i))*1000;
  342.             j = d;
  343.         
  344.             cos_angle[i] = j;
  345.         
  346.         }
  347.         
  348.         for(i=0; i<=4096; i++)
  349.         {
  350.             double t = i;
  351.             anti_sin[i] = asin(t/4096) * 57.29578;
  352.         }
  353.         
  354.         if(!(fp=fopen("moretrig.pre","w")))
  355.         {
  356.             printf("Failed to save sin/cos data!\n");
  357.             return;
  358.         }
  359.         
  360.         fwrite((void *) &sin_angle[0], sizeof(int), 360, fp);
  361.         fwrite((void *) &cos_angle[0], sizeof(int), 360, fp);
  362.         fwrite((void *) &anti_sin[0], sizeof(int), 4097, fp);
  363.         fclose(fp);
  364.     }
  365.     else
  366.     {
  367.         fread((void *) &sin_angle[0], sizeof(int), 360, fp);
  368.         fread((void *) &cos_angle[0], sizeof(int), 360, fp);
  369.         fread((void *) &anti_sin[0], sizeof(int), 4097, fp);
  370.         fclose(fp);
  371.     }
  372. }
  373.  
  374. void PrintShip(char *name)
  375. {
  376.     struct rastport *temp = rastport;
  377.     rastport = &my_rast_port;
  378.     SetAPen(rastport, 0);
  379.     RectFill(rastport, 129, 183, 189, 243);
  380.     SetAPen(rastport, 11);
  381.     Move(rastport, 132, 215);
  382.     Text(rastport, name, strlen(name));
  383.     rastport = &back_rast_port;
  384.     SetAPen(rastport, 0);
  385.     RectFill(rastport, 129, 183, 189, 243);
  386.     SetAPen(rastport, 11);
  387.     Move(rastport, 132, 215);
  388.     Text(rastport, name, strlen(name));
  389.     rastport = temp;
  390. }
  391.  
  392. void Print2Ship(char *name)
  393. {
  394.     struct rastport *temp = rastport;
  395.     rastport = &my_rast_port;
  396.     SetAPen(rastport, 11);
  397.     Move(rastport, 132, 230);
  398.     Text(rastport, name, strlen(name));
  399.     rastport = &back_rast_port;
  400.     SetAPen(rastport, 11);
  401.     Move(rastport, 132, 230);
  402.     Text(rastport, name, strlen(name));
  403.     rastport = temp;
  404. }
  405.  
  406. void IntroShips(void)
  407. /*
  408. Spins each ship in the game around for a while.
  409. Note the hidden surface bug in the shuttle!
  410. */
  411. {
  412.     int counter = 10, timeout = 0, timeoutlim = 300;
  413.     UBYTE value = 0;
  414.     
  415.     AddNewObject(counter, 4000, 360, 2000);
  416.     PrintShip("Player"); Print2Ship("Ship");
  417.     
  418.     while(value!=FIRE)
  419.     {
  420.         register int i;
  421.         
  422.         value = Joystick();
  423.         
  424.         timeout++;
  425.         
  426.         if(timeout==timeoutlim) /* make it blow up! */
  427.         {
  428.             active_list[0]->i_am_dying = 1;
  429.             active_list[0]->explode = 1;
  430.             StartSound(2);
  431.         }
  432.             
  433.         if(no_objects==0) /* create a new object */
  434.         {
  435.             Delay(100);
  436.             counter--;
  437.             if(counter<0) counter = 10;
  438.             if(counter==9) counter = 7;
  439.             
  440.             switch(counter)
  441.             {
  442.                 case 0: PrintShip("Enemy"); Print2Ship("Missile"); break;
  443.                 case 1: PrintShip("Space"); Print2Ship("Station"); break;
  444.                 case 2: PrintShip("Shuttle"); break;
  445.                 case 3: PrintShip("Krait"); break;
  446.                 case 4: PrintShip("Gecko"); break;
  447.                 case 5: PrintShip("Thargoid"); break;
  448.                 case 6: PrintShip("Cruiser"); break;
  449.                 case 7: PrintShip("Player"); Print2Ship("Missile"); break;
  450.                 case 10: PrintShip("Player"); Print2Ship("Ship"); break;
  451.             }
  452.                 
  453.             KillAllObjects();
  454.             SetUp3d();
  455.             AddNewObject(counter, 4000, 360, 2000);
  456.             timeoutlim = (active_list[0]->numpoints > 10) ? 150 : 300;
  457.             timeout = 0;
  458.         }
  459.         
  460.         for(i=0; i<no_objects; i++)
  461.         {
  462.             register object *obj = active_list[i];
  463.  
  464.             if(!obj->i_am_dying)
  465.                 obj->drawme = 1;
  466.             else
  467.                 continue;
  468.                 
  469.             if(obj->type==EXPLOSION)
  470.             {
  471.                 int rad;
  472.             
  473.                 if(--obj->timeinflight==0)
  474.                 {
  475.                     obj->i_am_dying = 1;
  476.                     break;
  477.                 }
  478.                 
  479.                 rad = getrandom(0,10);
  480.                 
  481.                 if(obj->up_or_down)
  482.                 {
  483.                     if(obj->trans_y<MAX_WORLD_Y-100)
  484.                         obj->trans_y += rad;
  485.                 }
  486.                 else
  487.                 {
  488.                     if(obj->trans_y>100)
  489.                         obj->trans_y -= rad;
  490.                 }
  491.                 
  492.                 if(rad>5)
  493.                     rad = getrandom(1, 6);
  494.                 else
  495.                     rad = -getrandom(1, 6);
  496.                 
  497.                 Rotate_Obj_Rel(obj, rad+2, rad-1, rad+1);
  498.             
  499.                 obj->trans_x += FastCos(obj->velocity, obj->heading);
  500.                 obj->trans_z -= FastSin(obj->velocity, obj->heading);
  501.  
  502.                 if(obj->trans_x<0)
  503.                     obj->trans_x = MAX_WORLD_X;
  504.                 else if(obj->trans_x > MAX_WORLD_X)
  505.                     obj->trans_x = 0;
  506.             
  507.                 if(obj->trans_z<0)
  508.                     obj->trans_z = MAX_WORLD_Z;
  509.                 else if(obj->trans_z>MAX_WORLD_Z)
  510.                     obj->trans_z = 0;
  511.             }
  512.             else
  513.                     Rotate_Obj_Rel(obj, 5, 5, 5);
  514.         }
  515.     
  516.         /* still interactive */
  517.         
  518.         if(value & LEFT)
  519.         {
  520.             U_rot+=2;
  521.             W_rot+=2;
  522.         }
  523.         else if(value & RIGHT)
  524.         {
  525.             U_rot-=2;
  526.             W_rot-=2;
  527.             
  528.         }
  529.  
  530.         if(value & UP)
  531.         {
  532.             if(ey <= MAX_WORLD_Y-Y_OFFSET)
  533.             {
  534.                 UpdateAlt();
  535.                 ey += Y_OFFSET;
  536.             }
  537.         }
  538.         else if(value & DOWN)
  539.         {
  540.             if(ey>0)
  541.             {
  542.                 ey -= Y_OFFSET;
  543.                 UpdateAlt();
  544.             }
  545.         }
  546.  
  547.         if(U_rot>359)
  548.             U_rot-=360;
  549.         else if(U_rot<0)
  550.             U_rot+= 360;
  551.         
  552.         if(W_rot>359)
  553.             W_rot-=360;
  554.         else if(W_rot<0)
  555.             W_rot+= 360;
  556.             
  557.         ux.numer = cos_angle[U_rot];
  558.         uz.numer = sin_angle[U_rot];
  559.         
  560.         wx.numer = cos_angle[W_rot];
  561.         wz.numer = sin_angle[W_rot];
  562.  
  563.         View_Angle = U_rot;
  564.  
  565.         SpinObjCentres();        
  566.         CalculateObjects();
  567.         ClearObjects();
  568.         DisplayObjects();
  569.                 
  570.          if(swapflag)
  571.         {
  572.             rastport = &my_rast_port;
  573.             swapflag = 0;
  574.             WaitBOVP(&my_view_port);
  575.             LoadView(&back_view);
  576.         }
  577.         else
  578.         {
  579.             rastport = &back_rast_port;
  580.             swapflag = 1;
  581.             WaitBOVP(&back_view_port);
  582.             LoadView(&my_view);
  583.         }
  584.     }
  585. }
  586.  
  587. void PrintView(char *name)
  588. {
  589.     register struct rastport *temp = rastport;
  590.     rastport = &my_rast_port;
  591.     SetAPen(rastport, 0);
  592.     RectFill(rastport, 245, 196, 280,210);
  593.     SetAPen(rastport, 11);
  594.     Move(rastport, 245, 206);
  595.     Text(rastport, name, strlen(name));
  596.     rastport = &back_rast_port;
  597.     SetAPen(rastport, 0);
  598.     RectFill(rastport, 245, 196, 280 , 210);
  599.     SetAPen(rastport, 11);
  600.     Move(rastport, 245, 206);
  601.     Text(rastport, name, strlen(name));
  602.     rastport = temp;
  603. }
  604.  
  605. void PrintRot(void)
  606. {
  607.     register struct rastport *temp = rastport;
  608.     register short t = U_rot;
  609.     
  610.     rotate[0] = t / 100;
  611.     t = t - (rotate[0]*100);
  612.     rotate[1] = t / 10;
  613.     t = t - (rotate[1]*10);
  614.  
  615.     rotate[2] = t + '0';
  616.     rotate[0] += '0';
  617.     rotate[1] += '0';
  618.     
  619.     rastport = &my_rast_port;
  620.     SetAPen(rastport, 0);
  621.     RectFill(rastport, 245, 210, 280, 221);
  622.     SetAPen(rastport, 11);
  623.     Move(rastport, 245, 220);
  624.     
  625.     Text(rastport, rotate, 3);
  626.     rastport = &back_rast_port;
  627.     SetAPen(rastport, 0);
  628.     RectFill(rastport, 245, 210, 280 , 221);
  629.     SetAPen(rastport, 11);
  630.     Move(rastport, 245, 220);
  631.     Text(rastport, rotate, 3);
  632.     rastport = temp;
  633. }
  634.  
  635. void Do3d(void)
  636. {
  637.     SetUp3d();
  638.     KillAllObjects();
  639.     
  640.     AddObject("cube.object", FIXED);             
  641.     AddObject("ops_missile.object", ENEMYMISSILE);
  642.     AddObject("missile.object", MYMISSILE);
  643.     AddObject("krait.object", KRAIT);
  644.     AddObject("shuttle.object",SHUTTLE);
  645.     AddObject("gecko.object", GECKO);
  646.     AddObject("thargoid.object", THARGOID);
  647.     AddObject("cruiser.object", MAMBA);
  648.     AddObject("guided.object",GUIDEDMISSILE);
  649.     AddObject("player.object",PLAYER);
  650.     
  651.     SetUpViews();
  652.     SetUpConsole();
  653.     
  654.     player_score = player_scale = last_draw = 0;
  655.     
  656.     Delay(25);
  657.  
  658.     IntroShips();
  659.     
  660.     SetUp3d();
  661.     KillAllObjects();
  662.     loadpic("screen.iff");
  663.  
  664.     /* clear radar area and screen display */    
  665.     {
  666.         struct rastport *temp = rastport;
  667.         rastport = &my_rast_port;
  668.         SetAPen(rastport, 0);
  669.         RectFill(rastport, 129, 183, 189, 243);
  670.         RectFill(rastport, X_MIN, Y_MIN, X_MAX, Y_MAX);
  671.         rastport = &back_rast_port;
  672.         SetAPen(rastport, 0);
  673.         RectFill(rastport, 129, 183, 189, 243);
  674.         RectFill(rastport, X_MIN, Y_MIN, X_MAX, Y_MAX);
  675.         rastport = temp;
  676.     }
  677.  
  678.     ez = 4000;
  679.     player_missiles = 25;
  680.     
  681.     PrintView("Front");
  682.     PrintRot();
  683.  
  684.     while(!am_i_dead)
  685.     {
  686.         register UBYTE value = Joystick();
  687.         register int speed;
  688.         static int fireframe = 21;
  689.         
  690.         fireframe++;
  691.         
  692.         if(value & FIRE)
  693.         {
  694.             if(fireframe>5)
  695.             {
  696.                 int tx = ex + FastCos(150, View_Angle);
  697.                 int tz = ez - FastSin(150, View_Angle);
  698.             
  699.                 AddNewObject(MYMISSILE, tx, ey-100, tz);
  700.                 StartSound(0);
  701.                 fireframe = 0;
  702.             }
  703.         }
  704.                     
  705.         if(value & LEFT)
  706.         {
  707.             U_rot+=2;
  708.             W_rot+=2;
  709.             PrintRot();
  710.         }
  711.         else if(value & RIGHT)
  712.         {
  713.             U_rot-=2;
  714.             W_rot-=2;
  715.             PrintRot();
  716.             
  717.         }
  718.  
  719.         if(value & UP)
  720.         {
  721.             if(ey <= MAX_WORLD_Y-Y_OFFSET)
  722.             {
  723.                 UpdateAlt();
  724.                 ey += Y_OFFSET;
  725.             }
  726.         }
  727.         else if(value & DOWN)
  728.         {
  729.             if(ey>0)
  730.             {
  731.                 ey -= Y_OFFSET;
  732.                 UpdateAlt();
  733.             }
  734.         }
  735.  
  736.         value = Keyboard(); /* read keyboard */
  737.         
  738.         if(value==0x40) /* space, increase speed */
  739.         {
  740.             if(velocity<9)
  741.             {
  742.                 velocity++;
  743.                 UpdateSpeed();
  744.             }
  745.         }
  746.         else if(value==0x41) /* backspace, decrease speed */
  747.         {
  748.             if(velocity)
  749.             {
  750.                 velocity--;
  751.                 UpdateSpeed(); /* only updates if changed */
  752.             }
  753.         }
  754.         else if(value==0x45) /* escape */
  755.             break;
  756.         else if(value==0x19) /* P key, pause */
  757.             while(Keyboard()!=0x16); /* wait for a u key press */
  758.         else if(value==0x50) /* front view */
  759.         {
  760.             PrintView("Front");
  761.             view_mode = 0;
  762.         }
  763.         else if(value==0x51) /* left view */
  764.         {
  765.             PrintView("Left");
  766.             view_mode = 1;
  767.         }
  768.         else if(value==0x52) /* right view */
  769.         {
  770.             PrintView("Right");
  771.             view_mode = 3;
  772.         }
  773.         else if(value==0x53) /* back view */
  774.         {
  775.             PrintView("Rear");
  776.             view_mode = 2;
  777.         }
  778.         else if(value==0x37)
  779.         {
  780.             if(fireframe>5 && player_missiles)
  781.             {
  782.                 int tx = ex + FastCos(150, View_Angle);
  783.                 int tz = ez - FastSin(150, View_Angle);
  784.             
  785.                 AddNewObject(GUIDEDMISSILE, tx, ey-100, tz);
  786.                 StartSound(0);
  787.                 fireframe = 0;
  788.                 player_missiles--;
  789.             }
  790.         }
  791.         
  792.         /* correct rotations in case it went over 360 or under 0 */
  793.         
  794.         if(U_rot>359)
  795.             U_rot-=360;
  796.         else if(U_rot<0)
  797.             U_rot+= 360;
  798.         
  799.         if(W_rot>359)
  800.             W_rot-=360;
  801.         else if(W_rot<0)
  802.             W_rot+= 360;
  803.             
  804.         switch(view_mode)
  805.         {
  806.             case 0: View_Angle = U_rot; break;
  807.             case 1: View_Angle = U_rot + 90; break;
  808.             case 2: View_Angle = U_rot + 180; break;
  809.             case 3: View_Angle = U_rot + 270; break;
  810.         }
  811.         
  812.         if(View_Angle>359) View_Angle -= 360;
  813.         
  814.         View2_Angle = View_Angle - 90;
  815.         
  816.         if(View2_Angle<0) View2_Angle += 360;
  817.         
  818.         ux.numer = cos_angle[View_Angle];
  819.         uz.numer = sin_angle[View_Angle];
  820.         
  821.         wx.numer = cos_angle[View2_Angle];
  822.         wz.numer = sin_angle[View2_Angle];
  823.  
  824.         /* Very simple code to move the ship according to velocity */
  825.         
  826.         speed = velocity * 2;
  827.         ex += FastCos(speed, U_rot);
  828.         ez -= FastSin(speed, U_rot);
  829.         
  830.         /* Keep ship in the world */
  831.         
  832.         if(ex<0)
  833.             ex = MAX_WORLD_X;
  834.         else if(ex>MAX_WORLD_X)
  835.             ex = 0;
  836.             
  837.         if(ez<0)
  838.             ez = MAX_WORLD_Z;
  839.         else if(ez>MAX_WORLD_Z)
  840.             ez = 0;
  841.         
  842.         SpinObjCentres();
  843.         MoveObjects();
  844.         UpdateObjects();
  845.         CalculateObjects();
  846.         ClearObjects();
  847.         UpdateRadar();
  848.         DisplayObjects();
  849.                 
  850.         /* swap views */
  851.         
  852.          if(swapflag)
  853.         {
  854.             rastport = &my_rast_port;
  855.             swapflag = 0;
  856.             WaitBOVP(&my_view_port);
  857.             LoadView(&back_view);
  858.         }
  859.         else
  860.         {
  861.             rastport = &back_rast_port;
  862.             swapflag = 1;
  863.             WaitBOVP(&back_view_port);
  864.             LoadView(&my_view);
  865.         }
  866.     }
  867.     
  868.     if(am_i_dead)
  869.     /*
  870.     A really cool extern death sequence!  Soon the wonder of external
  871.     views won't be confined to the death sequence
  872.     */
  873.     {
  874.         int i;
  875.         
  876.         StartSound(1);
  877.         
  878.         PrintView("Death");
  879.         AddNewObject(PLAYER, ex-100, ey-50, ez-50); /* add a ship then blow it up! */
  880.         active_list[no_objects-1]->i_am_dying = 1;
  881.         active_list[no_objects-1]->explode = 1;
  882.         
  883.         for(i=0; i<30; i++)
  884.         {
  885.             register int px, py, pz, speed;
  886.             
  887.             speed = velocity * 2;
  888.             ex += FastCos(speed, U_rot);
  889.             ez -= FastSin(speed, U_rot);
  890.         
  891.             /* Keep ship in the world */
  892.             
  893.             if(ex<0)
  894.                 ex = MAX_WORLD_X;
  895.             else if(ex>MAX_WORLD_X)
  896.                 ex = 0;
  897.             
  898.             if(ez<0)
  899.                 ez = MAX_WORLD_Z;
  900.             else if(ez>MAX_WORLD_Z)
  901.                 ez = 0;
  902.         
  903.             
  904.             if(ex>(MAX_WORLD_X/2))
  905.                 px = ex - 1000;
  906.             else
  907.                 px = ex + 1000;
  908.             
  909.             py = ey+150;
  910.             
  911.             if(ez>(MAX_WORLD_Y/2))
  912.                 pz = ez - 1000;
  913.             else
  914.                 pz = ez + 1000;
  915.                 
  916.             
  917.             SpinObjCentres();
  918.             
  919.             {
  920.                 int dummy;
  921.                 View_Angle = GetPointAngle(&dummy, px, pz);
  922.             }
  923.             
  924.             View2_Angle = View_Angle - 90;
  925.         
  926.             if(View2_Angle<0) View2_Angle += 360;
  927.         
  928.             ux.numer = cos_angle[View_Angle];
  929.             uz.numer = sin_angle[View_Angle];
  930.         
  931.             wx.numer = cos_angle[View2_Angle];
  932.             wz.numer = sin_angle[View2_Angle];
  933.  
  934.             {
  935.                 register int tempx, tempy, tempz;
  936.                 
  937.                 tempx = ex;
  938.                 tempy = ey;
  939.                 tempz = ez;
  940.                 ex = px;
  941.                 ey = py;
  942.                 ez = pz;
  943.                 
  944.                 
  945.                 MoveObjects();
  946.                 CalculateObjects();
  947.                 ClearObjects();
  948.                 UpdateRadar();
  949.                 DisplayObjects();
  950.                 
  951.                 ex = tempx;
  952.                 ey = tempy;
  953.                 ez = tempz;
  954.             }
  955.                 
  956.             /* swap views */
  957.         
  958.              if(swapflag)
  959.             {
  960.                 rastport = &my_rast_port;
  961.                 swapflag = 0;
  962.                 WaitBOVP(&my_view_port);
  963.                 LoadView(&back_view);
  964.             }
  965.             else
  966.             {
  967.                 rastport = &back_rast_port;
  968.                 swapflag = 1;
  969.                 WaitBOVP(&back_view_port);
  970.                 LoadView(&my_view);
  971.             }
  972.         }
  973.     }
  974.     
  975.     KillAllObjects();
  976.     FreeView();
  977. }
  978.  
  979. /* end of module */
  980.