home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / Source / GPCHAP16 / Starferr2.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-04-29  |  47.3 KB  |  1,843 lines

  1. // STARFERR2.CPP -  Game Engine Demo - STAR FERRET DELUXE!
  2. // try and add stuff!
  3. // remember to compile you need GPDUMB1.CPP, GPDUMB2.CPP and
  4. // DirectX libraries DDRAW.LIB, DSOUND.LIB, DINPUT.LIB,
  5. // DINPUT8.LIB, and WINMM.LIB
  6.  
  7. // INCLUDES ///////////////////////////////////////////////
  8.  
  9. #define WIN32_LEAN_AND_MEAN  
  10. #define INITGUID
  11.  
  12. #include <windows.h>   // include important windows stuff
  13. #include <windowsx.h> 
  14. #include <mmsystem.h>
  15. #include <iostream.h> // include important C/C++ stuff
  16. #include <conio.h>
  17. #include <stdlib.h>
  18. #include <malloc.h>
  19. #include <memory.h>
  20. #include <string.h>
  21. #include <stdarg.h>
  22. #include <stdio.h> 
  23. #include <math.h>
  24. #include <io.h>
  25. #include <fcntl.h>
  26.  
  27. #include <ddraw.h>  // directX includes
  28. #include <dsound.h>
  29. #include <dinput.h>
  30. #include "gpdumb1.h" // game library includes
  31. #include "gpdumb2.h"
  32.  
  33. //#include "mono.h"
  34.  
  35. // DEFINES ////////////////////////////////////////////////
  36.  
  37. // defines for windows 
  38. #define WINDOW_CLASS_NAME "WINXCLASS"  // class name
  39.  
  40. #define WINDOW_WIDTH    64   // size of window
  41. #define WINDOW_HEIGHT   48
  42.  
  43. // star ferret constants
  44.  
  45. // vertical extents of players motion
  46. #define MIN_STARFERRET_Y   300
  47. #define MAX_STARFERRET_Y   (screen_height-40)
  48.  
  49. // weapons defines
  50. #define MAX_PLASMA         8   // max number of plasma pulses
  51.  
  52. #define PLASMA_STATE_OFF   0   // this plasma is dead or off
  53. #define PLASMA_STATE_ON    1   // this one is alive and in flight
  54.  
  55. // starfield defines
  56. #define MAX_STARS          128
  57.  
  58. // asteroid field defines
  59. #define MAX_ROCKS             48
  60. #define ROCK_STATE_OFF        0   // this rock is dead or off
  61. #define ROCK_STATE_ON         1   // this one is alive and in flight
  62.  
  63. #define ROCK_LARGE            0   // sizes of rock
  64. #define ROCK_MEDIUM           1
  65. #define ROCK_SMALL            2
  66.  
  67. // explosion defines 
  68. #define MAX_BURSTS            8
  69. #define BURST_STATE_OFF       0   // this burst is dead or off
  70. #define BURST_STATE_ON        1   // this one is alive
  71.  
  72. // defines for player states
  73. #define PLAYER_STATE_DEAD           0
  74. #define PLAYER_STATE_DYING          1
  75. #define PLAYER_STATE_INVINCIBLE     2
  76. #define PLAYER_STATE_ALIVE          3
  77.  
  78. // sound id's
  79. #define MAX_FIRE_SOUNDS       8
  80. #define MAX_EXPL_SOUNDS       8
  81.  
  82. // PROTOTYPES /////////////////////////////////////////////
  83.  
  84. // game console
  85. int Game_Init(void *parms=NULL);
  86. int Game_Shutdown(void *parms=NULL);
  87. int Game_Main(void *parms=NULL);
  88.  
  89. // helper functions for game logic
  90. void Draw_Info(void);
  91. void Start_Burst(int x, int y, int width, int height, int xv,int yv);
  92. void Draw_Bursts(void);
  93. void Move_Bursts(void);
  94. void Delete_Bursts(void);
  95. void Init_Bursts(void);
  96. void Draw_Rocks(void);
  97. void Start_Rock(int x, int y, int size,int xv, int yv);
  98. void Move_Rocks(void);
  99. void Delete_Rocks(void);
  100. void Init_Rocks(void);
  101. void Fire_Plasma(int x,int y, int vel);
  102. void Draw_Plasma(void);
  103. void Move_Plasma(void);
  104.  
  105. void Delete_Plasma(void);
  106. void Init_Plasma(void);
  107. void Move_Stars(void);
  108. void Draw_Stars(void);
  109. void Init_Stars(void);
  110.  
  111. // TYPES //////////////////////////////////////////////////
  112.  
  113. // used to contain a single star
  114. typedef struct STAR_TYP
  115.     {
  116.     UCHAR color;  
  117.     int x,y;
  118.     int velocity;
  119.     } STAR, *STAR_PTR;
  120.  
  121. // GLOBALS ////////////////////////////////////////////////
  122.  
  123. HWND main_window_handle = NULL; // save the window handle
  124. HINSTANCE main_instance = NULL; // save the instance
  125. char buffer[80];                // used to print text
  126.  
  127. BITMAP_IMAGE background_bmp; // used to hold backgrounds
  128.  
  129. BOB starferret;            // the player 
  130. int moving_up = 0;         // used to track if player is moving up for
  131.                            // various parallax effects
  132. BOB plasma[MAX_PLASMA];    // plasma pulses
  133. BOB rocks[MAX_ROCKS];      // the asteroids
  134. BOB bursts[MAX_BURSTS];    // the explosion bursts
  135.  
  136. int rock_sizes[3] = {96,32,12}; // width X height sizes for scaler
  137.  
  138. STAR stars[MAX_STARS]; // the star field
  139.  
  140. // player state variables
  141. int player_state       = PLAYER_STATE_ALIVE;
  142. int player_score       = 0;  // the score
  143. int player_ships       = 3;  // ships left
  144. int player_damage      = 0;  // damage of player
  145. int player_counter     = 0;  // used for state transition tracking
  146. int player_regen_count = 0; // used to regenerate player
  147.  
  148. // sound id's
  149. int intro_music_id = -1,
  150.     main_music_id  = -1,
  151.     ready_id       = -1,
  152.     engines_id     = -1,
  153.     scream_id      = -1;
  154.  
  155. int expl_ids[MAX_EXPL_SOUNDS] = {-1,-1,-1,-1,-1,-1,-1,-1};
  156. int fire_ids[MAX_FIRE_SOUNDS] = {-1,-1,-1,-1,-1,-1,-1,-1};
  157.  
  158. //MONOPRINT mono;
  159.  
  160. // PROTOTYPES //////////////////////////////////////////////
  161.  
  162. // FUNCTIONS //////////////////////////////////////////////
  163.  
  164. LRESULT CALLBACK WindowProc(HWND hwnd, 
  165.                             UINT msg, 
  166.                             WPARAM wparam, 
  167.                             LPARAM lparam)
  168. {
  169. // this is the main message handler of the system
  170. PAINTSTRUCT    ps;           // used in WM_PAINT
  171. HDC            hdc;       // handle to a device context
  172.  
  173. // what is the message 
  174. switch(msg)
  175.     {    
  176.     case WM_CREATE: 
  177.         {
  178.         // do initialization stuff here
  179.         return(0);
  180.         } break;
  181.  
  182.     case WM_PAINT:
  183.          {
  184.          // start painting
  185.          hdc = BeginPaint(hwnd,&ps);
  186.  
  187.          // end painting
  188.          EndPaint(hwnd,&ps);
  189.          return(0);
  190.         } break;
  191.  
  192.     case WM_DESTROY: 
  193.         {
  194.         // kill the application            
  195.         PostQuitMessage(0);
  196.         return(0);
  197.         } break;
  198.  
  199.     default:break;
  200.  
  201.     } // end switch
  202.  
  203. // process any messages that we didn't take care of 
  204. return (DefWindowProc(hwnd, msg, wparam, lparam));
  205.  
  206. } // end WinProc
  207.  
  208. // WINMAIN ////////////////////////////////////////////////
  209.  
  210. int WINAPI WinMain(    HINSTANCE hinstance,
  211.                     HINSTANCE hprevinstance,
  212.                     LPSTR lpcmdline,
  213.                     int ncmdshow)
  214. {
  215. // this is the winmain function
  216.  
  217. WNDCLASS winclass;    // this will hold the class we create
  218. HWND     hwnd;        // generic window handle
  219. MSG         msg;        // generic message
  220. HDC      hdc;       // generic dc
  221. PAINTSTRUCT ps;     // generic paintstruct
  222.  
  223. // first fill in the window class stucture
  224. winclass.style            = CS_DBLCLKS | CS_OWNDC | 
  225.                           CS_HREDRAW | CS_VREDRAW;
  226. winclass.lpfnWndProc    = WindowProc;
  227. winclass.cbClsExtra        = 0;
  228. winclass.cbWndExtra        = 0;
  229. winclass.hInstance        = hinstance;
  230. winclass.hIcon            = LoadIcon(NULL, IDI_APPLICATION);
  231. winclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  232. winclass.hbrBackground    = (HBRUSH)GetStockObject(BLACK_BRUSH);
  233. winclass.lpszMenuName    = NULL; 
  234. winclass.lpszClassName    = WINDOW_CLASS_NAME;
  235.  
  236. // register the window class
  237. if (!RegisterClass(&winclass))
  238.     return(0);
  239.  
  240. // create the window, note the use of WS_POPUP
  241. if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, // class
  242.                           "WinX Game Console",     // title
  243.                           WS_POPUP | WS_VISIBLE,
  244.                            0,0,       // x,y
  245.                           WINDOW_WIDTH,  // width
  246.                           WINDOW_HEIGHT, // height
  247.                           NULL,       // handle to parent 
  248.                           NULL,       // handle to menu
  249.                           hinstance,// instance
  250.                           NULL)))    // creation parms
  251. return(0);
  252.  
  253. // save the window handle and instance in a global
  254. main_window_handle = hwnd;
  255. main_instance      = hinstance;
  256.  
  257. // perform all game console specific initialization
  258. Game_Init();
  259.  
  260. // enter main event loop
  261. while(1)
  262.     {
  263.     if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  264.         { 
  265.         // test if this is a quit
  266.         if (msg.message == WM_QUIT)
  267.            break;
  268.     
  269.         // translate any accelerator keys
  270.         TranslateMessage(&msg);
  271.  
  272.         // send the message to the window proc
  273.         DispatchMessage(&msg);
  274.         } // end if
  275.     
  276.     // main game processing goes here
  277.     Game_Main();
  278.  
  279.     } // end while
  280.  
  281. // shutdown game and release all resources
  282. Game_Shutdown();
  283.  
  284. // return to Windows like this
  285. return(msg.wParam);
  286.  
  287. } // end WinMain
  288.  
  289.  
  290. ///////////////////////////////////////////////////////////
  291.  
  292. void Init_Stars(void)
  293. {
  294. // this function initializes all the stars in such a way
  295. // that their intensity is proportional to their 
  296. // velocity
  297.  
  298. for (int index=0; index<MAX_STARS; index++)
  299.     {
  300.     // random postion
  301.     stars[index].x = rand()%screen_width;
  302.     stars[index].y = rand()%screen_height;
  303.  
  304.     // select star plane
  305.     int plane = rand()%4; // (1..4)
  306.  
  307.     // based on plane select velocity and color
  308.     stars[index].velocity = -(1 + plane*2);
  309.     stars[index].color = 25 - (plane*3);
  310.  
  311.     } // end for index
  312.  
  313. } // end Init_Stars
  314.  
  315. ///////////////////////////////////////////////////////////
  316.  
  317. void Move_Stars(void)
  318. {
  319. // this function moves all the stars
  320.  
  321. for (int index=0; index<MAX_STARS; index++)
  322.     {
  323.     // translate upward
  324.     if (!moving_up)
  325.        stars[index].y-=stars[index].velocity;
  326.     else
  327.        stars[index].y-=(stars[index].velocity+((moving_up*stars[index].velocity)));
  328.      
  329.     // test for collision with top of screen
  330.     if (stars[index].y >= screen_height)
  331.         stars[index].y-=screen_height;
  332.  
  333.     } // end for index
  334.  
  335. } // end Move_Stars
  336.  
  337. ///////////////////////////////////////////////////////////
  338.  
  339. void Draw_Stars(void)
  340. {
  341. // this function draws all the stars
  342.  
  343. // lock back surface
  344. DD_Lock_Back_Surface();
  345.  
  346. // draw all the stars
  347. for (int index=0; index<MAX_STARS; index++)
  348.     {
  349.     // draw stars 
  350.     Draw_Pixel(stars[index].x,stars[index].y, stars[index].color,back_buffer, back_lpitch);
  351.  
  352.     } // end for index
  353.  
  354. // unlock the secondary surface
  355. DD_Unlock_Back_Surface();
  356.  
  357. } // end Draw_Stars
  358.  
  359. ///////////////////////////////////////////////////////////
  360.  
  361. void Init_Plasma(void)
  362. {
  363. // this function initializes and loads all the plasma 
  364. // weapon pulses
  365.  
  366. // load the plasma imagery 
  367. Load_Bitmap_File(&bitmap8bit, "PLASMA8.BMP");
  368.  
  369.  
  370. #if 1
  371. // now create and load each plasma pulse
  372. for (int pulse=0; pulse<MAX_PLASMA; pulse++)
  373.     {
  374.     // create the bob to hold pulse
  375.     Create_BOB(&plasma[pulse],0,0,16,24,6,
  376.                BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,
  377.                DDSCAPS_SYSTEMMEMORY);
  378.  
  379.     // load animation frames
  380.     for (int frame=0; frame<6; frame++)
  381.          Load_Frame_BOB(&plasma[pulse],&bitmap8bit,frame,frame,0,BITMAP_EXTRACT_MODE_CELL);  
  382.  
  383.     // set animation rate
  384.     Set_Anim_Speed_BOB(&plasma[pulse],1);
  385.  
  386.     // set state to off
  387.     plasma[pulse].state = PLASMA_STATE_OFF;
  388.  
  389.     } // end for pulse
  390. #endif
  391.  
  392. #if 0
  393. // create the first bob
  394. Create_BOB(&plasma[0],0,0,16,24,6,
  395.             BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,
  396.             DDSCAPS_SYSTEMMEMORY);
  397.  
  398. // load animation frames
  399. for (int frame=0; frame<6; frame++)
  400.      Load_Frame_BOB(&plasma[0],&bitmap8bit,frame,frame,0,BITMAP_EXTRACT_MODE_CELL);  
  401.  
  402. // set animation rate
  403. Set_Anim_Speed_BOB(&plasma[0],1);
  404.  
  405. // set state to off
  406. plasma[0].state = PLASMA_STATE_OFF;
  407.  
  408. for (int pulse=1; pulse<MAX_PLASMA; pulse++)
  409.     {
  410.     memcpy(&plasma[pulse], &plasma[0], sizeof(BOB));
  411.     } // end for pulse
  412.  
  413. #endif
  414.  
  415.  
  416. // unload data infile
  417. Unload_Bitmap_File(&bitmap8bit);
  418.  
  419. } // end Init_Plasma
  420.  
  421. ///////////////////////////////////////////////////////////
  422.  
  423. void Delete_Plasma(void)
  424. {
  425. // this function simply deletes all memory and surfaces
  426. // related to the plasma pulses
  427.  
  428. for (int index=0; index<MAX_PLASMA; index++)
  429.     Destroy_BOB(&plasma[index]);
  430.  
  431. } // end Delete_Plasma
  432.  
  433. ///////////////////////////////////////////////////////////
  434.  
  435. void Move_Plasma(void)
  436. {
  437. // this function moves all the plasma pulses and checks for
  438. // collision with the rocks
  439.  
  440. for (int index=0; index<MAX_PLASMA; index++)
  441.     {
  442.     // test if plasma pulse is in flight
  443.     if (plasma[index].state == PLASMA_STATE_ON)
  444.         {
  445.         // move the pulse upward
  446.         Move_BOB(&plasma[index]);
  447.   
  448.         // test for boundaries
  449.         if (plasma[index].y < 0 )
  450.             {
  451.             // kill the pulse
  452.             plasma[index].state = PLASMA_STATE_OFF;
  453.  
  454.             // move to next pulse
  455.             continue;
  456.             } // end if
  457.  
  458.         // test for collision with rocks
  459.  
  460.         for (int rock=0; rock<MAX_ROCKS; rock++)
  461.             {
  462.             if (rocks[rock].state==ROCK_STATE_ON)
  463.                 {
  464.                 // test for collision 
  465.                 if (Collision_Test(plasma[index].x, plasma[index].y, 
  466.                                    plasma[index].width, plasma[index].height,
  467.                                    rocks[rock].x, rocks[rock].y,
  468.                                    rocks[rock].varsI[1], rocks[rock].varsI[1]))
  469.                     {
  470.                     // kill pulse
  471.                     plasma[index].state = PLASMA_STATE_OFF;
  472.   
  473.                     switch(rocks[rock].varsI[0])
  474.                           {
  475.                           case ROCK_LARGE:
  476.                               {
  477.                               // start explosion
  478.                               Start_Burst(plasma[index].x, plasma[index].y, 
  479.                                           68+rand()%12,54+rand()%10,
  480.                                           rocks[rock].xv*.5, rocks[rock].yv*.5);
  481.                                         
  482.                               } break;
  483.  
  484.                           case ROCK_MEDIUM:
  485.                               {
  486.                               // start explosion
  487.                               Start_Burst(plasma[index].x, plasma[index].y, 
  488.                                           52+rand()%10,44+rand()%8,
  489.                                           rocks[rock].xv*.5, rocks[rock].yv*.5);
  490.  
  491.                               } break;
  492.  
  493.                           case ROCK_SMALL:
  494.                               {
  495.  
  496.                               // start explosion
  497.                               Start_Burst(plasma[index].x, plasma[index].y, 
  498.                                           34-4+rand()%8,30-3+rand()%6,
  499.                                           rocks[rock].xv*.5, rocks[rock].yv*.5);
  500.  
  501.                               } break;
  502.                           
  503.                           } // end switch
  504.  
  505.                     // update score
  506.                     player_score+=rocks[rock].varsI[2];
  507.  
  508.                     // test strength of rock, cause damage
  509.                     rocks[rock].varsI[2]-=50;
  510.  
  511.                     // split test
  512.                     if (rocks[rock].varsI[2] > 0 && rocks[rock].varsI[2] < 50)
  513.                         {
  514.                         // test the size of rock
  515.                         switch(rocks[rock].varsI[0])
  516.                         {
  517.                         case ROCK_LARGE:
  518.                             {
  519.                             // split into two medium
  520.                             Start_Rock(rocks[rock].x+rand()%16,rocks[rock].y+rand()%16,
  521.                                        ROCK_MEDIUM,
  522.                                        rocks[rock].xv-2+rand()%4,rocks[rock].yv-2+rand()%4);
  523.                     
  524.                            Start_Rock(rocks[rock].x+rand()%16,rocks[rock].y+rand()%16,
  525.                                        ROCK_MEDIUM,
  526.                                        rocks[rock].xv-2+rand()%4,rocks[rock].yv-2+rand()%4);
  527.                             
  528.                            // throw in a small?
  529.                            if ((rand()%3)==1)
  530.                             Start_Rock(rocks[rock].x+rand()%16,rocks[rock].y+rand()%16,
  531.                                        ROCK_SMALL,
  532.                                        rocks[rock].xv-2+rand()%4,rocks[rock].yv-2+rand()%4);
  533.  
  534.                             // kill the original
  535.                             rocks[rock].state = ROCK_STATE_OFF;     
  536.             
  537.                             } break;
  538.  
  539.                         case ROCK_MEDIUM:
  540.                             {
  541.                             // split into 1 - 3 small
  542.                             int num_rocks = 1+rand()%3;
  543.  
  544.                             for (; num_rocks >=1; num_rocks--)
  545.                                 {
  546.                                 Start_Rock(rocks[rock].x+rand()%8,rocks[rock].y+rand()%8,
  547.                                            ROCK_SMALL,
  548.                                            rocks[rock].xv-2+rand()%4,rocks[rock].yv-2+rand()%4);
  549.  
  550.                                 } // end for num_rocks
  551.                  
  552.                             // kill the original
  553.                             rocks[rock].state = ROCK_STATE_OFF;
  554.  
  555.                             } break;
  556.  
  557.                         case ROCK_SMALL:
  558.                             {
  559.                             // just kill it
  560.                             rocks[rock].state = ROCK_STATE_OFF;
  561.  
  562.                             } break;
  563.  
  564.                         default:break;
  565.  
  566.         
  567.                         } // end switch
  568.  
  569.                         } // end if split
  570.                     else
  571.                     if (rocks[rock].varsI[2] <= 0)
  572.                         {
  573.                         // kill rock
  574.                         rocks[rock].state = ROCK_STATE_OFF;
  575.                         } // end else
  576.  
  577.                     // break out of loop
  578.                     break;
  579.  
  580.                    } // end if collision
  581.                 } // end if rock alive
  582.             } // end for rock
  583.  
  584.       } // end if
  585.  
  586.     } // end for index
  587.  
  588. } // end Move_Plasma
  589.  
  590. ///////////////////////////////////////////////////////////
  591.  
  592. void Draw_Plasma(void)
  593. {
  594. // this function draws all the plasma pulses
  595.  
  596. for (int index=0; index<MAX_PLASMA; index++)
  597.     {
  598.     // test if plasma pulse is in flight
  599.     if (plasma[index].state == PLASMA_STATE_ON)
  600.         {
  601.         // draw the pulse
  602.         Draw_BOB(&plasma[index],lpddsback);
  603.          
  604.         // animate the pulse
  605.         Animate_BOB(&plasma[index]);
  606.  
  607.         } // end if
  608.  
  609.     } // end for index
  610.  
  611. } // end Draw_Plasma
  612.  
  613. ///////////////////////////////////////////////////////////
  614.  
  615. void Fire_Plasma(int x,int y, int vel)
  616. {
  617. // this function fires a plasma pulse at the given starting
  618. // position and velocity, of course, one must be free for 
  619. // this to work
  620.  
  621. // scan for a pulse that is available
  622. for (int index=0; index<MAX_PLASMA; index++)
  623.     {
  624.     // is this one available
  625.       // test if plasma pulse is in flight
  626.     if (plasma[index].state == PLASMA_STATE_OFF)
  627.        {
  628.        // start this one up
  629.        plasma[index].x  = x;
  630.        plasma[index].y  = y;
  631.        plasma[index].yv = -vel;
  632.        plasma[index].curr_frame = 0;
  633.        plasma[index].state =  PLASMA_STATE_ON;
  634.  
  635.        // start sound up
  636.        for (int sound_index=0; sound_index < MAX_FIRE_SOUNDS; sound_index++)
  637.            {
  638.            // test if this sound is playing
  639.            if (Status_Sound(fire_ids[sound_index])==0)
  640.               {
  641.               Play_Sound(fire_ids[sound_index]);
  642.               break;
  643.               } // end if
  644.         
  645.            } // end for sound_index
  646.  
  647.        // later
  648.        return;
  649.  
  650.        } // end if
  651.  
  652.     } // end for
  653.  
  654. } // end Fire_Plasma
  655.  
  656. ///////////////////////////////////////////////////////////
  657.  
  658. void Init_Rocks(void)
  659. {
  660. // this function initializes and loads all the rocks 
  661.  
  662. // load the rocks imagery 
  663. Load_Bitmap_File(&bitmap8bit, "ROCKS8.BMP");
  664.  
  665. // create the first bob
  666. Create_BOB(&rocks[0],0,0,96,96,20,
  667.             BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,
  668.             DDSCAPS_SYSTEMMEMORY);
  669.  
  670. // load animation frames
  671. for (int frame=0; frame < 20; frame++)
  672.      Load_Frame_BOB(&rocks[0],&bitmap8bit,frame,frame%6,frame/6,BITMAP_EXTRACT_MODE_CELL);  
  673.  
  674. // set animation rate
  675. Set_Anim_Speed_BOB(&rocks[0],1+rand()%5);
  676. Set_Vel_BOB(&rocks[0], -4+rand()%8, 4+rand()%4);
  677. Set_Pos_BOB(&rocks[0], rand()%screen_width, rand()%screen_height);
  678.  
  679. // set size of rock
  680. rocks[0].varsI[0] = rand()%3;
  681. rocks[0].varsI[1] = rock_sizes[rocks[0].varsI[0]];
  682.  
  683. // set state to off
  684. rocks[0].state = ROCK_STATE_OFF;
  685.  
  686. for (int rock=1; rock<MAX_ROCKS; rock++)
  687.     {
  688.     memcpy(&rocks[rock], &rocks[0], sizeof(BOB));
  689.  
  690.     // set animation rate
  691.     Set_Anim_Speed_BOB(&rocks[rock],1+rand()%5);
  692.     
  693.     // set velocity
  694.     Set_Vel_BOB(&rocks[rock], -4+rand()%8, 4+rand()%4);
  695.     
  696.     // set position
  697.     Set_Pos_BOB(&rocks[rock], rand()%screen_width, rand()%screen_height);
  698.     
  699.     // set size of rock
  700.     rocks[rock].varsI[0] = rand()%3;
  701.     rocks[rock].varsI[1] = rock_sizes[rocks[rock].varsI[0]];
  702.     } // end for rock
  703.  
  704. // unload data infile
  705. Unload_Bitmap_File(&bitmap8bit);
  706.  
  707. } // end Init_Rocks
  708.  
  709. ///////////////////////////////////////////////////////////
  710.  
  711. void Delete_Rocks(void)
  712. {
  713. // this function simply deletes all memory and surfaces
  714. // related to the rocks pulses
  715.  
  716. for (int index=0; index<MAX_ROCKS; index++)
  717.     Destroy_BOB(&rocks[index]);
  718.  
  719. } // end Delete_Rocks
  720.  
  721. ///////////////////////////////////////////////////////////
  722.  
  723. void Move_Rocks(void)
  724. {
  725. // this function moves all the rocks pulses and checks for
  726. // collision with the rocks
  727.  
  728. for (int index=0; index<MAX_ROCKS; index++)
  729.     {
  730.     // test if rocks pulse is in flight
  731.     if (rocks[index].state == ROCK_STATE_ON)
  732.         {
  733.         // move the rock
  734.         Move_BOB(&rocks[index]);
  735.  
  736.         // add player motion in
  737.         if (moving_up)
  738.             rocks[index].y+=(rocks[index].yv*.5);
  739.  
  740.         // test if rock is off screen
  741.         if (rocks[index].y > screen_height)
  742.            {
  743.            // kill rock and put back on available list
  744.            rocks[index].state = ROCK_STATE_OFF;
  745.            } // end if
  746.         
  747.         // test for collision with rocks
  748.         if (Collision_Test(starferret.x, starferret.y, 
  749.                        starferret.width, starferret.height,
  750.                        rocks[index].x, rocks[index].y,
  751.                        rocks[index].varsI[1], rocks[index].varsI[1]))
  752.         {
  753.         // what size rock did we hit?
  754.  
  755.         switch(rocks[index].varsI[0])
  756.               {
  757.               case ROCK_LARGE:
  758.                    {
  759.                    // start explosion
  760.                    Start_Burst(rocks[index].x, rocks[index].y, 
  761.                                68+rand()%12,54+rand()%10,
  762.                                rocks[index].xv*.5, rocks[index].yv*.5);
  763.                    
  764.                     // update players damage
  765.                     player_damage+=50;
  766.  
  767.                     } break;
  768.  
  769.                case ROCK_MEDIUM:
  770.                     {
  771.                     // start explosion
  772.                     Start_Burst(rocks[index].x, rocks[index].y, 
  773.                                 52+rand()%10,44+rand()%8,
  774.                                 rocks[index].xv*.5, rocks[index].yv*.5);
  775.  
  776.                     // update players damage
  777.                     player_damage+=20;
  778.  
  779.                     } break;
  780.  
  781.                 case ROCK_SMALL:
  782.                      {
  783.                      // start explosion
  784.                      Start_Burst(rocks[index].x, rocks[index].y, 
  785.                                  34-4+rand()%8,30-3+rand()%6,
  786.                                  rocks[index].xv*.5, rocks[index].yv*.5);
  787.  
  788.                       // update players damage
  789.                       player_damage+=10;
  790.  
  791.                       } break;
  792.                           
  793.                 } // end switch
  794.  
  795.                 // update score
  796.                 player_score+=rocks[index].varsI[2];
  797.  
  798.                 // kill the original
  799.                 rocks[index].state = ROCK_STATE_OFF;     
  800.  
  801.             } // end if collision
  802.  
  803.         } // end if rock
  804.  
  805.     } // end for index
  806.  
  807. // now test if it's time to add a new rock to the list
  808. if ((rand()%6)==3 && player_state == PLAYER_STATE_ALIVE)
  809.    {
  810.    // scan for a rock to initialize
  811.    for (index=0; index<MAX_ROCKS; index++)
  812.        {
  813.        // is this rock available?
  814.        if (rocks[index].state == ROCK_STATE_OFF)
  815.           {
  816.           // set animation rate
  817.           Set_Anim_Speed_BOB(&rocks[index],1+rand()%5);
  818.     
  819.           // set velocity
  820.           Set_Vel_BOB(&rocks[index], -4+rand()%8, 4+rand()%12);
  821.     
  822.           // set position
  823.           Set_Pos_BOB(&rocks[index], rand()%screen_width, -128);
  824.     
  825.           // set size of rock
  826.           rocks[index].varsI[0] = rand()%3;
  827.           rocks[index].varsI[1] = rock_sizes[rocks[index].varsI[0]];
  828.           
  829.           // set strength of rock
  830.           switch(rocks[index].varsI[0])
  831.                 {
  832.                 case ROCK_LARGE:
  833.                      {
  834.                      // set hardness of rock
  835.                      rocks[index].varsI[2] = 100+rand()%100;
  836.                      } break;
  837.  
  838.                 case ROCK_MEDIUM:
  839.                      {
  840.                      // set hardness of rock
  841.                      rocks[index].varsI[2] = 40 + rand()%30;
  842.                      } break;     
  843.  
  844.                 case ROCK_SMALL:
  845.                      {
  846.                      // set hardness of rock
  847.                      rocks[index].varsI[2] = 10;
  848.                      } break;
  849.  
  850.                 default:break;
  851.  
  852.                 } // end switch
  853.  
  854.           // turn rock on
  855.           rocks[index].state = ROCK_STATE_ON;
  856.           
  857.           // later
  858.           return;
  859.  
  860.           } // end if
  861.  
  862.        } // end for index
  863.  
  864.    } // end if
  865.  
  866. } // end Move_Rocks
  867.  
  868. ///////////////////////////////////////////////////////////
  869.  
  870. void Start_Rock(int x, int y, int size,int xv, int yv)
  871. {
  872. // this functions starts a rock up with the sent parms, considering
  873. // there is one left
  874.  
  875. // scan for a rock to initialize
  876.    for (int index=0; index<MAX_ROCKS; index++)
  877.        {
  878.        // is this rock available?
  879.        if (rocks[index].state == ROCK_STATE_OFF)
  880.           {
  881.           // set animation rate
  882.           Set_Anim_Speed_BOB(&rocks[index],1+rand()%5);
  883.     
  884.           // set velocity
  885.           Set_Vel_BOB(&rocks[index], xv,yv);
  886.     
  887.           // set position
  888.           Set_Pos_BOB(&rocks[index], x,y);
  889.     
  890.           // set size of rock
  891.           rocks[index].varsI[0] = size;
  892.           rocks[index].varsI[1] = rock_sizes[rocks[index].varsI[0]];
  893.           
  894.           // set strength of rock
  895.           switch(rocks[index].varsI[0])
  896.                 {
  897.                 case ROCK_LARGE:
  898.                      {
  899.                      // set hardness of rock
  900.                      rocks[index].varsI[2] = 100+rand()%100;
  901.                      } break;
  902.  
  903.                 case ROCK_MEDIUM:
  904.                      {
  905.                      // set hardness of rock
  906.                      rocks[index].varsI[2] = 40 + rand()%30;
  907.                      } break;     
  908.  
  909.                 case ROCK_SMALL:
  910.                      {
  911.                      // set hardness of rock
  912.                      rocks[index].varsI[2] = 10;
  913.                      } break;
  914.  
  915.                 default:break;
  916.  
  917.                 } // end switch
  918.  
  919.           // turn rock on
  920.           rocks[index].state = ROCK_STATE_ON;
  921.           
  922.           // later
  923.           return;
  924.  
  925.           } // end if
  926.  
  927.        } // end for index
  928.  
  929. } // end Start_Rock
  930.  
  931. ///////////////////////////////////////////////////////////
  932.  
  933. void Draw_Rocks(void)
  934. {
  935. // this function draws all the rocks 
  936.  
  937. for (int index=0; index<MAX_ROCKS; index++)
  938.     {
  939.     // test if rocks pulse is in flight
  940.     if (rocks[index].state == ROCK_STATE_ON)
  941.         {
  942.  
  943.         if (rocks[index].varsI[0]!=ROCK_LARGE)
  944.             {
  945.             // draw the rock scaled
  946.             Draw_Scaled_BOB(&rocks[index],
  947.                             rocks[index].varsI[1],rocks[index].varsI[1],
  948.                             lpddsback);
  949.             }
  950.         else // draw normal
  951.            Draw_BOB(&rocks[index],lpddsback);
  952.          
  953.         // animate the pulse
  954.         Animate_BOB(&rocks[index]);
  955.  
  956.         } // end if
  957.  
  958.     } // end for index
  959.  
  960. } // end Draw_Rocks
  961.  
  962. ///////////////////////////////////////////////////////////
  963.  
  964. void Init_Bursts(void)
  965. {
  966. // this function initializes and loads all the bursts 
  967.  
  968. // load the bursts imagery 
  969. Load_Bitmap_File(&bitmap8bit, "EXPL8.BMP");
  970.  
  971. // create the first bob
  972. Create_BOB(&bursts[0],0,0,42,36,14,
  973.             BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,
  974.             DDSCAPS_SYSTEMMEMORY);
  975.  
  976. // load animation frames
  977. for (int frame=0; frame < 14; frame++)
  978.      Load_Frame_BOB(&bursts[0],&bitmap8bit,frame,frame%6,frame/6,BITMAP_EXTRACT_MODE_CELL);  
  979.  
  980. // set animation rate
  981. Set_Anim_Speed_BOB(&bursts[0],1);
  982.  
  983. // set size of burst
  984. bursts[0].varsI[0] = bursts[0].width;
  985. bursts[0].varsI[1] = bursts[0].height;
  986.  
  987. // set state to off
  988. bursts[0].state = BURST_STATE_OFF;
  989.  
  990. for (int burst=1; burst<MAX_BURSTS; burst++)
  991.     {
  992.     memcpy(&bursts[burst], &bursts[0], sizeof(BOB));
  993.     } // end for burst
  994.  
  995. // unload data infile
  996. Unload_Bitmap_File(&bitmap8bit);
  997.  
  998. } // end Init_Bursts
  999.  
  1000. ///////////////////////////////////////////////////////////
  1001.  
  1002. void Delete_Bursts(void)
  1003. {
  1004. // this function simply deletes all memory and surfaces
  1005. // related to the bursts pulses
  1006.  
  1007. for (int index=0; index < MAX_BURSTS; index++)
  1008.     Destroy_BOB(&bursts[index]);
  1009.  
  1010. } // end Delete_Bursts
  1011.  
  1012. ///////////////////////////////////////////////////////////
  1013.  
  1014. void Move_Bursts(void)
  1015. {
  1016. // this function moves all the bursts 
  1017.  
  1018. for (int index=0; index<MAX_BURSTS; index++)
  1019.     {
  1020.     // test if bursts pulse is in moving
  1021.     if (bursts[index].state == BURST_STATE_ON)
  1022.        {
  1023.        // move the burst
  1024.        Move_BOB(&bursts[index]);
  1025.  
  1026.         // add player motion in
  1027.         if (moving_up)
  1028.             bursts[index].y+=(bursts[index].yv*.5);
  1029.  
  1030.         // test if burst is off screen or done with animation
  1031.         if ((bursts[index].y > screen_height) || bursts[index].curr_frame >= bursts[index].num_frames-1) 
  1032.            {
  1033.            // kill burst and put back on available list
  1034.            bursts[index].state = BURST_STATE_OFF;
  1035.            } // end if
  1036.         
  1037.         } // end if
  1038.  
  1039.     } // end for index
  1040.  
  1041. } // end Move_Bursts
  1042.  
  1043. ///////////////////////////////////////////////////////////
  1044.  
  1045. void Draw_Bursts(void)
  1046. {
  1047. // this function draws all the bursts 
  1048. for (int index=0; index<MAX_BURSTS; index++)
  1049.     {
  1050.     // test if bursts pulse is in flight
  1051.     if (bursts[index].state == BURST_STATE_ON)
  1052.         {
  1053.         if (bursts[index].varsI[0]!=bursts[index].width || 
  1054.             bursts[index].varsI[1]!=bursts[index].height)
  1055.             {
  1056.             // draw the burst scaled
  1057.             Draw_Scaled_BOB(&bursts[index],
  1058.                             bursts[index].varsI[0],bursts[index].varsI[1],
  1059.                             lpddsback);
  1060.             }
  1061.         else // draw normal
  1062.            Draw_BOB(&bursts[index],lpddsback);
  1063.          
  1064.         // animate the explosion
  1065.         Animate_BOB(&bursts[index]);
  1066.  
  1067.         } // end if
  1068.  
  1069.     } // end for index
  1070.  
  1071. } // end Draw_Bursts
  1072.  
  1073. ///////////////////////////////////////////////////////////
  1074.  
  1075. void Start_Burst(int x, int y, int width, int height, int xv,int yv)
  1076. {
  1077. // this function starts a burst up
  1078.  
  1079. // now test if it's time to add a new burst to the list
  1080.  
  1081. // scan for a burst to initialize
  1082. for (int index=0; index<MAX_BURSTS; index++)
  1083.     {
  1084.     // is this burst available?
  1085.     if (bursts[index].state == BURST_STATE_OFF)
  1086.        {
  1087.        // set animation rate
  1088.        Set_Anim_Speed_BOB(&bursts[index],1);
  1089.        bursts[index].curr_frame = 0;
  1090.     
  1091.        // set velocity
  1092.        Set_Vel_BOB(&bursts[index], xv,yv);
  1093.     
  1094.        // set position
  1095.        Set_Pos_BOB(&bursts[index], x,y);
  1096.     
  1097.        // set size of burst
  1098.        bursts[index].varsI[0] = width;
  1099.        bursts[index].varsI[1] = height;
  1100.  
  1101.        // turn burst on
  1102.        bursts[index].state = BURST_STATE_ON;
  1103.  
  1104.        // start sound up
  1105.        for (int sound_index=0; sound_index < MAX_EXPL_SOUNDS; sound_index++)
  1106.            {
  1107.            // test if this sound is playing
  1108.            if (Status_Sound(expl_ids[sound_index])==0)
  1109.               {
  1110.               Play_Sound(expl_ids[sound_index]);
  1111.               break;
  1112.               } // end if
  1113.         
  1114.            } // end for sound_index       
  1115.  
  1116.        // later
  1117.        return;
  1118.  
  1119.        } // end if
  1120.  
  1121.     } // end for index
  1122.  
  1123. } // end Start_Burst
  1124.  
  1125. ///////////////////////////////////////////////////////////
  1126.  
  1127. void Draw_Info(void)
  1128. {
  1129. // this function draws all the information at the top of the screen
  1130.  
  1131. char score[16]; // hold score
  1132. static int red_glow = 0; // used for damage display
  1133.  
  1134. // build up scrore string
  1135. sprintf(score,"0000000%d",player_score);
  1136.  
  1137. // build up final string
  1138. sprintf(buffer,"SCORE %s",&score[strlen(score)-8]);
  1139. Draw_Text_GDI(buffer,10,10,RGB(0,255,0),lpddsback);
  1140.  
  1141. // draw damage
  1142. sprintf(buffer,"DAMAGE %d%%",player_damage);
  1143.  
  1144. if (player_damage < 90)
  1145.    Draw_Text_GDI(buffer,320-8*strlen(buffer),10,RGB(0,255,0),lpddsback);
  1146. else
  1147.   Draw_Text_GDI(buffer,320-8*strlen(buffer),10,RGB(red_glow,0,0),lpddsback);
  1148.  
  1149. // update red glow
  1150. if ((red_glow+=15) > 255)
  1151.    red_glow = 0;
  1152.  
  1153. // draw ships
  1154. sprintf(buffer,"SHIPS %d",player_ships);
  1155. Draw_Text_GDI(buffer,500,10,RGB(0,255,0),lpddsback);
  1156.  
  1157. } // end Draw_Info
  1158.  
  1159. ///////////////////////////////////////////////////////////
  1160.  
  1161. void Do_Intro(void)
  1162. {
  1163. // the worlds simples intro
  1164.  
  1165. int shade; // used as looping var
  1166.  
  1167. // load bitmap into primary buffer
  1168. Load_Bitmap_File(&bitmap8bit, "STARSB8.BMP");
  1169. Create_Bitmap(&background_bmp,0,0,640,480);
  1170. Load_Image_Bitmap(&background_bmp, &bitmap8bit,0,0,BITMAP_EXTRACT_MODE_CELL);
  1171. DD_Lock_Primary_Surface();
  1172. Draw_Bitmap(&background_bmp,primary_buffer, primary_lpitch, 0);
  1173. DD_Unlock_Primary_Surface();
  1174. Unload_Bitmap_File(&bitmap8bit);
  1175. Destroy_Bitmap(&background_bmp);
  1176.  
  1177. for (shade=0; shade < 256; shade++)
  1178.     {
  1179.     // draw text in shades
  1180.     Draw_Text_GDI("DUMB GAMES INC.",320-4*strlen("DUMB GAMES INC."),200,
  1181.                    RGB(shade,shade,shade),lpddsprimary);
  1182.     Sleep(2);
  1183.  
  1184.     // is user trying to bail
  1185.     if (KEY_DOWN(VK_ESCAPE))
  1186.         return;
  1187.  
  1188.     } // end for shade
  1189.  
  1190. Sleep(2000);
  1191.  
  1192. for (shade=255; shade >=0; shade--)
  1193.     {
  1194.     // draw text in shades
  1195.     Draw_Text_GDI("DUMB GAMES INC.",320-4*strlen("DUMB GAMES INC."),200,
  1196.                    RGB(0,0,shade),lpddsprimary);
  1197.     Sleep(2);
  1198.  
  1199.      // is user trying to bail
  1200.     if (KEY_DOWN(VK_ESCAPE))
  1201.         return;
  1202.     
  1203.     } // end for shade
  1204.  
  1205. Sleep(1000);
  1206.  
  1207. for (shade=0; shade < 256; shade++)
  1208.     {
  1209.     // draw text in shades
  1210.     Draw_Text_GDI("- PRESENTS -",320-4*strlen("- PRESENTS -"),200,
  1211.                    RGB(shade,shade,shade),lpddsprimary);
  1212.     Sleep(2);
  1213.     
  1214.     // is user trying to bail
  1215.     if (KEY_DOWN(VK_ESCAPE))
  1216.         return;
  1217.  
  1218.     } // end for shade
  1219.  
  1220. Sleep(2000);
  1221.  
  1222. for (shade=255; shade >=0; shade--)
  1223.     {
  1224.     // draw text in shades
  1225.     Draw_Text_GDI("- PRESENTS -",320-4*strlen("- PRESENTS -"),200,
  1226.                    RGB(0,0,shade),lpddsprimary);
  1227.     Sleep(2);
  1228.     
  1229.     // is user trying to bail
  1230.     if (KEY_DOWN(VK_ESCAPE))
  1231.         return;
  1232.  
  1233.     } // end for shade
  1234.  
  1235. Sleep(1000);
  1236.  
  1237. for (shade=0; shade < 256; shade++)
  1238.     {
  1239.     // draw text in shades
  1240.     Draw_Text_GDI("A NECRON PRODUCTION",320-4*strlen("A NECRON PRODUCTION"),200,
  1241.                    RGB(shade,shade,shade),lpddsprimary);
  1242.     Sleep(2);
  1243.     
  1244.     // is user trying to bail
  1245.     if (KEY_DOWN(VK_ESCAPE))
  1246.         return;
  1247.  
  1248.     } // end for shade
  1249.  
  1250. Sleep(1000);
  1251.  
  1252. for (shade=255; shade >=0; shade--)
  1253.     {
  1254.     // draw text in shades
  1255.     Draw_Text_GDI("A NECRON PRODUCTION",320-4*strlen("A NECRON PRODUCTION"),200,
  1256.                    RGB(0,0,shade),lpddsprimary);
  1257.     Sleep(2);
  1258.     
  1259.     // is user trying to bail
  1260.     if (KEY_DOWN(VK_ESCAPE))
  1261.         return;
  1262.  
  1263.     } // end for shade
  1264.  
  1265. Sleep(1000);
  1266.  
  1267. for (shade=0; shade < 256; shade++)
  1268.     {
  1269.     // draw text in shades
  1270.     Draw_Text_GDI("S T A R   F E R R E T   D E L U X E !",320-3*strlen("S T A R   F E R R E T   D E L U X E !"),200,
  1271.                    RGB(shade,shade,shade),lpddsprimary);
  1272.     Sleep(2);
  1273.  
  1274.     // is user trying to bail
  1275.     if (KEY_DOWN(VK_ESCAPE))
  1276.         return;    
  1277.  
  1278.     } // end for shade
  1279.  
  1280. Sleep(2000);
  1281.  
  1282. for (shade=255; shade >=0; shade--)
  1283.     {
  1284.     // draw text in shades
  1285.     Draw_Text_GDI("S T A R   F E R R E T   D E L U X E !",320-3*strlen("S T A R   F E R R E T   D E L U X E !"),200,
  1286.                    RGB(0,0,shade),lpddsprimary);
  1287.     Sleep(2);
  1288.   
  1289.     // is user trying to bail
  1290.     if (KEY_DOWN(VK_ESCAPE))
  1291.         return;  
  1292.  
  1293.     } // end for shade
  1294.  
  1295. Sleep(1500);
  1296.  
  1297. for (shade=0; shade < 256; shade++)
  1298.     {
  1299.     // draw text in shades
  1300.     Draw_Text_GDI("M U S I C  B Y  T O D D  M A S T E N",320-3*strlen("M U S I C  B Y  T O D D  M A S T E N"),200,
  1301.                    RGB(shade,shade,shade),lpddsprimary);
  1302.     Sleep(2);
  1303.  
  1304.     // is user trying to bail
  1305.     if (KEY_DOWN(VK_ESCAPE))
  1306.         return;    
  1307.  
  1308.     } // end for shade
  1309.  
  1310. Sleep(2500);
  1311.  
  1312. for (shade=255; shade >=0; shade--)
  1313.     {
  1314.     // draw text in shades
  1315.     Draw_Text_GDI("M U S I C  B Y  T O D D  M A S T E N",320-3*strlen("M U S I C  B Y  T O D D  M A S T E N"),200,
  1316.                    RGB(0,0,shade),lpddsprimary);
  1317.     Sleep(2);
  1318.   
  1319.     // is user trying to bail
  1320.     if (KEY_DOWN(VK_ESCAPE))
  1321.         return;  
  1322.  
  1323.     } // end for shade
  1324.  
  1325. } // end Do_Intro
  1326.  
  1327. ///////////////////////////////////////////////////////////
  1328.  
  1329. int Load_Sound_Music(void)
  1330. {
  1331. // this function loads all the sounds and music
  1332.  
  1333. // load in intro music
  1334. if ((intro_music_id = Load_WAV("INTRO.WAV"))==-1)
  1335.    return(0);
  1336.     
  1337. // load the main music
  1338. if ((main_music_id = Load_WAV("STARSNG.WAV"))==-1)
  1339.    return(0);
  1340.  
  1341. // load get ready
  1342. if ((ready_id = Load_WAV("READY.WAV"))==-1)
  1343.    return(0);
  1344.  
  1345. // load engines
  1346. if ((engines_id = Load_WAV("ENGINES.WAV"))==-1)
  1347.    return(0);
  1348.  
  1349. // load scream
  1350. if ((scream_id = Load_WAV("SCREAM.WAV"))==-1)
  1351.    return(0);
  1352.  
  1353. // load the explosions sounds
  1354.  
  1355. // these are the two different source masters
  1356. if ((expl_ids[0] = Load_WAV("EXPL1.WAV"))==-1)
  1357.     return(0);
  1358.  
  1359. if ((expl_ids[1] = Load_WAV("EXPL2.WAV"))==-1)
  1360.     return(0);
  1361.  
  1362. // now make copies
  1363. for (int index=2; index < MAX_EXPL_SOUNDS; index++)
  1364.     {
  1365.     // replicate sound
  1366.     expl_ids[index] = Replicate_Sound(expl_ids[rand()%2]);  
  1367.  
  1368.     } // end for index
  1369.  
  1370.  
  1371. // load the plasma weapons sounds
  1372. if ((fire_ids[0] = Load_WAV("PULSE.WAV"))==-1)
  1373.     return(0);
  1374.  
  1375. // now make copies
  1376. for (index=1; index < MAX_FIRE_SOUNDS; index++)
  1377.     {
  1378.     // replicate sound
  1379.     fire_ids[index] = Replicate_Sound(fire_ids[0]);  
  1380.     } // end for index
  1381.  
  1382. // return sucess
  1383. return(1);
  1384.  
  1385. } // end Load_Sound_Music
  1386.  
  1387. // WINX GAME PROGRAMMING CONSOLE FUNCTIONS ////////////////
  1388.  
  1389. int Game_Init(void *parms)
  1390. {
  1391. // this function is where you do all the initialization 
  1392. // for your game
  1393.  
  1394. int index;         // looping var
  1395. char filename[80]; // used to build up files names
  1396.  
  1397. //mono.clear();
  1398. //mono.print("\ndebugger on-line\n");
  1399.  
  1400. // set screen stuff
  1401. screen_width = 640;
  1402. screen_height = 480;
  1403. screen_bpp = 8;
  1404.  
  1405. // initialize directdraw
  1406. DD_Init(screen_width, screen_height, screen_bpp);
  1407.  
  1408. // initialize directsound
  1409. DSound_Init();
  1410.  
  1411. // initialize Directinput
  1412. DInput_Init();
  1413.  
  1414. // initialize all input devices
  1415. DI_Init_Keyboard();
  1416. DI_Init_Joystick(-16,16,-16,16);
  1417. DI_Init_Mouse();
  1418.  
  1419.  
  1420. // load all the sound and music
  1421. Load_Sound_Music();
  1422.  
  1423. // load the starferret ship
  1424. Load_Bitmap_File(&bitmap8bit, "STAR8.BMP");
  1425.  
  1426. // set the palette to background image palette
  1427. Set_Palette(bitmap8bit.palette);
  1428.  
  1429. // now create the starferret
  1430. Create_BOB(&starferret,0,0,56,38,3,
  1431.            BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,
  1432.            DDSCAPS_SYSTEMMEMORY);
  1433.  
  1434. // load star ferret frames
  1435. for (index=0; index<3; index++)
  1436.      Load_Frame_BOB(&starferret,&bitmap8bit,index,index,0,BITMAP_EXTRACT_MODE_CELL);  
  1437.  
  1438. // set position
  1439. Set_Pos_BOB(&starferret,320-starferret.width/2,350);
  1440.  
  1441. // set animation speed
  1442. Set_Anim_Speed_BOB(&starferret,1);
  1443.  
  1444. // unload data infile
  1445. Unload_Bitmap_File(&bitmap8bit);
  1446.  
  1447. // initialize the plasma pulses
  1448. Init_Plasma();
  1449.  
  1450. // initialize all the stars
  1451. Init_Stars();
  1452.  
  1453. // init rocks
  1454. Init_Rocks();
  1455.  
  1456. // init all the explosions
  1457. Init_Bursts();
  1458.  
  1459. // set clipping rectangle to screen extents so objects dont
  1460. // mess up at edges
  1461. RECT screen_rect = {0,0,screen_width,screen_height};
  1462. lpddclipper = DD_Attach_Clipper(lpddsback,1,&screen_rect);
  1463.  
  1464. // seed random number generate
  1465. srand(Start_Clock());
  1466.  
  1467. // hide the mouse
  1468. ShowCursor(FALSE);
  1469.  
  1470. // start the intro music
  1471. Play_Sound(intro_music_id);
  1472.  
  1473. // do the introdcution
  1474. Do_Intro();
  1475.  
  1476. // start the music
  1477. Play_Sound(main_music_id, DSBPLAY_LOOPING);
  1478.  
  1479. // return success
  1480. return(1);
  1481.  
  1482. } // end Game_Init
  1483.  
  1484. ///////////////////////////////////////////////////////////
  1485.  
  1486. int Game_Shutdown(void *parms)
  1487. {
  1488. // this function is where you shutdown your game and
  1489. // release all resources that you allocated
  1490.  
  1491. // delete all the explosions
  1492. Delete_Bursts();
  1493.     
  1494. // delete the player
  1495. Destroy_BOB(&starferret);
  1496.  
  1497. // the delete all the rocks
  1498. Delete_Rocks();
  1499.  
  1500. // delete all the plasma pulses
  1501. Delete_Plasma();
  1502.  
  1503. // shutdown directdraw
  1504. DD_Shutdown();
  1505.  
  1506. // unload sounds
  1507. Delete_All_Sounds();
  1508.  
  1509. // shutdown directsound
  1510. DSound_Shutdown();
  1511.  
  1512. // release all input devices
  1513. DI_Release_Keyboard();
  1514. DI_Release_Joystick();
  1515. DI_Release_Mouse();
  1516.  
  1517. // return success
  1518. return(1);
  1519. } // end Game_Shutdown
  1520.  
  1521. ///////////////////////////////////////////////////////////
  1522.  
  1523. int Game_Main(void *parms)
  1524. {
  1525. // this is the workhorse of your game it will be called
  1526. // continuously in real-time this is like main() in C
  1527. // all the calls for you game go here!
  1528.  
  1529. static int ready_counter = 0, // used to draw a little "get ready"
  1530.            ready_state   = 0;
  1531.  
  1532. int  index;             // looping var
  1533. int  dx,dy;             // general deltas used in collision detection
  1534.  
  1535. // start the timing clock
  1536. Start_Clock();
  1537.  
  1538. // reset upward motion flag
  1539. moving_up = 0;
  1540.  
  1541. // clear the drawing surface
  1542. DD_Fill_Surface(lpddsback, 0);
  1543.  
  1544. // read all input devices
  1545. DI_Read_Keyboard();
  1546. DI_Read_Mouse();
  1547. DI_Read_Joystick();
  1548.  
  1549. // only process player if alive
  1550. if (player_state == PLAYER_STATE_ALIVE)
  1551. {
  1552.  
  1553. // test if player is moving
  1554. if (keyboard_state[DIK_RIGHT])
  1555.     {
  1556.     // move player to right
  1557.     starferret.x+=8;
  1558.  
  1559.     } // end if
  1560. else
  1561. if (keyboard_state[DIK_LEFT])
  1562.     {
  1563.     // move player to left
  1564.     starferret.x-=8;
  1565.  
  1566.     } // end if
  1567.  
  1568. // vertical/speed motion
  1569. if (keyboard_state[DIK_UP])
  1570.     {
  1571.     // move player up
  1572.     starferret.y-=4;
  1573.  
  1574.     // set upward motion flag
  1575.     moving_up = 1;
  1576.  
  1577.     // change engine freq
  1578.     Set_Sound_Freq(engines_id, 16000);
  1579.  
  1580.     } // end if
  1581.  
  1582. if (keyboard_state[DIK_DOWN])
  1583.     {
  1584.     // move player to left
  1585.     starferret.y+=2;
  1586.  
  1587.     } // end if
  1588.  
  1589.  
  1590. // merge mouse input
  1591. starferret.x+=mouse_state.lX;
  1592. starferret.y+=mouse_state.lY;
  1593.  
  1594. // merge joystick input
  1595. starferret.x+=joy_state.lX;
  1596. starferret.y+=joy_state.lY;
  1597.  
  1598. // test upward joystick component
  1599. if (joy_state.lY < 0) 
  1600.     {
  1601.     moving_up = 1; // set upward motion flag
  1602.  
  1603.     // change engine freq
  1604.     Set_Sound_Freq(engines_id, 16000);
  1605.     } // end if
  1606.  
  1607. // turn the engines down
  1608. if (!keyboard_state[DIK_UP] && joy_state.lY >=0)
  1609.    {
  1610.    // change engine freq
  1611.    Set_Sound_Freq(engines_id, 11000);
  1612.    } // end if
  1613.  
  1614. // test if player is firing
  1615. if (keyboard_state[DIK_LCONTROL] || keyboard_state[DIK_SPACE] || 
  1616.     mouse_state.rgbButtons[0] || joy_state.rgbButtons[0])
  1617.    Fire_Plasma(starferret.x+28-8,starferret.y-8,16);
  1618.  
  1619. // apply friction, or downward motion
  1620. starferret.y++;
  1621.  
  1622. // do bounds check
  1623.  
  1624. // first vertical axis
  1625. if (starferret.y < MIN_STARFERRET_Y)
  1626.    starferret.y = MIN_STARFERRET_Y;
  1627. else
  1628. if (starferret.y > MAX_STARFERRET_Y)
  1629.    starferret.y = MAX_STARFERRET_Y;
  1630.  
  1631. // now horizontal axis
  1632. if (starferret.x < 0)
  1633.    starferret.x = 0;
  1634. else
  1635. if (starferret.x > (screen_width - starferret.width))
  1636.    starferret.x = (screen_width - starferret.width);
  1637.  
  1638. // animate player
  1639. Animate_BOB(&starferret);
  1640.  
  1641. // regenerate player
  1642. if (++player_regen_count > 60)
  1643.     {
  1644.     // reset regen counter
  1645.     player_regen_count=0;
  1646.  
  1647.     // regenerate healt a bit
  1648.     if (player_damage > 0)
  1649.         player_damage--;
  1650.     
  1651.     } // end if
  1652.  
  1653. // test for dying state transition
  1654. if (player_damage >= 100)
  1655.     {
  1656.     // set damage to 100
  1657.     player_damage = 100;
  1658.  
  1659.     // kill player
  1660.     player_state = PLAYER_STATE_DYING;
  1661.     player_ships--;
  1662.  
  1663.     // set counter to 0
  1664.     player_counter = 0;
  1665.     
  1666.     // start scream
  1667.     Play_Sound(scream_id);
  1668.  
  1669.     } // end if
  1670.  
  1671. } // end if player alive
  1672. else
  1673. if (player_state == PLAYER_STATE_DYING)
  1674.    { 
  1675.    // player is dying
  1676.  
  1677.    // start random bursts
  1678.    float bwidth  = 16 + rand()%64;
  1679.    float bheight = bwidth*1.16;
  1680.  
  1681.    if ((rand()%4)==1)
  1682.         Start_Burst(starferret.x-16+rand()%40, starferret.y-64+rand()%8,
  1683.                    (int)bwidth,(int)bheight, 
  1684.                    -4+rand()%8,2+rand()%4);    
  1685.  
  1686.    // bumb ship around
  1687.    starferret.x-=(-3+rand()%6);
  1688.    starferret.y-=(-3+rand()%6);
  1689.  
  1690.    // update state counter
  1691.    if (++player_counter > 100)
  1692.       {
  1693.       // set state to invincible  
  1694.       player_state = PLAYER_STATE_INVINCIBLE;
  1695.  
  1696.       // reset counter
  1697.       player_counter = 0;
  1698.  
  1699.       // reset damage
  1700.       player_damage = 0;
  1701.  
  1702.       // set position
  1703.       Set_Pos_BOB(&starferret,320-starferret.width/2,350);
  1704.     
  1705.       } // end if
  1706.  
  1707.    } // end if
  1708. else
  1709. if (player_state == PLAYER_STATE_INVINCIBLE)
  1710.    {
  1711.    // player is invincible
  1712.    
  1713.    // update state counter
  1714.    if (++player_counter > 70)
  1715.       {
  1716.       // set state to invincible  
  1717.       player_state = PLAYER_STATE_ALIVE;
  1718.  
  1719.       // reset counter
  1720.       player_counter = 0;
  1721.  
  1722.       // decrease player ships
  1723.       if (player_ships == 0)
  1724.          {
  1725.          // change state to dead, reset all vars
  1726.          player_state   = PLAYER_STATE_DEAD;
  1727.          player_counter = 0;
  1728.          ready_state    = 1;
  1729.          ready_counter  = 0;
  1730.  
  1731.          // turn engines
  1732.          Stop_Sound(engines_id);
  1733.  
  1734.          } // end if       
  1735.  
  1736.       } // end if
  1737.  
  1738.     // start ready again
  1739.     if ((player_counter == 20) && (player_ships > 0))
  1740.       {
  1741.       // reset to ready
  1742.       ready_counter = 0, 
  1743.       ready_state   = 0;
  1744.       } // end if
  1745.  
  1746.    } // end if
  1747.  
  1748. if (player_state == PLAYER_STATE_DEAD)
  1749.    {
  1750.    // player is dead
  1751.    ready_state   = 1;
  1752.    ready_counter = 0;
  1753.  
  1754.    ////////////////////////////////////////////////////////////////
  1755.  
  1756.    // Y O U  A D D   T H I S   S E C T I O N !!!
  1757.    
  1758.    ////////////////////////////////////////////////////////////////
  1759.  
  1760.     // draw text
  1761.    Draw_Text_GDI("G A M E    O V E R    M A N",
  1762.                  320-6*strlen("G A M E    O V E R    M A N")/2,
  1763.                  200,RGB(255,0,0),lpddsback);
  1764.    } // end if
  1765.  
  1766. // move the plasma
  1767. Move_Plasma();
  1768.  
  1769. // move the asteroids
  1770. Move_Rocks();
  1771.  
  1772. // move the stars
  1773. Move_Stars();
  1774.  
  1775. // move the explosions
  1776. Move_Bursts();
  1777.  
  1778. // draw the tocks
  1779. Draw_Rocks();
  1780.  
  1781. // draw the plasma
  1782. Draw_Plasma();
  1783.  
  1784. // draw the player if alive
  1785. if (player_state == PLAYER_STATE_ALIVE || 
  1786.      (player_state == PLAYER_STATE_DYING && player_counter < 70))
  1787.     {
  1788.     Draw_BOB(&starferret,lpddsback);
  1789.     } // end if
  1790.  
  1791. // draw the stars
  1792. Draw_Stars();
  1793.  
  1794. // draw explosions last
  1795. Draw_Bursts();
  1796.  
  1797. // draw the score and ships left
  1798. Draw_Info();
  1799.  
  1800. // draw get ready?
  1801. if (ready_state==0)
  1802.    {
  1803.    // test if counter is 0 for engines
  1804.    if (ready_counter==0)
  1805.        Play_Sound(engines_id,DSBPLAY_LOOPING);
  1806.  
  1807.    // test if counter is 10 for voice
  1808.    if (ready_counter==10)
  1809.        Play_Sound(ready_id);
  1810.  
  1811.    // draw text
  1812.    Draw_Text_GDI("GET READY!",320-8*strlen("GET READY!")/2, 200,RGB(0,rand()%255,0),lpddsback);
  1813.  
  1814.    // increment counter
  1815.    if (++ready_counter > 60)
  1816.       {
  1817.       // set state to ready
  1818.       ready_state = 1;
  1819.       ready_counter = 0;
  1820.  
  1821.       // stop the intro if not already
  1822.       Stop_Sound(intro_music_id);
  1823.  
  1824.       } // end if
  1825.  
  1826.    } // end if
  1827.  
  1828. // flip the surfaces
  1829. DD_Flip();
  1830.  
  1831. // sync to 30ish fps
  1832. Wait_Clock(30);
  1833.  
  1834. // check of user is trying to exit
  1835. if ((KEY_DOWN(VK_ESCAPE) || keyboard_state[DIK_ESCAPE]) && ready_state)
  1836.     PostMessage(main_window_handle, WM_DESTROY,0,0);
  1837.  
  1838. // return success
  1839. return(1);
  1840.  
  1841. } // end Game_Main
  1842.  
  1843. //////////////////////////////////////////////////////////