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

  1. // STARFERR2_16b.CPP -  16-bit version 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.     int 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.     int shade = rand()%31;
  310.     stars[index].color = _RGB16BIT565(0, shade*2, 0);
  311.  
  312.  
  313.     } // end for index
  314.  
  315. } // end Init_Stars
  316.  
  317. ///////////////////////////////////////////////////////////
  318.  
  319. void Move_Stars(void)
  320. {
  321. // this function moves all the stars
  322.  
  323. for (int index=0; index<MAX_STARS; index++)
  324.     {
  325.     // translate upward
  326.     if (!moving_up)
  327.        stars[index].y-=stars[index].velocity;
  328.     else
  329.        stars[index].y-=(stars[index].velocity+((moving_up*stars[index].velocity)));
  330.      
  331.     // test for collision with top of screen
  332.     if (stars[index].y >= screen_height)
  333.         stars[index].y-=screen_height;
  334.  
  335.     } // end for index
  336.  
  337. } // end Move_Stars
  338.  
  339. ///////////////////////////////////////////////////////////
  340.  
  341. void Draw_Stars(void)
  342. {
  343. // this function draws all the stars
  344.  
  345. // lock back surface
  346. DD_Lock_Back_Surface();
  347.  
  348. // draw all the stars
  349. for (int index=0; index<MAX_STARS; index++)
  350.     {
  351.     // draw stars 
  352.     Draw_Pixel16(stars[index].x,stars[index].y, stars[index].color,back_buffer, back_lpitch);
  353.  
  354.     } // end for index
  355.  
  356. // unlock the secondary surface
  357. DD_Unlock_Back_Surface();
  358.  
  359. } // end Draw_Stars
  360.  
  361. ///////////////////////////////////////////////////////////
  362.  
  363. void Init_Plasma(void)
  364. {
  365. // this function initializes and loads all the plasma 
  366. // weapon pulses
  367.  
  368. // load the plasma imagery 
  369. Load_Bitmap_File(&bitmap16bit, "PLASMA16.BMP");
  370.  
  371.  
  372. #if 1
  373. // now create and load each plasma pulse
  374. for (int pulse=0; pulse<MAX_PLASMA; pulse++)
  375.     {
  376.     // create the bob to hold pulse
  377.     Create_BOB16(&plasma[pulse],0,0,16,24,6,
  378.                BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,
  379.                DDSCAPS_SYSTEMMEMORY);
  380.  
  381.     // load animation frames
  382.     for (int frame=0; frame<6; frame++)
  383.          Load_Frame_BOB16(&plasma[pulse],&bitmap16bit,frame,frame,0,BITMAP_EXTRACT_MODE_CELL);  
  384.  
  385.     // set animation rate
  386.     Set_Anim_Speed_BOB16(&plasma[pulse],1);
  387.  
  388.     // set state to off
  389.     plasma[pulse].state = PLASMA_STATE_OFF;
  390.  
  391.     } // end for pulse
  392. #endif
  393.  
  394. #if 0
  395. // create the first bob
  396. Create_BOB16(&plasma[0],0,0,16,24,6,
  397.             BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,
  398.             DDSCAPS_SYSTEMMEMORY);
  399.  
  400. // load animation frames
  401. for (int frame=0; frame<6; frame++)
  402.      Load_Frame_BOB16(&plasma[0],&bitmap16bit,frame,frame,0,BITMAP_EXTRACT_MODE_CELL);  
  403.  
  404. // set animation rate
  405. Set_Anim_Speed_BOB16(&plasma[0],1);
  406.  
  407. // set state to off
  408. plasma[0].state = PLASMA_STATE_OFF;
  409.  
  410. for (int pulse=1; pulse<MAX_PLASMA; pulse++)
  411.     {
  412.     memcpy(&plasma[pulse], &plasma[0], sizeof(BOB));
  413.     } // end for pulse
  414.  
  415. #endif
  416.  
  417.  
  418. // unload data infile
  419. Unload_Bitmap_File(&bitmap16bit);
  420.  
  421. } // end Init_Plasma
  422.  
  423. ///////////////////////////////////////////////////////////
  424.  
  425. void Delete_Plasma(void)
  426. {
  427. // this function simply deletes all memory and surfaces
  428. // related to the plasma pulses
  429.  
  430. for (int index=0; index<MAX_PLASMA; index++)
  431.     Destroy_BOB16(&plasma[index]);
  432.  
  433. } // end Delete_Plasma
  434.  
  435. ///////////////////////////////////////////////////////////
  436.  
  437. void Move_Plasma(void)
  438. {
  439. // this function moves all the plasma pulses and checks for
  440. // collision with the rocks
  441.  
  442. for (int index=0; index<MAX_PLASMA; index++)
  443.     {
  444.     // test if plasma pulse is in flight
  445.     if (plasma[index].state == PLASMA_STATE_ON)
  446.         {
  447.         // move the pulse upward
  448.         Move_BOB16(&plasma[index]);
  449.   
  450.         // test for boundaries
  451.         if (plasma[index].y < 0 )
  452.             {
  453.             // kill the pulse
  454.             plasma[index].state = PLASMA_STATE_OFF;
  455.  
  456.             // move to next pulse
  457.             continue;
  458.             } // end if
  459.  
  460.         // test for collision with rocks
  461.  
  462.         for (int rock=0; rock<MAX_ROCKS; rock++)
  463.             {
  464.             if (rocks[rock].state==ROCK_STATE_ON)
  465.                 {
  466.                 // test for collision 
  467.                 if (Collision_Test(plasma[index].x, plasma[index].y, 
  468.                                    plasma[index].width, plasma[index].height,
  469.                                    rocks[rock].x, rocks[rock].y,
  470.                                    rocks[rock].varsI[1], rocks[rock].varsI[1]))
  471.                     {
  472.                     // kill pulse
  473.                     plasma[index].state = PLASMA_STATE_OFF;
  474.   
  475.                     switch(rocks[rock].varsI[0])
  476.                           {
  477.                           case ROCK_LARGE:
  478.                               {
  479.                               // start explosion
  480.                               Start_Burst(plasma[index].x, plasma[index].y, 
  481.                                           68+rand()%12,54+rand()%10,
  482.                                           rocks[rock].xv*.5, rocks[rock].yv*.5);
  483.                                         
  484.                               } break;
  485.  
  486.                           case ROCK_MEDIUM:
  487.                               {
  488.                               // start explosion
  489.                               Start_Burst(plasma[index].x, plasma[index].y, 
  490.                                           52+rand()%10,44+rand()%8,
  491.                                           rocks[rock].xv*.5, rocks[rock].yv*.5);
  492.  
  493.                               } break;
  494.  
  495.                           case ROCK_SMALL:
  496.                               {
  497.  
  498.                               // start explosion
  499.                               Start_Burst(plasma[index].x, plasma[index].y, 
  500.                                           34-4+rand()%8,30-3+rand()%6,
  501.                                           rocks[rock].xv*.5, rocks[rock].yv*.5);
  502.  
  503.                               } break;
  504.                           
  505.                           } // end switch
  506.  
  507.                     // update score
  508.                     player_score+=rocks[rock].varsI[2];
  509.  
  510.                     // test strength of rock, cause damage
  511.                     rocks[rock].varsI[2]-=50;
  512.  
  513.                     // split test
  514.                     if (rocks[rock].varsI[2] > 0 && rocks[rock].varsI[2] < 50)
  515.                         {
  516.                         // test the size of rock
  517.                         switch(rocks[rock].varsI[0])
  518.                         {
  519.                         case ROCK_LARGE:
  520.                             {
  521.                             // split into two medium
  522.                             Start_Rock(rocks[rock].x+rand()%16,rocks[rock].y+rand()%16,
  523.                                        ROCK_MEDIUM,
  524.                                        rocks[rock].xv-2+rand()%4,rocks[rock].yv-2+rand()%4);
  525.                     
  526.                            Start_Rock(rocks[rock].x+rand()%16,rocks[rock].y+rand()%16,
  527.                                        ROCK_MEDIUM,
  528.                                        rocks[rock].xv-2+rand()%4,rocks[rock].yv-2+rand()%4);
  529.                             
  530.                            // throw in a small?
  531.                            if ((rand()%3)==1)
  532.                             Start_Rock(rocks[rock].x+rand()%16,rocks[rock].y+rand()%16,
  533.                                        ROCK_SMALL,
  534.                                        rocks[rock].xv-2+rand()%4,rocks[rock].yv-2+rand()%4);
  535.  
  536.                             // kill the original
  537.                             rocks[rock].state = ROCK_STATE_OFF;     
  538.             
  539.                             } break;
  540.  
  541.                         case ROCK_MEDIUM:
  542.                             {
  543.                             // split into 1 - 3 small
  544.                             int num_rocks = 1+rand()%3;
  545.  
  546.                             for (; num_rocks >=1; num_rocks--)
  547.                                 {
  548.                                 Start_Rock(rocks[rock].x+rand()%8,rocks[rock].y+rand()%8,
  549.                                            ROCK_SMALL,
  550.                                            rocks[rock].xv-2+rand()%4,rocks[rock].yv-2+rand()%4);
  551.  
  552.                                 } // end for num_rocks
  553.                  
  554.                             // kill the original
  555.                             rocks[rock].state = ROCK_STATE_OFF;
  556.  
  557.                             } break;
  558.  
  559.                         case ROCK_SMALL:
  560.                             {
  561.                             // just kill it
  562.                             rocks[rock].state = ROCK_STATE_OFF;
  563.  
  564.                             } break;
  565.  
  566.                         default:break;
  567.  
  568.         
  569.                         } // end switch
  570.  
  571.                         } // end if split
  572.                     else
  573.                     if (rocks[rock].varsI[2] <= 0)
  574.                         {
  575.                         // kill rock
  576.                         rocks[rock].state = ROCK_STATE_OFF;
  577.                         } // end else
  578.  
  579.                     // break out of loop
  580.                     break;
  581.  
  582.                    } // end if collision
  583.                 } // end if rock alive
  584.             } // end for rock
  585.  
  586.       } // end if
  587.  
  588.     } // end for index
  589.  
  590. } // end Move_Plasma
  591.  
  592. ///////////////////////////////////////////////////////////
  593.  
  594. void Draw_Plasma(void)
  595. {
  596. // this function draws all the plasma pulses
  597.  
  598. for (int index=0; index<MAX_PLASMA; index++)
  599.     {
  600.     // test if plasma pulse is in flight
  601.     if (plasma[index].state == PLASMA_STATE_ON)
  602.         {
  603.         // draw the pulse
  604.         Draw_BOB16(&plasma[index],lpddsback);
  605.          
  606.         // animate the pulse
  607.         Animate_BOB16(&plasma[index]);
  608.  
  609.         } // end if
  610.  
  611.     } // end for index
  612.  
  613. } // end Draw_Plasma
  614.  
  615. ///////////////////////////////////////////////////////////
  616.  
  617. void Fire_Plasma(int x,int y, int vel)
  618. {
  619. // this function fires a plasma pulse at the given starting
  620. // position and velocity, of course, one must be free for 
  621. // this to work
  622.  
  623. // scan for a pulse that is available
  624. for (int index=0; index<MAX_PLASMA; index++)
  625.     {
  626.     // is this one available
  627.       // test if plasma pulse is in flight
  628.     if (plasma[index].state == PLASMA_STATE_OFF)
  629.        {
  630.        // start this one up
  631.        plasma[index].x  = x;
  632.        plasma[index].y  = y;
  633.        plasma[index].yv = -vel;
  634.        plasma[index].curr_frame = 0;
  635.        plasma[index].state =  PLASMA_STATE_ON;
  636.  
  637.        // start sound up
  638.        for (int sound_index=0; sound_index < MAX_FIRE_SOUNDS; sound_index++)
  639.            {
  640.            // test if this sound is playing
  641.            if (Status_Sound(fire_ids[sound_index])==0)
  642.               {
  643.               Play_Sound(fire_ids[sound_index]);
  644.               break;
  645.               } // end if
  646.         
  647.            } // end for sound_index
  648.  
  649.        // later
  650.        return;
  651.  
  652.        } // end if
  653.  
  654.     } // end for
  655.  
  656. } // end Fire_Plasma
  657.  
  658. ///////////////////////////////////////////////////////////
  659.  
  660. void Init_Rocks(void)
  661. {
  662. // this function initializes and loads all the rocks 
  663.  
  664. // load the rocks imagery 
  665. Load_Bitmap_File(&bitmap16bit, "ROCKS16.BMP");
  666.  
  667. // create the first bob
  668. Create_BOB16(&rocks[0],0,0,96,96,20,
  669.             BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,
  670.             DDSCAPS_SYSTEMMEMORY);
  671.  
  672. // load animation frames
  673. for (int frame=0; frame < 20; frame++)
  674.      Load_Frame_BOB16(&rocks[0],&bitmap16bit,frame,frame%6,frame/6,BITMAP_EXTRACT_MODE_CELL);  
  675.  
  676. // set animation rate
  677. Set_Anim_Speed_BOB16(&rocks[0],1+rand()%5);
  678. Set_Vel_BOB16(&rocks[0], -4+rand()%8, 4+rand()%4);
  679. Set_Pos_BOB16(&rocks[0], rand()%screen_width, rand()%screen_height);
  680.  
  681. // set size of rock
  682. rocks[0].varsI[0] = rand()%3;
  683. rocks[0].varsI[1] = rock_sizes[rocks[0].varsI[0]];
  684.  
  685. // set state to off
  686. rocks[0].state = ROCK_STATE_OFF;
  687.  
  688. for (int rock=1; rock<MAX_ROCKS; rock++)
  689.     {
  690.     memcpy(&rocks[rock], &rocks[0], sizeof(BOB));
  691.  
  692.     // set animation rate
  693.     Set_Anim_Speed_BOB16(&rocks[rock],1+rand()%5);
  694.     
  695.     // set velocity
  696.     Set_Vel_BOB16(&rocks[rock], -4+rand()%8, 4+rand()%4);
  697.     
  698.     // set position
  699.     Set_Pos_BOB16(&rocks[rock], rand()%screen_width, rand()%screen_height);
  700.     
  701.     // set size of rock
  702.     rocks[rock].varsI[0] = rand()%3;
  703.     rocks[rock].varsI[1] = rock_sizes[rocks[rock].varsI[0]];
  704.     } // end for rock
  705.  
  706. // unload data infile
  707. Unload_Bitmap_File(&bitmap16bit);
  708.  
  709. } // end Init_Rocks
  710.  
  711. ///////////////////////////////////////////////////////////
  712.  
  713. void Delete_Rocks(void)
  714. {
  715. // this function simply deletes all memory and surfaces
  716. // related to the rocks pulses
  717.  
  718. for (int index=0; index<MAX_ROCKS; index++)
  719.     Destroy_BOB16(&rocks[index]);
  720.  
  721. } // end Delete_Rocks
  722.  
  723. ///////////////////////////////////////////////////////////
  724.  
  725. void Move_Rocks(void)
  726. {
  727. // this function moves all the rocks pulses and checks for
  728. // collision with the rocks
  729.  
  730. for (int index=0; index<MAX_ROCKS; index++)
  731.     {
  732.     // test if rocks pulse is in flight
  733.     if (rocks[index].state == ROCK_STATE_ON)
  734.         {
  735.         // move the rock
  736.         Move_BOB16(&rocks[index]);
  737.  
  738.         // add player motion in
  739.         if (moving_up)
  740.             rocks[index].y+=(rocks[index].yv*.5);
  741.  
  742.         // test if rock is off screen
  743.         if (rocks[index].y > screen_height)
  744.            {
  745.            // kill rock and put back on available list
  746.            rocks[index].state = ROCK_STATE_OFF;
  747.            } // end if
  748.         
  749.         // test for collision with rocks
  750.         if (Collision_Test(starferret.x, starferret.y, 
  751.                        starferret.width, starferret.height,
  752.                        rocks[index].x, rocks[index].y,
  753.                        rocks[index].varsI[1], rocks[index].varsI[1]))
  754.         {
  755.         // what size rock did we hit?
  756.  
  757.         switch(rocks[index].varsI[0])
  758.               {
  759.               case ROCK_LARGE:
  760.                    {
  761.                    // start explosion
  762.                    Start_Burst(rocks[index].x, rocks[index].y, 
  763.                                68+rand()%12,54+rand()%10,
  764.                                rocks[index].xv*.5, rocks[index].yv*.5);
  765.                    
  766.                     // update players damage
  767.                     player_damage+=50;
  768.  
  769.                     } break;
  770.  
  771.                case ROCK_MEDIUM:
  772.                     {
  773.                     // start explosion
  774.                     Start_Burst(rocks[index].x, rocks[index].y, 
  775.                                 52+rand()%10,44+rand()%8,
  776.                                 rocks[index].xv*.5, rocks[index].yv*.5);
  777.  
  778.                     // update players damage
  779.                     player_damage+=20;
  780.  
  781.                     } break;
  782.  
  783.                 case ROCK_SMALL:
  784.                      {
  785.                      // start explosion
  786.                      Start_Burst(rocks[index].x, rocks[index].y, 
  787.                                  34-4+rand()%8,30-3+rand()%6,
  788.                                  rocks[index].xv*.5, rocks[index].yv*.5);
  789.  
  790.                       // update players damage
  791.                       player_damage+=10;
  792.  
  793.                       } break;
  794.                           
  795.                 } // end switch
  796.  
  797.                 // update score
  798.                 player_score+=rocks[index].varsI[2];
  799.  
  800.                 // kill the original
  801.                 rocks[index].state = ROCK_STATE_OFF;     
  802.  
  803.             } // end if collision
  804.  
  805.         } // end if rock
  806.  
  807.     } // end for index
  808.  
  809. // now test if it's time to add a new rock to the list
  810. if ((rand()%6)==3 && player_state == PLAYER_STATE_ALIVE)
  811.    {
  812.    // scan for a rock to initialize
  813.    for (index=0; index<MAX_ROCKS; index++)
  814.        {
  815.        // is this rock available?
  816.        if (rocks[index].state == ROCK_STATE_OFF)
  817.           {
  818.           // set animation rate
  819.           Set_Anim_Speed_BOB16(&rocks[index],1+rand()%5);
  820.     
  821.           // set velocity
  822.           Set_Vel_BOB16(&rocks[index], -4+rand()%8, 4+rand()%12);
  823.     
  824.           // set position
  825.           Set_Pos_BOB16(&rocks[index], rand()%screen_width, -128);
  826.     
  827.           // set size of rock
  828.           rocks[index].varsI[0] = rand()%3;
  829.           rocks[index].varsI[1] = rock_sizes[rocks[index].varsI[0]];
  830.           
  831.           // set strength of rock
  832.           switch(rocks[index].varsI[0])
  833.                 {
  834.                 case ROCK_LARGE:
  835.                      {
  836.                      // set hardness of rock
  837.                      rocks[index].varsI[2] = 100+rand()%100;
  838.                      } break;
  839.  
  840.                 case ROCK_MEDIUM:
  841.                      {
  842.                      // set hardness of rock
  843.                      rocks[index].varsI[2] = 40 + rand()%30;
  844.                      } break;     
  845.  
  846.                 case ROCK_SMALL:
  847.                      {
  848.                      // set hardness of rock
  849.                      rocks[index].varsI[2] = 10;
  850.                      } break;
  851.  
  852.                 default:break;
  853.  
  854.                 } // end switch
  855.  
  856.           // turn rock on
  857.           rocks[index].state = ROCK_STATE_ON;
  858.           
  859.           // later
  860.           return;
  861.  
  862.           } // end if
  863.  
  864.        } // end for index
  865.  
  866.    } // end if
  867.  
  868. } // end Move_Rocks
  869.  
  870. ///////////////////////////////////////////////////////////
  871.  
  872. void Start_Rock(int x, int y, int size,int xv, int yv)
  873. {
  874. // this functions starts a rock up with the sent parms, considering
  875. // there is one left
  876.  
  877. // scan for a rock to initialize
  878.    for (int index=0; index<MAX_ROCKS; index++)
  879.        {
  880.        // is this rock available?
  881.        if (rocks[index].state == ROCK_STATE_OFF)
  882.           {
  883.           // set animation rate
  884.           Set_Anim_Speed_BOB16(&rocks[index],1+rand()%5);
  885.     
  886.           // set velocity
  887.           Set_Vel_BOB16(&rocks[index], xv,yv);
  888.     
  889.           // set position
  890.           Set_Pos_BOB16(&rocks[index], x,y);
  891.     
  892.           // set size of rock
  893.           rocks[index].varsI[0] = size;
  894.           rocks[index].varsI[1] = rock_sizes[rocks[index].varsI[0]];
  895.           
  896.           // set strength of rock
  897.           switch(rocks[index].varsI[0])
  898.                 {
  899.                 case ROCK_LARGE:
  900.                      {
  901.                      // set hardness of rock
  902.                      rocks[index].varsI[2] = 100+rand()%100;
  903.                      } break;
  904.  
  905.                 case ROCK_MEDIUM:
  906.                      {
  907.                      // set hardness of rock
  908.                      rocks[index].varsI[2] = 40 + rand()%30;
  909.                      } break;     
  910.  
  911.                 case ROCK_SMALL:
  912.                      {
  913.                      // set hardness of rock
  914.                      rocks[index].varsI[2] = 10;
  915.                      } break;
  916.  
  917.                 default:break;
  918.  
  919.                 } // end switch
  920.  
  921.           // turn rock on
  922.           rocks[index].state = ROCK_STATE_ON;
  923.           
  924.           // later
  925.           return;
  926.  
  927.           } // end if
  928.  
  929.        } // end for index
  930.  
  931. } // end Start_Rock
  932.  
  933. ///////////////////////////////////////////////////////////
  934.  
  935. void Draw_Rocks(void)
  936. {
  937. // this function draws all the rocks 
  938.  
  939. for (int index=0; index<MAX_ROCKS; index++)
  940.     {
  941.     // test if rocks pulse is in flight
  942.     if (rocks[index].state == ROCK_STATE_ON)
  943.         {
  944.  
  945.         if (rocks[index].varsI[0]!=ROCK_LARGE)
  946.             {
  947.             // draw the rock scaled
  948.             Draw_Scaled_BOB16(&rocks[index],
  949.                             rocks[index].varsI[1],rocks[index].varsI[1],
  950.                             lpddsback);
  951.             }
  952.         else // draw normal
  953.            Draw_BOB16(&rocks[index],lpddsback);
  954.          
  955.         // animate the pulse
  956.         Animate_BOB16(&rocks[index]);
  957.  
  958.         } // end if
  959.  
  960.     } // end for index
  961.  
  962. } // end Draw_Rocks
  963.  
  964. ///////////////////////////////////////////////////////////
  965.  
  966. void Init_Bursts(void)
  967. {
  968. // this function initializes and loads all the bursts 
  969.  
  970. // load the bursts imagery 
  971. Load_Bitmap_File(&bitmap16bit, "EXPL16.BMP");
  972.  
  973. // create the first bob
  974. Create_BOB16(&bursts[0],0,0,42,36,14,
  975.             BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,
  976.             DDSCAPS_SYSTEMMEMORY);
  977.  
  978. // load animation frames
  979. for (int frame=0; frame < 14; frame++)
  980.      Load_Frame_BOB16(&bursts[0],&bitmap16bit,frame,frame%6,frame/6,BITMAP_EXTRACT_MODE_CELL);  
  981.  
  982. // set animation rate
  983. Set_Anim_Speed_BOB16(&bursts[0],1);
  984.  
  985. // set size of burst
  986. bursts[0].varsI[0] = bursts[0].width;
  987. bursts[0].varsI[1] = bursts[0].height;
  988.  
  989. // set state to off
  990. bursts[0].state = BURST_STATE_OFF;
  991.  
  992. for (int burst=1; burst<MAX_BURSTS; burst++)
  993.     {
  994.     memcpy(&bursts[burst], &bursts[0], sizeof(BOB));
  995.     } // end for burst
  996.  
  997. // unload data infile
  998. Unload_Bitmap_File(&bitmap16bit);
  999.  
  1000. } // end Init_Bursts
  1001.  
  1002. ///////////////////////////////////////////////////////////
  1003.  
  1004. void Delete_Bursts(void)
  1005. {
  1006. // this function simply deletes all memory and surfaces
  1007. // related to the bursts pulses
  1008.  
  1009. for (int index=0; index < MAX_BURSTS; index++)
  1010.     Destroy_BOB16(&bursts[index]);
  1011.  
  1012. } // end Delete_Bursts
  1013.  
  1014. ///////////////////////////////////////////////////////////
  1015.  
  1016. void Move_Bursts(void)
  1017. {
  1018. // this function moves all the bursts 
  1019.  
  1020. for (int index=0; index<MAX_BURSTS; index++)
  1021.     {
  1022.     // test if bursts pulse is in moving
  1023.     if (bursts[index].state == BURST_STATE_ON)
  1024.        {
  1025.        // move the burst
  1026.        Move_BOB16(&bursts[index]);
  1027.  
  1028.         // add player motion in
  1029.         if (moving_up)
  1030.             bursts[index].y+=(bursts[index].yv*.5);
  1031.  
  1032.         // test if burst is off screen or done with animation
  1033.         if ((bursts[index].y > screen_height) || bursts[index].curr_frame >= bursts[index].num_frames-1) 
  1034.            {
  1035.            // kill burst and put back on available list
  1036.            bursts[index].state = BURST_STATE_OFF;
  1037.            } // end if
  1038.         
  1039.         } // end if
  1040.  
  1041.     } // end for index
  1042.  
  1043. } // end Move_Bursts
  1044.  
  1045. ///////////////////////////////////////////////////////////
  1046.  
  1047. void Draw_Bursts(void)
  1048. {
  1049. // this function draws all the bursts 
  1050. for (int index=0; index<MAX_BURSTS; index++)
  1051.     {
  1052.     // test if bursts pulse is in flight
  1053.     if (bursts[index].state == BURST_STATE_ON)
  1054.         {
  1055.         if (bursts[index].varsI[0]!=bursts[index].width || 
  1056.             bursts[index].varsI[1]!=bursts[index].height)
  1057.             {
  1058.             // draw the burst scaled
  1059.             Draw_Scaled_BOB16(&bursts[index],
  1060.                             bursts[index].varsI[0],bursts[index].varsI[1],
  1061.                             lpddsback);
  1062.             }
  1063.         else // draw normal
  1064.            Draw_BOB16(&bursts[index],lpddsback);
  1065.          
  1066.         // animate the explosion
  1067.         Animate_BOB16(&bursts[index]);
  1068.  
  1069.         } // end if
  1070.  
  1071.     } // end for index
  1072.  
  1073. } // end Draw_Bursts
  1074.  
  1075. ///////////////////////////////////////////////////////////
  1076.  
  1077. void Start_Burst(int x, int y, int width, int height, int xv,int yv)
  1078. {
  1079. // this function starts a burst up
  1080.  
  1081. // now test if it's time to add a new burst to the list
  1082.  
  1083. // scan for a burst to initialize
  1084. for (int index=0; index<MAX_BURSTS; index++)
  1085.     {
  1086.     // is this burst available?
  1087.     if (bursts[index].state == BURST_STATE_OFF)
  1088.        {
  1089.        // set animation rate
  1090.        Set_Anim_Speed_BOB16(&bursts[index],1);
  1091.        bursts[index].curr_frame = 0;
  1092.     
  1093.        // set velocity
  1094.        Set_Vel_BOB16(&bursts[index], xv,yv);
  1095.     
  1096.        // set position
  1097.        Set_Pos_BOB16(&bursts[index], x,y);
  1098.     
  1099.        // set size of burst
  1100.        bursts[index].varsI[0] = width;
  1101.        bursts[index].varsI[1] = height;
  1102.  
  1103.        // turn burst on
  1104.        bursts[index].state = BURST_STATE_ON;
  1105.  
  1106.        // start sound up
  1107.        for (int sound_index=0; sound_index < MAX_EXPL_SOUNDS; sound_index++)
  1108.            {
  1109.            // test if this sound is playing
  1110.            if (Status_Sound(expl_ids[sound_index])==0)
  1111.               {
  1112.               Play_Sound(expl_ids[sound_index]);
  1113.               break;
  1114.               } // end if
  1115.         
  1116.            } // end for sound_index       
  1117.  
  1118.        // later
  1119.        return;
  1120.  
  1121.        } // end if
  1122.  
  1123.     } // end for index
  1124.  
  1125. } // end Start_Burst
  1126.  
  1127. ///////////////////////////////////////////////////////////
  1128.  
  1129. void Draw_Info(void)
  1130. {
  1131. // this function draws all the information at the top of the screen
  1132.  
  1133. char score[16]; // hold score
  1134. static int red_glow = 0; // used for damage display
  1135.  
  1136. // build up scrore string
  1137. sprintf(score,"0000000%d",player_score);
  1138.  
  1139. // build up final string
  1140. sprintf(buffer,"SCORE %s",&score[strlen(score)-8]);
  1141. Draw_Text_GDI(buffer,10,10,RGB(0,255,0),lpddsback);
  1142.  
  1143. // draw damage
  1144. sprintf(buffer,"DAMAGE %d%%",player_damage);
  1145.  
  1146. if (player_damage < 90)
  1147.    Draw_Text_GDI(buffer,320-8*strlen(buffer),10,RGB(0,255,0),lpddsback);
  1148. else
  1149.   Draw_Text_GDI(buffer,320-8*strlen(buffer),10,RGB(red_glow,0,0),lpddsback);
  1150.  
  1151. // update red glow
  1152. if ((red_glow+=15) > 255)
  1153.    red_glow = 0;
  1154.  
  1155. // draw ships
  1156. sprintf(buffer,"SHIPS %d",player_ships);
  1157. Draw_Text_GDI(buffer,500,10,RGB(0,255,0),lpddsback);
  1158.  
  1159. } // end Draw_Info
  1160.  
  1161. ///////////////////////////////////////////////////////////
  1162.  
  1163. void Do_Intro(void)
  1164. {
  1165. // the worlds simples intro
  1166.  
  1167. int shade; // used as looping var
  1168.  
  1169. // load bitmap into primary buffer
  1170. Load_Bitmap_File(&bitmap16bit, "STARSB16.BMP");
  1171. Create_Bitmap16(&background_bmp,0,0,640,480);
  1172. Load_Image_Bitmap16(&background_bmp, &bitmap16bit,0,0,BITMAP_EXTRACT_MODE_CELL);
  1173. DD_Lock_Primary_Surface();
  1174. Draw_Bitmap16(&background_bmp,primary_buffer, primary_lpitch, 0);
  1175. DD_Unlock_Primary_Surface();
  1176. Unload_Bitmap_File(&bitmap16bit);
  1177. Destroy_Bitmap16(&background_bmp);
  1178.  
  1179. for (shade=0; shade < 256; shade++)
  1180.     {
  1181.     // draw text in shades
  1182.     Draw_Text_GDI("DUMB GAMES INC.",320-4*strlen("DUMB GAMES INC."),200,
  1183.                    RGB(shade,shade,shade),lpddsprimary);
  1184.     Sleep(2);
  1185.  
  1186.     // is user trying to bail
  1187.     if (KEY_DOWN(VK_ESCAPE))
  1188.         return;
  1189.  
  1190.     } // end for shade
  1191.  
  1192. Sleep(2000);
  1193.  
  1194. for (shade=255; shade >=0; shade--)
  1195.     {
  1196.     // draw text in shades
  1197.     Draw_Text_GDI("DUMB GAMES INC.",320-4*strlen("DUMB GAMES INC."),200,
  1198.                    RGB(0,0,shade),lpddsprimary);
  1199.     Sleep(2);
  1200.  
  1201.      // is user trying to bail
  1202.     if (KEY_DOWN(VK_ESCAPE))
  1203.         return;
  1204.     
  1205.     } // end for shade
  1206.  
  1207. Sleep(1000);
  1208.  
  1209. for (shade=0; shade < 256; shade++)
  1210.     {
  1211.     // draw text in shades
  1212.     Draw_Text_GDI("- PRESENTS -",320-4*strlen("- PRESENTS -"),200,
  1213.                    RGB(shade,shade,shade),lpddsprimary);
  1214.     Sleep(2);
  1215.     
  1216.     // is user trying to bail
  1217.     if (KEY_DOWN(VK_ESCAPE))
  1218.         return;
  1219.  
  1220.     } // end for shade
  1221.  
  1222. Sleep(2000);
  1223.  
  1224. for (shade=255; shade >=0; shade--)
  1225.     {
  1226.     // draw text in shades
  1227.     Draw_Text_GDI("- PRESENTS -",320-4*strlen("- PRESENTS -"),200,
  1228.                    RGB(0,0,shade),lpddsprimary);
  1229.     Sleep(2);
  1230.     
  1231.     // is user trying to bail
  1232.     if (KEY_DOWN(VK_ESCAPE))
  1233.         return;
  1234.  
  1235.     } // end for shade
  1236.  
  1237. Sleep(1000);
  1238.  
  1239. for (shade=0; shade < 256; shade++)
  1240.     {
  1241.     // draw text in shades
  1242.     Draw_Text_GDI("A NECRON PRODUCTION",320-4*strlen("A NECRON PRODUCTION"),200,
  1243.                    RGB(shade,shade,shade),lpddsprimary);
  1244.     Sleep(2);
  1245.     
  1246.     // is user trying to bail
  1247.     if (KEY_DOWN(VK_ESCAPE))
  1248.         return;
  1249.  
  1250.     } // end for shade
  1251.  
  1252. Sleep(1000);
  1253.  
  1254. for (shade=255; shade >=0; shade--)
  1255.     {
  1256.     // draw text in shades
  1257.     Draw_Text_GDI("A NECRON PRODUCTION",320-4*strlen("A NECRON PRODUCTION"),200,
  1258.                    RGB(0,0,shade),lpddsprimary);
  1259.     Sleep(2);
  1260.     
  1261.     // is user trying to bail
  1262.     if (KEY_DOWN(VK_ESCAPE))
  1263.         return;
  1264.  
  1265.     } // end for shade
  1266.  
  1267. Sleep(1000);
  1268.  
  1269. for (shade=0; shade < 256; shade++)
  1270.     {
  1271.     // draw text in shades
  1272.     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,
  1273.                    RGB(shade,shade,shade),lpddsprimary);
  1274.     Sleep(2);
  1275.  
  1276.     // is user trying to bail
  1277.     if (KEY_DOWN(VK_ESCAPE))
  1278.         return;    
  1279.  
  1280.     } // end for shade
  1281.  
  1282. Sleep(2000);
  1283.  
  1284. for (shade=255; shade >=0; shade--)
  1285.     {
  1286.     // draw text in shades
  1287.     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,
  1288.                    RGB(0,0,shade),lpddsprimary);
  1289.     Sleep(2);
  1290.   
  1291.     // is user trying to bail
  1292.     if (KEY_DOWN(VK_ESCAPE))
  1293.         return;  
  1294.  
  1295.     } // end for shade
  1296.  
  1297. Sleep(1500);
  1298.  
  1299. for (shade=0; shade < 256; shade++)
  1300.     {
  1301.     // draw text in shades
  1302.     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,
  1303.                    RGB(shade,shade,shade),lpddsprimary);
  1304.     Sleep(2);
  1305.  
  1306.     // is user trying to bail
  1307.     if (KEY_DOWN(VK_ESCAPE))
  1308.         return;    
  1309.  
  1310.     } // end for shade
  1311.  
  1312. Sleep(2500);
  1313.  
  1314. for (shade=255; shade >=0; shade--)
  1315.     {
  1316.     // draw text in shades
  1317.     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,
  1318.                    RGB(0,0,shade),lpddsprimary);
  1319.     Sleep(2);
  1320.   
  1321.     // is user trying to bail
  1322.     if (KEY_DOWN(VK_ESCAPE))
  1323.         return;  
  1324.  
  1325.     } // end for shade
  1326.  
  1327. } // end Do_Intro
  1328.  
  1329. ///////////////////////////////////////////////////////////
  1330.  
  1331. int Load_Sound_Music(void)
  1332. {
  1333. // this function loads all the sounds and music
  1334.  
  1335. // load in intro music
  1336. if ((intro_music_id = Load_WAV("INTRO.WAV"))==-1)
  1337.    return(0);
  1338.     
  1339. // load the main music
  1340. if ((main_music_id = Load_WAV("STARSNG.WAV"))==-1)
  1341.    return(0);
  1342.  
  1343. // load get ready
  1344. if ((ready_id = Load_WAV("READY.WAV"))==-1)
  1345.    return(0);
  1346.  
  1347. // load engines
  1348. if ((engines_id = Load_WAV("ENGINES.WAV"))==-1)
  1349.    return(0);
  1350.  
  1351. // load scream
  1352. if ((scream_id = Load_WAV("SCREAM.WAV"))==-1)
  1353.    return(0);
  1354.  
  1355. // load the explosions sounds
  1356.  
  1357. // these are the two different source masters
  1358. if ((expl_ids[0] = Load_WAV("EXPL1.WAV"))==-1)
  1359.     return(0);
  1360.  
  1361. if ((expl_ids[1] = Load_WAV("EXPL2.WAV"))==-1)
  1362.     return(0);
  1363.  
  1364. // now make copies
  1365. for (int index=2; index < MAX_EXPL_SOUNDS; index++)
  1366.     {
  1367.     // replicate sound
  1368.     expl_ids[index] = Replicate_Sound(expl_ids[rand()%2]);  
  1369.  
  1370.     } // end for index
  1371.  
  1372.  
  1373. // load the plasma weapons sounds
  1374. if ((fire_ids[0] = Load_WAV("PULSE.WAV"))==-1)
  1375.     return(0);
  1376.  
  1377. // now make copies
  1378. for (index=1; index < MAX_FIRE_SOUNDS; index++)
  1379.     {
  1380.     // replicate sound
  1381.     fire_ids[index] = Replicate_Sound(fire_ids[0]);  
  1382.     } // end for index
  1383.  
  1384. // return sucess
  1385. return(1);
  1386.  
  1387. } // end Load_Sound_Music
  1388.  
  1389. // WINX GAME PROGRAMMING CONSOLE FUNCTIONS ////////////////
  1390.  
  1391. int Game_Init(void *parms)
  1392. {
  1393. // this function is where you do all the initialization 
  1394. // for your game
  1395.  
  1396. int index;         // looping var
  1397. char filename[80]; // used to build up files names
  1398.  
  1399. //mono.clear();
  1400. //mono.print("\ndebugger on-line\n");
  1401.  
  1402. // set screen stuff
  1403. screen_width = 640;
  1404. screen_height = 480;
  1405. screen_bpp = 16;
  1406.  
  1407. // initialize directdraw
  1408. DD_Init(screen_width, screen_height, screen_bpp);
  1409.  
  1410. // initialize directsound
  1411. DSound_Init();
  1412.  
  1413. // initialize Directinput
  1414. DInput_Init();
  1415.  
  1416. // initialize all input devices
  1417. DI_Init_Keyboard();
  1418. DI_Init_Joystick(-16,16,-16,16);
  1419. DI_Init_Mouse();
  1420.  
  1421.  
  1422. // load all the sound and music
  1423. Load_Sound_Music();
  1424.  
  1425. // load the starferret ship
  1426. Load_Bitmap_File(&bitmap16bit, "STAR16.BMP");
  1427.  
  1428. // now create the starferret
  1429. Create_BOB16(&starferret,0,0,56,38,3,
  1430.            BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,
  1431.            DDSCAPS_SYSTEMMEMORY);
  1432.  
  1433. // load star ferret frames
  1434. for (index=0; index<3; index++)
  1435.      Load_Frame_BOB16(&starferret,&bitmap16bit,index,index,0,BITMAP_EXTRACT_MODE_CELL);  
  1436.  
  1437. // set position
  1438. Set_Pos_BOB16(&starferret,320-starferret.width/2,350);
  1439.  
  1440. // set animation speed
  1441. Set_Anim_Speed_BOB16(&starferret,1);
  1442.  
  1443. // unload data infile
  1444. Unload_Bitmap_File(&bitmap16bit);
  1445.  
  1446. // initialize the plasma pulses
  1447. Init_Plasma();
  1448.  
  1449. // initialize all the stars
  1450. Init_Stars();
  1451.  
  1452. // init rocks
  1453. Init_Rocks();
  1454.  
  1455. // init all the explosions
  1456. Init_Bursts();
  1457.  
  1458. // set clipping rectangle to screen extents so objects dont
  1459. // mess up at edges
  1460. RECT screen_rect = {0,0,screen_width,screen_height};
  1461. lpddclipper = DD_Attach_Clipper(lpddsback,1,&screen_rect);
  1462.  
  1463. // seed random number generate
  1464. srand(Start_Clock());
  1465.  
  1466. // hide the mouse
  1467. ShowCursor(FALSE);
  1468.  
  1469. // start the intro music
  1470. Play_Sound(intro_music_id);
  1471.  
  1472. // do the introdcution
  1473. Do_Intro();
  1474.  
  1475. // start the music
  1476. Play_Sound(main_music_id, DSBPLAY_LOOPING);
  1477.  
  1478. // return success
  1479. return(1);
  1480.  
  1481. } // end Game_Init
  1482.  
  1483. ///////////////////////////////////////////////////////////
  1484.  
  1485. int Game_Shutdown(void *parms)
  1486. {
  1487. // this function is where you shutdown your game and
  1488. // release all resources that you allocated
  1489.  
  1490. // delete all the explosions
  1491. Delete_Bursts();
  1492.     
  1493. // delete the player
  1494. Destroy_BOB16(&starferret);
  1495.  
  1496. // the delete all the rocks
  1497. Delete_Rocks();
  1498.  
  1499. // delete all the plasma pulses
  1500. Delete_Plasma();
  1501.  
  1502. // shutdown directdraw
  1503. DD_Shutdown();
  1504.  
  1505. // unload sounds
  1506. Delete_All_Sounds();
  1507.  
  1508. // shutdown directsound
  1509. DSound_Shutdown();
  1510.  
  1511. // release all input devices
  1512. DI_Release_Keyboard();
  1513. DI_Release_Joystick();
  1514. DI_Release_Mouse();
  1515.  
  1516. // return success
  1517. return(1);
  1518. } // end Game_Shutdown
  1519.  
  1520. ///////////////////////////////////////////////////////////
  1521.  
  1522. int Game_Main(void *parms)
  1523. {
  1524. // this is the workhorse of your game it will be called
  1525. // continuously in real-time this is like main() in C
  1526. // all the calls for you game go here!
  1527.  
  1528. static int ready_counter = 0, // used to draw a little "get ready"
  1529.            ready_state   = 0;
  1530.  
  1531. int  index;             // looping var
  1532. int  dx,dy;             // general deltas used in collision detection
  1533.  
  1534. // start the timing clock
  1535. Start_Clock();
  1536.  
  1537. // reset upward motion flag
  1538. moving_up = 0;
  1539.  
  1540. // clear the drawing surface
  1541. DD_Fill_Surface(lpddsback, 0);
  1542.  
  1543. // read all input devices
  1544. DI_Read_Keyboard();
  1545. DI_Read_Mouse();
  1546. DI_Read_Joystick();
  1547.  
  1548. // only process player if alive
  1549. if (player_state == PLAYER_STATE_ALIVE)
  1550. {
  1551.  
  1552. // test if player is moving
  1553. if (keyboard_state[DIK_RIGHT])
  1554.     {
  1555.     // move player to right
  1556.     starferret.x+=8;
  1557.  
  1558.     } // end if
  1559. else
  1560. if (keyboard_state[DIK_LEFT])
  1561.     {
  1562.     // move player to left
  1563.     starferret.x-=8;
  1564.  
  1565.     } // end if
  1566.  
  1567. // vertical/speed motion
  1568. if (keyboard_state[DIK_UP])
  1569.     {
  1570.     // move player up
  1571.     starferret.y-=4;
  1572.  
  1573.     // set upward motion flag
  1574.     moving_up = 1;
  1575.  
  1576.     // change engine freq
  1577.     Set_Sound_Freq(engines_id, 16000);
  1578.  
  1579.     } // end if
  1580.  
  1581. if (keyboard_state[DIK_DOWN])
  1582.     {
  1583.     // move player to left
  1584.     starferret.y+=2;
  1585.  
  1586.     } // end if
  1587.  
  1588.  
  1589. // merge mouse input
  1590. starferret.x+=mouse_state.lX;
  1591. starferret.y+=mouse_state.lY;
  1592.  
  1593. // merge joystick input
  1594. starferret.x+=joy_state.lX;
  1595. starferret.y+=joy_state.lY;
  1596.  
  1597. // test upward joystick component
  1598. if (joy_state.lY < 0) 
  1599.     {
  1600.     moving_up = 1; // set upward motion flag
  1601.  
  1602.     // change engine freq
  1603.     Set_Sound_Freq(engines_id, 16000);
  1604.     } // end if
  1605.  
  1606. // turn the engines down
  1607. if (!keyboard_state[DIK_UP] && joy_state.lY >=0)
  1608.    {
  1609.    // change engine freq
  1610.    Set_Sound_Freq(engines_id, 11000);
  1611.    } // end if
  1612.  
  1613. // test if player is firing
  1614. if (keyboard_state[DIK_LCONTROL] || keyboard_state[DIK_SPACE] || 
  1615.     mouse_state.rgbButtons[0] || joy_state.rgbButtons[0])
  1616.    Fire_Plasma(starferret.x+28-8,starferret.y-8,16);
  1617.  
  1618. // apply friction, or downward motion
  1619. starferret.y++;
  1620.  
  1621. // do bounds check
  1622.  
  1623. // first vertical axis
  1624. if (starferret.y < MIN_STARFERRET_Y)
  1625.    starferret.y = MIN_STARFERRET_Y;
  1626. else
  1627. if (starferret.y > MAX_STARFERRET_Y)
  1628.    starferret.y = MAX_STARFERRET_Y;
  1629.  
  1630. // now horizontal axis
  1631. if (starferret.x < 0)
  1632.    starferret.x = 0;
  1633. else
  1634. if (starferret.x > (screen_width - starferret.width))
  1635.    starferret.x = (screen_width - starferret.width);
  1636.  
  1637. // animate player
  1638. Animate_BOB16(&starferret);
  1639.  
  1640. // regenerate player
  1641. if (++player_regen_count > 60)
  1642.     {
  1643.     // reset regen counter
  1644.     player_regen_count=0;
  1645.  
  1646.     // regenerate healt a bit
  1647.     if (player_damage > 0)
  1648.         player_damage--;
  1649.     
  1650.     } // end if
  1651.  
  1652. // test for dying state transition
  1653. if (player_damage >= 100)
  1654.     {
  1655.     // set damage to 100
  1656.     player_damage = 100;
  1657.  
  1658.     // kill player
  1659.     player_state = PLAYER_STATE_DYING;
  1660.     player_ships--;
  1661.  
  1662.     // set counter to 0
  1663.     player_counter = 0;
  1664.     
  1665.     // start scream
  1666.     Play_Sound(scream_id);
  1667.  
  1668.     } // end if
  1669.  
  1670. } // end if player alive
  1671. else
  1672. if (player_state == PLAYER_STATE_DYING)
  1673.    { 
  1674.    // player is dying
  1675.  
  1676.    // start random bursts
  1677.    float bwidth  = 16 + rand()%64;
  1678.    float bheight = bwidth*1.16;
  1679.  
  1680.    if ((rand()%4)==1)
  1681.         Start_Burst(starferret.x-16+rand()%40, starferret.y-64+rand()%8,
  1682.                    (int)bwidth,(int)bheight, 
  1683.                    -4+rand()%8,2+rand()%4);    
  1684.  
  1685.    // bumb ship around
  1686.    starferret.x-=(-3+rand()%6);
  1687.    starferret.y-=(-3+rand()%6);
  1688.  
  1689.    // update state counter
  1690.    if (++player_counter > 100)
  1691.       {
  1692.       // set state to invincible  
  1693.       player_state = PLAYER_STATE_INVINCIBLE;
  1694.  
  1695.       // reset counter
  1696.       player_counter = 0;
  1697.  
  1698.       // reset damage
  1699.       player_damage = 0;
  1700.  
  1701.       // set position
  1702.       Set_Pos_BOB16(&starferret,320-starferret.width/2,350);
  1703.     
  1704.       } // end if
  1705.  
  1706.    } // end if
  1707. else
  1708. if (player_state == PLAYER_STATE_INVINCIBLE)
  1709.    {
  1710.    // player is invincible
  1711.    
  1712.    // update state counter
  1713.    if (++player_counter > 70)
  1714.       {
  1715.       // set state to invincible  
  1716.       player_state = PLAYER_STATE_ALIVE;
  1717.  
  1718.       // reset counter
  1719.       player_counter = 0;
  1720.  
  1721.       // decrease player ships
  1722.       if (player_ships == 0)
  1723.          {
  1724.          // change state to dead, reset all vars
  1725.          player_state   = PLAYER_STATE_DEAD;
  1726.          player_counter = 0;
  1727.          ready_state    = 1;
  1728.          ready_counter  = 0;
  1729.  
  1730.          // turn engines
  1731.          Stop_Sound(engines_id);
  1732.  
  1733.          } // end if       
  1734.  
  1735.       } // end if
  1736.  
  1737.     // start ready again
  1738.     if ((player_counter == 20) && (player_ships > 0))
  1739.       {
  1740.       // reset to ready
  1741.       ready_counter = 0, 
  1742.       ready_state   = 0;
  1743.       } // end if
  1744.  
  1745.    } // end if
  1746.  
  1747. if (player_state == PLAYER_STATE_DEAD)
  1748.    {
  1749.    // player is dead
  1750.    ready_state   = 1;
  1751.    ready_counter = 0;
  1752.  
  1753.    ////////////////////////////////////////////////////////////////
  1754.  
  1755.    // Y O U  A D D   T H I S   S E C T I O N !!!
  1756.    
  1757.    ////////////////////////////////////////////////////////////////
  1758.  
  1759.     // draw text
  1760.    Draw_Text_GDI("G A M E    O V E R    M A N",
  1761.                  320-6*strlen("G A M E    O V E R    M A N")/2,
  1762.                  200,RGB(255,0,0),lpddsback);
  1763.    } // end if
  1764.  
  1765. // move the plasma
  1766. Move_Plasma();
  1767.  
  1768. // move the asteroids
  1769. Move_Rocks();
  1770.  
  1771. // move the stars
  1772. Move_Stars();
  1773.  
  1774. // move the explosions
  1775. Move_Bursts();
  1776.  
  1777. // draw the tocks
  1778. Draw_Rocks();
  1779.  
  1780. // draw the plasma
  1781. Draw_Plasma();
  1782.  
  1783. // draw the player if alive
  1784. if (player_state == PLAYER_STATE_ALIVE || 
  1785.      (player_state == PLAYER_STATE_DYING && player_counter < 70))
  1786.     {
  1787.     Draw_BOB16(&starferret,lpddsback);
  1788.     } // end if
  1789.  
  1790. // draw the stars
  1791. Draw_Stars();
  1792.  
  1793. // draw explosions last
  1794. Draw_Bursts();
  1795.  
  1796. // draw the score and ships left
  1797. Draw_Info();
  1798.  
  1799. // draw get ready?
  1800. if (ready_state==0)
  1801.    {
  1802.    // test if counter is 0 for engines
  1803.    if (ready_counter==0)
  1804.        Play_Sound(engines_id,DSBPLAY_LOOPING);
  1805.  
  1806.    // test if counter is 10 for voice
  1807.    if (ready_counter==10)
  1808.        Play_Sound(ready_id);
  1809.  
  1810.    // draw text
  1811.    Draw_Text_GDI("GET READY!",320-8*strlen("GET READY!")/2, 200,RGB(0,rand()%255,0),lpddsback);
  1812.  
  1813.    // increment counter
  1814.    if (++ready_counter > 60)
  1815.       {
  1816.       // set state to ready
  1817.       ready_state = 1;
  1818.       ready_counter = 0;
  1819.  
  1820.       // stop the intro if not already
  1821.       Stop_Sound(intro_music_id);
  1822.  
  1823.       } // end if
  1824.  
  1825.    } // end if
  1826.  
  1827. // flip the surfaces
  1828. DD_Flip();
  1829.  
  1830. // sync to 30ish fps
  1831. Wait_Clock(30);
  1832.  
  1833. // check of user is trying to exit
  1834. if ((KEY_DOWN(VK_ESCAPE) || keyboard_state[DIK_ESCAPE]) && ready_state)
  1835.     PostMessage(main_window_handle, WM_DESTROY,0,0);
  1836.  
  1837. // return success
  1838. return(1);
  1839.  
  1840. } // end Game_Main
  1841.  
  1842. //////////////////////////////////////////////////////////