1. // from: Beginning Game Programming, Second Edition
  2.  
  3. #include "game.h"
  4.  
  5. // some globals
  6. //TODO: do this better.
  7. CPInput input;
  8. CPGraphicsEngine graphicsEngine;
  9.  
  10.  //RP - Load instances for sound effects
  11. weapon_fire guns;
  12.  gun_change change;
  13. environment en_sounds;
  14.  
  15. /* THESE WILL BE THE IN-GAME OPTIONS */
  16. int DIFF_LEVEL = 5; // AVG
  17.  
  18. // counters for score
  19. int MAX_SYTEM =0;
  20. int MAX_PLANET =0;
  21.  
  22. int ScrollX=0, ScrollY=0;       //current scroll position
  23. int SpeedX, SpeedY;             //scroll speed
  24. CPTexture scrollbuffer;         //scroll buffer
  25. CPTexture space_tiles,surface_tiles[NUM_MAPS_PLANET],system_tiles[NUM_MAPS_SYSTEM];         //source image(s) containing tiles
  26. bool gamestart = true;
  27.  
  28. // flag to turn off MUSIC at load time
  29. bool MUSIC_ENABLED = false;
  30.  
  31. //timing variable
  32. long start;                        
  33.  
  34. // keep track of which state the game is in
  35. GAME_STATE gameView = SPACE;
  36. bool initialized = false;
  37.  
  38. // TILE MAP Data
  39. int MAPDATA[MAPWIDTH][MAPHEIGHT];
  40. int SYSTEM_MAPDATA[MAPWIDTH][MAPHEIGHT];
  41.  
  42. // track players progress -- and mobs, etc --
  43. bool clearedArea[NUM_MAPS_SYSTEM][NUM_MAPS_PLANET];
  44.  
  45. struct debrisType
  46. {
  47.     bool space[DEBRIS_AMT_SPACE];
  48.     bool system[DEBRIS_AMT_SYSTEM];
  49.     bool surface[DEBRIS_AMT_PLANET];
  50. } hitDebris;
  51.  
  52. struct planetType
  53. {
  54.     bool space[IMMOBILE_AMT_SPACE];
  55.     bool system[IMMOBILE_AMT_SYSTEM];
  56.     bool surface[IMMOBILE_AMT_PLANET];
  57. } hitPlanet[NUM_MAPS_PLANET];
  58.  
  59. float COLL_RADIUS = 0.40f; // 80% of mass
  60.  
  61. // FLAG if player is at a dock-able object (planet,sun,etc)
  62. // will be -1 if not
  63. int DOCKED_AT = -1;
  64.  
  65. struct dType
  66. {
  67.     int planet;
  68.     int system;
  69.     int space;
  70. };
  71. dType docked = {-1,-1};
  72. dType CURR_MAP = {0,0,0};
  73.  
  74. float scalex=1.0f,scaley=1.0f; // used for sprite scaling
  75. float ScaleX=1.0f,ScaleY=1.0f; // used for sprite scaling
  76.  
  77. // static objects for the guns/ammo
  78. CGuns       *Guns[MAX_GUNS];
  79. CProjectile *Ammo[MAX_AMMO];
  80. int Alt_Weapon = 3; // missiles, 4 is torpedo
  81.  
  82. // FOR AI guns and such
  83. CGuns       *Guns_AI[MAX_GUNS_AI];
  84. CProjectile *Ammo_AI[MAX_GUNS_AI];
  85.  
  86. // max # of projectiles to track
  87. int cntBullets=0; // projectiles in motion
  88. int bulletsDrawn=0;
  89. int rCode=0;
  90. int enemyBullets=0;
  91. int bulletsHit=0;
  92.  
  93. // astronauts rescued
  94. int astronauts = 0;
  95.  
  96. // auto fire for laser beam
  97. bool AUTOFIRE = false;
  98.  
  99. // enemy
  100. const int NUM_DRONE_SHIPS=3;
  101. const int NUM_ENEMIES=10;
  102. CShip *enemy[NUM_ENEMIES];
  103. CShip *boss; // only one at a time
  104. CSprite *beeks;
  105. int deaths=0; // number of times boss has died , starts with frame #0 (grey)
  106. const int lives = 8; // 8 colors/frames
  107.  
  108. // Players ship
  109. CShip   *player = NULL;
  110. CSprite *shield = NULL;
  111.  
  112. // keep track of enter/exit locations
  113. // pt is xy location, number is object collides with last, dir is facing
  114. struct LAST_LOC
  115. {
  116.     CPPOINT pt;     // xy location
  117.     int number;     // object # collided with
  118.     DIRS direction;     // direction you were facing
  119.     CPPOINT scroll;     // scrollx and scrolly at entrance xy
  120. };
  121.  
  122. struct LAST_COLL
  123. {
  124.     int space;  // numbers reflect # of last object collided with in that view
  125.     int system;
  126.     int surface;
  127. };
  128. LAST_COLL lastColl = {0,0,0};
  129. LAST_COLL currColl = {0,0,0};
  130. LAST_COLL lastPlanetColl = {0,0,0};
  131. LAST_COLL currPlanetColl = {0,0,0};
  132.  
  133. // used to save previous locations and entrance locations
  134. LAST_LOC enterPLANET,enterSYSTEM,enterSPACE;
  135.  
  136. struct lastType
  137. {
  138.     LAST_LOC space;
  139.     LAST_LOC system;
  140.     LAST_LOC planet;
  141. } prev;
  142.  
  143. // health bars
  144. CPTexture color_bars;
  145. CPTexture sun;
  146.  
  147. CSprite *yellowBmp = NULL;
  148. CSprite *redBmp = NULL;
  149. CSprite *infectedPlanet = NULL;
  150.  
  151. // random space debris
  152. // Debris class to handle the moving debris
  153. CDebris *debris_space[DEBRIS_AMT_SPACE];
  154. CDebris *debris_system[DEBRIS_AMT_SYSTEM];
  155. CDebris *debris_planet[DEBRIS_AMT_PLANET];
  156.  
  157. CPlanet *immobile_space[IMMOBILE_AMT_SPACE];
  158. CPlanet *immobile_system[NUM_MAPS_SYSTEM][IMMOBILE_AMT_SYSTEM];
  159. CPlanet *immobile_planet[NUM_MAPS_PLANET][IMMOBILE_AMT_PLANET];
  160. //CPlanet *infected_planet;
  161.  
  162. // collision stuff
  163. double vPx;
  164. double vPy;
  165. double vJx;
  166. double vJy;
  167. //  ---
  168.  
  169. const int MAX_EXPLOSIONS = 30;
  170. CSprite *explosion[MAX_EXPLOSIONS];
  171. bool activeEXP[MAX_EXPLOSIONS];
  172.  
  173. const int RIGHT = 1;
  174. const int LEFT  = 0;
  175.  
  176. // timer to delay key presses
  177. bool KEY_PRESSED=false;
  178.  
  179. // Updated functions to read setup tokens from config file
  180. bool isLetter(int charValue)
  181. {
  182.      return (  (charValue >= 'a' && charValue <= 'z') ||
  183.                (charValue >= 'A' && charValue <= 'Z')  );
  184. }
  185.  
  186. bool isNumber(int charValue)
  187. {
  188.      return ( charValue >= '0' && charValue <= '9' );
  189. }
  190. int getToken(string token)
  191. {
  192.      if (token == "SCREEN_X")        
  193.           return SCREEN_WIDTH;
  194.      if (token == "SCREEN_Y")        
  195.           return SCREEN_HEIGHT;
  196.      if (token == "SCREEN_FULL")        
  197.           return FULLSCREEN;
  198.      if (token == "PLAYER_ENERGY")        
  199.           return START_energy;
  200.      if (token == "PLAYER_RCHRG")        
  201.           return START_eRecharge;
  202.      if (token == "PLAYER_SHIELDS")        
  203.           return START_Shields;
  204.      if (token == "PLAYER_ARMOR")        
  205.           return START_Armor;
  206.      if (token == "PLAYER_HULL")        
  207.           return START_Hull;
  208.      if (token == "PLAYER_SRGN")        
  209.           return START_shield_regen_delay;
  210.      if (token == "DRONE_MAXSPD")        
  211.           return DRONE_maxSpd;
  212.      if (token == "DRONE_CURSPD")        
  213.           return DRONE_curSpd;
  214.      if (token == "DRONE_ENERGY")        
  215.           return DRONE_energy;
  216.      if (token == "DRONE_ERCHRG")        
  217.           return DRONE_eRecharge;
  218.      if (token == "DRONE_SHIELDS")        
  219.           return DRONE_Shields;
  220.      if (token == "DRONE_ARMOR")        
  221.           return DRONE_Armor;
  222.      if (token == "DRONE_HULL")        
  223.           return DRONE_Hull;
  224.      if (token == "BOSS_ARMOR")        
  225.           return BOSS_ARMOR;
  226.      if (token == "BOSS_HULL")        
  227.           return BOSS_HULL;
  228.  
  229.      cout << "token (" << token << ") not found" << endl;
  230.      return 0;
  231. }
  232. void setToken(string token, string value)
  233. {
  234.      int iValue = atoi(value.c_str());
  235.  
  236.      // display new value
  237.      cout << token << " = " << iValue << endl;
  238.  
  239.      if (token == "SCREEN_X")        
  240.           SCREEN_WIDTH = iValue;
  241.      else if (token == "SCREEN_Y")        
  242.           SCREEN_HEIGHT = iValue;
  243.      else if (token == "SCREEN_FULL")        
  244.           FULLSCREEN = iValue;
  245.      else if (token == "PLAYER_ENERGY")        
  246.           START_energy = iValue;
  247.      else if (token == "PLAYER_RCHRG")        
  248.           START_eRecharge = iValue;
  249.      else if (token == "PLAYER_SHIELDS")        
  250.           START_Shields = iValue;
  251.      else if (token == "PLAYER_ARMOR")        
  252.           START_Armor = iValue;
  253.      else if (token == "PLAYER_HULL")        
  254.           START_Hull = iValue;
  255.      else if (token == "PLAYER_SRGN")        
  256.           START_shield_regen_delay = iValue;
  257.      else if (token == "DRONE_MAXSPD")        
  258.           DRONE_maxSpd = iValue;
  259.      else if (token == "DRONE_CURSPD")        
  260.           DRONE_curSpd = iValue;
  261.      else if (token == "DRONE_ENERGY")        
  262.           DRONE_energy = iValue;
  263.      else if (token == "DRONE_ERCHRG")        
  264.           DRONE_eRecharge = iValue;
  265.      else if (token == "DRONE_SHIELDS")        
  266.           DRONE_Shields = iValue;
  267.      else if (token == "DRONE_ARMOR")        
  268.           DRONE_Armor = iValue;
  269.      else if (token == "DRONE_HULL")        
  270.           DRONE_Hull = iValue;
  271.      else if (token == "BOSS_ARMOR")        
  272.           BOSS_ARMOR = iValue;
  273.      else if (token == "BOSS_HULL")        
  274.           BOSS_HULL = iValue;
  275. }
  276.  
  277. bool load_Config(string filename)
  278. {
  279.      // open the file
  280.      ifstream input_file(filename.c_str());
  281.  
  282.      if (! input_file.is_open())
  283.      {
  284.           cout << "Unable to open file: " << filename << endl;
  285.           return false;
  286.      }
  287.  
  288.      cout << endl << "Loading variables from config file ..." << endl;
  289.  
  290.      // setup variables
  291.      string inputText;
  292.      string tToken = "" , tValue = "";
  293.      string lastToken;    
  294.  
  295.      //
  296.      const int MAX_TOKENS = 99;
  297.      string tokens[MAX_TOKENS];
  298.      string values[MAX_TOKENS]; // string (int) value of each token
  299.  
  300.      int currChar = 0;
  301.      int tokensFound = 0;
  302.      int tLoc = 0, tVLoc = 0;
  303.      int strLen;
  304.      char tChar;
  305.      int lineCnt = 0;
  306.      bool blankLine = true;
  307.      bool declaringVar = false;
  308.  
  309.      // 2-D array for variables
  310.      // read from file
  311.      while (! input_file.eof() )
  312.      {
  313.           // get it one line at a time
  314.           getline (input_file, inputText);
  315.           lineCnt++;
  316.  
  317.           currChar = 0;
  318.           tLoc = 0;
  319.           strLen = inputText.length();
  320.           blankLine = true;
  321.  
  322.           // get tokens
  323.           //token   value          
  324.  
  325.           // while not at end of the string
  326.           while ( currChar < strLen )
  327.           {
  328.                tChar = inputText[currChar];
  329.                // parse string
  330.  
  331.                // is it an expression ? then check for prior declaration of variable name
  332.                if ( tChar == '/' )
  333.                     currChar = strLen; // exit loop
  334.  
  335.                // if it is a letter or _ character.
  336.                if (isLetter(tChar) || (tChar == '_'))
  337.                {
  338.                     // its a letter, so we assume its a token string
  339.                     tToken += tChar;
  340.                     tLoc++;
  341.                     blankLine = false;
  342.                }
  343.                else if (isNumber(tChar))
  344.                {
  345.                     // its a number, so we assume its a value
  346.                     tValue += tChar;
  347.                     tVLoc++;
  348.                     blankLine = false;
  349.                }
  350.                else
  351.                {
  352.                     // white space or special tokens
  353.  
  354.                     // handle special characters
  355.                     if ( tLoc > 0 )
  356.                     {
  357.                          // close out the token
  358.                          tokens[tokensFound] = tToken;
  359.                          lastToken = tToken;
  360.                          tToken = ""; // reset for next token
  361.                          tLoc = 0;
  362.                          blankLine = false;
  363.                     }
  364.                     if ( tVLoc > 0 )
  365.                     {
  366.                          // close out the value token
  367.                          values[tokensFound] = tValue;
  368.                          setToken(tokens[tokensFound],values[tokensFound]); // override default
  369.  
  370.                          tokensFound++; // increment for next token
  371.                          tValue = ""; // reset for next token
  372.                          tVLoc = 0;
  373.                          blankLine = false;
  374.                     }
  375.                }
  376.                // next character
  377.                currChar++;
  378.           } // while ... parsing each line
  379.      } // while ... not end of file
  380.  
  381.      input_file.close();
  382.  
  383.      return true;
  384. }
  385.  
  386. //-------------------------------------------------------//
  387. //-----------------   GAME INIT -------------------------//
  388. //initializes the game
  389.  int Game_Init(HWND hwnd)
  390.  {
  391.     cout << "Loading Game ..." << endl;
  392.  
  393.     bool read_from_config = load_Config("setup.cfg");
  394.  
  395.     SDL_Init( SDL_INIT_EVERYTHING );
  396.  
  397.     //Initialize SDL_mixer
  398.     if( Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 ) == -1 )
  399.     {
  400.         cout << "Error: Unable to initialize Audio Mixer" << endl;
  401.         return false;
  402.     }
  403.  
  404.     // load sound effects and music
  405.     if ( en_sounds.setup() == false )
  406.         {
  407.          cout << "Error: Unable to initialize Audio Sounds (environment)" << endl;
  408.          return false;
  409.         }
  410.     if ( guns.setup() == false )
  411.         {
  412.          cout << "Error: Unable to initialize Audio Sounds (guns)" << endl;
  413.          return false;
  414.         }
  415.  
  416.     if ( change.setup() == false )
  417.     {
  418.      cout << "Error: Unable to initialize Audio Sounds (changes)" << endl;
  419.          return false;
  420.     }
  421.  
  422.     // Start the music
  423.      if (MUSIC_ENABLED)
  424.          en_sounds.background_music(); 
  425.     initialized = true;
  426.  
  427.      // initialize graphics
  428.     graphicsEngine.Init_Graphics((long)hwnd, SCREEN_WIDTH, SCREEN_HEIGHT, FULLSCREEN);
  429.  
  430.      // int to string
  431.      ostringstream buffer;
  432.      buffer << SCREEN_WIDTH << "x" << SCREEN_HEIGHT;
  433.      string screen_res = buffer.str();
  434.      CPRECT tRect = {0,0,128,64};
  435.  
  436.     // loading title image:
  437.     CPTexture titleImage;
  438.     titleImage.LoadTextureFromFile("./Media/Images/BugHuntTitle.png", 0 /*CPCOLOR_XRGB(255,0,255)*/, false);
  439.     graphicsEngine.StartFrame();
  440.     graphicsEngine.DrawTexture(SCREEN_WIDTH / 2 - 275, SCREEN_HEIGHT/2 - 100, 550, 200, 1.0f, 1.0f, 0.0f, CPCOLOR_XRGB(255,0, 255), titleImage, NULL, false);
  441.      graphicsEngine.DrawTextToRect(screen_res, tRect,CP_WHITE);
  442.     graphicsEngine.EndFrame();
  443.  
  444. #ifndef USE_SDL
  445.     // Windows Input
  446.     Init_DirectInput(hwnd);
  447.     Init_Keyboard(hwnd);
  448. #endif
  449.  
  450.     // set all explosions to false
  451.     for (int i=0; i < MAX_EXPLOSIONS; i++)
  452.         activeEXP[i] = false;
  453.  
  454.     // set all map data to (1) ... SPACE/PLANET (for now)
  455.     for (int row=0; row < MAPHEIGHT;row++)
  456.         for (int column=0; column < MAPWIDTH; column++)
  457.             MAPDATA[column][row] = 1; // all will use sprite #1
  458.  
  459.    
  460.     // system map data
  461.     int cnt = 0;
  462.     for (int row=0; row < MAPHEIGHT;row++)
  463.         for (int column=0; column < MAPWIDTH; column++)
  464.             SYSTEM_MAPDATA[column][row] = cnt++; // so it draws the bmp using tiles
  465.  
  466.     // setup the guns and ammo for the ships
  467.     Init_Guns();
  468.  
  469.     //load the tile images 
  470.     bool result = space_tiles.LoadTextureFromFile("./Media/Images/space_00.png", CPCOLOR_XRGB(0,0,0), true);
  471.         if (! result)
  472.         {
  473.          cout << "Error: Unable to load texture from file : ./Media/Images/space_00.png" << endl;
  474.          return false;
  475.         }
  476.  
  477.      //load the tile images
  478.     cout << "Loading Images ";
  479.     for (int p=0; p < NUM_MAPS_PLANET; p++)
  480.     {
  481.         char myText[100];
  482.         sprintf(myText,"./Media/Images/planet_0%d.png",p);
  483.         result = surface_tiles[p].LoadTextureFromFile(myText, CPCOLOR_XRGB(0,0,0), true);
  484.             if (! result)
  485.             {
  486.                 cout << "Error: Unable to load texture from file : " << myText << endl;
  487.                 return false;
  488.             }
  489.         else
  490.             cout << ".";
  491.     }
  492.  
  493.     //load the tile images
  494.     for (int s=0; s < NUM_MAPS_SYSTEM; s++)
  495.     {
  496.         char myText[100];
  497.         sprintf(myText,"./Media/Images/system_0%d.png",s);
  498.         result = system_tiles[s].LoadTextureFromFile(myText, CPCOLOR_XRGB(0,0,0), true);
  499.                 if (! result)
  500.                 {
  501.                         cout << "Error: Unable to load texture from file : " << myText << endl;
  502.                         return false;
  503.                 }
  504.                 else
  505.                         cout << ".";
  506.     }
  507.     cout << endl;
  508.  
  509.     //create the scroll buffer surface in memory, slightly bigger
  510.     //than the screen
  511.     scrollbuffer.CreateOffscreenTexture(SCROLLBUFFERWIDTH, SCROLLBUFFERHEIGHT);
  512.  
  513.     // test bitmap
  514.     // will draw under objects that are collided with ... as a test
  515.     yellowBmp = new CSprite(0,0,120,100,"./Media/Images/test1.bmp");   
  516.     assert(yellowBmp);
  517.  
  518.     redBmp = new CSprite(0,0,120,100,"./Media/Images/test2.png");  
  519.     assert(redBmp);
  520.  
  521.      // sprite of infected planet
  522.      infectedPlanet = new CSprite(0,0,96,96,"./Media/Images/infected.png");
  523.      assert(infectedPlanet);
  524.  
  525.     //player
  526.     // now using GAME WORLD coordinates
  527.     // starting ship  Max Speed 8, Solar Energy 20, Recharge Delay 50, BLASTERS, shields, armor, hull (hit points)
  528.      // (int x, int y, int width, int height, char* filename, int newSpeed, int newMaxSpd,int Energy, int eRecharge, CGuns *Weapon, int GunNum, int Shields,int Armor, int Hull)
  529.     player = new CShip(16,16,128,128,"./Media/Images/ship.png",0,8,START_energy,START_eRecharge,Guns[0],0,START_Shields,START_Armor,START_Hull,START_shield_regen_delay);
  530.     player->setupAnim(4,SOUTH,4); // sprites per anim, initially heading, sprites per row on sheet 
  531.     player->setAngle(90);
  532.     player->setSTATE(ACTIVE);  
  533.     player->setAltRecharge(DELAY_LONG);
  534.     player->setBorder(0,0,GAMEWORLDWIDTH - 64,GAMEWORLDHEIGHT - 64); // set border to game window
  535.     assert(player);
  536.  
  537.     shield = new CSprite(50,50,128,128,"./Media/Images/shield.png");
  538.     shield->setupAnim(4,EAST,4);
  539.     shield->setSTATE(ACTIVE);
  540.     assert(shield);
  541.  
  542.     // spawn/create the Enemy SHIPs & BOSS
  543.     cout << "creating drones ..." << endl;
  544.     createDrones();
  545.  
  546.     // randomly initializes the debris
  547.     cout << "creating debris ..." << endl;
  548.     createDebris();
  549.  
  550.     // load the static objects (planets)
  551.     cout << "loading maps ..." << endl;
  552.     loadMaps();
  553.  
  554.     // SCORE
  555.     // SYSTEMS CLEARED
  556.     int cntPl=0,cntSys=0, temp=0;
  557.     for (int s=0; s < NUM_MAPS_SYSTEM; s++)
  558.     {
  559.         temp=cntPl;
  560.         for (int p=0; p < NUM_MAPS_SYSTEM; p++)
  561.             if (clearedArea[s][p] == false)
  562.                 cntPl++;
  563.  
  564.         if (temp != cntPl)
  565.         {
  566.             cntSys++;
  567.             temp = cntPl;
  568.         }
  569.     }              
  570.  
  571.     MAX_SYTEM  =cntSys;
  572.     MAX_PLANET =cntPl; // <- this is THE SCORE (max)
  573.  
  574.     // Status bars for players
  575.     result = color_bars.LoadTextureFromFile("./Media/Images/bars.bmp", CPCOLOR_XRGB(255,0,255), true);
  576.         if (! result)
  577.         {
  578.          cout << "Error: Unable to load texture from file : ./Media/Images/bars.bmp" << endl;
  579.          return false;
  580.         }
  581.  
  582.     // setup the enter/exit objects
  583.     enterPLANET.pt.x = 1;
  584.     enterPLANET.pt.y = 1;
  585.     enterPLANET.direction = SE;
  586.     enterPLANET.scroll.x = 0;
  587.     enterPLANET.scroll.y = 0;
  588.  
  589.     enterSYSTEM.pt.x = 1;
  590.     enterSYSTEM.pt.y = 1;
  591.     enterSYSTEM.direction = SE;
  592.     enterSYSTEM.scroll.x = 0;
  593.     enterSYSTEM.scroll.y = 0;
  594.  
  595.     enterSPACE.pt.x = 150;
  596.     enterSPACE.pt.y = 150;
  597.     enterSPACE.direction = SE;
  598.     enterSPACE.scroll.x = 0;
  599.     enterSPACE.scroll.y = 0;
  600.  
  601.     cout << endl << "Loading complete!" << endl;
  602.  
  603.     return 1;
  604. }
  605.  
  606.  
  607. // -------------------------------------------------- //
  608. // ------------ GAME RUN ---------------------------- //
  609. static int lastView;
  610. static bool dontZone = false;
  611. void currView()
  612. {
  613.     cout << " current gameView is ";
  614.     switch( gameView )
  615.     {
  616.         case SPACE:   cout << "SYSTEM"; break;
  617.         case SYSTEM:  cout << "SYSTEM"; break;
  618.         case PLANET:  cout << "PLANET"; break;
  619.         default: cout << "error - unknown game view!!"; break;
  620.     }
  621.     cout << endl;
  622. }
  623. void planetView(int newPlanet)
  624. {
  625.      cout << "Entering new planet (" << newPlanet << ")" << endl;
  626.      currView();
  627.  
  628.      cout << "changing view from SYSTEM to newPlanet?" << endl;
  629.  
  630.      // make sure player doesnt zone repeatedly
  631.      if (dontZone)
  632.      {
  633.           cout << "dontZone is set to TRUE" << endl;
  634.      }
  635.      else
  636.           dontZone = true;
  637.  
  638.      //
  639.      //           { // SYSTEM -> PLANET
  640.  
  641.      // check if any enemies in this system
  642.      // if all planets cleared, then its safe
  643.      if ( clearedArea[CURR_MAP.system][newPlanet] )
  644.      {
  645.           cout << "planet (" << newPlanet << ") in system (" << CURR_MAP.system << "," << docked.system << ") is already cleared." << endl;
  646.           // make boss inactive
  647.           boss->setSTATE(INACTIVE);
  648.           deaths=0;
  649.           return; // exits if planet is already "safe"
  650.      }
  651.  
  652.      // else planet not safe
  653.      respawnDrones(8);
  654.      deaths=0;
  655.      respawnBoss(true);
  656.  
  657.      // keep track of what system # you are entering
  658.      docked.planet = newPlanet;
  659.      CURR_MAP.planet = newPlanet;
  660.  
  661.      // save current location
  662.      prev.system.direction = player->getFacing();
  663.      prev.system.pt.x = player->getX();
  664.      prev.system.pt.y = player->getY();
  665.  
  666.      // enter planet
  667.      gameView=PLANET;                      
  668.      SpeedX=0;
  669.      SpeedY=0;
  670.      player->setSpeed(0);
  671.  
  672.      // move to starting location
  673.      player->setPT(enterPLANET.pt);
  674.      player->setFacing(enterPLANET.direction);
  675.      ScrollX = enterPLANET.scroll.x; // map scroll values for given xy starting location
  676.      ScrollY = enterPLANET.scroll.y;
  677.  
  678.      en_sounds.teleport();
  679.  
  680.      lastView = SYSTEM;
  681.      //
  682.  
  683. }
  684. void systemView(int newSystem)
  685. {
  686.      cout << "Entering new system (" << newSystem << ")" << endl;
  687.      currView();
  688.  
  689.      // assumes SPACE -> SYSTEM
  690.      cout << "changing view from SPACE to SYSTEM?" << endl;
  691.  
  692.      // make sure player doesnt zone repeatedly
  693.      if (dontZone)
  694.      {
  695.           cout << "dontZone is set to TRUE" << endl;
  696.      }
  697.      else
  698.           dontZone = true;
  699.  
  700.      // check if any enemies in this system
  701.      // if all planets cleared, then its safe
  702.      bool systemSafe=true;
  703.      int pcnt =0 ;
  704.      for (int p=0; p < NUM_MAPS_PLANET; p++)
  705.           if ( clearedArea[newSystem][p] == false)
  706.           {
  707.                cout << "system (" << newSystem << ") planet (" << p << ") is not safe" << endl;
  708.                systemSafe=false;
  709.                pcnt++; // number of unsafe planets, will control number of drones that spawn
  710.           }
  711.  
  712.      CPlanet *sun = immobile_space[newSystem]; 
  713.  
  714.      if (sun->getMap() == -1)
  715.      {
  716.           cout << "invalid map returned for solar system object" << endl;
  717.           return;
  718.      }
  719.  
  720.      if ( systemSafe )
  721.      {
  722.           cout << "system (" << newSystem << ") safe, not zoning" << endl;
  723.           return;
  724.      }
  725.  
  726.      cout << "system (" << newSystem << ") is not safe ... zoning" << endl;
  727.      // ignore "safe" systems
  728.  
  729.      // respawn aliens (1 per planet)
  730.      // pcnt = planets w enemies
  731.      // can have up to 10 planets
  732.      // max of 10 enemies
  733.  
  734.      // when in SPACE view, there should be no boss attacks ...
  735.      // else not safe
  736.      respawnDrones(pcnt);
  737.      boss->setSTATE(INACTIVE);
  738.      deaths=0;
  739.  
  740.      // keep track of what system # you are entering
  741.      docked.system = newSystem;
  742.      CURR_MAP.system = newSystem;
  743.  
  744.      // save current location
  745.      prev.space.direction = player->getFacing();
  746.      prev.space.pt.x = player->getX();
  747.      prev.space.pt.y = player->getY();
  748.      // enter system
  749.      gameView=SYSTEM;
  750.  
  751.      // set speed,location,etc ...
  752.      SpeedX=0;
  753.      SpeedY=0;
  754.      player->setSpeed(0);          
  755.      player->setPT(enterSYSTEM.pt);
  756.      player->setFacing(enterSYSTEM.direction);
  757.      ScrollX = enterSYSTEM.scroll.x;
  758.      ScrollY = enterSYSTEM.scroll.y;
  759.  
  760.      en_sounds.teleport(); 
  761. }
  762.  
  763. void changeToSPACE()
  764. {
  765.      //
  766.      // send player back to space station and heal them
  767.     gameView=SPACE;
  768.  
  769.     // un-spawn the drones
  770.     respawnDrones(0); // sets them all to inactive
  771.     boss->setSTATE(INACTIVE);
  772.     deaths=0; // reset boss
  773.  
  774.     // move to starting location
  775.     CPPOINT dest = { 105, 105 }; // GAMEWORLDWIDTH HEIGHT
  776.     player->setPT(dest);
  777.     ScrollX=0;ScrollY=0;
  778.     player->setSpeed(0);
  779.  
  780. //  player->fullHeal();
  781.     player->setSTATE(ACTIVE);
  782.  
  783.     en_sounds.teleport();
  784.      //
  785. }
  786. void changeView(int docked_object)
  787. {
  788.      cout << "Entering change View" << endl;
  789.      currView();
  790.  
  791.      if (docked_object == -1)
  792.           return;
  793.  
  794.      string outText = "";    
  795.      stringstream out;
  796.      out.clear();
  797.  
  798.      // else    
  799.      switch (gameView)
  800.      {
  801.           case SPACE:
  802.               {    
  803.                     debugOut("changing view from SPACE to SYSTEM?");
  804.                     // make sure player doesnt zone repeatedly
  805.                     dontZone = true;
  806.  
  807.                  // check if any enemies in this system
  808.                  // if all planets cleared, then its safe
  809.                  bool systemSafe=true;
  810.                     int pcnt =0 ;
  811.                  for (int p=0; p < NUM_MAPS_PLANET; p++)
  812.                      if ( clearedArea[docked_object][p] == false)
  813.                          {
  814.                               out.clear();
  815.                               out << "system (" << docked_object << ") planet (" << p << ") is not safe" << endl;
  816.                               debugOut(out.str());
  817.                              
  818.                               systemSafe=false;
  819.                               pcnt++; // number of unsafe planets, will control number of drones that spawn
  820.                          }
  821.  
  822.                    CPlanet *sun = immobile_space[docked_object];   
  823.  
  824.                    if (sun->getMap() == -1)
  825.                    {
  826.                         debugOut("invalid map returned for solar system object");
  827.                         return;
  828.                    }
  829.  
  830.                    if ( systemSafe )
  831.                    {
  832.                         out.clear();
  833.                         out << "system (" << docked_object << ") safe, not zoning";
  834.                         debugOut(out.str());
  835.  
  836.                         return;
  837.                    }
  838.  
  839.                    out.clear();
  840.                    out << "system (" << docked_object << ") safe, not ... zoning";
  841.                    debugOut(out.str());
  842.  
  843.                     // ignore "safe" systems
  844.  
  845.                  // respawn aliens (1 per planet)
  846.                  // pcnt = planets w enemies
  847.                  // can have up to 10 planets
  848.                  // max of 10 enemies
  849.  
  850.                     // when in SPACE view, there should be no boss attacks ...
  851.                     // else not safe
  852.                  respawnDrones(pcnt);
  853.                  boss->setSTATE(INACTIVE);
  854.                  deaths=0;
  855.  
  856.                  // keep track of what system # you are entering
  857.                  docked.system = docked_object;
  858.                  CURR_MAP.system = docked_object;
  859.  
  860.                  // save current location
  861.                  prev.space.direction = player->getFacing();
  862.                  prev.space.pt.x = player->getX();
  863.                  prev.space.pt.y = player->getY();
  864.  
  865.                  // enter system
  866.                  gameView=SYSTEM;
  867.                
  868.                  // set speed,location,etc ...
  869.                  SpeedX=0;
  870.                  SpeedY=0;
  871.  
  872.                  player->setSpeed(0);          
  873.                  player->setPT(enterSYSTEM.pt);
  874.                  player->setFacing(enterSYSTEM.direction);
  875.                  ScrollX = enterSYSTEM.scroll.x;
  876.                  ScrollY = enterSYSTEM.scroll.y;
  877.  
  878.                  en_sounds.teleport(); 
  879.  
  880.                     lastView = SPACE;
  881.               };
  882.               break;
  883.           case SYSTEM:
  884.               { // SYSTEM -> PLANET
  885.                     // make sure player doesnt zone repeatedly
  886.                     dontZone = true;
  887.  
  888.                  // check if any enemies in this system
  889.                  // if all planets cleared, then its safe
  890.                     if ( clearedArea[CURR_MAP.system][docked_object] )
  891.                     {                
  892.                         out.clear();
  893.                         out << "planet (" << docked_object << ") in system (" << CURR_MAP.system << "," << docked.system << ") is already cleared.";
  894.                         debugOut(out.str());
  895.  
  896.                         // make boss inactive
  897.                     boss->setSTATE(INACTIVE);
  898.                     deaths=0;
  899.                         return; // exits if planet is already "safe"
  900.                     }
  901.  
  902.                     // else planet not safe
  903.                  respawnDrones(8);
  904.                  deaths=0;
  905.                  respawnBoss(true);
  906.  
  907.                  // keep track of what system # you are entering
  908.                  docked.planet = docked_object;
  909.                  CURR_MAP.planet = docked_object;
  910.  
  911.                  // save current location
  912.                  prev.system.direction = player->getFacing();
  913.                  prev.system.pt.x = player->getX();
  914.                  prev.system.pt.y = player->getY();
  915.  
  916.                  // enter planet
  917.                  gameView=PLANET;                      
  918.                  SpeedX=0;
  919.                  SpeedY=0;
  920.                  player->setSpeed(0);
  921.  
  922.                  // move to starting location
  923.                  player->setPT(enterPLANET.pt);
  924.                  player->setFacing(enterPLANET.direction);
  925.                  ScrollX = enterPLANET.scroll.x; // map scroll values for given xy starting location
  926.                  ScrollY = enterPLANET.scroll.y;
  927.  
  928.                  en_sounds.teleport();
  929.  
  930.                     lastView = SYSTEM;
  931.               };    break;
  932.            case PLANET:
  933.                 {
  934.                     lastView = PLANET;
  935.  
  936.                     return; // exit
  937.                 }
  938.                 break; // do nothing, its already PLANET
  939.     }
  940. }
  941. // ----------------------------
  942. //the main game loop
  943. void Game_Run(HWND hwnd)
  944. {
  945. #ifndef USE_SDL
  946.    //make sure the Direct3D device is valid
  947.     if (d3ddev == NULL)
  948.         return;
  949.  
  950.     //poll DirectInput devices
  951.     Poll_Keyboard();
  952.  
  953.     //check for escape key (to exit program)
  954.     if (input.IsKeyDown(VK_ESCAPE)) // DIK_ESCAPE
  955.         PostMessage(hwnd, WM_DESTROY, 0, 0);
  956. #endif
  957.  
  958.     int temp=0;
  959.      stringstream out; // for convert into to string
  960.  
  961.     // check for player pressing a key
  962.     Check_Keys();
  963.  
  964.     // set player ship scale based on view level
  965.     switch(gameView)
  966.     {
  967.     case SPACE:
  968.         {
  969.             scalex=0.5f;
  970.             scaley=0.5f;
  971.         };
  972.         break;
  973.     case SYSTEM:
  974.         {
  975.             scalex=0.75f;
  976.             scaley=0.75f;
  977.         };
  978.         break;
  979.     case PLANET:
  980.         {
  981.             scalex=1.0f;
  982.             scaley=1.0f;
  983.         };
  984.         break;
  985.     }
  986.  
  987. // RECOVER
  988.     // regen solar energy & shields & guns
  989.     player->recharge();
  990.  
  991.     // recharge power on enemy ships, so they can continue shooting at you
  992.     for (int i=0; i < NUM_ENEMIES; i++)
  993.         if ((enemy[i]->getSTATE() != DEAD) && (enemy[i]->getSTATE() != INACTIVE))
  994.             enemy[i]->recharge();
  995.  
  996.     if ( (boss->getSTATE() != DEAD) && (boss->getSTATE() != INACTIVE) )
  997.         boss->recharge();
  998.  
  999. // MOVE
  1000.     //move the sprite
  1001.     player->doMove();
  1002.  
  1003.     // Bullet movement
  1004.     moveBullets();
  1005.  
  1006.     // process Enemy Actions (FSM)
  1007.     // and MOVE enemy ships
  1008.     EnemyAI();
  1009.     BossAI();
  1010.  
  1011.     // move Debris in current Game View
  1012.     moveDebris();
  1013.  
  1014. // CHECK MOVES
  1015.     // Player - check if left screen or not
  1016.     // make sure ship doesnt leave game coordinates
  1017.     if (player->checkBounds(0,0,GAMEWORLDWIDTH,GAMEWORLDHEIGHT))
  1018.         player->setSpeed(0);// border collision occured ... now what? player ship is stopped
  1019.    
  1020.     //update the scrolling view
  1021.     UpdateScrollPosition();
  1022.  
  1023. //COLLISIONS
  1024.     // AI bullets vs Player
  1025.     bullet_AI_Collision(player);
  1026.  
  1027.       // check if player ship  destroyed & respawn if so
  1028.       if (player->getCur(LOC_HULL) < 1)
  1029.           respawnPlayer();
  1030.  
  1031.     // player bullets vs AI
  1032.     for (int i=0;i < NUM_ENEMIES; i++)
  1033.         if ((enemy[i]->getSTATE() != DEAD) && (enemy[i]->getSTATE() != INACTIVE))
  1034.             bulletCollision(enemy[i]);
  1035.  
  1036.     // player bullets vs Boss
  1037.     if ( (boss->getSTATE() != DEAD) && (boss->getSTATE() != INACTIVE) )
  1038.         bulletCollision(boss);
  1039.  
  1040.     // check for player vs. debris collision ... and determine the results
  1041.     checkDebris();
  1042.  
  1043.     // if player collides with a planet - enter planet mode
  1044.     temp = planetCollision(player); // object # collided with (or -1)
  1045.  
  1046.     // track current and last object collided with     
  1047.     if (gameView == SPACE) 
  1048.     {
  1049.         lastPlanetColl.space   = currPlanetColl.space; // resets to (0) if no collision
  1050.         currPlanetColl.space   = temp; // resets to (0) if no collision
  1051.     }
  1052.     if (gameView == SYSTEM)
  1053.     {
  1054.         lastPlanetColl.system = currPlanetColl.system;
  1055.         currPlanetColl.system  = temp;
  1056.     }
  1057.     if (gameView == PLANET)
  1058.     {
  1059.         lastPlanetColl.surface = currPlanetColl.surface;
  1060.         currPlanetColl.surface = temp;
  1061.     }      
  1062.  
  1063.     // Will hold the current object player is docked at
  1064.     // DOCKED_AT = temp;
  1065.     DOCKED_AT = -1;
  1066.  
  1067.     // OK- if you are docked at a planet -- you can hit the + key to "zoom in"
  1068.     // check to make sure its a valid DOCK target
  1069.      // temp = -1 means no collisions
  1070.      if (temp == -1)
  1071.           dontZone = false; // no collisions, so now let player zone next time he collides 
  1072.      else
  1073.          switch(gameView)
  1074.          {
  1075.              case SPACE:
  1076.                  {
  1077.                      // DOCKED_AT only holds the [i] last collision w/ object
  1078.                      // lets get the frame # from the given sprite                 
  1079.                      // find the resulting frame # which represents which type of system it will be
  1080.                      // make sure its a valid #
  1081.                      if ( temp < IMMOBILE_AMT_SPACE)
  1082.                      {
  1083.                          // this should tell us the map # associated, (-1) if none
  1084.                          if (immobile_space[temp]->getMap() > -1)
  1085.                         {
  1086.                             DOCKED_AT = immobile_space[temp]->getMap();
  1087.                              
  1088.                                    out.clear();
  1089.                                    out << "player is docked at system (" << temp << ") map # " << DOCKED_AT;
  1090.                                    debugOut(out.str());
  1091.  
  1092.                                  // try to auto-zone
  1093.                                  //changeView(DOCKED_AT);
  1094.                              systemView(temp); // system #
  1095.                         }
  1096.                      }
  1097.                  };
  1098.                  break;
  1099.              case SYSTEM:
  1100.                  {
  1101.                      // make sure its a valid #
  1102.                      if ( temp < IMMOBILE_AMT_SYSTEM)
  1103.                      {
  1104.                          if (immobile_system[docked.system][temp]->getMap() > -1)
  1105.                         {
  1106.                             DOCKED_AT = immobile_system[docked.system][temp]->getMap();
  1107.                                    out.clear();
  1108.                                    out << "player is docked at system (" << docked.system << ") planet ("  << temp << ") map # " << DOCKED_AT;
  1109.                                    debugOut(out.str());
  1110.  
  1111.                             // try to auto-zone
  1112.                             planetView(temp);
  1113.                         }
  1114.                      }
  1115.                  };
  1116.                  break;
  1117.              case PLANET:
  1118.                  {
  1119.                          // DOCKED_AT stays (-1)
  1120.                  };
  1121.                  break;
  1122.          };
  1123.          
  1124.  
  1125.     // check for debris leaving the screen
  1126.     respawnDebris();
  1127.  
  1128. // ANIMATE
  1129.     // change shield color
  1130.     shield->setFrame(shield->getLastFrame() - player->getShields());
  1131.  
  1132.     // animate explosions
  1133.     animExp();
  1134.  
  1135.     //start rendering
  1136.     if (graphicsEngine.StartFrame())
  1137.     {          
  1138.         //draw tiles onto the scroll buffer
  1139.         switch (gameView)
  1140.         {
  1141.             case SPACE: DrawBG(space_tiles); break;
  1142.             case SYSTEM:
  1143.                 {
  1144.                     int c = docked.system;
  1145.                     if ((c > NUM_MAPS_SYSTEM) || (c < 0))
  1146.                         c = 0;
  1147.                     DrawBG(system_tiles[c]);
  1148.                 }; break;
  1149.             case PLANET:
  1150.                 {
  1151.                     int c = docked.planet;
  1152.                     if ((c > NUM_MAPS_PLANET) || (c < 0))
  1153.                         c = 0;
  1154.                     DrawBG(surface_tiles[c]);
  1155.                 }; break;
  1156.         }
  1157.            
  1158.  
  1159.         // SCORE BOARD
  1160.         drawText("Shots Fired",    25, 0, CP_GREEN);
  1161.         drawText("Enemy Bullets", 125, 0, CP_RED);
  1162.         drawText("Targets Hit",   225, 0, CP_GREEN);
  1163.         drawText("Rescues",       335, 0, CP_BLUE);
  1164.  
  1165.         drawNumbers(cntBullets,   50,30);
  1166.         drawNumbers(enemyBullets,150,30, CP_RED);
  1167.         drawNumbers(bulletsHit,  250,30);
  1168.         drawNumbers(astronauts,  350,30, CP_BLUE);
  1169.  
  1170.           //DEBUG
  1171.           int rx = SCREEN_WIDTH / 2;
  1172.           int ry = 8;
  1173.           drawNumbers(docked.space,     rx,   ry, CP_RED);       rx+=30;
  1174.           drawNumbers(docked.system,    rx,   ry, CP_RED);       rx+=30;
  1175.           drawNumbers(docked.planet,    rx,   ry, CP_RED);       rx-=60;   ry +=40;
  1176.  
  1177.           drawNumbers(CURR_MAP.space,   rx,   ry, CP_RED);       rx+=30;
  1178.           drawNumbers(CURR_MAP.system,  rx,   ry, CP_RED);       rx+=30;
  1179.           drawNumbers(CURR_MAP.planet,  rx,   ry, CP_RED);       rx-=60;   ry +=40;
  1180.  
  1181.           drawNumbers(DOCKED_AT    ,    rx,   ry, CP_GREEN);     rx+=30;
  1182.           drawNumbers(temp         ,    rx,   ry, CP_GREEN);     rx-=30;   ry+=40;
  1183.  
  1184.             drawNumbers(currPlanetColl.space   ,rx,ry,CP_RED);     rx+=30;
  1185.         drawNumbers(currPlanetColl.system  ,rx,ry,CP_RED);     rx+=30;
  1186.         drawNumbers(currPlanetColl.surface ,rx,ry,CP_RED);
  1187.  
  1188.           // DEBUG
  1189.           // clearedArea[NUM_MAPS_SYSTEM][NUM_MAPS_PLANET];
  1190.           for (int system=0; system < NUM_MAPS_SYSTEM; system++)           // Y                      
  1191.                for (int planet=0; planet < NUM_MAPS_PLANET; planet++)      // X
  1192.                     if (system % 2 == 0)
  1193.                          drawNumbers(clearedArea[system][planet] ,(planet * 20),150+(system * 40),CP_BLUE);
  1194.                     else
  1195.                          drawNumbers(clearedArea[system][planet] ,(planet * 20),150+(system * 40),CP_GREEN);
  1196.           // --------//
  1197.  
  1198.           // DEBUG
  1199.  
  1200.           int rBorder = SCREEN_WIDTH - (SCREEN_WIDTH * 0.2); // 1024 - 20% = 1024 - 204 = 820
  1201.         drawText("Unsafe",   rBorder+60 , 30, CP_RED); // 790
  1202.         drawText("Total",    rBorder+70 , 50, CP_GREEN); // 790
  1203.         drawText("Systems ", rBorder    ,  0, CP_GREEN); // 730
  1204.           drawText("Planets ", rBorder+100,  0, CP_GREEN); // 840
  1205.  
  1206.         // SCORE
  1207.         // SYSTEMS CLEARED
  1208.         int cntPl=0,cntSys=0, temp=0;
  1209.         for (int s=0; s < NUM_MAPS_SYSTEM; s++)
  1210.         {
  1211.             temp=cntPl;
  1212.             for (int p=0; p < NUM_MAPS_PLANET; p++)
  1213.                 if (clearedArea[s][p] == false)
  1214.                     cntPl++;
  1215.  
  1216.             if (temp != cntPl)
  1217.             {
  1218.                 cntSys++;
  1219.                 temp = cntPl;
  1220.             }
  1221.         }  
  1222.           drawNumbers(cntSys,    rBorder+ 20, 28, CP_RED); // 750
  1223.         drawNumbers(cntPl,     rBorder+120, 28, CP_RED); // 850
  1224.         drawNumbers(MAX_SYTEM, rBorder+ 20, 50); // 750
  1225.         drawNumbers(MAX_PLANET,rBorder+120, 50); // 850
  1226.  
  1227.         // draw the STATIC objects (not moving; planets and such)
  1228.         drawPlanets();
  1229.  
  1230.         //draw the space debris sprites (clouds, asteroids, etc)
  1231.         drawDebris();
  1232.  
  1233.         // this should draw all the player's bullets that are active
  1234.         drawBullets();
  1235.  
  1236.         // draw the health bars for enemy / player ships
  1237.         drawBars();
  1238.  
  1239.         //draw shield under the player sprite          
  1240.         graphicsEngine.DrawTexture( player->getX()-ScrollX,player->getY()-ScrollY,
  1241.                     shield->getWidth(),shield->getHeight(),
  1242.                     scalex, scaley, player->getAngle(),
  1243.                     CPCOLOR_XRGB(255,255,255),
  1244.                     shield->getTexture(),
  1245.                     &shield->getRect(),
  1246.                     true);
  1247.  
  1248.         //draw the player sprite
  1249.         graphicsEngine.DrawTexture( player->getX()-ScrollX,player->getY()-ScrollY,
  1250.                     player->getWidth(),player->getHeight(),
  1251.                     scalex, scaley, player->getAngle(),
  1252.                     CPCOLOR_XRGB(255,255,255),
  1253.                     player->getTexture(),
  1254.                     &player->getRect(),
  1255.                     true);
  1256.  
  1257.        
  1258.         for (int i=0;i < NUM_ENEMIES; i++)
  1259.             if ((enemy[i]->getSTATE() != DEAD) && (enemy[i]->getSTATE() != INACTIVE))
  1260.                 if (enemy[i]->getHP() > 0)// check for ZOMBIES :P
  1261.                 {
  1262.                     graphicsEngine.DrawTexture( enemy[i]->getX()-ScrollX,enemy[i]->getY()-ScrollY,
  1263.                                 enemy[i]->getWidth(),enemy[i]->getHeight(),
  1264.                                 scalex, scaley, enemy[i]->getAngle(),
  1265.                                 CPCOLOR_XRGB(255,255,255),
  1266.                                 enemy[i]->getTexture(),
  1267.                                 &enemy[i]->getRect(),
  1268.                                 true);             
  1269.                 }
  1270.                 else
  1271.                     enemy[i]->setSTATE(DEAD);  
  1272.  
  1273.         if ((boss->getSTATE() != DEAD) && (boss->getSTATE() != INACTIVE))
  1274.             if (boss->getHP() > 0)// check for ZOMBIES :P
  1275.             {
  1276.                 graphicsEngine.DrawTexture( boss->getX()-ScrollX,boss->getY()-ScrollY,
  1277.                             boss->getWidth(),boss->getHeight(),
  1278.                             scalex, scaley, boss->getAngle(),
  1279.                             CPCOLOR_XRGB(255,255,255),
  1280.                             boss->getTexture(),
  1281.                             &boss->getRect(),
  1282.                             true); 
  1283.  
  1284.                 // Draw Beeks over-top
  1285.                 graphicsEngine.DrawTexture( boss->getX()-ScrollX,boss->getY()-ScrollY,
  1286.                             beeks->getWidth(),beeks->getHeight(),
  1287.                             scalex, scaley, boss->getAngle(),
  1288.                             CPCOLOR_XRGB(255,255,255),
  1289.                             beeks->getTexture(),
  1290.                             &beeks->getRect(),
  1291.                             true);             
  1292.             }
  1293.             else
  1294.                 boss->setSTATE(DEAD);  
  1295.  
  1296.         // draw the Explosions (if any)
  1297.         drawExp();
  1298.  
  1299.         graphicsEngine.EndFrame();
  1300.     } // if (startFrame) ...
  1301. }
  1302.  
  1303. // -------------------------------------- //
  1304. // ---------- GAME END ------------------ //
  1305. //frees memory and cleans up before the game ends
  1306. void Game_End(HWND hwnd)
  1307. {
  1308.     if (yellowBmp != NULL) delete yellowBmp;
  1309.     if (redBmp != NULL) delete redBmp;
  1310.     if (player != NULL) delete player;
  1311.     if (shield != NULL) delete shield;
  1312.  
  1313.     if (initialized)
  1314.     {
  1315.         int i, j;
  1316.         for ( i = 0; i < NUM_MAPS_PLANET; i++ )
  1317.         {
  1318.             for ( j = 0; j < IMMOBILE_AMT_PLANET; j++ )
  1319.             {
  1320.                 delete immobile_planet[i][j];
  1321.             }
  1322.         }
  1323.         for ( i = 0; i < IMMOBILE_AMT_SPACE; i++ )
  1324.         {
  1325.             delete immobile_space[i];
  1326.         }
  1327.         for ( i = 0; i < NUM_MAPS_SYSTEM; i++)
  1328.         {
  1329.             for ( j = 0; j < IMMOBILE_AMT_SYSTEM; j++ )
  1330.             {
  1331.                 delete immobile_system[i][j];
  1332.             }
  1333.         }
  1334.         for ( i = 0; i < 5; i++ )
  1335.         {
  1336.             delete Ammo[i];
  1337.             delete Guns[i];
  1338.         }
  1339.         delete Ammo_AI[0];
  1340.         delete Ammo_AI[1];
  1341.         delete Guns_AI[0];
  1342.         delete Guns_AI[1];
  1343.         for ( i = 0; i < DEBRIS_AMT_SPACE; i++ )
  1344.         {
  1345.             delete debris_space[i];
  1346.         }
  1347.         for ( i = 0; i < DEBRIS_AMT_SYSTEM; i++ )
  1348.         {
  1349.             delete debris_system[i];
  1350.         }
  1351.         for ( i = 0; i < DEBRIS_AMT_PLANET; i++ )
  1352.         {
  1353.             delete debris_planet[i];
  1354.         }
  1355.         for ( i = 0; i < MAX_EXPLOSIONS; i++ )
  1356.         {
  1357.             if (activeEXP[i] == true)
  1358.             {
  1359.                 activeEXP[i] = false;
  1360.  
  1361.                 delete explosion[i];
  1362.             }
  1363.         }
  1364.         for (int i=0; i < NUM_ENEMIES; i++)
  1365.         {
  1366.             delete enemy[i];
  1367.         }
  1368.         delete boss;
  1369.         delete beeks;
  1370.     }
  1371.  
  1372.      // Sound
  1373.      Mix_CloseAudio();
  1374.  
  1375. #ifdef USE_SDL
  1376.     // SDL
  1377.      // text
  1378.      TTF_Quit();
  1379.  
  1380.      // Cross platform library
  1381.      SDL_Quit();
  1382. #else
  1383.     // Windows DirectX
  1384.      //release the Direct3D device
  1385.     if (d3ddev != NULL)
  1386.         d3ddev->Release();
  1387.  
  1388.     //release the Direct3D object
  1389.     if (d3d != NULL)
  1390.         d3d->Release();
  1391.  
  1392.     Kill_Keyboard();
  1393.     Kill_Mouse();
  1394.     dinput->Release();
  1395. #endif
  1396. }
  1397.  
  1398. // -------------------------------------- //
  1399. // ------------ Functions --------------- //
  1400.  
  1401.  
  1402. void drawText(char* outText, int screenX, int screenY,  CPCOLOR color = CP_GREEN)
  1403. {
  1404.     string text(outText);
  1405.     CPRECT textbox;
  1406.     textbox.left   = screenX;
  1407.     textbox.top    = screenY;
  1408.      textbox.right  = screenX + ( text.length() * 32);
  1409.     textbox.bottom = screenY + 32;
  1410.  
  1411.     graphicsEngine.DrawTextToRect( text, textbox, color); //CPCOLOR_ARGB( 255, 120, 255, 120 ) );
  1412. };
  1413.  
  1414. // draw numbers to screen
  1415. void drawNumbers(int number, int screenX, int screenY, CPCOLOR color)
  1416. {
  1417.     static char outText[10];
  1418.      sprintf(outText,"%d",number);
  1419.     string text(outText);
  1420.  
  1421.     CPRECT textbox;
  1422.     textbox.left   = screenX;
  1423.     textbox.top    = screenY;
  1424.     textbox.right  = screenX + ( text.length() * 32);
  1425.     textbox.bottom = screenY + 30;
  1426.  
  1427.     graphicsEngine.DrawTextToRect( text, textbox, color);
  1428. };
  1429.  
  1430.  
  1431.  
  1432.  
  1433. // checks to see if player is trying to move with keys
  1434. void Check_Keys()
  1435. {
  1436.     //added input key to allow player to re-activate background music ... key is "9", toggles Music on/off/resume
  1437.     if(input.IsKeyDown(0x39))
  1438.     {
  1439.         if(KEY_PRESSED)
  1440.             return;
  1441.         en_sounds.toggleMusic();
  1442.         KEY_PRESSED = true;
  1443.     }
  1444.  
  1445.     if (input.IsKeyDown(VK_DOWN))
  1446.     {
  1447.         if (KEY_PRESSED)
  1448.             return;
  1449.         // slowing down
  1450.         player->addSpeed(-2);
  1451.         KEY_PRESSED=true;      
  1452.     }
  1453.     else if (input.IsKeyDown(VK_UP))
  1454.     {
  1455.         if (KEY_PRESSED)
  1456.             return;
  1457.         // increment current speed
  1458.         player->addSpeed(1);
  1459.         KEY_PRESSED=true;
  1460.         player->useSolar(1); // burst uses some energy
  1461.     }
  1462.     else if (input.IsKeyDown(VK_RIGHT))
  1463.     {
  1464.         if (KEY_PRESSED)
  1465.             return;
  1466.  
  1467.         player->turn(RIGHT);
  1468.  
  1469.         KEY_PRESSED=true;
  1470.     }  
  1471.     else if (input.IsKeyDown(VK_LEFT))
  1472.     {
  1473.         if (KEY_PRESSED)
  1474.             return;
  1475.  
  1476.         player->turn(LEFT); // left
  1477.  
  1478.         KEY_PRESSED=true;
  1479.     }
  1480.     else if (input.IsKeyDown(VK_ADD) || input.IsKeyDown(VK_OEM_PLUS))
  1481.     { // zoom in
  1482.         if (KEY_PRESSED == true)
  1483.             return;
  1484.  
  1485.           if (DOCKED_AT > -1)
  1486.              switch (gameView)
  1487.              {
  1488.              case SPACE:
  1489.                  { // space -> system
  1490.                     // check if any enemies in this system
  1491.                     // if all planets cleared, then its safe
  1492.                     bool systemSafe=true;
  1493.                     int pcnt=0;
  1494.                     for (int p=0; p < NUM_MAPS_PLANET; p++)
  1495.                         if ( clearedArea[DOCKED_AT][p] == false)
  1496.                         {
  1497.                             pcnt++;
  1498.                             systemSafe=false;
  1499.                         }
  1500.                     // respawn aliens (1 per planet)
  1501.                     // pcnt = planets w enemies
  1502.                     // can have up to 10 planets
  1503.                     // max of 10 enemies
  1504.  
  1505.                          // when in SPACE view, there should be no boss attacks ...
  1506.                     if (! systemSafe)
  1507.                         respawnDrones(pcnt);
  1508.                     else
  1509.                         {
  1510.                             boss->setSTATE(INACTIVE);
  1511.                             deaths=0;
  1512.                         }
  1513.  
  1514.                     // keep track of what system # you are entering
  1515.                     docked.system = DOCKED_AT;
  1516.                     CURR_MAP.system = DOCKED_AT;
  1517.  
  1518.                     // save current location
  1519.                     prev.space.direction = player->getFacing();
  1520.                     prev.space.pt.x = player->getX();
  1521.                     prev.space.pt.y = player->getY();
  1522.  
  1523.                     // enter system
  1524.                     gameView=SYSTEM;
  1525.                    
  1526.                     // set speed,location,etc ...
  1527.                     SpeedX=0;
  1528.                     SpeedY=0;
  1529.  
  1530.                     player->setSpeed(0);           
  1531.                     player->setPT(enterSYSTEM.pt);
  1532.                     player->setFacing(enterSYSTEM.direction);
  1533.                     ScrollX = enterSYSTEM.scroll.x;
  1534.                     ScrollY = enterSYSTEM.scroll.y;
  1535.  
  1536.                     en_sounds.teleport();          
  1537.                  };
  1538.                  break;
  1539.              case SYSTEM:
  1540.                  { // SYSTEM -> PLANET
  1541.                     // check if any enemies in this system
  1542.                     // if all planets cleared, then its safe
  1543.                     if ( clearedArea[CURR_MAP.system][DOCKED_AT] == false)
  1544.                         {
  1545.                             // planet NOT Safe
  1546.                             // max of 10 enemies
  1547.                             respawnDrones(8);
  1548.                             deaths=0;
  1549.                             respawnBoss(true);
  1550.                         }
  1551.                     else
  1552.                         {
  1553.                             boss->setSTATE(INACTIVE);
  1554.                             deaths=0;
  1555.                         }
  1556.  
  1557.                     // keep track of what system # you are entering
  1558.                     docked.planet = DOCKED_AT;
  1559.                     CURR_MAP.planet = DOCKED_AT;
  1560.  
  1561.                     // save current location
  1562.                     prev.system.direction = player->getFacing();
  1563.                     prev.system.pt.x = player->getX();
  1564.                     prev.system.pt.y = player->getY();
  1565.  
  1566.                     // enter planet
  1567.                     gameView=PLANET;                       
  1568.                     SpeedX=0;
  1569.                     SpeedY=0;
  1570.                     player->setSpeed(0);
  1571.  
  1572.                     // move to starting location
  1573.                     player->setPT(enterPLANET.pt);
  1574.                     player->setFacing(enterPLANET.direction);
  1575.                     ScrollX = enterPLANET.scroll.x; // map scroll values for given xy starting location
  1576.                     ScrollY = enterPLANET.scroll.y;
  1577.  
  1578.                     en_sounds.teleport();
  1579.                  }; break;
  1580.               case PLANET: break; // do nothing, its already PLANET
  1581.             }
  1582.         KEY_PRESSED=true;
  1583.     }
  1584.     else if (input.IsKeyDown(VK_SUBTRACT) || input.IsKeyDown(VK_OEM_MINUS) || (player->getSTATE() == DEAD) )
  1585.     {
  1586.         if (KEY_PRESSED == true)
  1587.             return;
  1588.  
  1589.         // --- NOTE --- //
  1590.         // the "-" key  ///
  1591.         // sends you back to starting location and does full heal
  1592.           if (dontZone)
  1593.           {
  1594.                cout << "not supposed to zone right now ..." << endl;
  1595.                return;
  1596.           }
  1597.  
  1598.         switch (gameView)
  1599.         {
  1600.             case SPACE:
  1601.                 {
  1602.                          // make sure player doesnt zone repeatedly
  1603.                          dontZone = true;
  1604.  
  1605.                     // this is the "panic" button
  1606.                     // so if you FLY off the map or some crazy thing --
  1607.                     // hit "-" and .. teleports u back                 
  1608.                     CPPOINT dest = { 105, 105 }; // GAMEWORLDWIDTH HEIGHT
  1609.                     player->setPT(dest);
  1610.                     ScrollX=0;ScrollY=0;
  1611.  
  1612.                          player->fullHeal();
  1613.                     player->setSTATE(ACTIVE);
  1614.  
  1615.                     en_sounds.teleport();
  1616.                 }; break;
  1617.  
  1618.             case SYSTEM:
  1619.                 {
  1620.                          // make sure player doesnt zone repeatedly
  1621.                          dontZone = true;
  1622.                          
  1623.                          // SYSTEM -> SPACE view                   
  1624.                     gameView=SPACE;
  1625.  
  1626.                     // un-spawn the drones
  1627.                     respawnDrones(0); // sets them all to inactive
  1628.  
  1629.                          // we want boss to not spawn
  1630.                     boss->setSTATE(INACTIVE);
  1631.                     deaths=0; // reset boss
  1632.  
  1633.                     // move to starting location
  1634.                     player->setPT(prev.space.pt);
  1635.                     player->setFacing(prev.space.direction);
  1636.                     ScrollX = getScrollX(prev.space.pt.x);
  1637.                     ScrollY = getScrollY(prev.space.pt.y);
  1638.                     SpeedX= 0;
  1639.                     SpeedY=0;
  1640.                     player->setSpeed(0);
  1641.                     KEY_PRESSED=true;
  1642.  
  1643.                     player->fullHeal();
  1644.                     player->setSTATE(ACTIVE);
  1645.  
  1646.                     en_sounds.teleport();
  1647.  
  1648.                 };break;
  1649.             case PLANET:
  1650.                 {
  1651.                          // make sure player doesnt zone repeatedly
  1652.                          dontZone = true;
  1653.  
  1654.                          // PLANET -> SYSTEM view
  1655.                     gameView=SYSTEM;  
  1656.  
  1657.                     // check if any enemies in this system
  1658.                     // if all planets cleared, then its safe
  1659.                     int pcnt=0; // number of unsafe planets
  1660.                     for (int p=0; p < NUM_MAPS_PLANET; p++)
  1661.                         if ( clearedArea[DOCKED_AT][p] == false)
  1662.                               {
  1663.                                    cout << pcnt << ". system (" << DOCKED_AT << ") planet (" << p << ") not safe" << endl;
  1664.                             pcnt++;
  1665.                               }
  1666.                     if (pcnt > DIFF_LEVEL)
  1667.                         pcnt = DIFF_LEVEL;
  1668.  
  1669.                     // respawn aliens (1 per planet)
  1670.                     respawnDrones(pcnt); // NONE if all planets safe
  1671.                     boss->setSTATE(INACTIVE);
  1672.                     deaths=0; // reset boss
  1673.  
  1674.                          player->fullHeal();
  1675.                     player->setSTATE(ACTIVE);
  1676.  
  1677.                     // move to starting location
  1678.                     player->setPT(prev.system.pt);
  1679.                     player->setFacing(prev.system.direction);
  1680.                     ScrollX = getScrollX(prev.system.pt.x);
  1681.                     ScrollY = getScrollY(prev.system.pt.y);
  1682.                     SpeedX= 0;
  1683.                     SpeedY=0;
  1684.                     player->setSpeed(0);
  1685.                     KEY_PRESSED=true;
  1686.  
  1687.                     en_sounds.teleport();
  1688.                 };break;
  1689.         }
  1690.     }
  1691.     else if (input.IsKeyDown(VK_SPACE) || (SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(1)))
  1692.     {
  1693.           // disabled this - so you can hold down fire key
  1694. //          if (KEY_PRESSED == true)
  1695. //          return;
  1696.  
  1697.         // fire the weapon
  1698.         if ( player->canFire() )
  1699.         {          
  1700.             // ok got enough power to fire the gun
  1701.             switch(player->getGun())
  1702.             {          
  1703.                 case 4: guns.plasma();   break;
  1704.                 case 3: guns.missile();  break;
  1705.                 case 2: guns.cannon();   break;
  1706.                 case 1: guns.laser();    break;
  1707.                 default: guns.blaster(); break;
  1708.             }  
  1709.  
  1710.             // start bullets out front at a safe distance
  1711.             rCode = Ammo[player->getAmmo()]->spawnBullet(player->getAnchor(),player->getFacing());
  1712.             if (rCode > -1)
  1713.                 cntBullets++;
  1714.         }
  1715.         else
  1716.         {
  1717.             // SOUND
  1718.             // make a sound that tells player it couldnt fire because you are out of power!!!
  1719.         }  
  1720.  
  1721.         KEY_PRESSED=true;
  1722.     }
  1723.     else if ( (SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(2)) || SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(3) || input.IsKeyDown(VK_LCONTROL) || input.IsKeyDown(VK_RCONTROL) )
  1724.     {
  1725.           // allow player to hold down fire buttons //
  1726.     //  if (KEY_PRESSED == true)
  1727.     //      return;
  1728.           KEY_PRESSED=true;
  1729.  
  1730.         // left/right control
  1731.         // fires missile(s)
  1732.         if ( player->getAltLoaded() )
  1733.         {
  1734.             string filename;
  1735.             // ok got enough power to fire the gun
  1736.             switch(Alt_Weapon)
  1737.             {
  1738.                 case 4: guns.plasma(); break;      // torpedo
  1739.                 default: guns.missile(); break;    // missiles
  1740.             }  
  1741.  
  1742.             // start bullets out front at a safe distance
  1743.             CPPOINT destPT = player->getAnchor();//, player->getWidth(),player->getHeight(),player->getFacing());
  1744.             rCode= Ammo[Alt_Weapon]->spawnBullet(destPT,player->getFacing()); // missiles=3, torpedoes=4
  1745.             if (rCode > -1)
  1746.                 cntBullets++;
  1747.  
  1748.                // reset the delay for refire
  1749.                player->fireAlt();
  1750.         }
  1751.     }
  1752.     else if (input.IsKeyDown('1')) // 1 key
  1753.     {
  1754.         if (KEY_PRESSED == true)
  1755.             return;
  1756.  
  1757.         change.gun_change1();
  1758.            
  1759.         player->setGun(Guns[0],0);
  1760.         KEY_PRESSED=true;
  1761.     }
  1762.     else if (input.IsKeyDown('2')) // 2 key
  1763.     {
  1764.         if (KEY_PRESSED == true)
  1765.             return;
  1766.  
  1767.         change.gun_change2();
  1768.         player->setGun(Guns[1],1);
  1769.         KEY_PRESSED=true;
  1770.     }
  1771.     else if (input.IsKeyDown('3')) // 3 key
  1772.     {
  1773.         if (KEY_PRESSED == true)
  1774.             return;
  1775.  
  1776.         change.gun_change3();
  1777.         player->setGun(Guns[2],2);
  1778.         KEY_PRESSED=true;
  1779.     }
  1780.     else if (input.IsKeyDown('4')) // 4 key
  1781.     {
  1782.         if (KEY_PRESSED == true)
  1783.             return;
  1784.  
  1785.           change.gun_change4();
  1786.         Alt_Weapon = 3;
  1787.           player->setAltRecharge(DELAY_LONG);
  1788.         KEY_PRESSED=true;
  1789.     }
  1790.     else if (input.IsKeyDown('5')) // 5 key
  1791.     {
  1792.         if (KEY_PRESSED == true)
  1793.             return;
  1794.  
  1795.         change.gun_change4();
  1796.         Alt_Weapon = 4;
  1797.           player->setAltRecharge(DELAY_MED);
  1798.         KEY_PRESSED=true;
  1799.     }
  1800.      else if (input.IsKeyDown(0x61) || input.IsKeyDown(0x41)) // A,a key for AUTOFIRE
  1801.      {
  1802.         if (KEY_PRESSED == true)
  1803.             return;
  1804.  
  1805.           // simple toggle for auto fire
  1806.           if (AUTOFIRE)
  1807.                AUTOFIRE = false;
  1808.           else
  1809.                AUTOFIRE = true;
  1810.  
  1811.           KEY_PRESSED=true;
  1812.      }
  1813.     else
  1814.         KEY_PRESSED=false;
  1815.         // if none of the are pressed, we can press keys again
  1816.  
  1817.      // code to Auto fire weapons
  1818.      if (AUTOFIRE) // do this last to not interfere w/ other key pressing //
  1819.         // fire the weapon
  1820.         if ( player->canFire() )
  1821.         {          
  1822.             // start bullets out front at a safe distance
  1823.             rCode = Ammo[player->getAmmo()]->spawnBullet(player->getAnchor(),player->getFacing());
  1824.  
  1825.             if (rCode > -1)
  1826.                {
  1827.                 cntBullets++;
  1828.  
  1829.                  // make gun sounds
  1830.                  switch(player->getGun())
  1831.                  {                           
  1832.                      case 4:  guns.plasma();   break;
  1833.                      case 3:  guns.missile();  break;
  1834.                      case 2:  guns.cannon();   break;
  1835.                      case 1:  guns.laser();    break;
  1836.                      default: guns.blaster();  break;
  1837.                  }
  1838.                }
  1839.         }
  1840. }
  1841.  
  1842. bool canScroll(DIRS direction,int speed)
  1843. {
  1844.     //ScrollX and ScrollY
  1845.     int testX=ScrollX;
  1846.     int testY=ScrollY;
  1847.  
  1848.     switch(direction)
  1849.     {
  1850.         case NORTH:  testY-=speed;      break;
  1851.         case SOUTH:  testY+=speed;      break;
  1852.         case EAST:   testX+=speed;      break;
  1853.         case WEST:   testX-=speed;      break;
  1854.         case NE:     testX+=speed;testY-=speed; break;
  1855.         case NW:     testX-=speed;testY-=speed; break;
  1856.         case SE:       testX+=speed;testY+=speed; break;
  1857.         case SW:       testX-=speed;testY+=speed; break;
  1858.     }
  1859.  
  1860.     return ( min_max(testX,0,GAMEWORLDWIDTH - SCREEN_WIDTH) && min_max(testY,0,GAMEWORLDHEIGHT - SCREEN_HEIGHT) );
  1861. }
  1862.  
  1863. //This function updates the scrolling position and speed
  1864. void UpdateScrollPosition()
  1865. {
  1866.     bool doScrollLeft  =  ((player->getX() - ScrollX) <= (SCREEN_WIDTH  * 0.25) && ((player->getFacing() == WEST)  || (player->getFacing() == NW) || (player->getFacing() == SW)) ); // WEST   
  1867.     bool doScrollRight =  ((player->getX() - ScrollX) >= (SCREEN_WIDTH  * 0.75) && ((player->getFacing() == EAST)  || (player->getFacing() == NE) || (player->getFacing() == SE)) ); // EAST
  1868.     bool doScrollUp    =  ((player->getY() - ScrollY) <= (SCREEN_HEIGHT * 0.25) && ((player->getFacing() == NORTH) || (player->getFacing() == NW) || (player->getFacing() == NE)) );   // NORTH
  1869.     bool doScrollDown  =  ((player->getY() - ScrollY) >= (SCREEN_HEIGHT * 0.75) && ((player->getFacing() == SOUTH) || (player->getFacing() == SE) || (player->getFacing() == SW)) );   // SOUTH
  1870.  
  1871.     if ((doScrollLeft || doScrollRight || doScrollUp || doScrollDown) == false)
  1872.         return;
  1873.  
  1874.     // exit if cant scroll
  1875.     if (! canScroll(player->getFacing(),player->getSpeed()) )
  1876.         return;
  1877.  
  1878.     SpeedX = 0; SpeedY=0;
  1879.     switch(player->getFacing())
  1880.     {       // based on direction we are heading, scroll the background - if possible
  1881.             case NORTH: SpeedY -= player->getSpeed(); break;
  1882.             case SOUTH: SpeedY += player->getSpeed(); break;
  1883.             case EAST:  SpeedX += player->getSpeed(); break;
  1884.             case WEST:  SpeedX -= player->getSpeed(); break;
  1885.             case NE:    SpeedX += player->getSpeed();
  1886.                         SpeedY -= player->getSpeed(); break;
  1887.             case NW:    SpeedX -= player->getSpeed();
  1888.                         SpeedY -= player->getSpeed(); break;
  1889.             case SE:    SpeedX += player->getSpeed();
  1890.                         SpeedY += player->getSpeed(); break;
  1891.             case SW:    SpeedX -= player->getSpeed();
  1892.                         SpeedY += player->getSpeed(); break;
  1893.     }
  1894.  
  1895.     // N/S movement
  1896.     if ((ScrollY + SpeedY) < 0)
  1897.     {
  1898.         ScrollY = 0;
  1899.         SpeedY  = 0;
  1900.     }
  1901.     else if ((ScrollY + SpeedY) > (GAMEWORLDHEIGHT - SCREEN_HEIGHT))
  1902.     {
  1903.         ScrollY = GAMEWORLDHEIGHT - SCREEN_HEIGHT;
  1904.         SpeedY = 0;
  1905.     }
  1906.     else
  1907.         ScrollY += SpeedY;      // OK to scroll Y
  1908.  
  1909.     // E/W movement
  1910.     if ((ScrollX + SpeedX) < 0)
  1911.     {
  1912.         ScrollX = 0;
  1913.         SpeedX  = 0;
  1914.     }
  1915.     else if ( (ScrollX + SpeedX) > (GAMEWORLDWIDTH - SCREEN_WIDTH))
  1916.     {
  1917.         ScrollX = GAMEWORLDWIDTH - SCREEN_WIDTH;
  1918.         SpeedX = 0;
  1919.     }
  1920.     else
  1921.         ScrollX += SpeedX;
  1922.  
  1923.     // now see what direction we are facing
  1924.     if ( (SpeedX < 0) && (SpeedY < 0) ) // NW
  1925.         player->setFacing(NW);
  1926.     if ((SpeedX > 0) && (SpeedY < 0)) // NE
  1927.         player->setFacing(NE);
  1928.     if ((SpeedX < 0) && (SpeedY > 0)) // SW
  1929.         player->setFacing(SW);
  1930.     if ((SpeedX > 0) && (SpeedY > 0)) // SE
  1931.         player->setFacing(SE);
  1932.     if ((SpeedX == 0) && (SpeedY > 0)) // SOUTH
  1933.         player->setFacing(SOUTH);
  1934.     if ((SpeedX == 0) && (SpeedY < 0)) // NORTH
  1935.         player->setFacing(NORTH);
  1936.     if ((SpeedX > 0) && (SpeedY == 0)) // EAST
  1937.         player->setFacing(EAST);
  1938.     if ((SpeedX < 0) && (SpeedY == 0)) // WEST
  1939.         player->setFacing(WEST);
  1940.  
  1941. }
  1942.  
  1943. // draw bar at location; using current, max # and color
  1944. void drawBar(int x, int y,int curr,int max, int color)
  1945. {
  1946. //      BARS
  1947. //      grey        0
  1948. //      blue        1
  1949. //      green       2
  1950. //      orange      3
  1951. //      blue        4
  1952. //      red         5
  1953. //      yellow      6
  1954.  
  1955.     int width  = 64;
  1956.     int height = 6;
  1957.  
  1958.     // 0 is grey bar
  1959.     // source
  1960.     CPRECT r1;
  1961.     r1.left   = 0;
  1962.     r1.right  = width;
  1963.     r1.top    = 0;
  1964.     r1.bottom = height;
  1965.  
  1966.     // dest
  1967.     CPRECT r2;
  1968.     r2.left = x;
  1969.     r2.top  = y;
  1970.     r2.right = x + (width*scalex);
  1971.     r2.bottom = y + (height*scaley);
  1972.  
  1973.     graphicsEngine.DrawStretchTexture(color_bars, r1, r2);
  1974.  
  1975.     // draw bar % percentage
  1976.     // change width to match %
  1977.     r1.left = (width * color);
  1978.     r1.right = r1.left + width;
  1979.     if (curr < max)
  1980.     {
  1981.         // only draw a portion of the rect if not equal
  1982.         r1.right = r1.left + (width * curr / max);
  1983.         r2.right = r2.left + (width * scalex * curr / max);
  1984.     }
  1985.     graphicsEngine.DrawStretchTexture(color_bars, r1, r2);
  1986. }
  1987.  
  1988. // returns t/f is given # is with the range
  1989. bool min_max(int num, int min,int max)
  1990. {
  1991.     return ((num <= max) && (num >= min));
  1992. }
  1993.  
  1994.  
  1995. void drawPlanets()
  1996. {
  1997.     CPlanet *planet;
  1998.  
  1999.     // check for debris leaving the screen
  2000.     switch(gameView)
  2001.     {
  2002.         case SPACE:
  2003.             {
  2004.                 for (int i=0; i < IMMOBILE_AMT_SPACE; i++)
  2005.                 {
  2006.                     planet = immobile_space[i];
  2007.                     CPPOINT dest = planet->getPT();
  2008.                     dest.x -= ScrollX; // since they use game world coords
  2009.                     dest.y -= ScrollY; // subtract the offset values to get screen coord
  2010.  
  2011.  
  2012.                     // draw the sprite if it would appear on screen
  2013.                     if ( (((dest.x + planet->getWidth()) > 0) || (dest.y + planet->getHeight() >= 0)) && (( dest.x < SCREEN_WIDTH) || (dest.y  < SCREEN_HEIGHT)) )
  2014.                     {
  2015.                         if  ( (hitPlanet[0].space[i] == true) && (planet->getMap() > -1) )                         
  2016.                         {
  2017.                             graphicsEngine.DrawTexture( dest.x, dest.y,
  2018.                                         yellowBmp->getWidth(),yellowBmp->getHeight(),
  2019.                                         ScaleX, ScaleY,
  2020.                                         planet->getAngle(),
  2021.                                         CPCOLOR_XRGB(255,255,255),
  2022.                                         yellowBmp->getTexture(),
  2023.                                         NULL, //&yellowBmp->getRect(),
  2024.                                         false);
  2025.                         }
  2026.  
  2027.                         graphicsEngine.DrawTexture( dest.x, dest.y,
  2028.                                     planet->getWidth(),planet->getHeight(),
  2029.                                     ScaleX, ScaleY,
  2030.                                     planet->getAngle(),
  2031.                                     CPCOLOR_XRGB(255,255,255),
  2032.                                     planet->getTexture(),
  2033.                                     &planet->getRect(),
  2034.                                     false);
  2035.                     }
  2036.                 }
  2037.             };break;
  2038.         case SYSTEM:
  2039.             {
  2040.                     int pMap;
  2041.                     bool pSafe;
  2042.                 for (int i=0; i < IMMOBILE_AMT_SYSTEM; i++)
  2043.                 {
  2044.                     planet = immobile_system[docked.system][i];           // planet #
  2045.                          pMap   = immobile_system[docked.system][i]->getMap();    // map, if any located there
  2046.                          pSafe  = clearedArea[docked.system][i];
  2047.  
  2048.                     CPPOINT dest = planet->getPT();
  2049.                     dest.x -= ScrollX; // since they use game world coords
  2050.                     dest.y -= ScrollY; // subtract the offset values to get screen coord
  2051.  
  2052.                     // draw the sprite if it would appear on screen
  2053.                     if ( (((dest.x + planet->getWidth()) > 0) || (dest.y + planet->getHeight() >= 0)) && (( dest.x < SCREEN_WIDTH) || (dest.y  < SCREEN_HEIGHT)) )
  2054.                     {
  2055.                               // DEBUG
  2056.                               // put RED circle behind planets not cleared, YELLOW if they are cleared
  2057.                               if (pMap > -1) // currPlanetColl.system
  2058.                                    drawNumbers(pMap,16+(dest.x + planet->getWidth()),dest.y - 16,CP_RED);
  2059.  
  2060.                         if (hitPlanet[docked.system].system[i] == true)
  2061.                             graphicsEngine.DrawTexture( dest.x, dest.y,
  2062.                                         yellowBmp->getWidth(),yellowBmp->getHeight(),
  2063.                                         ScaleX, ScaleY,
  2064.                                         planet->getAngle(),
  2065.                                         CPCOLOR_XRGB(255,255,255),
  2066.                                         yellowBmp->getTexture(),
  2067.                                         NULL,
  2068.                                         false);
  2069.  
  2070.                               if (! pSafe)
  2071.                               {
  2072.                                    //infected_planet
  2073.                              graphicsEngine.DrawTexture( dest.x, dest.y,
  2074.                                          infectedPlanet->getWidth(),infectedPlanet->getHeight(),
  2075.                                          ScaleX, ScaleY,
  2076.                                          planet->getAngle(), // uses same angle as host planet
  2077.                                          CPCOLOR_XRGB(255,255,255),
  2078.                                          infectedPlanet->getTexture(),
  2079.                                          &infectedPlanet->getRect(),
  2080.                                          false);
  2081.                               }
  2082.                               else
  2083.                              graphicsEngine.DrawTexture( dest.x, dest.y,
  2084.                                          planet->getWidth(),planet->getHeight(),
  2085.                                          ScaleX, ScaleY,
  2086.                                          planet->getAngle(),
  2087.                                          CPCOLOR_XRGB(255,255,255),
  2088.                                          planet->getTexture(),
  2089.                                          &planet->getRect(),
  2090.                                          false);
  2091.  
  2092.  
  2093.                     }
  2094.                 }
  2095.             };break;
  2096.         case PLANET:
  2097.             {
  2098.                 for (int i=0; i < IMMOBILE_AMT_PLANET; i++)
  2099.                 {
  2100.                     planet = immobile_planet[docked.planet][i];
  2101.  
  2102.                     CPPOINT dest = planet->getPT();
  2103.                     dest.x -= ScrollX; // since they use game world coords
  2104.                     dest.y -= ScrollY; // subtract the offset values to get screen coord
  2105.  
  2106.                     // draw the sprite if it would appear on screen
  2107.                     if ( (((dest.x + planet->getWidth()) > 0) || (dest.y + planet->getHeight() >= 0)) && (( dest.x < SCREEN_WIDTH) || (dest.y  < SCREEN_HEIGHT)) )
  2108.                     {
  2109.                         if ((hitPlanet[docked.planet].surface[i] == true) && (planet->getMap() > -1))
  2110.                         {
  2111.                             graphicsEngine.DrawTexture( dest.x, dest.y,
  2112.                                         yellowBmp->getWidth(),yellowBmp->getHeight(),
  2113.                                         ScaleX, ScaleY,
  2114.                                         planet->getAngle(),
  2115.                                         CPCOLOR_XRGB(255,255,255),
  2116.                                         yellowBmp->getTexture(),
  2117.                                         NULL, //&yellowBmp->getRect(),
  2118.                                         false);
  2119.                         }
  2120.  
  2121.                         graphicsEngine.DrawTexture( dest.x, dest.y,
  2122.                                     planet->getWidth(),planet->getHeight(),
  2123.                                     ScaleX, ScaleY, planet->getAngle(),
  2124.                                     CPCOLOR_XRGB(255,255,255),
  2125.                                     planet->getTexture(),
  2126.                                     &planet->getRect(),
  2127.                                     false);
  2128.                     }
  2129.                 };
  2130.             };break;
  2131.     } // end case ...
  2132. };
  2133. //draw the debris sprites
  2134. void drawDebris()
  2135. {
  2136.     CDebris *debris;
  2137.  
  2138.     // check for debris leaving the screen
  2139.     switch(gameView)
  2140.     {
  2141.         case SPACE:
  2142.             {
  2143.                 for (int i=0; i < DEBRIS_AMT_SPACE; i++)
  2144.                 {
  2145.                     debris = debris_space[i];  
  2146.                     CPPOINT dest = {debris->getX(),debris->getY()};
  2147.                     dest.x -= ScrollX; // since they use game world coords
  2148.                     dest.y -= ScrollY; // subtract the offset values to get screen coord
  2149.  
  2150.                     // draw the sprite if it would appear on screen
  2151.                     if ( (((dest.x + debris->getWidth()) > 0) || (dest.y + debris->getHeight() >= 0)) && (( dest.x < SCREEN_WIDTH) || (dest.y  < SCREEN_HEIGHT)) )
  2152.                     {
  2153.                         if (hitDebris.space[i] == true)
  2154.                         {
  2155.                             graphicsEngine.DrawTexture( dest.x, dest.y,
  2156.                                         redBmp->getWidth(),redBmp->getHeight(),
  2157.                                         scalex, scaley,
  2158.                                         debris->getAngle(),
  2159.                                         CPCOLOR_XRGB(255,255,255),
  2160.                                         redBmp->getTexture(),
  2161.                                         NULL,  //&debris->getRect(),
  2162.                                         false);
  2163.                         }
  2164.  
  2165.                         graphicsEngine.DrawTexture( dest.x, dest.y,
  2166.                                     debris->getWidth(),debris->getHeight(),
  2167.                                     scalex, scaley,
  2168.                                     debris->getAngle(),
  2169.                                     CPCOLOR_XRGB(255,255,255),
  2170.                                     debris->getTexture(),
  2171.                                     &debris->getRect(),
  2172.                                     false);
  2173.                     }
  2174.                 }
  2175.             };break;
  2176.         case SYSTEM:
  2177.             {
  2178.                 for (int i=0; i < DEBRIS_AMT_SYSTEM; i++)
  2179.                 {
  2180.                     debris = debris_system[i]; 
  2181.  
  2182.                     CPPOINT dest = {debris->getX(),debris->getY()};
  2183.                     dest.x -= ScrollX; // since they use game world coords
  2184.                     dest.y -= ScrollY; // subtract the offset values to get screen coord
  2185.  
  2186.                     // draw the sprite if it would appear on screen
  2187.                     if ( (((dest.x + debris->getWidth()) > 0) || (dest.y + debris->getHeight() >= 0)) && (( dest.x < SCREEN_WIDTH) || (dest.y  < SCREEN_HEIGHT)) )
  2188.                     {
  2189.                         if (hitDebris.system[i] == true)
  2190.                         {
  2191.                             graphicsEngine.DrawTexture( dest.x, dest.y,
  2192.                                         redBmp->getWidth(),redBmp->getHeight(),
  2193.                                         scalex, scaley,
  2194.                                         debris->getAngle(),
  2195.                                         CPCOLOR_XRGB(255,255,255),
  2196.                                         redBmp->getTexture(),
  2197.                                         NULL,  //&debris->getRect(),
  2198.                                         false);
  2199.                         }
  2200.  
  2201.                         graphicsEngine.DrawTexture( dest.x, dest.y,
  2202.                                     debris->getWidth(),debris->getHeight(),
  2203.                                     scalex, scaley,
  2204.                                     debris->getAngle(),
  2205.                                     CPCOLOR_XRGB(255,255,255),
  2206.                                     debris->getTexture(),
  2207.                                     &debris->getRect(),
  2208.                                     false);
  2209.                     }
  2210.                 }
  2211.             };break;
  2212.         case PLANET:
  2213.             {
  2214.                 for (int i=0; i < DEBRIS_AMT_PLANET; i++)
  2215.                 {
  2216.                     debris = debris_planet[i]; 
  2217.  
  2218.                     CPPOINT dest = {debris->getX(),debris->getY()};
  2219.                     dest.x -= ScrollX; // since they use game world coords
  2220.                     dest.y -= ScrollY; // subtract the offset values to get screen coord
  2221.  
  2222.                     // draw the sprite if it would appear on screen
  2223.                     if ( (((dest.x + debris->getWidth()) > 0) || (dest.y + debris->getHeight() >= 0)) && (( dest.x < SCREEN_WIDTH) || (dest.y  < SCREEN_HEIGHT)) )
  2224.                     {
  2225.                         if (hitDebris.surface[i] == true)
  2226.                         {
  2227.                             graphicsEngine.DrawTexture( dest.x, dest.y,
  2228.                                         redBmp->getWidth(),redBmp->getHeight(),
  2229.                                         scalex, scaley,
  2230.                                         debris->getAngle(),
  2231.                                         CPCOLOR_XRGB(255,255,255),
  2232.                                         yellowBmp->getTexture(),
  2233.                                         NULL,  //&debris->getRect(),
  2234.                                         false);
  2235.                         }
  2236.  
  2237.                         graphicsEngine.DrawTexture( dest.x, dest.y,
  2238.                                     debris->getWidth(),debris->getHeight(),
  2239.                                     scalex, scaley, debris->getAngle(),
  2240.                                     CPCOLOR_XRGB(255,255,255),
  2241.                                     debris->getTexture(),
  2242.                                     &debris->getRect(),
  2243.                                     false);
  2244.                     }
  2245.                 };
  2246.             };break;
  2247.     } // end case ...
  2248. }
  2249.  
  2250.  
  2251. // determine which direction to turn to face target
  2252. DIRS getDirection(CPPOINT sourcePT, CPPOINT targetPT)
  2253. {
  2254.     int a = 0; // centered horizontally
  2255.     // left to right
  2256.     if (sourcePT.x < targetPT.x) // left
  2257.         a = -1;
  2258.     if (sourcePT.x > targetPT.x) // right
  2259.         a = 1;
  2260.  
  2261.     int b = 0; // centered vertically
  2262.     // top to bottom
  2263.     if (sourcePT.y < targetPT.y) // above
  2264.         b = -1;
  2265.     if (sourcePT.y > targetPT.y) // below
  2266.         b = 1;
  2267.  
  2268.     switch(a)
  2269.     {
  2270.         case -1:
  2271.             {
  2272.                 if (b == -1)
  2273.                     { return NW; }
  2274.                 else if (b == 1)
  2275.                     { return SW; }
  2276.                 else
  2277.                     return WEST;
  2278.             }; break;
  2279.         case 1:
  2280.             {
  2281.                 if (b == -1)
  2282.                     { return NE; }
  2283.                 else if (b == 1)
  2284.                     { return SE; }
  2285.                 else
  2286.                     return EAST;
  2287.             }; break;
  2288.         case 0:
  2289.             {
  2290.                 if (b == -1)
  2291.                     { return NORTH; }
  2292.                 else
  2293.                     { return SOUTH; }
  2294.             };break;
  2295.     }
  2296.  
  2297.     return EAST; // default catch all
  2298. }
  2299.  
  2300. // returns distance in pixels
  2301. float findDistance(CPPOINT pt1,CPPOINT pt2)
  2302. {
  2303.     float distance;
  2304.     float   dx = pt1.x - pt2.x;
  2305.     float   dy = pt1.y - pt2.y;
  2306.     distance = sqrt(dx*dx + dy*dy);
  2307.     return distance;
  2308. }
  2309.  
  2310. // test for collisions
  2311. int SpriteCollision(CSprite *sprite1, CSprite *sprite2)
  2312. {
  2313.     CPRECT rect1,rect2,dest;
  2314.  
  2315.     rect1.left   = sprite1->getX() + 1;
  2316.     rect1.top    = sprite1->getY() + 1;
  2317.     rect1.right  = sprite1->getX() + sprite1->getWidth()  -2;
  2318.     rect1.bottom = sprite1->getY() + sprite1->getHeight() -2;
  2319.  
  2320.     rect2.left   = sprite2->getX() + 1;
  2321.     rect2.top    = sprite2->getY() + 1;
  2322.     rect2.right  = sprite2->getX() + sprite2->getWidth()  -2;
  2323.     rect2.bottom = sprite2->getY() + sprite2->getHeight() -2;
  2324.  
  2325. #ifdef USE_SDL
  2326.     return IntersectCPRect(dest, rect1, rect2);
  2327. #else
  2328.    return IntersectRect((LPRECT)&dest, (LPRECT)&rect1, (LPRECT)&rect2);
  2329. #endif
  2330. }
  2331.  
  2332. // test for collisions
  2333. bool rectCollision(CPRECT r1, CPRECT r2)
  2334. {
  2335.  
  2336. return ( r1.left   < r2.right  &&
  2337.          r1.top    < r2.bottom &&
  2338.          r1.right  > r2.left   &&        
  2339.          r1.bottom > r2.top    );
  2340. }
  2341.  
  2342. bool circleCollision(CPPOINT a,int radius1, CPPOINT b, int radius2)
  2343. {
  2344.     int dx = b.x - a.x;
  2345.     int dy = b.y - a.y;
  2346.     int radii = radius1 + radius2;
  2347.     return ( (dx*dx)+(dy*dy) < (radii * radii) );
  2348. };
  2349.  
  2350. int planetCollision(CSprite *target)
  2351. {
  2352.     CPlanet *planet;
  2353.  
  2354.     int i = -1;
  2355.  
  2356.     // see if player has collided with any debris
  2357.     switch(gameView)
  2358.     {
  2359.         case SPACE:
  2360.         {
  2361.             for (i=0; i < IMMOBILE_AMT_SPACE; i++)
  2362.             {
  2363.                 planet = immobile_space[i];
  2364.  
  2365.                 CPPOINT targetPT = target->getAnchor();
  2366.                 CPPOINT planetPT = planet->getAnchor();
  2367.  
  2368.                 int temp = target->getHeight();
  2369.                 if (target->getWidth() < target->getHeight())
  2370.                     temp = target->getWidth();
  2371.                 int radiusT = temp * COLL_RADIUS * scalex; // should cover most of the sprite in its radius ... 96/2=48-4=44
  2372.  
  2373.                 temp = planet->getHeight();
  2374.                 if (planet->getWidth() < planet->getHeight())
  2375.                     temp = planet->getWidth();             
  2376.                 int radiusD = temp * COLL_RADIUS; // should cover most of the sprite in its radius ... 120/2=60-
  2377.  
  2378.                 // use circle collision
  2379.                 if (circleCollision(targetPT,radiusT,planetPT,radiusD))
  2380.                 {
  2381.                     hitPlanet[0].space[i] = true;
  2382.                     return i;  
  2383.                 }
  2384.                 else
  2385.                     hitPlanet[0].space[i] = false;                 
  2386.             }
  2387.         }; break;
  2388.         case SYSTEM:
  2389.         {
  2390.             for (i=0; i < IMMOBILE_AMT_SYSTEM; i++)
  2391.             {
  2392.                 planet = immobile_system[docked.system][i];
  2393.  
  2394.                 CPPOINT targetPT = target->getAnchor();
  2395.                 CPPOINT planetPT = planet->getAnchor();
  2396.  
  2397.                 int temp = target->getHeight();
  2398.                 if (target->getWidth() < target->getHeight())
  2399.                     temp = target->getWidth();
  2400.                 int radiusT = temp * COLL_RADIUS * scalex; // should cover most of the sprite in its radius ... 96/2=48-4=44
  2401.  
  2402.                 temp = planet->getHeight();
  2403.                 if (planet->getWidth() < planet->getHeight())
  2404.                     temp = planet->getWidth();             
  2405.                 int radiusD = temp * COLL_RADIUS; // should cover most of the sprite in its radius ... 120/2=60-
  2406.  
  2407.                 // use circle collision
  2408.                 if (circleCollision(targetPT,radiusT,planetPT,radiusD))
  2409.                 {
  2410.                     hitPlanet[docked.system].system[i] = true;
  2411.                     return i;  
  2412.                 }
  2413.                 else
  2414.                     hitPlanet[docked.system].system[i] = false;
  2415.             }
  2416.         }; break;
  2417.         case PLANET:
  2418.         {
  2419.             for (i=0; i < IMMOBILE_AMT_PLANET; i++)
  2420.             {
  2421.                 planet = immobile_planet[docked.planet][i];
  2422.  
  2423.                 CPPOINT targetPT = target->getAnchor();
  2424.                 CPPOINT planetPT = planet->getAnchor();
  2425.  
  2426.                 int temp = target->getHeight();
  2427.                 if (target->getWidth() < target->getHeight())
  2428.                     temp = target->getWidth();
  2429.                 int radiusT = temp * COLL_RADIUS * scalex; // should cover most of the sprite in its radius ... 96/2=48-4=44
  2430.  
  2431.                 temp = planet->getHeight();
  2432.                 if (planet->getWidth() < planet->getHeight())
  2433.                     temp = planet->getWidth();             
  2434.                 int radiusD = temp * COLL_RADIUS; // should cover most of the sprite in its radius ... 120/2=60-
  2435.  
  2436.                 // use circle collision
  2437.                 if (circleCollision(targetPT,radiusT,planetPT,radiusD))
  2438.                 {
  2439.                     hitPlanet[docked.planet].surface[i] = true;
  2440.                     return i;  
  2441.                 }
  2442.                 else
  2443.                     hitPlanet[docked.planet].surface[i] = false;
  2444.             }
  2445.         };break;
  2446.     }
  2447.  
  2448.     // if no collisions (return -1)
  2449.     return -1;
  2450. } // end planet collision testing
  2451.  
  2452. int debrisCollision( CSprite *target)
  2453. {
  2454.     CDebris *debris;
  2455.  
  2456.     int i;
  2457.     // see if player has collided with any debris
  2458.     switch(gameView)
  2459.     {
  2460.         case SPACE:
  2461.         {          
  2462.             for (i=0; i < DEBRIS_AMT_SPACE; i++)
  2463.             {
  2464.                 debris = debris_space[i];
  2465.  
  2466.                 CPPOINT targetPT = target->getAnchor();
  2467.                 CPPOINT debrisPT = debris->getAnchor();
  2468.  
  2469.                 int temp = target->getHeight();
  2470.                 if (target->getWidth() < target->getHeight())
  2471.                     temp = target->getWidth();
  2472.                 int radiusT = temp * COLL_RADIUS * scalex; // should cover most of the sprite in its radius ... 96/2=48-4=44
  2473.  
  2474.                 temp = debris->getHeight();
  2475.                 if (debris->getWidth() < debris->getHeight())
  2476.                     temp = debris->getWidth();             
  2477.                 int radiusD = temp * COLL_RADIUS; // should cover most of the sprite in its radius ... 120/2=60-
  2478.  
  2479.                 // use circle collision
  2480.                 if (circleCollision(targetPT,radiusT,debrisPT,radiusD))
  2481.                 {
  2482.                     hitDebris.space[i] = true;
  2483.                     return i;  
  2484.                 }
  2485.                 else
  2486.                     hitDebris.space[i] = false;
  2487.             }
  2488.         }; break;
  2489.         case SYSTEM:
  2490.         {
  2491.             for (i=0; i < DEBRIS_AMT_SYSTEM; i++)
  2492.             {
  2493.                 debris = debris_system[i];
  2494.  
  2495.                 CPPOINT targetPT = target->getAnchor();
  2496.                 CPPOINT debrisPT = debris->getAnchor();
  2497.  
  2498.                 int temp = target->getHeight();
  2499.                 if (target->getWidth() < target->getHeight())
  2500.                     temp = target->getWidth();
  2501.                 int radiusT = temp * COLL_RADIUS * scalex; // should cover most of the sprite in its radius ... 96/2=48-4=44
  2502.  
  2503.                 temp = debris->getHeight();
  2504.                 if (debris->getWidth() < debris->getHeight())
  2505.                     temp = debris->getWidth();             
  2506.                 int radiusD = temp * COLL_RADIUS; // should cover most of the sprite in its radius ... 120/2=60-
  2507.  
  2508.                 // use circle collision
  2509.                 if (circleCollision(targetPT,radiusT,debrisPT,radiusD))
  2510.                 {
  2511.                     hitDebris.system[i] = true;
  2512.                     return i;  
  2513.                 }
  2514.                 else
  2515.                     hitDebris.system[i] = false;
  2516.             }
  2517.         }; break;
  2518.         case PLANET:
  2519.         {
  2520.             for (i=0; i < DEBRIS_AMT_PLANET; i++)
  2521.             {
  2522.                 debris = debris_planet[i];
  2523.  
  2524.                 CPPOINT targetPT = target->getAnchor();
  2525.                 CPPOINT debrisPT = debris->getAnchor();
  2526.  
  2527.                 int temp = target->getHeight();
  2528.                 if (target->getWidth() < target->getHeight())
  2529.                     temp = target->getWidth();
  2530.                 int radiusT = temp * COLL_RADIUS * scalex; // should cover most of the sprite in its radius ... 96/2=48-4=44
  2531.  
  2532.                 temp = debris->getHeight();
  2533.                 if (debris->getWidth() < debris->getHeight())
  2534.                     temp = debris->getWidth();             
  2535.                 int radiusD = temp * COLL_RADIUS; // should cover most of the sprite in its radius ... 120/2=60-
  2536.  
  2537.                 // use circle collision
  2538.                 if (circleCollision(targetPT,radiusT,debrisPT,radiusD))
  2539.                 {
  2540.                     hitDebris.surface[i] = true;
  2541.                     return i;  
  2542.                 }
  2543.                 else
  2544.                     hitDebris.surface[i] = false;
  2545.             }
  2546.         };break;
  2547.     }
  2548.  
  2549.     // if no collisions
  2550.     return -1;
  2551. } // end debris collision testing
  2552.  
  2553.  
  2554. // checks if debris has left screen and respawns it randomly
  2555. // only used for the space view
  2556. void respawnDebris()
  2557. {
  2558.     // it checks for objects leaving the game map
  2559.     // and respawns them with new image
  2560.     // heading etc ... from one of the 4 map borders
  2561.     for (int i=0; i < DEBRIS_AMT_SPACE; i++)
  2562.         debris_space[i]->checkExit();
  2563.     for (int i=0; i < DEBRIS_AMT_SYSTEM; i++)
  2564.         debris_system[i]->checkExit();
  2565.     for (int i=0; i < DEBRIS_AMT_PLANET; i++)
  2566.         debris_planet[i]->checkExit();
  2567. }
  2568.  
  2569.  
  2570. // calculates new velocity and heading
  2571. void collision2Ds(double m1, double m2,
  2572.                  double x1, double y1, double x2, double y2)
  2573. {
  2574. // globals
  2575. //double vPx; vx1
  2576. //double vPy; vy1
  2577. //double vJx; vx2
  2578. //double vJy; vy2
  2579.        double  m21,dvx2,a,x21,y21,vx21,vy21,fy21,sign;
  2580.  
  2581.        m21=m2/m1;
  2582.        x21=x2-x1;
  2583.        y21=y2-y1;
  2584.        vx21=vJx-vPx;
  2585.        vy21=vJy-vPy;
  2586.  
  2587. //     *** return old velocities if balls are not approaching ***
  2588.        if ( (vx21*x21 + vy21*y21) >= 0) return;
  2589.  
  2590.        fy21=1.0E-12*fabs(y21);                            
  2591.        if ( fabs(x21)<fy21 ) {  
  2592.                    if (x21<0) { sign=-1; } else { sign=1;}  
  2593.                    x21=fy21*sign;
  2594.         }
  2595.  
  2596. //     ***  update velocities ***
  2597.        a=y21/x21;
  2598.        dvx2= -2*(vx21 +a*vy21)/((1+a*a)*(1+m21)) ;
  2599.        vJx=vJx+dvx2;
  2600.        vJy=vJy+a*dvx2;
  2601.        vPx=vPx-m21*dvx2;
  2602.        vPy=vPy-a*m21*dvx2;
  2603. }
  2604.  
  2605. // translates a given x location to get ScrollX value
  2606. int getScrollX(int x)
  2607. {
  2608.     int temp = 0;
  2609.     if (x < (SCREEN_WIDTH*0.75))
  2610.         return 0;
  2611.  
  2612.     temp = x - (SCREEN_WIDTH /2); // 1000 - 480 = 520 scrollx
  2613.     if ( temp > (GAMEWORLDWIDTH - SCREEN_WIDTH))
  2614.         temp = GAMEWORLDWIDTH - SCREEN_WIDTH;
  2615.  
  2616.     return temp;
  2617. };
  2618.  
  2619. // translates a given y location to get ScrollY value
  2620. int getScrollY(int y)
  2621. {
  2622.     int temp = 0;
  2623.     if (y < (SCREEN_HEIGHT*0.75))
  2624.         return 0;
  2625.  
  2626.     temp = y - (SCREEN_HEIGHT /2); // 1000 - 480 = 520 scrollx
  2627.     if ( temp > (GAMEWORLDHEIGHT - SCREEN_HEIGHT))
  2628.         temp = GAMEWORLDHEIGHT - SCREEN_HEIGHT;
  2629.  
  2630.     return temp;
  2631. };
  2632.  
  2633. void loadMaps()
  2634. {
  2635.     int cnt=0;
  2636.     char buffer[256];
  2637.     char line[255];
  2638.     char filename[100];
  2639.     char* Filename;
  2640.  
  2641.     // setup cleared - by default all areas are cleared, until maps are loaded
  2642.     for (int s=0;s < NUM_MAPS_SYSTEM; s++)
  2643.         for (int p=0;p<NUM_MAPS_PLANET;p++)
  2644.             clearedArea[s][p] = true;
  2645.  
  2646. // ------------------------------------------------------------------------
  2647.     for (int map=0; map < NUM_MAPS_PLANET; map++)
  2648.     {
  2649.         sprintf(filename,"./Media/static_surface_0%d.txt",map);
  2650.  
  2651.         // load map data
  2652.         ifstream mapFile(filename);
  2653.  
  2654.         // read in data from map file
  2655.         assert(! mapFile.fail());
  2656.  
  2657.         // BITMAP SOURCE
  2658.         Filename = "./Media/Images/static_surface.png";
  2659.  
  2660.         cnt=0;
  2661.         while ((! mapFile.eof()) && (cnt < IMMOBILE_AMT_PLANET))
  2662.         {
  2663.             // read in the map data    
  2664.             mapFile.getline(line, sizeof(buffer), ','); // X
  2665.             int x = atoi(line);        
  2666.             mapFile.getline(line, sizeof(buffer), ','); // Y
  2667.             int y = atoi(line);        
  2668.             mapFile.getline(line, sizeof(buffer), ','); // FRAME #
  2669.             int frame = atoi(line);    
  2670.             mapFile.getline(line, sizeof(buffer), ','); // ANGLE
  2671.             int rotation = atoi(line);     
  2672.             mapFile.getline(line, sizeof(buffer), '\n'); // grab the end of line
  2673.             int Map = atoi(line);                   // rotation speed (if any)
  2674.  
  2675.             immobile_planet[map][cnt] = new CPlanet(x,y,120,110,Filename,IMMOBILE_AMT_PLANET);     
  2676.             immobile_planet[map][cnt]->setFrame(frame-1);
  2677.             immobile_planet[map][cnt]->setFacing(NORTH);
  2678.             immobile_planet[map][cnt]->setMap(Map);
  2679.             immobile_planet[map][cnt]->setAngle(rotation);
  2680.  
  2681.             hitPlanet[map].surface[cnt] = false;           
  2682.  
  2683.             assert(immobile_planet[map][cnt]);     
  2684.  
  2685.             cnt++;
  2686.         }
  2687.         mapFile.close();
  2688.     }
  2689. // ------------------------------------------------------------------------
  2690.     ifstream spaceFile("./Media/static_space_00.txt");
  2691.     assert(! spaceFile.fail());
  2692.  
  2693.     Filename = "./Media/Images/static_space.png";
  2694.  
  2695.     cnt=0;
  2696.     while ((! spaceFile.eof()) && (cnt < IMMOBILE_AMT_SPACE))
  2697.     {
  2698.         // read in the map data    
  2699.         spaceFile.getline(line, sizeof(buffer), ','); // X
  2700.         int x = atoi(line);        
  2701.         spaceFile.getline(line, sizeof(buffer), ','); // Y
  2702.         int y = atoi(line);        
  2703.         spaceFile.getline(line, sizeof(buffer), ','); // FRAME #
  2704.         int frame = atoi(line);    
  2705.         spaceFile.getline(line, sizeof(buffer), ','); // ANGLE
  2706.         int rotation = atoi(line);     
  2707.         spaceFile.getline(line, sizeof(buffer), '\n'); // grab the end of line
  2708.         int map = atoi(line);                   // rotation speed (if any)
  2709.  
  2710.         immobile_space[cnt] = new CPlanet(x,y,120,110,Filename,IMMOBILE_SPRITES_SPACE);    
  2711.         immobile_space[cnt]->setFrame(frame-1);
  2712.         immobile_space[cnt]->setAngle(rotation);
  2713.         immobile_space[cnt]->setMap(map);
  2714.         hitPlanet[0].space[cnt] = false;
  2715.         assert(immobile_space[cnt]);
  2716.  
  2717.         cnt++;
  2718.     }
  2719.     spaceFile.close();
  2720. // ------------------------------------------------------------------------
  2721.     for (int map=0; map < NUM_MAPS_SYSTEM; map++)
  2722.     {
  2723.         sprintf(filename,"./Media/static_system_0%d.txt",map);
  2724.  
  2725.         ifstream sysFile(filename);
  2726.         // read in data from map file
  2727.         assert(! sysFile.fail());
  2728.  
  2729.         // BITMAP SOURCE
  2730.         Filename = "./Media/Images/static_system.png";
  2731.  
  2732.         cnt=0;
  2733.         while ((! sysFile.eof()) && (cnt < IMMOBILE_AMT_SYSTEM))
  2734.         {
  2735.             // read in the map data    
  2736.             sysFile.getline(line, sizeof(buffer), ','); // X
  2737.             int x = atoi(line);        
  2738.             sysFile.getline(line, sizeof(buffer), ','); // Y
  2739.             int y = atoi(line);        
  2740.             sysFile.getline(line, sizeof(buffer), ','); // FRAME #
  2741.             int frame = atoi(line);    
  2742.             sysFile.getline(line, sizeof(buffer), ','); // ANGLE
  2743.             int rotation = atoi(line);     
  2744.             sysFile.getline(line, sizeof(buffer), '\n'); // grab the end of line
  2745.             int Map = atoi(line);                   // MAP (if not -1)
  2746.  
  2747.             // Map > -1 , cnt = Planet # // indicate enemy occupied areas
  2748.             if (Map > -1)
  2749.                 clearedArea[map][cnt] = false; // there will be enemies there now
  2750.  
  2751.             immobile_system[map][cnt] = new CPlanet(x,y,120,110,Filename,IMMOBILE_AMT_SYSTEM);     
  2752.             immobile_system[map][cnt]->setFrame(frame-1); // 0 is the first frame!
  2753.             immobile_system[map][cnt]->setAngle(rotation);     
  2754.             immobile_system[map][cnt]->setMap(Map);
  2755.  
  2756.             assert(immobile_system[map][cnt]);
  2757.  
  2758.             hitPlanet[map].system[cnt] = false;
  2759.             cnt++;
  2760.         }
  2761.         sysFile.close();
  2762.     }
  2763. };
  2764.  
  2765. void moveBullets()
  2766. {
  2767.     for (int a=0; a < MAX_AMMO; a++)
  2768.         Ammo[a]->doMoves(scalex); // only moves the active ones
  2769.     for (int a=0; a < MAX_GUNS_AI; a++)
  2770.         Ammo_AI[a]->doMoves(scalex); // only moves the active ones
  2771. };
  2772.  
  2773. // draw the active bullet sprites
  2774. void drawBullets()
  2775. {
  2776.     int cnt = 0;
  2777.  
  2778.     // PC bullets
  2779.     for (int a=0; a < MAX_AMMO; a++)
  2780.         for (int i=0; i < MAX_BULLETS; i++)
  2781.             if (Ammo[a]->Bullets[i].isActive == true)
  2782.             {   //draw the bullet sprite
  2783.                 cnt++; // keep track of number of bullets drawn
  2784.                 graphicsEngine.DrawTexture( Ammo[a]->Bullets[i].currPT.x-ScrollX,
  2785.                             Ammo[a]->Bullets[i].currPT.y-ScrollY,
  2786.                             Ammo[a]->getWidth(), Ammo[a]->getHeight(),
  2787.                             scalex, scaley,
  2788.                             Ammo[a]->Bullets[i].angle,
  2789.                             CPCOLOR_XRGB(255,255,255),
  2790.                             Ammo[a]->getTexture(),
  2791.                             & Ammo[a]->getRect(),
  2792.                             true);
  2793.             }
  2794.     // AI Bullets
  2795.     for (int a=0; a < MAX_GUNS_AI; a++)
  2796.         for (int i=0; i < MAX_BULLETS; i++)
  2797.             if (Ammo_AI[a]->Bullets[i].isActive == true)
  2798.             {   //draw the bullet sprite
  2799.                 cnt++; // keep track of number of bullets drawn
  2800.                 graphicsEngine.DrawTexture( Ammo_AI[a]->Bullets[i].currPT.x-ScrollX,
  2801.                             Ammo_AI[a]->Bullets[i].currPT.y-ScrollY,
  2802.                             Ammo_AI[a]->getWidth(), Ammo_AI[a]->getHeight(),
  2803.                             scalex, scaley,
  2804.                             Ammo_AI[a]->Bullets[i].angle,
  2805.                             CPCOLOR_XRGB(255,255,255),
  2806.                             Ammo_AI[a]->getTexture(),
  2807.                             & Ammo_AI[a]->getRect(),
  2808.                             true);
  2809.  
  2810.             }
  2811.     bulletsDrawn = cnt;
  2812. };
  2813.  
  2814. // draw the active bullet sprites (for players projectiles vs AI)
  2815. void bulletCollision(CShip *target)
  2816. {
  2817.     int cnt = 0;
  2818.     bool hit = false;
  2819.     int hitCnt = 0;
  2820.  
  2821.     for (int a=0; a < MAX_AMMO; a++)
  2822.         for (int i=0; i < MAX_BULLETS; i++)
  2823.             if (Ammo[a]->Bullets[i].isActive == true)
  2824.                 {
  2825.                     CPPOINT  pt1 = Ammo[a]->Bullets[i].currPT;
  2826.                     int halfW = Ammo[a]->getWidth()  / 2;
  2827.                     int halfH = Ammo[a]->getHeight() / 2;
  2828.  
  2829.                     CPPOINT center;
  2830.                     center.x = pt1.x + halfW;
  2831.                     center.y = pt1.y + halfH;
  2832.                     int radius1 = halfW;
  2833.  
  2834.                     // players location
  2835.                     CPPOINT pt2 = target->getAnchor();
  2836.                     int radius2 = target->getWidth() * 0.4f;               
  2837.  
  2838.                     if ( circleCollision(center,radius1,pt2,radius2) )
  2839.                     {
  2840.                         // this bullet has collided
  2841.                         hitCnt++;
  2842.  
  2843.                          Ammo[a]->Bullets[i].isActive = false;
  2844.  
  2845.                         DAMAGE dType = Ammo[a]->getDmgType();
  2846.                         int dmg    = Ammo[a]->getDmg();
  2847.  
  2848.                         if (target->applyDmg(dType,dmg))
  2849.                         {
  2850.                             // spawn new explosion
  2851.                             newExp(target->getAnchor());
  2852.  
  2853.                             // target is DEAD !!!
  2854.                             target->setSTATE(DEAD);                    
  2855.  
  2856.                             // TODO: BOOM SOUND
  2857.  
  2858.                                    // target is dead, lets leave                                  
  2859.                                    bulletsHit += hitCnt;
  2860.                                    return ;
  2861.                                    // remaining bullets keep on moving
  2862.                         }
  2863.                     }
  2864.                 }
  2865.     bulletsHit += hitCnt;
  2866. };
  2867.  
  2868. // checks AI bullets for collision (player sprite)
  2869. void bullet_AI_Collision(CShip *target)
  2870. {
  2871.      // dont bother if target already dead
  2872.      if (target->getSTATE() == DEAD)
  2873.           return;
  2874.  
  2875.     int cnt = 0;
  2876.     bool hit = false;
  2877.     int hitCnt = 0;
  2878.  
  2879.     for (int a=0; a < MAX_GUNS_AI; a++)
  2880.         for (int i=0; i < MAX_BULLETS; i++)
  2881.             if (Ammo_AI[a]->Bullets[i].isActive == true)
  2882.                 {
  2883.                     CPPOINT  pt1 = Ammo_AI[a]->Bullets[i].currPT;
  2884.                     int halfW = Ammo_AI[a]->getWidth()  / 2;
  2885.                     int halfH = Ammo_AI[a]->getHeight() / 2;
  2886.  
  2887.                     CPPOINT center;
  2888.                     center.x = pt1.x + halfW;
  2889.                     center.y = pt1.y + halfH;
  2890.                     int radius1 = halfW;
  2891.  
  2892.                     // players location
  2893.                     CPPOINT pt2 = target->getAnchor();
  2894.                     int radius2 = target->getWidth() * 0.4f;               
  2895.  
  2896.                     if ( circleCollision(center,radius1,pt2,radius2) )
  2897.                     {
  2898.                         // this bullet has collided
  2899.                         hitCnt++;
  2900.                         Ammo_AI[a]->Bullets[i].isActive = false;
  2901.  
  2902.                         DAMAGE dType = Ammo_AI[a]->getDmgType();
  2903.                         int dmg    = Ammo_AI[a]->getDmg();
  2904.  
  2905.                         if (target->applyDmg(dType,dmg))
  2906.                         {
  2907.                             // spawn new explosion
  2908.                             newExp(target->getAnchor());
  2909.  
  2910.                             // target is DEAD !!!
  2911.                             target->setSTATE(DEAD);                    
  2912.  
  2913.                             // TODO: BOOM SOUND
  2914.  
  2915.                                    // target dead
  2916.                                    // dont worry about any more damage
  2917.                                    bulletsHit += hitCnt;
  2918.                                    return;
  2919.                         }
  2920.                     }
  2921.                 }
  2922.     bulletsHit += hitCnt;
  2923. };
  2924.  
  2925. void Init_Guns()
  2926. {
  2927.     // [5]                 //dmg       speed
  2928.     Ammo[0] = new CProjectile(1,ENERGY,  14,RANGE_MED,  "./Media/Images/proj_blaster.png" ,30,30); // 24
  2929.     Ammo[1] = new CProjectile(2,ENERGY,  20,RANGE_LONG, "./Media/Images/proj_laser.bmp"   ,16,64); // 25
  2930.     Ammo[2] = new CProjectile(3,KINETIC, 12,RANGE_SHORT,"./Media/Images/cannon.png"       ,44,44); // 35
  2931.     Ammo[3] = new CProjectile(2,EXPLODE, 12,RANGE_LONG ,"./Media/Images/missile.png"      ,32,32); // 25
  2932.     Ammo[4] = new CProjectile(4,ENERGY,  10,RANGE_SHORT,"./Media/Images/proj_torpedo.bmp" ,32,32); // 25
  2933.     Ammo[3]->setupAnim(4,NORTH,4); // animated rocket frames
  2934.  
  2935.     for (int i=0;i < MAX_AMMO; i++)
  2936.         assert(Ammo[i]); // make sure all load successfully
  2937.  
  2938.     //                     reload cycl   energy per shot
  2939.     Guns[0] = new CGuns(0, DELAY_SHORT, 1,"Blaster");        // blaster
  2940.     Guns[1] = new CGuns(1, DELAY_SHORTEST,  2,"Laser");      // laser
  2941.     Guns[2] = new CGuns(2, DELAY_MED,        3,"Cannon");        // cannon
  2942.     Guns[3] = new CGuns(3, DELAY_LONG,       5,"Missile");       // missile
  2943.     Guns[4] = new CGuns(4, DELAY_LONG,       5,"Torpedo");       // photon torpedo
  2944.     for (int i=0;i < MAX_GUNS; i++)
  2945.         assert(Guns[i]); // make sure all load successfully
  2946.  
  2947.     //const int MAX_AI_GUNS;
  2948.                                //dmg  
  2949.     Ammo_AI[0] = new CProjectile(1,KINETIC,  9,RANGE_SHORT,"./Media/Images/mantabulletS.png" ,16,16); // 25
  2950.     Ammo_AI[1] = new CProjectile(2,ENERGY , 12,RANGE_LONG ,"./Media/Images/mantabullet.png"  ,32,32); // 25
  2951.     Guns_AI[0] = new CGuns(1, DELAY_MED, 2,"manta bullet"); // AI blasters
  2952.     Guns_AI[1] = new CGuns(2, DELAY_MED, 2,"boss bullet");  // AI blasters x 3
  2953.     for (int i=0;i < MAX_GUNS_AI; i++)
  2954.     {
  2955.         assert(Guns_AI[i]); // make sure all load successfully
  2956.         assert(Ammo_AI[i]); // make sure all load successfully
  2957.     }
  2958.  
  2959. }
  2960.  
  2961. // performs basic FSM and then moves enemy ship
  2962. void EnemyAI()
  2963. {
  2964.     int GUN_RANGE, distance;
  2965.     DIRS chaseDIR, fleeDIR;
  2966.      
  2967.      // default actions should be ; attack, shift l/r, shift back -- or move towards player/wander
  2968.  
  2969.     // Enemy AI //
  2970.     for (int i=0; i < NUM_ENEMIES; i++)
  2971.         if (enemy[i]->getSTATE() != INACTIVE) // ignore the enemy if its INACTIVE
  2972.         {
  2973.             GUN_RANGE = Ammo[ enemy[i]->getAmmo() ]->getRange() * scalex; // 75% range in SYSTEM, 50% range in SPACE
  2974.  
  2975.             distance  = findDistance(enemy[i]->getAnchor(),player->getAnchor());
  2976.             chaseDIR  = getDirection(player->getAnchor()  ,enemy[i]->getAnchor()); // used to CHASE
  2977.             fleeDIR   = getDirection(enemy[i]->getAnchor(),player->getAnchor());   // used to FLEE
  2978.  
  2979.             // always move away if super close
  2980.             if (distance <= TOO_CLOSE)
  2981.             {
  2982.                 enemy[i]->setSpeed(0);
  2983.                 if (distance <= (TOO_CLOSE/2))
  2984.                 {
  2985.                     enemy[i]->setSTATE(FLEEING); // way too close, get away
  2986.                     enemy[i]->addSpeed(2);
  2987.                 }
  2988.             }
  2989.  
  2990.             switch ( enemy[i]->getSTATE() )
  2991.             {
  2992.             case FLEEING:
  2993.                 {
  2994.                     // flee until at a safe distance away
  2995.                     if (distance > (2*TOO_CLOSE))
  2996.                     { // no longer need to flee
  2997.                         enemy[i]->setSTATE(ACTIVE);
  2998.                     }
  2999.                     else
  3000.                     {   // FLEE                    
  3001.                         enemy[i]->addSpeed(1); // move towards MAX speed (caps at max)
  3002.  
  3003.                         // face player
  3004.                         enemy[i]->setFacing(fleeDIR);
  3005.  
  3006.                         if ((rand() % 100) < 10) // 10% chance for random 45 degree turns
  3007.                             enemy[i]->turn(rand() % 2);
  3008.                     }
  3009.  
  3010.                 }; break;
  3011.             case ACTIVE:        // Moving around normally
  3012.                 {
  3013.                     if ((rand() % 100) < 10) // 10% chance for random 45 degree turns
  3014.                         enemy[i]->turn(rand() % 2);
  3015.  
  3016.                     // random +/- speed
  3017.                     enemy[i]->addSpeed(1);
  3018.                     // caps at MAX speed, so no harm in this
  3019.  
  3020.                     // change state if target visible
  3021.                     if (distance <= SIGHT_RANGE)
  3022.                         enemy[i]->setSTATE(SEARCHING); // sees player on radar
  3023.  
  3024.                     if (distance <= GUN_RANGE)
  3025.                         enemy[i]->setSTATE(ATTACKING);
  3026.                 }; break;
  3027.             case SEARCHING:
  3028.                 {   // HEAD towards player - AI "Sees" the player on radar
  3029.                     enemy[i]->addSpeed(1); // move towards MAX speed (caps at max)
  3030.  
  3031.                     // face player
  3032.                     enemy[i]->setFacing(chaseDIR);                 
  3033.  
  3034.                     // change state if target visible
  3035.                     if (distance > SIGHT_RANGE)
  3036.                         enemy[i]->setSTATE(ACTIVE); // sees player on radar
  3037.                     if (distance <= GUN_RANGE)
  3038.                         enemy[i]->setSTATE(ATTACKING);
  3039.                 }; break;
  3040.             case ATTACKING:     // Attacking player
  3041.                 {
  3042.                     // make sure the target is still in range
  3043.                     if (distance > GUN_RANGE)
  3044.                     {
  3045.                         // unable to fire ... move first
  3046.                         enemy[i]->setSTATE(ACTIVE);
  3047.  
  3048.                         // this should make him head towards player
  3049.                         enemy[i]->setFacing(chaseDIR);
  3050.                         enemy[i]->addSpeed(2);
  3051.                     }
  3052.                     else
  3053.                     {   // close enough to fire
  3054.                         // see if ship has enough power to shoot, returns true if able to fire
  3055.                         // also checks if the gun is reloaded or not
  3056.                         if ( enemy[i]->canFire())
  3057.                         {  
  3058.                             // try to match players speed
  3059.                             //enemy[i]->setSpeed(player->getSpeed());
  3060.                             enemy[i]->setSpeed(0);  // stop moving and fire gun
  3061.  
  3062.                             // face player
  3063.                             enemy[i]->setFacing(chaseDIR);
  3064.                            
  3065.                             Ammo_AI[0]->spawnBullet(enemy[i]->getAnchor(),enemy[i]->getFacing());                      
  3066.                             enemyBullets++;
  3067.  
  3068.                             // TODO: SOUND :: enemies guns firing at your
  3069.                         }
  3070.                         else
  3071.                         {
  3072.                                    // shift r/l while still facing target
  3073.                                    enemy[i]->addSpeed(1);        // speed up a little first
  3074.                                    enemy[i]->shift();    // then slide r/l to randomly avoid stuff
  3075.                                    // keep current facing
  3076.                         }
  3077.                     } // distance
  3078.                 }; break; // CASE ..
  3079.             } // end of SWITCH()
  3080.  
  3081.             // perform the actual MOVE for enemy
  3082.             enemy[i]->doMove();
  3083.  
  3084.             // check boundaries
  3085.             if ( enemy[i]->checkBounds(0,0,GAMEWORLDWIDTH,GAMEWORLDHEIGHT) )           // BOUNDARIES CHECK
  3086.             {
  3087.                 // warp back to top left corner
  3088.                 enemy[i]->setX(300 + (rand() % 200)); // spawn point
  3089.                 enemy[i]->setY(100 + (rand() % 200));
  3090.                 enemy[i]->setFacing(SOUTH);
  3091.                 enemy[i]->setSpeed(1);
  3092.             }
  3093.         } // END ... Enemy AI code //
  3094.  
  3095. }; // end EnemyAI function //
  3096.  
  3097. // performs basic FSM and then moves enemy ship
  3098. void BossAI()
  3099. {
  3100.     // Thw ANIM will be beaks added on top --
  3101.  
  3102.     // not activated
  3103.     if (boss->getSTATE() == INACTIVE)
  3104.         return;
  3105.  
  3106.     // died
  3107.     if (boss->getSTATE() == DEAD)
  3108.     {
  3109.         deaths++;
  3110.         if (deaths < lives)
  3111.         {    
  3112.                // respawn, next color
  3113.             boss->setSTATE(ACTIVE);
  3114.  
  3115.             // create new boss
  3116.                // but stay at same location
  3117.             respawnBoss(false);
  3118.  
  3119.             boss->setFrame(deaths);
  3120.             return;
  3121.         }
  3122.         else        // did boss just die? if so, make sure the planet is now "safe"
  3123.         {
  3124.             if (gameView == PLANET)
  3125.                 if ( clearedArea[CURR_MAP.system][CURR_MAP.planet] == false)
  3126.                      clearedArea[CURR_MAP.system][CURR_MAP.planet] = true;
  3127.             return; // either way, exit
  3128.         }
  3129.     }
  3130.  
  3131. // Boss AI //
  3132.     int GUN_RANGE=RANGE_LONG, distance, SIGHT = RANGE_LONG;
  3133.     DIRS chaseDIR, fleeDIR;
  3134.  
  3135.     GUN_RANGE = Ammo[ boss->getAmmo() ]->getRange() * scalex; // 75% range in SYSTEM, 50% range in SPACE
  3136.     distance  = findDistance(boss->getAnchor(),player->getAnchor());
  3137.     chaseDIR  = getDirection(player->getAnchor()  ,boss->getAnchor()); // used to CHASE
  3138.     fleeDIR   = getDirection(boss->getAnchor(),player->getAnchor());   // used to FLEE
  3139.  
  3140.     // always move away if super close
  3141.     if (distance <= 300)
  3142.     {
  3143.         boss->setSTATE(FLEEING); // way too close, get away
  3144.         boss->setSpeed(2);
  3145.     };
  3146.     if (distance <= 200)
  3147.     {
  3148.         boss->setSTATE(ATTACKING); // way too close, just attack
  3149.         boss->setSpeed(0);
  3150.     } ;
  3151.  
  3152.     switch ( boss->getSTATE() )
  3153.     {
  3154.     case FLEEING:
  3155.         {
  3156.             // flee until at a safe distance away
  3157.             if (distance > 400)
  3158.             { // no longer need to flee
  3159.                 boss->setSTATE(ACTIVE);
  3160.             }
  3161.             else
  3162.             {   // FLEE                    
  3163.                 boss->addSpeed(1); // move towards MAX speed (caps at max)
  3164.  
  3165.                 // face player
  3166.                 boss->setFacing(fleeDIR);
  3167.  
  3168.                 if ((rand() % 100) < 1) // 10% chance for random 45 degree turns
  3169.                     boss->turn(rand() % 2);
  3170.             }
  3171.  
  3172.         }; break;
  3173.     case ACTIVE:        // Moving around normally
  3174.         {
  3175.             if ((rand() % 100) < 1) // 10% chance for random 45 degree turn
  3176.                 boss->turn(rand() % 2);
  3177.  
  3178.             // random +/- speed
  3179.             boss->addSpeed(1);
  3180.             // caps at MAX speed, so no harm in this
  3181.  
  3182.             // change state if target visible
  3183.             if (distance <= 1000)
  3184.                 boss->setSTATE(SEARCHING); // sees player on radar
  3185.  
  3186.             if (distance <= RANGE_LONG)
  3187.                 boss->setSTATE(ATTACKING);
  3188.         }; break;
  3189.     case SEARCHING:
  3190.         {   // HEAD towards player - AI "Sees" the player on radar
  3191.             boss->addSpeed(1); // move towards MAX speed (caps at max)
  3192.  
  3193.             // face player
  3194.             boss->setFacing(chaseDIR);                 
  3195.  
  3196.             // change state if target visible
  3197.             if (distance > SIGHT_RANGE)
  3198.                 boss->setSTATE(ACTIVE); // sees player on radar
  3199.             if (distance <= GUN_RANGE)
  3200.                 boss->setSTATE(ATTACKING);
  3201.         }; break;
  3202.     case ATTACKING:     // Attacking player
  3203.         {
  3204.             // make sure the target is still in range
  3205.             if (distance > RANGE_LONG)
  3206.             {
  3207.                 // unable to fire ... move first
  3208.                 boss->setSTATE(ACTIVE);
  3209.  
  3210.                 // this should make him head towards player
  3211.                 boss->setFacing(chaseDIR);
  3212.                 boss->addSpeed(2);
  3213.             }
  3214.             else
  3215.             {   // close enough to fire
  3216.                 // see if ship has enough power to shoot, returns true if able to fire
  3217.                 // also checks if the gun is reloaded or not
  3218.                 if ( boss->canFire() )
  3219.                 {  
  3220.                     // try to match players speed
  3221.                     //boss->setSpeed(player->getSpeed());
  3222.                     boss->setSpeed(0);  // stop moving and fire gun
  3223.  
  3224.                     // face player
  3225.                     boss->setFacing(chaseDIR);
  3226.  
  3227.                     DIRS dir1=NW,dir2=chaseDIR,dir3=NE;
  3228.                     switch(boss->getFacing())
  3229.                     {
  3230.                         case NORTH  : dir1=NW;     dir3=NE;   break; // dir1 = left, dir3=right
  3231.                         case NE     : dir1=NORTH;  dir3=EAST; break;
  3232.                         case NW     : dir1=WEST;   dir3=NORTH;break;
  3233.                         case EAST        : dir1=NW;     dir3=SE;   break;
  3234.                         case WEST        : dir1=SW;     dir3=NW;   break;
  3235.                         case SOUTH  : dir1=SW;     dir3=SE;   break;
  3236.                         case SE          : dir1=EAST;   dir3=SOUTH;break;
  3237.                         case SW     : dir1=SOUTH;  dir3=WEST; break;
  3238.                     };
  3239.  
  3240.                     CPPOINT pt1,pt2=boss->getAnchor(),pt3;
  3241.                     pt1=pt2;
  3242.                     pt3=pt2;
  3243.                     switch(chaseDIR)
  3244.                     {
  3245.                         case NE:
  3246.                         case SW:
  3247.                             {
  3248.                                 pt1.x -= 64;
  3249.                                 pt3.x += 64;
  3250.  
  3251.                                 pt1.y -= 64;
  3252.                                 pt3.y += 64;
  3253.                             }; break;
  3254.  
  3255.                         case NW:
  3256.                         case SE:
  3257.                             {
  3258.                                 pt1.x += 64;
  3259.                                 pt3.x -= 64;
  3260.  
  3261.                                 pt1.y += 64;
  3262.                                 pt3.y -= 64;
  3263.                             }; break;
  3264.  
  3265.                         case WEST:
  3266.                         case EAST:
  3267.                             {
  3268.                                 pt1.x -= 64;
  3269.                                 pt3.x += 64;
  3270.                             }; break;
  3271.  
  3272.                         case NORTH:
  3273.                         case SOUTH:
  3274.                             {
  3275.                                 pt1.y -= 64;
  3276.                                 pt3.y += 64;
  3277.                             }; break;
  3278.                     }
  3279.                        
  3280.  
  3281.                     // fire (3) bullet towards player
  3282.                     Ammo_AI[1]->spawnBullet( pt1, dir3 ); // towards right
  3283.                     Ammo_AI[1]->spawnBullet( pt2, dir2);  // ahead     
  3284.                     Ammo_AI[1]->spawnBullet( pt3, dir1);  // towards left
  3285.                     enemyBullets+=3;
  3286.                     // TODO: SOUND :: enemies guns firing at your
  3287.                 }
  3288.             } // distance
  3289.         }; break; // CASE ..
  3290.     } // end of SWITCH()
  3291.  
  3292.         // perform the actual MOVE for enemy
  3293.         boss->doMove(); // which doesnt animate the body
  3294.         beeks->nextFrame();// animate the beeks tho
  3295.  
  3296.         // check boundaries
  3297.         if (boss->getX() < 0)
  3298.         {
  3299.             boss->setX(64);
  3300.             boss->setSpeed(0);
  3301.         };
  3302.         if (boss->getX() > (GAMEWORLDWIDTH-128))
  3303.         {
  3304.             boss->setX(0); // ha ha -- GAMEWORLDWIDTH-128);
  3305.             boss->setSpeed(0);
  3306.         };
  3307.         if (boss->getY() < 0)
  3308.         {
  3309.             boss->setY(1);
  3310.             boss->setSpeed(0);
  3311.         };
  3312.         if (boss->getY() > (GAMEWORLDHEIGHT-128))
  3313.         {
  3314.             boss->setY(0); // GAMEWORLDHEIGHT-128);
  3315.             boss->setSpeed(0);
  3316.         };
  3317. }; // end EnemyAI function //
  3318.  
  3319. void moveDebris()
  3320. {
  3321.     // move Debris (current view only)
  3322.     switch(gameView)
  3323.     {
  3324.         case SPACE:
  3325.             {
  3326.             for (int i=0; i < DEBRIS_AMT_SPACE; i++)
  3327.                 debris_space[i]->doMove(); // moves and rotates
  3328.             }; break;
  3329.         case SYSTEM:
  3330.             {
  3331.             for (int i=0; i < DEBRIS_AMT_SYSTEM; i++)
  3332.                 debris_system[i]->doMove(); // rotates only
  3333.             }; break;
  3334.         case PLANET:
  3335.             {
  3336.             for (int i=0; i < DEBRIS_AMT_PLANET; i++)
  3337.                 debris_planet[i]->doMove(); // static
  3338.             }; break;
  3339.     }
  3340. }
  3341.  
  3342. // check for collisions with moving debris ... and applies the effect there of
  3343. void checkDebris()
  3344. {
  3345.     //track recent collision
  3346.     if (gameView == SPACE)  lastColl.space   = currColl.space;
  3347.     if (gameView == SYSTEM) lastColl.system  = currColl.system;
  3348.     if (gameView == PLANET) lastColl.surface = currColl.surface;
  3349.  
  3350.     // check for player vs. debris collisions      
  3351.     int temp = debrisCollision(player);
  3352.     if (gameView == SPACE)  currColl.space  = temp; // resets to (0) if no collision
  3353.     if (gameView == SYSTEM) currColl.system = temp;
  3354.     if (gameView == PLANET) currColl.surface = temp;
  3355.  
  3356.     // ignore mid-air collisions on planets (clouds dont hurt)
  3357.     if (temp > -1)
  3358.         switch(gameView)
  3359.         {
  3360.             case PLANET:
  3361.                 {
  3362.                     lastColl.surface = temp;
  3363.                 };  break; // ignore collisions on planets         
  3364.             case SYSTEM:
  3365.                 {
  3366.                     //if its a new collision, apply damage
  3367.                     if (lastColl.system != temp)
  3368.                         player->applyDmg(ENERGY,1);
  3369.  
  3370.                          // see if you collided with a lost astronaut
  3371.                          if ( (debris_system[temp]->getFrame() == 1) || (debris_system[temp]->getFrame() == 3))
  3372.                          {
  3373.                               // you bumped into a lost astronaut
  3374.                               debris_system[temp]->nextFrame();
  3375.                               debris_system[temp]->randomSpawn();
  3376.  
  3377.                               astronauts++;
  3378.  
  3379.                               // full heal
  3380.                               player->fullHeal();
  3381.                          //mp3->OpenFile(".\\Media\\Sound\\teleport_activate.mp3",800, 0, 0);
  3382.                         //mp3->Play(); //remarked out by RP
  3383.                         en_sounds.teleport();
  3384.                          }
  3385.  
  3386.                     // save collision
  3387.                     lastColl.system = temp;
  3388.                 }; break;
  3389.             case SPACE:
  3390.                 {
  3391.                     //if its a new collision, apply damage
  3392.                     if (lastColl.system != temp)
  3393.                         player->applyDmg(ENERGY,1);
  3394.  
  3395.                          // see if you collided with a lost astronaut
  3396.                          if (debris_space[temp]->getFrame() < 2)
  3397.                          {
  3398.                               // you bumped into a lost astronaut
  3399.                               debris_space[temp]->nextFrame();
  3400.                               debris_space[temp]->randomSpawn();
  3401.  
  3402.                               astronauts++;
  3403.  
  3404.                               // full heal
  3405.                               player->fullHeal();
  3406.                         // mp3->OpenFile(".\\Media\\Sound\\teleport_activate.mp3",800, 0, 0);
  3407.                         // mp3->Play(); //remarked out by RP
  3408.                         en_sounds.teleport();
  3409.                          }
  3410.  
  3411.                     // save collision
  3412.                     lastColl.system =  temp;
  3413.                 }; break;
  3414.         }
  3415.         // TODO: we can apply physics for collision if want to -- got the formula already --
  3416.         // sure, if shields deflect a large collision - you bounce away
  3417.         // NOTE: I have this algorithm in another program, too (ADV)
  3418. }
  3419.  
  3420. void createDebris()
  3421. {
  3422.     // load the moving objects (asteroids and such)
  3423.     for (int i=0;i < DEBRIS_AMT_SPACE;i++)
  3424.     {
  3425.     debris_space[i] = new CDebris(120,110,"./Media/Images/debris_space.png",DEBRIS_SPRITES_SPACE,GAMEWORLDWIDTH,GAMEWORLDHEIGHT);      
  3426.         hitDebris.space[i] = false;
  3427.         assert(debris_space[i]);
  3428.     }
  3429.     for (int i=0;i < DEBRIS_AMT_SYSTEM;i++)
  3430.     {
  3431.     debris_system[i] = new CDebris(120,110,"./Media/Images/debris_system.png",DEBRIS_SPRITES_SYSTEM,GAMEWORLDWIDTH,GAMEWORLDHEIGHT);       
  3432.         hitDebris.system[i] = false;
  3433.         assert(debris_system[i]);
  3434.     }
  3435.     for (int i=0;i < DEBRIS_AMT_PLANET;i++)
  3436.     {
  3437.     debris_planet[i] = new CDebris(120,110,"./Media/Images/debris_surface.png", DEBRIS_SPRITES_PLANET, GAMEWORLDWIDTH, GAMEWORLDHEIGHT);       
  3438.         hitDebris.surface[i] = false;
  3439.         assert(debris_planet[i]);
  3440.     }
  3441. }
  3442.  
  3443. void drawBars()
  3444. {
  3445.     // draw enemy health bars?
  3446.     // scale the bar per the gameView
  3447.     int sx = 32 / scalex;
  3448.     int sy =  6 * scaley;
  3449.     CPPOINT dest;
  3450.     CPPOINT curr;
  3451.  
  3452.     // Draw Players Health Bars
  3453.     dest = player->getAnchor();
  3454.     dest.x -= ScrollX;  // + sx
  3455.     dest.y -= ScrollY;
  3456.     dest.y += (player->getHeight()/2) * scaley;
  3457.  
  3458.     drawBar(dest.x,dest.y, player->getCur(LOC_SHIELD), player->getMax(LOC_SHIELD), 1);      // SHIELDS
  3459.     dest.y += sy;
  3460.     drawBar(dest.x,dest.y, player->getCur(LOC_ARMOR) , player->getMax(LOC_ARMOR),  2);      // ARMOR
  3461.     dest.y += sy;
  3462.     drawBar(dest.x,dest.y, player->getCur(LOC_HULL)  , player->getMax(LOC_HULL),   5);      // HULL
  3463.     dest.y += sy;
  3464.     drawBar(dest.x,dest.y, player->getSolar()        , player->getSolarMax(),      6);      // solar power
  3465.     dest.y += sy;
  3466.     if (player->isLoaded())                                                                 // gun reload
  3467.         drawBar(dest.x,dest.y, 1,1,3);
  3468.     else
  3469.         drawBar(dest.x,dest.y, player->getGunDelay()     , player->weapon->getReload(),3);
  3470.  
  3471.  
  3472.     for (int i=0; i < NUM_ENEMIES; i++)
  3473.         if ( (enemy[i]->getSTATE() != DEAD) && (enemy[i]->getSTATE() != INACTIVE) )
  3474.             {
  3475.                 curr = enemy[i]->getAnchor();
  3476.                 curr.x -= ScrollX; // convert to window coord (not game coord)
  3477.                 curr.y -= ScrollY;
  3478.  
  3479.                 dest.x = enemy[i]->getX() - ScrollX;
  3480.                 dest.y = enemy[i]->getY() - ScrollY + ((enemy[i]->getHeight() / 2) *scaley);
  3481.  
  3482.                 // on-screen ?
  3483.                 if ((curr.x >= 0) && (curr.x <= SCREEN_WIDTH) && (curr.y >= 0) && (curr.y <= SCREEN_HEIGHT))
  3484.                 { // should be visible on screen - so draw health bars
  3485.                     drawBar(dest.x,dest.y, enemy[i]->getHP(),      enemy[i]->getMaxHP(),            5);
  3486.                     dest.y += sy;
  3487.                     drawBar(dest.x,dest.y, enemy[i]->getSolar(),   enemy[i]->getSolarMax(),         6); // Power
  3488.                     dest.y += sy;
  3489.                     if ( enemy[i]->isLoaded() )
  3490.                         drawBar(dest.x,dest.y, 1, 1, 3);
  3491.                     else
  3492.                         drawBar(dest.x,dest.y, enemy[i]->getGunDelay(),enemy[i]->weapon->getReload(),   3);
  3493.                 }
  3494.             }
  3495. }
  3496.  
  3497. void DrawBG(CPTexture& pSource)
  3498. {
  3499.     CPRECT r1 = { ScrollX, ScrollY, ScrollX+SCREEN_WIDTH, ScrollY+SCREEN_HEIGHT };
  3500.     CPRECT r2 = { 0, 0, SCREEN_WIDTH-1, SCREEN_HEIGHT-1 };
  3501.    
  3502.     graphicsEngine.DrawStretchTexture(pSource, r1, r2);
  3503. };
  3504.  
  3505. void animExp()
  3506. {
  3507.     for (int i=0;i < MAX_EXPLOSIONS;i++)
  3508.         if (activeEXP[i] == true)
  3509.             if (explosion[i]->nextFrame() == 1)
  3510.             { // animation complete
  3511.                 activeEXP[i] = false;
  3512.  
  3513.                 delete explosion[i];
  3514.                 // does that destroy it safely ?
  3515.             }
  3516. }
  3517. //
  3518. void newExp(CPPOINT dest)
  3519. {
  3520.     // find the next available one to use
  3521.     int i=0;
  3522.     while ((activeEXP[i] == true) && (i < MAX_EXPLOSIONS))
  3523.         i++;
  3524.  
  3525.     if (i >= MAX_EXPLOSIONS)
  3526.         return; // quit
  3527.  
  3528.     // make it ACTIVE duh
  3529.     activeEXP[i] = true;
  3530.  
  3531.     int Height=120;
  3532.     int Width =120;
  3533.     int Frames=12;
  3534.     char* Filename = "./Media/Images/exp_red.png";
  3535.     explosion[i] = new CSprite(dest.x,dest.y,Height, Width, Filename);
  3536.     explosion[i]->setupAnim(Frames,EAST,4);
  3537.     explosion[i]->setSTATE(ACTIVE);
  3538.  
  3539.     en_sounds.explosion();
  3540.  
  3541. }
  3542.  
  3543. void drawExp()
  3544. {
  3545.     for (int i=0;i < MAX_EXPLOSIONS;i++)
  3546.         if (activeEXP[i] == true)
  3547.             graphicsEngine.DrawTexture( explosion[i]->getX()-ScrollX,explosion[i]->getY()-ScrollY,
  3548.                         explosion[i]->getWidth(),explosion[i]->getHeight(),
  3549.                         scalex, scaley, explosion[i]->getAngle(),
  3550.                         CPCOLOR_XRGB(255,255,255),
  3551.                         explosion[i]->getTexture(),
  3552.                         &explosion[i]->getRect(),
  3553.                         false);
  3554. }
  3555.  
  3556.  
  3557. // sets up random enemy drones
  3558. void createDrones()
  3559. {
  3560.      for (int i=0; i < NUM_ENEMIES; i++)
  3561.     {
  3562.         int aiGun = 0;// Guns[5] = AI Blasters
  3563.         CPPOINT dest = {rand()%2000+24,rand()%2000+24};
  3564.         enemy[i] = new CShip(dest.x,dest.y,64,64,"./Media/Images/manta.png",DRONE_curSpd,DRONE_maxSpd,DRONE_energy,DRONE_eRecharge,Guns_AI[aiGun],aiGun,DRONE_Shields,DRONE_Armor,DRONE_Hull,0);  
  3565.         enemy[i]->setupAnim(3,NORTH,3); // sprites per anim, initially heading, sprites per row on sheet   
  3566.         enemy[i]->setFrame(0);
  3567.         enemy[i]->setSTATE(INACTIVE);  
  3568.         enemy[i]->setBorder(0,0,GAMEWORLDWIDTH - 16,GAMEWORLDHEIGHT - 16); // set border to game window
  3569.         assert(enemy[i]);
  3570.     }
  3571.  
  3572.      // RANDOMIZE
  3573.     int Shield = 0;
  3574.     int Armor  = rand()%6 +5; // 6-10
  3575.     int Hull   = rand()%5 +8; // 8-12
  3576.      //BOSS_ARMOR   8   // (- 1) for each life lost (max -7) = 1
  3577.      //BOSS_HULL    10  // (- 1) for each life lost (max -7) = 3
  3578.  
  3579.     int Speed  = 2;
  3580.     int bossGun = 1;// BOSS GUN
  3581.     CPPOINT dest = {rand()%800+1200,rand()%800+1200};
  3582.    
  3583.     boss = new CShip(900,900,256,256,"./Media/Images/bens-jellyboss.png",0,Speed,40,40,Guns_AI[bossGun],bossGun,Shield,BOSS_ARMOR,BOSS_HULL,0);  
  3584.     boss->setupAnim(8,EAST,4); // sprites per anim, initially heading, sprites per row on sheet
  3585.     boss->setDelay(6);
  3586.     boss->setSTATE(ACTIVE);
  3587.     boss->setBorder(0,0,GAMEWORLDWIDTH - 16,GAMEWORLDHEIGHT - 16); // set border to game window
  3588.  
  3589.     boss->setFrame(0);
  3590.     boss->setLastFrame(1);
  3591.     boss->setAnimate(false);
  3592.  
  3593.     beeks = new CSprite(900,900,256,256,"./Media/Images/jelly-beeks.png");
  3594.     beeks->setupAnim(16,EAST,4);
  3595.     beeks->setDelay(5);
  3596.     beeks->setFrame(0);
  3597.  
  3598.     assert(boss);
  3599. }
  3600.  
  3601. void respawnDrones(int MAX = NUM_ENEMIES)
  3602. {
  3603.     // call this when you enter a new system or map
  3604.  
  3605.     if (MAX < NUM_ENEMIES)
  3606.         for (int i=MAX; i < NUM_ENEMIES; i++)
  3607.             enemy[i]->setSTATE(INACTIVE); // be sure the others are ignored then
  3608.  
  3609.     for (int i=0; i < MAX; i++)
  3610.     {
  3611.         CPPOINT dest = {rand()%1200+800,rand()%1200+800};
  3612.         int Shield = 0;
  3613.         int Armor  = rand()%4 +1;   // 1-4
  3614.         int Hull   = rand()%2 +1; // 1-2
  3615.         int Speed  = 9 - (Armor + Hull);
  3616.         int Angle  = rand() % 360;
  3617.  
  3618.         enemy[i]->setFrame(0);
  3619.         enemy[i]->setSTATE(ACTIVE);
  3620.         enemy[i]->setPT(dest);
  3621.         enemy[i]->setMaxSpeed(Speed);
  3622.         enemy[i]->setSpeed(Speed);
  3623.         enemy[i]->setAngle(Angle);
  3624.         enemy[i]->setupShip(Shield,Armor,Hull);
  3625.     }
  3626. }
  3627.  
  3628. void respawnBoss(bool randLoc)
  3629. {
  3630.      //spawns boss on far side of map
  3631.      //when boss is destroyed this zone becomes clear
  3632.      // areacleared[CURR_MAP.system][CURR_MAP.planet] = true;
  3633.  
  3634.           // random new location
  3635.           CPPOINT dest = { rand()%1200+800,rand()%1200+800 };
  3636.          
  3637.           if (! randLoc)
  3638.                dest = boss->getPT(); // stay at same location
  3639.                
  3640.         int Shield = 0;
  3641.         int Armor  = rand()%6 + 5; // 5-10
  3642.         int Hull   = rand()%5 + 8; // 8-12
  3643.         int Speed  = 2;
  3644.         int Angle  = rand() % 360;
  3645.  
  3646.         boss->setFrame(deaths);
  3647.         boss->setDelay(16);
  3648.         boss->setPT(dest);     
  3649.         boss->setSpeed(Speed);             
  3650.         boss->setAngle(Angle);
  3651.         boss->setSTATE(ACTIVE);
  3652.         boss->setupShip(Shield,Armor,Hull);
  3653. };
  3654.  
  3655. CPPOINT offsetPT(CPPOINT pt1, int Width, int Height,DIRS Facing)
  3656. {
  3657.         CPPOINT dPT = pt1;
  3658.         int halfW = Width  / 2 * scalex;
  3659.         int halfH = Height / 2 * scaley;
  3660.          DIRS dir = Facing;
  3661.  
  3662.         if ( (dir == NORTH) || (dir == NE) || (dir == NW))  dPT.y -= halfH;
  3663.         if ( (dir == SOUTH) || (dir == SE) || (dir == SW))  dPT.y += halfH;
  3664.         if ( (dir == WEST)  || (dir == SW) || (dir == NW))  dPT.x -= halfW;
  3665.         if ( (dir == EAST)  || (dir == SE) || (dir == NE))  dPT.x += halfW;
  3666.  
  3667.         return dPT;
  3668. }
  3669.  
  3670. void respawnPlayer()
  3671. {
  3672.      // send player back to space station and heal them
  3673.     gameView=SPACE;
  3674.  
  3675.     // un-spawn the drones
  3676.     respawnDrones(0); // sets them all to inactive
  3677.     boss->setSTATE(INACTIVE);
  3678.     deaths=0; // reset boss
  3679.  
  3680.     // move to starting location
  3681.     CPPOINT dest = { 105, 105 }; // GAMEWORLDWIDTH HEIGHT
  3682.     player->setPT(dest);
  3683.     ScrollX=0;ScrollY=0;
  3684.     player->setSpeed(0);
  3685.  
  3686.     player->fullHeal();
  3687.     player->setSTATE(ACTIVE);
  3688.  
  3689.     en_sounds.teleport();
  3690. }