// from: Beginning Game Programming, Second Edition
#include "game.h"
// some globals
//TODO: do this better.
CPInput input;
CPGraphicsEngine graphicsEngine;
//RP - Load instances for sound effects
weapon_fire guns;
gun_change change;
environment en_sounds;
/* THESE WILL BE THE IN-GAME OPTIONS */
int DIFF_LEVEL = 5; // AVG
// counters for score
int MAX_SYTEM =0;
int MAX_PLANET =0;
int ScrollX=0, ScrollY=0; //current scroll position
int SpeedX, SpeedY; //scroll speed
CPTexture scrollbuffer; //scroll buffer
CPTexture space_tiles,surface_tiles[NUM_MAPS_PLANET],system_tiles[NUM_MAPS_SYSTEM]; //source image(s) containing tiles
bool gamestart = true;
// flag to turn off MUSIC at load time
bool MUSIC_ENABLED = false;
//timing variable
long start;
// keep track of which state the game is in
GAME_STATE gameView = SPACE;
bool initialized = false;
// TILE MAP Data
int MAPDATA[MAPWIDTH][MAPHEIGHT];
int SYSTEM_MAPDATA[MAPWIDTH][MAPHEIGHT];
// track players progress -- and mobs, etc --
bool clearedArea[NUM_MAPS_SYSTEM][NUM_MAPS_PLANET];
struct debrisType
{
bool space[DEBRIS_AMT_SPACE];
bool
system[DEBRIS_AMT_SYSTEM
];
bool surface[DEBRIS_AMT_PLANET];
} hitDebris;
struct planetType
{
bool space[IMMOBILE_AMT_SPACE];
bool
system[IMMOBILE_AMT_SYSTEM
];
bool surface[IMMOBILE_AMT_PLANET];
} hitPlanet[NUM_MAPS_PLANET];
float COLL_RADIUS = 0.40f; // 80% of mass
// FLAG if player is at a dock-able object (planet,sun,etc)
// will be -1 if not
int DOCKED_AT = -1;
struct dType
{
int planet;
int space;
};
dType docked = {-1,-1};
dType CURR_MAP = {0,0,0};
float scalex=1.0f,scaley=1.0f; // used for sprite scaling
float ScaleX=1.0f,ScaleY=1.0f; // used for sprite scaling
// static objects for the guns/ammo
CGuns *Guns[MAX_GUNS];
CProjectile *Ammo[MAX_AMMO];
int Alt_Weapon = 3; // missiles, 4 is torpedo
// FOR AI guns and such
CGuns *Guns_AI[MAX_GUNS_AI];
CProjectile *Ammo_AI[MAX_GUNS_AI];
// max # of projectiles to track
int cntBullets=0; // projectiles in motion
int bulletsDrawn=0;
int rCode=0;
int enemyBullets=0;
int bulletsHit=0;
// astronauts rescued
int astronauts = 0;
// auto fire for laser beam
bool AUTOFIRE = false;
// enemy
const int NUM_DRONE_SHIPS=3;
const int NUM_ENEMIES=10;
CShip *enemy[NUM_ENEMIES];
CShip *boss; // only one at a time
CSprite *beeks;
int deaths=0; // number of times boss has died , starts with frame #0 (grey)
const int lives = 8; // 8 colors/frames
// Players ship
CShip *player = NULL;
CSprite *shield = NULL;
// keep track of enter/exit locations
// pt is xy location, number is object collides with last, dir is facing
struct LAST_LOC
{
CPPOINT pt; // xy location
int number; // object # collided with
DIRS direction; // direction you were facing
CPPOINT scroll; // scrollx and scrolly at entrance xy
};
struct LAST_COLL
{
int space; // numbers reflect # of last object collided with in that view
int surface;
};
LAST_COLL lastColl = {0,0,0};
LAST_COLL currColl = {0,0,0};
LAST_COLL lastPlanetColl = {0,0,0};
LAST_COLL currPlanetColl = {0,0,0};
// used to save previous locations and entrance locations
LAST_LOC enterPLANET,enterSYSTEM,enterSPACE;
struct lastType
{
LAST_LOC space;
LAST_LOC planet;
// health bars
CPTexture color_bars;
CPTexture sun;
CSprite *yellowBmp = NULL;
CSprite *redBmp = NULL;
CSprite *infectedPlanet = NULL;
// random space debris
// Debris class to handle the moving debris
CDebris *debris_space[DEBRIS_AMT_SPACE];
CDebris *debris_system[DEBRIS_AMT_SYSTEM];
CDebris *debris_planet[DEBRIS_AMT_PLANET];
CPlanet *immobile_space[IMMOBILE_AMT_SPACE];
CPlanet *immobile_system[NUM_MAPS_SYSTEM][IMMOBILE_AMT_SYSTEM];
CPlanet *immobile_planet[NUM_MAPS_PLANET][IMMOBILE_AMT_PLANET];
//CPlanet *infected_planet;
// collision stuff
double vPx;
double vPy;
double vJx;
double vJy;
// ---
const int MAX_EXPLOSIONS = 30;
CSprite *explosion[MAX_EXPLOSIONS];
bool activeEXP[MAX_EXPLOSIONS];
const int RIGHT = 1;
const int LEFT = 0;
// timer to delay key presses
bool KEY_PRESSED=false;
// Updated functions to read setup tokens from config file
bool isLetter(int charValue)
{
return ( (charValue >= 'a' && charValue <= 'z') ||
(charValue >= 'A' && charValue <= 'Z') );
}
bool isNumber(int charValue)
{
return ( charValue >= '0' && charValue <= '9' );
}
int getToken(string token)
{
if (token == "SCREEN_X")
return SCREEN_WIDTH;
if (token == "SCREEN_Y")
return SCREEN_HEIGHT;
if (token == "SCREEN_FULL")
return FULLSCREEN;
if (token == "PLAYER_ENERGY")
return START_energy;
if (token == "PLAYER_RCHRG")
return START_eRecharge;
if (token == "PLAYER_SHIELDS")
return START_Shields;
if (token == "PLAYER_ARMOR")
return START_Armor;
if (token == "PLAYER_HULL")
return START_Hull;
if (token == "PLAYER_SRGN")
return START_shield_regen_delay;
if (token == "DRONE_MAXSPD")
return DRONE_maxSpd;
if (token == "DRONE_CURSPD")
return DRONE_curSpd;
if (token == "DRONE_ENERGY")
return DRONE_energy;
if (token == "DRONE_ERCHRG")
return DRONE_eRecharge;
if (token == "DRONE_SHIELDS")
return DRONE_Shields;
if (token == "DRONE_ARMOR")
return DRONE_Armor;
if (token == "DRONE_HULL")
return DRONE_Hull;
if (token == "BOSS_ARMOR")
return BOSS_ARMOR;
if (token == "BOSS_HULL")
return BOSS_HULL;
cout << "token (" << token << ") not found" << endl;
return 0;
}
void setToken(string token, string value)
{
int iValue = atoi(value.c_str());
// display new value
cout << token << " = " << iValue << endl;
if (token == "SCREEN_X")
SCREEN_WIDTH = iValue;
else if (token == "SCREEN_Y")
SCREEN_HEIGHT = iValue;
else if (token == "SCREEN_FULL")
FULLSCREEN = iValue;
else if (token == "PLAYER_ENERGY")
START_energy = iValue;
else if (token == "PLAYER_RCHRG")
START_eRecharge = iValue;
else if (token == "PLAYER_SHIELDS")
START_Shields = iValue;
else if (token == "PLAYER_ARMOR")
START_Armor = iValue;
else if (token == "PLAYER_HULL")
START_Hull = iValue;
else if (token == "PLAYER_SRGN")
START_shield_regen_delay = iValue;
else if (token == "DRONE_MAXSPD")
DRONE_maxSpd = iValue;
else if (token == "DRONE_CURSPD")
DRONE_curSpd = iValue;
else if (token == "DRONE_ENERGY")
DRONE_energy = iValue;
else if (token == "DRONE_ERCHRG")
DRONE_eRecharge = iValue;
else if (token == "DRONE_SHIELDS")
DRONE_Shields = iValue;
else if (token == "DRONE_ARMOR")
DRONE_Armor = iValue;
else if (token == "DRONE_HULL")
DRONE_Hull = iValue;
else if (token == "BOSS_ARMOR")
BOSS_ARMOR = iValue;
else if (token == "BOSS_HULL")
BOSS_HULL = iValue;
}
bool load_Config(string filename)
{
// open the file
ifstream input_file(filename.c_str());
if (! input_file.is_open())
{
cout << "Unable to open file: " << filename << endl;
return false;
}
cout << endl << "Loading variables from config file ..." << endl;
// setup variables
string inputText;
string tToken = "" , tValue = "";
string lastToken;
//
const int MAX_TOKENS = 99;
string tokens[MAX_TOKENS];
string values[MAX_TOKENS]; // string (int) value of each token
int currChar = 0;
int tokensFound = 0;
int tLoc = 0, tVLoc = 0;
char tChar;
int lineCnt = 0;
bool blankLine = true;
bool declaringVar = false;
// 2-D array for variables
// read from file
while (! input_file.eof() )
{
// get it one line at a time
getline (input_file, inputText);
lineCnt++;
currChar = 0;
tLoc = 0;
blankLine = true;
// get tokens
//token value
// while not at end of the string
{
tChar = inputText[currChar];
// parse string
// is it an expression ? then check for prior declaration of variable name
if ( tChar == '/' )
currChar
= strLen; // exit loop
// if it is a letter or _ character.
if (isLetter(tChar) || (tChar == '_'))
{
// its a letter, so we assume its a token string
tToken += tChar;
tLoc++;
blankLine = false;
}
else if (isNumber(tChar))
{
// its a number, so we assume its a value
tValue += tChar;
tVLoc++;
blankLine = false;
}
else
{
// white space or special tokens
// handle special characters
if ( tLoc > 0 )
{
// close out the token
tokens[tokensFound] = tToken;
lastToken = tToken;
tToken = ""; // reset for next token
tLoc = 0;
blankLine = false;
}
if ( tVLoc > 0 )
{
// close out the value token
values[tokensFound] = tValue;
setToken(tokens[tokensFound],values[tokensFound]); // override default
tokensFound++; // increment for next token
tValue = ""; // reset for next token
tVLoc = 0;
blankLine = false;
}
}
// next character
currChar++;
} // while ... parsing each line
} // while ... not end of file
input_file.close();
return true;
}
//-------------------------------------------------------//
//----------------- GAME INIT -------------------------//
//initializes the game
int Game_Init(HWND hwnd)
{
cout << "Loading Game ..." << endl;
bool read_from_config = load_Config("setup.cfg");
SDL_Init( SDL_INIT_EVERYTHING );
//Initialize SDL_mixer
if( Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 ) == -1 )
{
cout << "Error: Unable to initialize Audio Mixer" << endl;
return false;
}
// load sound effects and music
if ( en_sounds.setup() == false )
{
cout << "Error: Unable to initialize Audio Sounds (environment)" << endl;
return false;
}
if ( guns.setup() == false )
{
cout << "Error: Unable to initialize Audio Sounds (guns)" << endl;
return false;
}
if ( change.setup() == false )
{
cout << "Error: Unable to initialize Audio Sounds (changes)" << endl;
return false;
}
// Start the music
if (MUSIC_ENABLED)
en_sounds.background_music();
initialized = true;
// initialize graphics
graphicsEngine.Init_Graphics((long)hwnd, SCREEN_WIDTH, SCREEN_HEIGHT, FULLSCREEN);
// int to string
ostringstream buffer;
buffer << SCREEN_WIDTH << "x" << SCREEN_HEIGHT;
string screen_res = buffer.str();
CPRECT tRect = {0,0,128,64};
// loading title image:
CPTexture titleImage;
titleImage.LoadTextureFromFile("./Media/Images/BugHuntTitle.png", 0 /*CPCOLOR_XRGB(255,0,255)*/, false);
graphicsEngine.StartFrame();
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);
graphicsEngine.DrawTextToRect(screen_res, tRect,CP_WHITE);
graphicsEngine.EndFrame();
#ifndef USE_SDL
// Windows Input
Init_DirectInput(hwnd);
Init_Keyboard(hwnd);
#endif
// set all explosions to false
for (int i=0; i < MAX_EXPLOSIONS; i++)
activeEXP[i] = false;
// set all map data to (1) ... SPACE/PLANET (for now)
for (int row=0; row < MAPHEIGHT;row++)
for (int column=0; column < MAPWIDTH; column++)
MAPDATA[column][row] = 1; // all will use sprite #1
// system map data
int cnt = 0;
for (int row=0; row < MAPHEIGHT;row++)
for (int column=0; column < MAPWIDTH; column++)
SYSTEM_MAPDATA[column][row] = cnt++; // so it draws the bmp using tiles
// setup the guns and ammo for the ships
Init_Guns();
//load the tile images
bool result = space_tiles.LoadTextureFromFile("./Media/Images/space_00.png", CPCOLOR_XRGB(0,0,0), true);
if (! result)
{
cout << "Error: Unable to load texture from file : ./Media/Images/space_00.png" << endl;
return false;
}
//load the tile images
cout << "Loading Images ";
for (int p=0; p < NUM_MAPS_PLANET; p++)
{
char myText[100];
sprintf(myText
,"./Media/Images/planet_0%d.png",p
);
result = surface_tiles[p].LoadTextureFromFile(myText, CPCOLOR_XRGB(0,0,0), true);
if (! result)
{
cout << "Error: Unable to load texture from file : " << myText << endl;
return false;
}
else
cout << ".";
}
//load the tile images
for (int s=0; s < NUM_MAPS_SYSTEM; s++)
{
char myText[100];
sprintf(myText
,"./Media/Images/system_0%d.png",s
);
result = system_tiles[s].LoadTextureFromFile(myText, CPCOLOR_XRGB(0,0,0), true);
if (! result)
{
cout << "Error: Unable to load texture from file : " << myText << endl;
return false;
}
else
cout << ".";
}
cout << endl;
//create the scroll buffer surface in memory, slightly bigger
//than the screen
scrollbuffer.CreateOffscreenTexture(SCROLLBUFFERWIDTH, SCROLLBUFFERHEIGHT);
// test bitmap
// will draw under objects that are collided with ... as a test
yellowBmp = new CSprite(0,0,120,100,"./Media/Images/test1.bmp");
redBmp = new CSprite(0,0,120,100,"./Media/Images/test2.png");
// sprite of infected planet
infectedPlanet = new CSprite(0,0,96,96,"./Media/Images/infected.png");
//player
// now using GAME WORLD coordinates
// starting ship Max Speed 8, Solar Energy 20, Recharge Delay 50, BLASTERS, shields, armor, hull (hit points)
// (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)
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);
player->setupAnim(4,SOUTH,4); // sprites per anim, initially heading, sprites per row on sheet
player->setAngle(90);
player->setSTATE(ACTIVE);
player->setAltRecharge(DELAY_LONG);
player->setBorder(0,0,GAMEWORLDWIDTH - 64,GAMEWORLDHEIGHT - 64); // set border to game window
shield = new CSprite(50,50,128,128,"./Media/Images/shield.png");
shield->setupAnim(4,EAST,4);
shield->setSTATE(ACTIVE);
// spawn/create the Enemy SHIPs & BOSS
cout << "creating drones ..." << endl;
createDrones();
// randomly initializes the debris
cout << "creating debris ..." << endl;
createDebris();
// load the static objects (planets)
cout << "loading maps ..." << endl;
loadMaps();
// SCORE
// SYSTEMS CLEARED
int cntPl=0,cntSys=0, temp=0;
for (int s=0; s < NUM_MAPS_SYSTEM; s++)
{
temp=cntPl;
for (int p=0; p < NUM_MAPS_SYSTEM; p++)
if (clearedArea[s][p] == false)
cntPl++;
if (temp != cntPl)
{
cntSys++;
temp = cntPl;
}
}
MAX_SYTEM =cntSys;
MAX_PLANET =cntPl; // <- this is THE SCORE (max)
// Status bars for players
result = color_bars.LoadTextureFromFile("./Media/Images/bars.bmp", CPCOLOR_XRGB(255,0,255), true);
if (! result)
{
cout << "Error: Unable to load texture from file : ./Media/Images/bars.bmp" << endl;
return false;
}
// setup the enter/exit objects
enterPLANET.pt.x = 1;
enterPLANET.pt.y = 1;
enterPLANET.direction = SE;
enterPLANET.scroll.x = 0;
enterPLANET.scroll.y = 0;
enterSYSTEM.pt.x = 1;
enterSYSTEM.pt.y = 1;
enterSYSTEM.direction = SE;
enterSYSTEM.scroll.x = 0;
enterSYSTEM.scroll.y = 0;
enterSPACE.pt.x = 150;
enterSPACE.pt.y = 150;
enterSPACE.direction = SE;
enterSPACE.scroll.x = 0;
enterSPACE.scroll.y = 0;
cout << endl << "Loading complete!" << endl;
return 1;
}
// -------------------------------------------------- //
// ------------ GAME RUN ---------------------------- //
static int lastView;
static bool dontZone = false;
void currView()
{
cout << " current gameView is ";
switch( gameView )
{
case SPACE: cout << "SYSTEM"; break;
case SYSTEM: cout
<< "SYSTEM"; break;
case PLANET: cout << "PLANET"; break;
default: cout << "error - unknown game view!!"; break;
}
cout << endl;
}
void planetView(int newPlanet)
{
cout << "Entering new planet (" << newPlanet << ")" << endl;
currView();
cout << "changing view from SYSTEM to newPlanet?" << endl;
// make sure player doesnt zone repeatedly
if (dontZone)
{
cout << "dontZone is set to TRUE" << endl;
}
else
dontZone = true;
//
// { // SYSTEM -> PLANET
// check if any enemies in this system
// if all planets cleared, then its safe
if ( clearedArea
[CURR_MAP
.system][newPlanet
] )
{
cout
<< "planet (" << newPlanet
<< ") in system (" << CURR_MAP
.system << "," << docked
.system << ") is already cleared." << endl
;
// make boss inactive
boss->setSTATE(INACTIVE);
deaths=0;
return; // exits if planet is already "safe"
}
// else planet not safe
respawnDrones(8);
deaths=0;
respawnBoss(true);
// keep track of what system # you are entering
docked.planet = newPlanet;
CURR_MAP.planet = newPlanet;
// save current location
// enter planet
gameView=PLANET;
SpeedX=0;
SpeedY=0;
player->setSpeed(0);
// move to starting location
player->setPT(enterPLANET.pt);
player->setFacing(enterPLANET.direction);
ScrollX = enterPLANET.scroll.x; // map scroll values for given xy starting location
ScrollY = enterPLANET.scroll.y;
en_sounds.teleport();
//
}
void systemView(int newSystem)
{
cout << "Entering new system (" << newSystem << ")" << endl;
currView();
// assumes SPACE -> SYSTEM
cout << "changing view from SPACE to SYSTEM?" << endl;
// make sure player doesnt zone repeatedly
if (dontZone)
{
cout << "dontZone is set to TRUE" << endl;
}
else
dontZone = true;
// check if any enemies in this system
// if all planets cleared, then its safe
bool systemSafe=true;
int pcnt =0 ;
for (int p=0; p < NUM_MAPS_PLANET; p++)
if ( clearedArea[newSystem][p] == false)
{
cout << "system (" << newSystem << ") planet (" << p << ") is not safe" << endl;
systemSafe=false;
pcnt++; // number of unsafe planets, will control number of drones that spawn
}
CPlanet *sun = immobile_space[newSystem];
if (sun->getMap() == -1)
{
cout << "invalid map returned for solar system object" << endl;
return;
}
if ( systemSafe )
{
cout << "system (" << newSystem << ") safe, not zoning" << endl;
return;
}
cout << "system (" << newSystem << ") is not safe ... zoning" << endl;
// ignore "safe" systems
// respawn aliens (1 per planet)
// pcnt = planets w enemies
// can have up to 10 planets
// max of 10 enemies
// when in SPACE view, there should be no boss attacks ...
// else not safe
respawnDrones(pcnt);
boss->setSTATE(INACTIVE);
deaths=0;
// keep track of what system # you are entering
// save current location
prev.space
.direction
= player
->getFacing();
prev.space
.pt
.x
= player
->getX();
prev.space
.pt
.y
= player
->getY();
// enter system
// set speed,location,etc ...
SpeedX=0;
SpeedY=0;
player->setSpeed(0);
player->setPT(enterSYSTEM.pt);
player->setFacing(enterSYSTEM.direction);
ScrollX = enterSYSTEM.scroll.x;
ScrollY = enterSYSTEM.scroll.y;
en_sounds.teleport();
}
void changeToSPACE()
{
//
// send player back to space station and heal them
gameView=SPACE;
// un-spawn the drones
respawnDrones(0); // sets them all to inactive
boss->setSTATE(INACTIVE);
deaths=0; // reset boss
// move to starting location
CPPOINT dest = { 105, 105 }; // GAMEWORLDWIDTH HEIGHT
player->setPT(dest);
ScrollX=0;ScrollY=0;
player->setSpeed(0);
// player->fullHeal();
player->setSTATE(ACTIVE);
en_sounds.teleport();
//
}
void changeView(int docked_object)
{
cout << "Entering change View" << endl;
currView();
if (docked_object == -1)
return;
string outText = "";
stringstream out;
out.clear();
// else
switch (gameView)
{
case SPACE:
{
debugOut("changing view from SPACE to SYSTEM?");
// make sure player doesnt zone repeatedly
dontZone = true;
// check if any enemies in this system
// if all planets cleared, then its safe
bool systemSafe=true;
int pcnt =0 ;
for (int p=0; p < NUM_MAPS_PLANET; p++)
if ( clearedArea[docked_object][p] == false)
{
out.clear();
out << "system (" << docked_object << ") planet (" << p << ") is not safe" << endl;
debugOut(out.str());
systemSafe=false;
pcnt++; // number of unsafe planets, will control number of drones that spawn
}
CPlanet *sun = immobile_space[docked_object];
if (sun->getMap() == -1)
{
debugOut("invalid map returned for solar system object");
return;
}
if ( systemSafe )
{
out.clear();
out << "system (" << docked_object << ") safe, not zoning";
debugOut(out.str());
return;
}
out.clear();
out << "system (" << docked_object << ") safe, not ... zoning";
debugOut(out.str());
// ignore "safe" systems
// respawn aliens (1 per planet)
// pcnt = planets w enemies
// can have up to 10 planets
// max of 10 enemies
// when in SPACE view, there should be no boss attacks ...
// else not safe
respawnDrones(pcnt);
boss->setSTATE(INACTIVE);
deaths=0;
// keep track of what system # you are entering
docked
.system = docked_object
;
CURR_MAP
.system = docked_object
;
// save current location
prev.space
.direction
= player
->getFacing();
prev.space
.pt
.x
= player
->getX();
prev.space
.pt
.y
= player
->getY();
// enter system
// set speed,location,etc ...
SpeedX=0;
SpeedY=0;
player->setSpeed(0);
player->setPT(enterSYSTEM.pt);
player->setFacing(enterSYSTEM.direction);
ScrollX = enterSYSTEM.scroll.x;
ScrollY = enterSYSTEM.scroll.y;
en_sounds.teleport();
lastView = SPACE;
};
break;
{ // SYSTEM -> PLANET
// make sure player doesnt zone repeatedly
dontZone = true;
// check if any enemies in this system
// if all planets cleared, then its safe
if ( clearedArea
[CURR_MAP
.system][docked_object
] )
{
out.clear();
out
<< "planet (" << docked_object
<< ") in system (" << CURR_MAP
.system << "," << docked
.system << ") is already cleared.";
debugOut(out.str());
// make boss inactive
boss->setSTATE(INACTIVE);
deaths=0;
return; // exits if planet is already "safe"
}
// else planet not safe
respawnDrones(8);
deaths=0;
respawnBoss(true);
// keep track of what system # you are entering
docked.planet = docked_object;
CURR_MAP.planet = docked_object;
// save current location
// enter planet
gameView=PLANET;
SpeedX=0;
SpeedY=0;
player->setSpeed(0);
// move to starting location
player->setPT(enterPLANET.pt);
player->setFacing(enterPLANET.direction);
ScrollX = enterPLANET.scroll.x; // map scroll values for given xy starting location
ScrollY = enterPLANET.scroll.y;
en_sounds.teleport();
}; break;
case PLANET:
{
lastView = PLANET;
return; // exit
}
break; // do nothing, its already PLANET
}
}
// ----------------------------
//the main game loop
void Game_Run(HWND hwnd)
{
#ifndef USE_SDL
//make sure the Direct3D device is valid
if (d3ddev == NULL)
return;
//poll DirectInput devices
Poll_Keyboard();
//check for escape key (to exit program)
if (input.IsKeyDown(VK_ESCAPE)) // DIK_ESCAPE
PostMessage(hwnd, WM_DESTROY, 0, 0);
#endif
int temp=0;
stringstream out; // for convert into to string
// check for player pressing a key
Check_Keys();
// set player ship scale based on view level
switch(gameView)
{
case SPACE:
{
scalex=0.5f;
scaley=0.5f;
};
break;
{
scalex=0.75f;
scaley=0.75f;
};
break;
case PLANET:
{
scalex=1.0f;
scaley=1.0f;
};
break;
}
// RECOVER
// regen solar energy & shields & guns
player->recharge();
// recharge power on enemy ships, so they can continue shooting at you
for (int i=0; i < NUM_ENEMIES; i++)
if ((enemy[i]->getSTATE() != DEAD) && (enemy[i]->getSTATE() != INACTIVE))
enemy[i]->recharge();
if ( (boss->getSTATE() != DEAD) && (boss->getSTATE() != INACTIVE) )
boss->recharge();
// MOVE
//move the sprite
player->doMove();
// Bullet movement
moveBullets();
// process Enemy Actions (FSM)
// and MOVE enemy ships
EnemyAI();
BossAI();
// move Debris in current Game View
moveDebris();
// CHECK MOVES
// Player - check if left screen or not
// make sure ship doesnt leave game coordinates
if (player->checkBounds(0,0,GAMEWORLDWIDTH,GAMEWORLDHEIGHT))
player->setSpeed(0);// border collision occured ... now what? player ship is stopped
//update the scrolling view
UpdateScrollPosition();
//COLLISIONS
// AI bullets vs Player
bullet_AI_Collision(player);
// check if player ship destroyed & respawn if so
if (player->getCur(LOC_HULL) < 1)
respawnPlayer();
// player bullets vs AI
for (int i=0;i < NUM_ENEMIES; i++)
if ((enemy[i]->getSTATE() != DEAD) && (enemy[i]->getSTATE() != INACTIVE))
bulletCollision(enemy[i]);
// player bullets vs Boss
if ( (boss->getSTATE() != DEAD) && (boss->getSTATE() != INACTIVE) )
bulletCollision(boss);
// check for player vs. debris collision ... and determine the results
checkDebris();
// if player collides with a planet - enter planet mode
temp = planetCollision(player); // object # collided with (or -1)
// track current and last object collided with
if (gameView == SPACE)
{
lastPlanetColl.space = currPlanetColl.space; // resets to (0) if no collision
currPlanetColl.space = temp; // resets to (0) if no collision
}
{
}
if (gameView == PLANET)
{
lastPlanetColl.surface = currPlanetColl.surface;
currPlanetColl.surface = temp;
}
// Will hold the current object player is docked at
// DOCKED_AT = temp;
DOCKED_AT = -1;
// OK- if you are docked at a planet -- you can hit the + key to "zoom in"
// check to make sure its a valid DOCK target
// temp = -1 means no collisions
if (temp == -1)
dontZone = false; // no collisions, so now let player zone next time he collides
else
switch(gameView)
{
case SPACE:
{
// DOCKED_AT only holds the [i] last collision w/ object
// lets get the frame # from the given sprite
// find the resulting frame # which represents which type of system it will be
// make sure its a valid #
if ( temp < IMMOBILE_AMT_SPACE)
{
// this should tell us the map # associated, (-1) if none
if (immobile_space[temp]->getMap() > -1)
{
DOCKED_AT = immobile_space[temp]->getMap();
out.clear();
out << "player is docked at system (" << temp << ") map # " << DOCKED_AT;
debugOut(out.str());
// try to auto-zone
//changeView(DOCKED_AT);
systemView(temp); // system #
}
}
};
break;
{
// make sure its a valid #
if ( temp < IMMOBILE_AMT_SYSTEM)
{
if (immobile_system
[docked
.system][temp
]->getMap() > -1)
{
DOCKED_AT
= immobile_system
[docked
.system][temp
]->getMap();
out.clear();
out
<< "player is docked at system (" << docked
.system << ") planet (" << temp
<< ") map # " << DOCKED_AT
;
debugOut(out.str());
// try to auto-zone
planetView(temp);
}
}
};
break;
case PLANET:
{
// DOCKED_AT stays (-1)
};
break;
};
// check for debris leaving the screen
respawnDebris();
// ANIMATE
// change shield color
shield->setFrame(shield->getLastFrame() - player->getShields());
// animate explosions
animExp();
//start rendering
if (graphicsEngine.StartFrame())
{
//draw tiles onto the scroll buffer
switch (gameView)
{
case SPACE: DrawBG(space_tiles); break;
{
if ((c > NUM_MAPS_SYSTEM) || (c < 0))
c = 0;
DrawBG(system_tiles[c]);
}; break;
case PLANET:
{
int c = docked.planet;
if ((c > NUM_MAPS_PLANET) || (c < 0))
c = 0;
DrawBG(surface_tiles[c]);
}; break;
}
// SCORE BOARD
drawText("Shots Fired", 25, 0, CP_GREEN);
drawText("Enemy Bullets", 125, 0, CP_RED);
drawText("Targets Hit", 225, 0, CP_GREEN);
drawText("Rescues", 335, 0, CP_BLUE);
drawNumbers(cntBullets, 50,30);
drawNumbers(enemyBullets,150,30, CP_RED);
drawNumbers(bulletsHit, 250,30);
drawNumbers(astronauts, 350,30, CP_BLUE);
//DEBUG
int rx = SCREEN_WIDTH / 2;
int ry = 8;
drawNumbers(docked.space, rx, ry, CP_RED); rx+=30;
drawNumbers
(docked
.system, rx
, ry
, CP_RED
); rx
+=30;
drawNumbers(docked.planet, rx, ry, CP_RED); rx-=60; ry +=40;
drawNumbers(CURR_MAP.space, rx, ry, CP_RED); rx+=30;
drawNumbers
(CURR_MAP
.system, rx
, ry
, CP_RED
); rx
+=30;
drawNumbers(CURR_MAP.planet, rx, ry, CP_RED); rx-=60; ry +=40;
drawNumbers(DOCKED_AT , rx, ry, CP_GREEN); rx+=30;
drawNumbers(temp , rx, ry, CP_GREEN); rx-=30; ry+=40;
drawNumbers(currPlanetColl.space ,rx,ry,CP_RED); rx+=30;
drawNumbers
(currPlanetColl
.system ,rx
,ry
,CP_RED
); rx
+=30;
drawNumbers(currPlanetColl.surface ,rx,ry,CP_RED);
// DEBUG
// clearedArea[NUM_MAPS_SYSTEM][NUM_MAPS_PLANET];
for (int planet=0; planet < NUM_MAPS_PLANET; planet++) // X
drawNumbers
(clearedArea
[system][planet
] ,(planet
* 20),150+(system * 40),CP_BLUE
);
else
drawNumbers
(clearedArea
[system][planet
] ,(planet
* 20),150+(system * 40),CP_GREEN
);
// --------//
// DEBUG
int rBorder = SCREEN_WIDTH - (SCREEN_WIDTH * 0.2); // 1024 - 20% = 1024 - 204 = 820
drawText("Unsafe", rBorder+60 , 30, CP_RED); // 790
drawText("Total", rBorder+70 , 50, CP_GREEN); // 790
drawText("Systems ", rBorder , 0, CP_GREEN); // 730
drawText("Planets ", rBorder+100, 0, CP_GREEN); // 840
// SCORE
// SYSTEMS CLEARED
int cntPl=0,cntSys=0, temp=0;
for (int s=0; s < NUM_MAPS_SYSTEM; s++)
{
temp=cntPl;
for (int p=0; p < NUM_MAPS_PLANET; p++)
if (clearedArea[s][p] == false)
cntPl++;
if (temp != cntPl)
{
cntSys++;
temp = cntPl;
}
}
drawNumbers(cntSys, rBorder+ 20, 28, CP_RED); // 750
drawNumbers(cntPl, rBorder+120, 28, CP_RED); // 850
drawNumbers(MAX_SYTEM, rBorder+ 20, 50); // 750
drawNumbers(MAX_PLANET,rBorder+120, 50); // 850
// draw the STATIC objects (not moving; planets and such)
drawPlanets();
//draw the space debris sprites (clouds, asteroids, etc)
drawDebris();
// this should draw all the player's bullets that are active
drawBullets();
// draw the health bars for enemy / player ships
drawBars();
//draw shield under the player sprite
graphicsEngine.DrawTexture( player->getX()-ScrollX,player->getY()-ScrollY,
shield->getWidth(),shield->getHeight(),
scalex, scaley, player->getAngle(),
CPCOLOR_XRGB(255,255,255),
shield->getTexture(),
&shield->getRect(),
true);
//draw the player sprite
graphicsEngine.DrawTexture( player->getX()-ScrollX,player->getY()-ScrollY,
player->getWidth(),player->getHeight(),
scalex, scaley, player->getAngle(),
CPCOLOR_XRGB(255,255,255),
player->getTexture(),
&player->getRect(),
true);
for (int i=0;i < NUM_ENEMIES; i++)
if ((enemy[i]->getSTATE() != DEAD) && (enemy[i]->getSTATE() != INACTIVE))
if (enemy[i]->getHP() > 0)// check for ZOMBIES :P
{
graphicsEngine.DrawTexture( enemy[i]->getX()-ScrollX,enemy[i]->getY()-ScrollY,
enemy[i]->getWidth(),enemy[i]->getHeight(),
scalex, scaley, enemy[i]->getAngle(),
CPCOLOR_XRGB(255,255,255),
enemy[i]->getTexture(),
&enemy[i]->getRect(),
true);
}
else
enemy[i]->setSTATE(DEAD);
if ((boss->getSTATE() != DEAD) && (boss->getSTATE() != INACTIVE))
if (boss->getHP() > 0)// check for ZOMBIES :P
{
graphicsEngine.DrawTexture( boss->getX()-ScrollX,boss->getY()-ScrollY,
boss->getWidth(),boss->getHeight(),
scalex, scaley, boss->getAngle(),
CPCOLOR_XRGB(255,255,255),
boss->getTexture(),
&boss->getRect(),
true);
// Draw Beeks over-top
graphicsEngine.DrawTexture( boss->getX()-ScrollX,boss->getY()-ScrollY,
beeks->getWidth(),beeks->getHeight(),
scalex, scaley, boss->getAngle(),
CPCOLOR_XRGB(255,255,255),
beeks->getTexture(),
&beeks->getRect(),
true);
}
else
boss->setSTATE(DEAD);
// draw the Explosions (if any)
drawExp();
graphicsEngine.EndFrame();
} // if (startFrame) ...
}
// -------------------------------------- //
// ---------- GAME END ------------------ //
//frees memory and cleans up before the game ends
void Game_End(HWND hwnd)
{
if (yellowBmp != NULL) delete yellowBmp;
if (redBmp != NULL) delete redBmp;
if (player != NULL) delete player;
if (shield != NULL) delete shield;
if (initialized)
{
int i, j;
for ( i = 0; i < NUM_MAPS_PLANET; i++ )
{
for ( j = 0; j < IMMOBILE_AMT_PLANET; j++ )
{
delete immobile_planet[i][j];
}
}
for ( i = 0; i < IMMOBILE_AMT_SPACE; i++ )
{
delete immobile_space[i];
}
for ( i = 0; i < NUM_MAPS_SYSTEM; i++)
{
for ( j = 0; j < IMMOBILE_AMT_SYSTEM; j++ )
{
delete immobile_system[i][j];
}
}
for ( i = 0; i < 5; i++ )
{
delete Ammo[i];
delete Guns[i];
}
delete Ammo_AI[0];
delete Ammo_AI[1];
delete Guns_AI[0];
delete Guns_AI[1];
for ( i = 0; i < DEBRIS_AMT_SPACE; i++ )
{
delete debris_space[i];
}
for ( i = 0; i < DEBRIS_AMT_SYSTEM; i++ )
{
delete debris_system[i];
}
for ( i = 0; i < DEBRIS_AMT_PLANET; i++ )
{
delete debris_planet[i];
}
for ( i = 0; i < MAX_EXPLOSIONS; i++ )
{
if (activeEXP[i] == true)
{
activeEXP[i] = false;
delete explosion[i];
}
}
for (int i=0; i < NUM_ENEMIES; i++)
{
delete enemy[i];
}
delete boss;
delete beeks;
}
// Sound
Mix_CloseAudio();
#ifdef USE_SDL
// SDL
// text
TTF_Quit();
// Cross platform library
SDL_Quit();
#else
// Windows DirectX
//release the Direct3D device
if (d3ddev != NULL)
d3ddev->Release();
//release the Direct3D object
if (d3d != NULL)
d3d->Release();
Kill_Keyboard();
Kill_Mouse();
dinput->Release();
#endif
}
// -------------------------------------- //
// ------------ Functions --------------- //
void drawText(char* outText, int screenX, int screenY, CPCOLOR color = CP_GREEN)
{
string text(outText);
CPRECT textbox;
textbox.left = screenX;
textbox.top = screenY;
textbox.right = screenX + ( text.length() * 32);
textbox.bottom = screenY + 32;
graphicsEngine.DrawTextToRect( text, textbox, color); //CPCOLOR_ARGB( 255, 120, 255, 120 ) );
};
// draw numbers to screen
void drawNumbers(int number, int screenX, int screenY, CPCOLOR color)
{
static char outText[10];
string text(outText);
CPRECT textbox;
textbox.left = screenX;
textbox.top = screenY;
textbox.right = screenX + ( text.length() * 32);
textbox.bottom = screenY + 30;
graphicsEngine.DrawTextToRect( text, textbox, color);
};
// checks to see if player is trying to move with keys
void Check_Keys()
{
//added input key to allow player to re-activate background music ... key is "9", toggles Music on/off/resume
if(input.IsKeyDown(0x39))
{
if(KEY_PRESSED)
return;
en_sounds.toggleMusic();
KEY_PRESSED = true;
}
if (input.IsKeyDown(VK_DOWN))
{
if (KEY_PRESSED)
return;
// slowing down
player->addSpeed(-2);
KEY_PRESSED=true;
}
else if (input.IsKeyDown(VK_UP))
{
if (KEY_PRESSED)
return;
// increment current speed
player->addSpeed(1);
KEY_PRESSED=true;
player->useSolar(1); // burst uses some energy
}
else if (input.IsKeyDown(VK_RIGHT))
{
if (KEY_PRESSED)
return;
player->turn(RIGHT);
KEY_PRESSED=true;
}
else if (input.IsKeyDown(VK_LEFT))
{
if (KEY_PRESSED)
return;
player->turn(LEFT); // left
KEY_PRESSED=true;
}
else if (input.IsKeyDown(VK_ADD) || input.IsKeyDown(VK_OEM_PLUS))
{ // zoom in
if (KEY_PRESSED == true)
return;
if (DOCKED_AT > -1)
switch (gameView)
{
case SPACE:
{ // space -> system
// check if any enemies in this system
// if all planets cleared, then its safe
bool systemSafe=true;
int pcnt=0;
for (int p=0; p < NUM_MAPS_PLANET; p++)
if ( clearedArea[DOCKED_AT][p] == false)
{
pcnt++;
systemSafe=false;
}
// respawn aliens (1 per planet)
// pcnt = planets w enemies
// can have up to 10 planets
// max of 10 enemies
// when in SPACE view, there should be no boss attacks ...
if (! systemSafe)
respawnDrones(pcnt);
else
{
boss->setSTATE(INACTIVE);
deaths=0;
}
// keep track of what system # you are entering
// save current location
prev.space
.direction
= player
->getFacing();
prev.space
.pt
.x
= player
->getX();
prev.space
.pt
.y
= player
->getY();
// enter system
// set speed,location,etc ...
SpeedX=0;
SpeedY=0;
player->setSpeed(0);
player->setPT(enterSYSTEM.pt);
player->setFacing(enterSYSTEM.direction);
ScrollX = enterSYSTEM.scroll.x;
ScrollY = enterSYSTEM.scroll.y;
en_sounds.teleport();
};
break;
{ // SYSTEM -> PLANET
// check if any enemies in this system
// if all planets cleared, then its safe
if ( clearedArea
[CURR_MAP
.system][DOCKED_AT
] == false)
{
// planet NOT Safe
// max of 10 enemies
respawnDrones(8);
deaths=0;
respawnBoss(true);
}
else
{
boss->setSTATE(INACTIVE);
deaths=0;
}
// keep track of what system # you are entering
docked.planet = DOCKED_AT;
CURR_MAP.planet = DOCKED_AT;
// save current location
// enter planet
gameView=PLANET;
SpeedX=0;
SpeedY=0;
player->setSpeed(0);
// move to starting location
player->setPT(enterPLANET.pt);
player->setFacing(enterPLANET.direction);
ScrollX = enterPLANET.scroll.x; // map scroll values for given xy starting location
ScrollY = enterPLANET.scroll.y;
en_sounds.teleport();
}; break;
case PLANET: break; // do nothing, its already PLANET
}
KEY_PRESSED=true;
}
else if (input.IsKeyDown(VK_SUBTRACT) || input.IsKeyDown(VK_OEM_MINUS) || (player->getSTATE() == DEAD) )
{
if (KEY_PRESSED == true)
return;
// --- NOTE --- //
// the "-" key ///
// sends you back to starting location and does full heal
if (dontZone)
{
cout << "not supposed to zone right now ..." << endl;
return;
}
switch (gameView)
{
case SPACE:
{
// make sure player doesnt zone repeatedly
dontZone = true;
// this is the "panic" button
// so if you FLY off the map or some crazy thing --
// hit "-" and .. teleports u back
CPPOINT dest = { 105, 105 }; // GAMEWORLDWIDTH HEIGHT
player->setPT(dest);
ScrollX=0;ScrollY=0;
player->fullHeal();
player->setSTATE(ACTIVE);
en_sounds.teleport();
}; break;
{
// make sure player doesnt zone repeatedly
dontZone = true;
// SYSTEM -> SPACE view
gameView=SPACE;
// un-spawn the drones
respawnDrones(0); // sets them all to inactive
// we want boss to not spawn
boss->setSTATE(INACTIVE);
deaths=0; // reset boss
// move to starting location
player
->setPT(prev.space
.pt
);
player
->setFacing(prev.space
.direction
);
ScrollX
= getScrollX
(prev.space
.pt
.x
);
ScrollY
= getScrollY
(prev.space
.pt
.y
);
SpeedX= 0;
SpeedY=0;
player->setSpeed(0);
KEY_PRESSED=true;
player->fullHeal();
player->setSTATE(ACTIVE);
en_sounds.teleport();
};break;
case PLANET:
{
// make sure player doesnt zone repeatedly
dontZone = true;
// PLANET -> SYSTEM view
// check if any enemies in this system
// if all planets cleared, then its safe
int pcnt=0; // number of unsafe planets
for (int p=0; p < NUM_MAPS_PLANET; p++)
if ( clearedArea[DOCKED_AT][p] == false)
{
cout << pcnt << ". system (" << DOCKED_AT << ") planet (" << p << ") not safe" << endl;
pcnt++;
}
if (pcnt > DIFF_LEVEL)
pcnt = DIFF_LEVEL;
// respawn aliens (1 per planet)
respawnDrones(pcnt); // NONE if all planets safe
boss->setSTATE(INACTIVE);
deaths=0; // reset boss
player->fullHeal();
player->setSTATE(ACTIVE);
// move to starting location
SpeedX= 0;
SpeedY=0;
player->setSpeed(0);
KEY_PRESSED=true;
en_sounds.teleport();
};break;
}
}
else if (input.IsKeyDown(VK_SPACE) || (SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(1)))
{
// disabled this - so you can hold down fire key
// if (KEY_PRESSED == true)
// return;
// fire the weapon
if ( player->canFire() )
{
// ok got enough power to fire the gun
switch(player->getGun())
{
case 4: guns.plasma(); break;
case 3: guns.missile(); break;
case 2: guns.cannon(); break;
case 1: guns.laser(); break;
default: guns.blaster(); break;
}
// start bullets out front at a safe distance
rCode = Ammo[player->getAmmo()]->spawnBullet(player->getAnchor(),player->getFacing());
if (rCode > -1)
cntBullets++;
}
else
{
// SOUND
// make a sound that tells player it couldnt fire because you are out of power!!!
}
KEY_PRESSED=true;
}
else if ( (SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(2)) || SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(3) || input.IsKeyDown(VK_LCONTROL) || input.IsKeyDown(VK_RCONTROL) )
{
// allow player to hold down fire buttons //
// if (KEY_PRESSED == true)
// return;
KEY_PRESSED=true;
// left/right control
// fires missile(s)
if ( player->getAltLoaded() )
{
string filename;
// ok got enough power to fire the gun
switch(Alt_Weapon)
{
case 4: guns.plasma(); break; // torpedo
default: guns.missile(); break; // missiles
}
// start bullets out front at a safe distance
CPPOINT destPT = player->getAnchor();//, player->getWidth(),player->getHeight(),player->getFacing());
rCode= Ammo[Alt_Weapon]->spawnBullet(destPT,player->getFacing()); // missiles=3, torpedoes=4
if (rCode > -1)
cntBullets++;
// reset the delay for refire
player->fireAlt();
}
}
else if (input.IsKeyDown('1')) // 1 key
{
if (KEY_PRESSED == true)
return;
change.gun_change1();
player->setGun(Guns[0],0);
KEY_PRESSED=true;
}
else if (input.IsKeyDown('2')) // 2 key
{
if (KEY_PRESSED == true)
return;
change.gun_change2();
player->setGun(Guns[1],1);
KEY_PRESSED=true;
}
else if (input.IsKeyDown('3')) // 3 key
{
if (KEY_PRESSED == true)
return;
change.gun_change3();
player->setGun(Guns[2],2);
KEY_PRESSED=true;
}
else if (input.IsKeyDown('4')) // 4 key
{
if (KEY_PRESSED == true)
return;
change.gun_change4();
Alt_Weapon = 3;
player->setAltRecharge(DELAY_LONG);
KEY_PRESSED=true;
}
else if (input.IsKeyDown('5')) // 5 key
{
if (KEY_PRESSED == true)
return;
change.gun_change4();
Alt_Weapon = 4;
player->setAltRecharge(DELAY_MED);
KEY_PRESSED=true;
}
else if (input.IsKeyDown(0x61) || input.IsKeyDown(0x41)) // A,a key for AUTOFIRE
{
if (KEY_PRESSED == true)
return;
// simple toggle for auto fire
if (AUTOFIRE)
AUTOFIRE = false;
else
AUTOFIRE = true;
KEY_PRESSED=true;
}
else
KEY_PRESSED=false;
// if none of the are pressed, we can press keys again
// code to Auto fire weapons
if (AUTOFIRE) // do this last to not interfere w/ other key pressing //
// fire the weapon
if ( player->canFire() )
{
// start bullets out front at a safe distance
rCode = Ammo[player->getAmmo()]->spawnBullet(player->getAnchor(),player->getFacing());
if (rCode > -1)
{
cntBullets++;
// make gun sounds
switch(player->getGun())
{
case 4: guns.plasma(); break;
case 3: guns.missile(); break;
case 2: guns.cannon(); break;
case 1: guns.laser(); break;
default: guns.blaster(); break;
}
}
}
}
bool canScroll(DIRS direction,int speed)
{
//ScrollX and ScrollY
int testX=ScrollX;
int testY=ScrollY;
switch(direction)
{
case NORTH: testY-=speed; break;
case SOUTH: testY+=speed; break;
case EAST: testX+=speed; break;
case WEST: testX-=speed; break;
case NE: testX+=speed;testY-=speed; break;
case NW: testX-=speed;testY-=speed; break;
case SE: testX+=speed;testY+=speed; break;
case SW: testX-=speed;testY+=speed; break;
}
return ( min_max(testX,0,GAMEWORLDWIDTH - SCREEN_WIDTH) && min_max(testY,0,GAMEWORLDHEIGHT - SCREEN_HEIGHT) );
}
//This function updates the scrolling position and speed
void UpdateScrollPosition()
{
bool doScrollLeft = ((player->getX() - ScrollX) <= (SCREEN_WIDTH * 0.25) && ((player->getFacing() == WEST) || (player->getFacing() == NW) || (player->getFacing() == SW)) ); // WEST
bool doScrollRight = ((player->getX() - ScrollX) >= (SCREEN_WIDTH * 0.75) && ((player->getFacing() == EAST) || (player->getFacing() == NE) || (player->getFacing() == SE)) ); // EAST
bool doScrollUp = ((player->getY() - ScrollY) <= (SCREEN_HEIGHT * 0.25) && ((player->getFacing() == NORTH) || (player->getFacing() == NW) || (player->getFacing() == NE)) ); // NORTH
bool doScrollDown = ((player->getY() - ScrollY) >= (SCREEN_HEIGHT * 0.75) && ((player->getFacing() == SOUTH) || (player->getFacing() == SE) || (player->getFacing() == SW)) ); // SOUTH
if ((doScrollLeft || doScrollRight || doScrollUp || doScrollDown) == false)
return;
// exit if cant scroll
if (! canScroll(player->getFacing(),player->getSpeed()) )
return;
SpeedX = 0; SpeedY=0;
switch(player->getFacing())
{ // based on direction we are heading, scroll the background - if possible
case NORTH: SpeedY -= player->getSpeed(); break;
case SOUTH: SpeedY += player->getSpeed(); break;
case EAST: SpeedX += player->getSpeed(); break;
case WEST: SpeedX -= player->getSpeed(); break;
case NE: SpeedX += player->getSpeed();
SpeedY -= player->getSpeed(); break;
case NW: SpeedX -= player->getSpeed();
SpeedY -= player->getSpeed(); break;
case SE: SpeedX += player->getSpeed();
SpeedY += player->getSpeed(); break;
case SW: SpeedX -= player->getSpeed();
SpeedY += player->getSpeed(); break;
}
// N/S movement
if ((ScrollY + SpeedY) < 0)
{
ScrollY = 0;
SpeedY = 0;
}
else if ((ScrollY + SpeedY) > (GAMEWORLDHEIGHT - SCREEN_HEIGHT))
{
ScrollY = GAMEWORLDHEIGHT - SCREEN_HEIGHT;
SpeedY = 0;
}
else
ScrollY += SpeedY; // OK to scroll Y
// E/W movement
if ((ScrollX + SpeedX) < 0)
{
ScrollX = 0;
SpeedX = 0;
}
else if ( (ScrollX + SpeedX) > (GAMEWORLDWIDTH - SCREEN_WIDTH))
{
ScrollX = GAMEWORLDWIDTH - SCREEN_WIDTH;
SpeedX = 0;
}
else
ScrollX += SpeedX;
// now see what direction we are facing
if ( (SpeedX < 0) && (SpeedY < 0) ) // NW
player->setFacing(NW);
if ((SpeedX > 0) && (SpeedY < 0)) // NE
player->setFacing(NE);
if ((SpeedX < 0) && (SpeedY > 0)) // SW
player->setFacing(SW);
if ((SpeedX > 0) && (SpeedY > 0)) // SE
player->setFacing(SE);
if ((SpeedX == 0) && (SpeedY > 0)) // SOUTH
player->setFacing(SOUTH);
if ((SpeedX == 0) && (SpeedY < 0)) // NORTH
player->setFacing(NORTH);
if ((SpeedX > 0) && (SpeedY == 0)) // EAST
player->setFacing(EAST);
if ((SpeedX < 0) && (SpeedY == 0)) // WEST
player->setFacing(WEST);
}
// draw bar at location; using current, max # and color
void drawBar
(int x
, int y
,int curr
,int
max, int color
)
{
// BARS
// grey 0
// blue 1
// green 2
// orange 3
// blue 4
// red 5
// yellow 6
int width = 64;
int height = 6;
// 0 is grey bar
// source
CPRECT r1;
r1.left = 0;
r1.right = width;
r1.top = 0;
r1.bottom = height;
// dest
CPRECT r2;
r2.left = x;
r2.top = y;
r2.right = x + (width*scalex);
r2.bottom = y + (height*scaley);
graphicsEngine.DrawStretchTexture(color_bars, r1, r2);
// draw bar % percentage
// change width to match %
r1.left = (width * color);
r1.right = r1.left + width;
{
// only draw a portion of the rect if not equal
r1
.right
= r1
.left
+ (width
* curr
/ max);
r2
.right
= r2
.left
+ (width
* scalex
* curr
/ max);
}
graphicsEngine.DrawStretchTexture(color_bars, r1, r2);
}
// returns t/f is given # is with the range
bool min_max
(int num
, int
min,int
max)
{
return ((num
<= max) && (num
>= min));
}
void drawPlanets()
{
CPlanet *planet;
// check for debris leaving the screen
switch(gameView)
{
case SPACE:
{
for (int i=0; i < IMMOBILE_AMT_SPACE; i++)
{
planet = immobile_space[i];
CPPOINT dest = planet->getPT();
dest.x -= ScrollX; // since they use game world coords
dest.y -= ScrollY; // subtract the offset values to get screen coord
// draw the sprite if it would appear on screen
if ( (((dest.x + planet->getWidth()) > 0) || (dest.y + planet->getHeight() >= 0)) && (( dest.x < SCREEN_WIDTH) || (dest.y < SCREEN_HEIGHT)) )
{
if ( (hitPlanet[0].space[i] == true) && (planet->getMap() > -1) )
{
graphicsEngine.DrawTexture( dest.x, dest.y,
yellowBmp->getWidth(),yellowBmp->getHeight(),
ScaleX, ScaleY,
planet->getAngle(),
CPCOLOR_XRGB(255,255,255),
yellowBmp->getTexture(),
NULL, //&yellowBmp->getRect(),
false);
}
graphicsEngine.DrawTexture( dest.x, dest.y,
planet->getWidth(),planet->getHeight(),
ScaleX, ScaleY,
planet->getAngle(),
CPCOLOR_XRGB(255,255,255),
planet->getTexture(),
&planet->getRect(),
false);
}
}
};break;
{
int pMap;
bool pSafe;
for (int i=0; i < IMMOBILE_AMT_SYSTEM; i++)
{
planet
= immobile_system
[docked
.system][i
]; // planet #
pMap
= immobile_system
[docked
.system][i
]->getMap(); // map, if any located there
pSafe
= clearedArea
[docked
.system][i
];
CPPOINT dest = planet->getPT();
dest.x -= ScrollX; // since they use game world coords
dest.y -= ScrollY; // subtract the offset values to get screen coord
// draw the sprite if it would appear on screen
if ( (((dest.x + planet->getWidth()) > 0) || (dest.y + planet->getHeight() >= 0)) && (( dest.x < SCREEN_WIDTH) || (dest.y < SCREEN_HEIGHT)) )
{
// DEBUG
// put RED circle behind planets not cleared, YELLOW if they are cleared
if (pMap > -1) // currPlanetColl.system
drawNumbers(pMap,16+(dest.x + planet->getWidth()),dest.y - 16,CP_RED);
graphicsEngine.DrawTexture( dest.x, dest.y,
yellowBmp->getWidth(),yellowBmp->getHeight(),
ScaleX, ScaleY,
planet->getAngle(),
CPCOLOR_XRGB(255,255,255),
yellowBmp->getTexture(),
NULL,
false);
if (! pSafe)
{
//infected_planet
graphicsEngine.DrawTexture( dest.x, dest.y,
infectedPlanet->getWidth(),infectedPlanet->getHeight(),
ScaleX, ScaleY,
planet->getAngle(), // uses same angle as host planet
CPCOLOR_XRGB(255,255,255),
infectedPlanet->getTexture(),
&infectedPlanet->getRect(),
false);
}
else
graphicsEngine.DrawTexture( dest.x, dest.y,
planet->getWidth(),planet->getHeight(),
ScaleX, ScaleY,
planet->getAngle(),
CPCOLOR_XRGB(255,255,255),
planet->getTexture(),
&planet->getRect(),
false);
}
}
};break;
case PLANET:
{
for (int i=0; i < IMMOBILE_AMT_PLANET; i++)
{
planet = immobile_planet[docked.planet][i];
CPPOINT dest = planet->getPT();
dest.x -= ScrollX; // since they use game world coords
dest.y -= ScrollY; // subtract the offset values to get screen coord
// draw the sprite if it would appear on screen
if ( (((dest.x + planet->getWidth()) > 0) || (dest.y + planet->getHeight() >= 0)) && (( dest.x < SCREEN_WIDTH) || (dest.y < SCREEN_HEIGHT)) )
{
if ((hitPlanet[docked.planet].surface[i] == true) && (planet->getMap() > -1))
{
graphicsEngine.DrawTexture( dest.x, dest.y,
yellowBmp->getWidth(),yellowBmp->getHeight(),
ScaleX, ScaleY,
planet->getAngle(),
CPCOLOR_XRGB(255,255,255),
yellowBmp->getTexture(),
NULL, //&yellowBmp->getRect(),
false);
}
graphicsEngine.DrawTexture( dest.x, dest.y,
planet->getWidth(),planet->getHeight(),
ScaleX, ScaleY, planet->getAngle(),
CPCOLOR_XRGB(255,255,255),
planet->getTexture(),
&planet->getRect(),
false);
}
};
};break;
} // end case ...
};
//draw the debris sprites
void drawDebris()
{
CDebris *debris;
// check for debris leaving the screen
switch(gameView)
{
case SPACE:
{
for (int i=0; i < DEBRIS_AMT_SPACE; i++)
{
debris = debris_space[i];
CPPOINT dest = {debris->getX(),debris->getY()};
dest.x -= ScrollX; // since they use game world coords
dest.y -= ScrollY; // subtract the offset values to get screen coord
// draw the sprite if it would appear on screen
if ( (((dest.x + debris->getWidth()) > 0) || (dest.y + debris->getHeight() >= 0)) && (( dest.x < SCREEN_WIDTH) || (dest.y < SCREEN_HEIGHT)) )
{
if (hitDebris.space[i] == true)
{
graphicsEngine.DrawTexture( dest.x, dest.y,
redBmp->getWidth(),redBmp->getHeight(),
scalex, scaley,
debris->getAngle(),
CPCOLOR_XRGB(255,255,255),
redBmp->getTexture(),
NULL, //&debris->getRect(),
false);
}
graphicsEngine.DrawTexture( dest.x, dest.y,
debris->getWidth(),debris->getHeight(),
scalex, scaley,
debris->getAngle(),
CPCOLOR_XRGB(255,255,255),
debris->getTexture(),
&debris->getRect(),
false);
}
}
};break;
{
for (int i=0; i < DEBRIS_AMT_SYSTEM; i++)
{
debris = debris_system[i];
CPPOINT dest = {debris->getX(),debris->getY()};
dest.x -= ScrollX; // since they use game world coords
dest.y -= ScrollY; // subtract the offset values to get screen coord
// draw the sprite if it would appear on screen
if ( (((dest.x + debris->getWidth()) > 0) || (dest.y + debris->getHeight() >= 0)) && (( dest.x < SCREEN_WIDTH) || (dest.y < SCREEN_HEIGHT)) )
{
if (hitDebris
.system[i
] == true)
{
graphicsEngine.DrawTexture( dest.x, dest.y,
redBmp->getWidth(),redBmp->getHeight(),
scalex, scaley,
debris->getAngle(),
CPCOLOR_XRGB(255,255,255),
redBmp->getTexture(),
NULL, //&debris->getRect(),
false);
}
graphicsEngine.DrawTexture( dest.x, dest.y,
debris->getWidth(),debris->getHeight(),
scalex, scaley,
debris->getAngle(),
CPCOLOR_XRGB(255,255,255),
debris->getTexture(),
&debris->getRect(),
false);
}
}
};break;
case PLANET:
{
for (int i=0; i < DEBRIS_AMT_PLANET; i++)
{
debris = debris_planet[i];
CPPOINT dest = {debris->getX(),debris->getY()};
dest.x -= ScrollX; // since they use game world coords
dest.y -= ScrollY; // subtract the offset values to get screen coord
// draw the sprite if it would appear on screen
if ( (((dest.x + debris->getWidth()) > 0) || (dest.y + debris->getHeight() >= 0)) && (( dest.x < SCREEN_WIDTH) || (dest.y < SCREEN_HEIGHT)) )
{
if (hitDebris.surface[i] == true)
{
graphicsEngine.DrawTexture( dest.x, dest.y,
redBmp->getWidth(),redBmp->getHeight(),
scalex, scaley,
debris->getAngle(),
CPCOLOR_XRGB(255,255,255),
yellowBmp->getTexture(),
NULL, //&debris->getRect(),
false);
}
graphicsEngine.DrawTexture( dest.x, dest.y,
debris->getWidth(),debris->getHeight(),
scalex, scaley, debris->getAngle(),
CPCOLOR_XRGB(255,255,255),
debris->getTexture(),
&debris->getRect(),
false);
}
};
};break;
} // end case ...
}
// determine which direction to turn to face target
DIRS getDirection(CPPOINT sourcePT, CPPOINT targetPT)
{
int a = 0; // centered horizontally
// left to right
if (sourcePT.x < targetPT.x) // left
a = -1;
if (sourcePT.x > targetPT.x) // right
a = 1;
int b = 0; // centered vertically
// top to bottom
if (sourcePT.y < targetPT.y) // above
b = -1;
if (sourcePT.y > targetPT.y) // below
b = 1;
switch(a)
{
case -1:
{
if (b == -1)
{ return NW; }
else if (b == 1)
{ return SW; }
else
return WEST;
}; break;
case 1:
{
if (b == -1)
{ return NE; }
else if (b == 1)
{ return SE; }
else
return EAST;
}; break;
case 0:
{
if (b == -1)
{ return NORTH; }
else
{ return SOUTH; }
};break;
}
return EAST; // default catch all
}
// returns distance in pixels
float findDistance(CPPOINT pt1,CPPOINT pt2)
{
float distance;
float dx = pt1.x - pt2.x;
float dy = pt1.y - pt2.y;
distance
= sqrt(dx
*dx
+ dy
*dy
);
return distance;
}
// test for collisions
int SpriteCollision(CSprite *sprite1, CSprite *sprite2)
{
CPRECT rect1,rect2,dest;
rect1.left = sprite1->getX() + 1;
rect1.top = sprite1->getY() + 1;
rect1.right = sprite1->getX() + sprite1->getWidth() -2;
rect1.bottom = sprite1->getY() + sprite1->getHeight() -2;
rect2.left = sprite2->getX() + 1;
rect2.top = sprite2->getY() + 1;
rect2.right = sprite2->getX() + sprite2->getWidth() -2;
rect2.bottom = sprite2->getY() + sprite2->getHeight() -2;
#ifdef USE_SDL
return IntersectCPRect(dest, rect1, rect2);
#else
return IntersectRect((LPRECT)&dest, (LPRECT)&rect1, (LPRECT)&rect2);
#endif
}
// test for collisions
bool rectCollision(CPRECT r1, CPRECT r2)
{
return ( r1.left < r2.right &&
r1.top < r2.bottom &&
r1.right > r2.left &&
r1.bottom > r2.top );
}
bool circleCollision(CPPOINT a,int radius1, CPPOINT b, int radius2)
{
int dx = b.x - a.x;
int dy = b.y - a.y;
int radii = radius1 + radius2;
return ( (dx*dx)+(dy*dy) < (radii * radii) );
};
int planetCollision(CSprite *target)
{
CPlanet *planet;
int i = -1;
// see if player has collided with any debris
switch(gameView)
{
case SPACE:
{
for (i=0; i < IMMOBILE_AMT_SPACE; i++)
{
planet = immobile_space[i];
CPPOINT targetPT = target->getAnchor();
CPPOINT planetPT = planet->getAnchor();
int temp = target->getHeight();
if (target->getWidth() < target->getHeight())
temp = target->getWidth();
int radiusT = temp * COLL_RADIUS * scalex; // should cover most of the sprite in its radius ... 96/2=48-4=44
temp = planet->getHeight();
if (planet->getWidth() < planet->getHeight())
temp = planet->getWidth();
int radiusD = temp * COLL_RADIUS; // should cover most of the sprite in its radius ... 120/2=60-
// use circle collision
if (circleCollision(targetPT,radiusT,planetPT,radiusD))
{
hitPlanet[0].space[i] = true;
return i;
}
else
hitPlanet[0].space[i] = false;
}
}; break;
{
for (i=0; i < IMMOBILE_AMT_SYSTEM; i++)
{
planet
= immobile_system
[docked
.system][i
];
CPPOINT targetPT = target->getAnchor();
CPPOINT planetPT = planet->getAnchor();
int temp = target->getHeight();
if (target->getWidth() < target->getHeight())
temp = target->getWidth();
int radiusT = temp * COLL_RADIUS * scalex; // should cover most of the sprite in its radius ... 96/2=48-4=44
temp = planet->getHeight();
if (planet->getWidth() < planet->getHeight())
temp = planet->getWidth();
int radiusD = temp * COLL_RADIUS; // should cover most of the sprite in its radius ... 120/2=60-
// use circle collision
if (circleCollision(targetPT,radiusT,planetPT,radiusD))
{
return i;
}
else
}
}; break;
case PLANET:
{
for (i=0; i < IMMOBILE_AMT_PLANET; i++)
{
planet = immobile_planet[docked.planet][i];
CPPOINT targetPT = target->getAnchor();
CPPOINT planetPT = planet->getAnchor();
int temp = target->getHeight();
if (target->getWidth() < target->getHeight())
temp = target->getWidth();
int radiusT = temp * COLL_RADIUS * scalex; // should cover most of the sprite in its radius ... 96/2=48-4=44
temp = planet->getHeight();
if (planet->getWidth() < planet->getHeight())
temp = planet->getWidth();
int radiusD = temp * COLL_RADIUS; // should cover most of the sprite in its radius ... 120/2=60-
// use circle collision
if (circleCollision(targetPT,radiusT,planetPT,radiusD))
{
hitPlanet[docked.planet].surface[i] = true;
return i;
}
else
hitPlanet[docked.planet].surface[i] = false;
}
};break;
}
// if no collisions (return -1)
return -1;
} // end planet collision testing
int debrisCollision( CSprite *target)
{
CDebris *debris;
int i;
// see if player has collided with any debris
switch(gameView)
{
case SPACE:
{
for (i=0; i < DEBRIS_AMT_SPACE; i++)
{
debris = debris_space[i];
CPPOINT targetPT = target->getAnchor();
CPPOINT debrisPT = debris->getAnchor();
int temp = target->getHeight();
if (target->getWidth() < target->getHeight())
temp = target->getWidth();
int radiusT = temp * COLL_RADIUS * scalex; // should cover most of the sprite in its radius ... 96/2=48-4=44
temp = debris->getHeight();
if (debris->getWidth() < debris->getHeight())
temp = debris->getWidth();
int radiusD = temp * COLL_RADIUS; // should cover most of the sprite in its radius ... 120/2=60-
// use circle collision
if (circleCollision(targetPT,radiusT,debrisPT,radiusD))
{
hitDebris.space[i] = true;
return i;
}
else
hitDebris.space[i] = false;
}
}; break;
{
for (i=0; i < DEBRIS_AMT_SYSTEM; i++)
{
debris = debris_system[i];
CPPOINT targetPT = target->getAnchor();
CPPOINT debrisPT = debris->getAnchor();
int temp = target->getHeight();
if (target->getWidth() < target->getHeight())
temp = target->getWidth();
int radiusT = temp * COLL_RADIUS * scalex; // should cover most of the sprite in its radius ... 96/2=48-4=44
temp = debris->getHeight();
if (debris->getWidth() < debris->getHeight())
temp = debris->getWidth();
int radiusD = temp * COLL_RADIUS; // should cover most of the sprite in its radius ... 120/2=60-
// use circle collision
if (circleCollision(targetPT,radiusT,debrisPT,radiusD))
{
return i;
}
else
}
}; break;
case PLANET:
{
for (i=0; i < DEBRIS_AMT_PLANET; i++)
{
debris = debris_planet[i];
CPPOINT targetPT = target->getAnchor();
CPPOINT debrisPT = debris->getAnchor();
int temp = target->getHeight();
if (target->getWidth() < target->getHeight())
temp = target->getWidth();
int radiusT = temp * COLL_RADIUS * scalex; // should cover most of the sprite in its radius ... 96/2=48-4=44
temp = debris->getHeight();
if (debris->getWidth() < debris->getHeight())
temp = debris->getWidth();
int radiusD = temp * COLL_RADIUS; // should cover most of the sprite in its radius ... 120/2=60-
// use circle collision
if (circleCollision(targetPT,radiusT,debrisPT,radiusD))
{
hitDebris.surface[i] = true;
return i;
}
else
hitDebris.surface[i] = false;
}
};break;
}
// if no collisions
return -1;
} // end debris collision testing
// checks if debris has left screen and respawns it randomly
// only used for the space view
void respawnDebris()
{
// it checks for objects leaving the game map
// and respawns them with new image
// heading etc ... from one of the 4 map borders
for (int i=0; i < DEBRIS_AMT_SPACE; i++)
debris_space[i]->checkExit();
for (int i=0; i < DEBRIS_AMT_SYSTEM; i++)
debris_system[i]->checkExit();
for (int i=0; i < DEBRIS_AMT_PLANET; i++)
debris_planet[i]->checkExit();
}
// calculates new velocity and heading
void collision2Ds(double m1, double m2,
double x1, double y1, double x2, double y2)
{
// globals
//double vPx; vx1
//double vPy; vy1
//double vJx; vx2
//double vJy; vy2
double m21,dvx2,a,x21,y21,vx21,vy21,fy21,sign;
m21=m2/m1;
x21=x2-x1;
y21=y2-y1;
vx21=vJx-vPx;
vy21=vJy-vPy;
// *** return old velocities if balls are not approaching ***
if ( (vx21*x21 + vy21*y21) >= 0) return;
fy21=1.0E-12*fabs(y21);
if ( fabs(x21)<fy21 ) {
if (x21<0) { sign=-1; } else { sign=1;}
x21=fy21*sign;
}
// *** update velocities ***
a=y21/x21;
dvx2= -2*(vx21 +a*vy21)/((1+a*a)*(1+m21)) ;
vJx=vJx+dvx2;
vJy=vJy+a*dvx2;
vPx=vPx-m21*dvx2;
vPy=vPy-a*m21*dvx2;
}
// translates a given x location to get ScrollX value
int getScrollX(int x)
{
int temp = 0;
if (x < (SCREEN_WIDTH*0.75))
return 0;
temp = x - (SCREEN_WIDTH /2); // 1000 - 480 = 520 scrollx
if ( temp > (GAMEWORLDWIDTH - SCREEN_WIDTH))
temp = GAMEWORLDWIDTH - SCREEN_WIDTH;
return temp;
};
// translates a given y location to get ScrollY value
int getScrollY(int y)
{
int temp = 0;
if (y < (SCREEN_HEIGHT*0.75))
return 0;
temp = y - (SCREEN_HEIGHT /2); // 1000 - 480 = 520 scrollx
if ( temp > (GAMEWORLDHEIGHT - SCREEN_HEIGHT))
temp = GAMEWORLDHEIGHT - SCREEN_HEIGHT;
return temp;
};
void loadMaps()
{
int cnt=0;
char buffer[256];
char line[255];
char filename[100];
char* Filename;
// setup cleared - by default all areas are cleared, until maps are loaded
for (int s=0;s < NUM_MAPS_SYSTEM; s++)
for (int p=0;p<NUM_MAPS_PLANET;p++)
clearedArea[s][p] = true;
// ------------------------------------------------------------------------
for (int map=0; map < NUM_MAPS_PLANET; map++)
{
sprintf(filename
,"./Media/static_surface_0%d.txt",map
);
// load map data
ifstream mapFile(filename);
// read in data from map file
// BITMAP SOURCE
Filename = "./Media/Images/static_surface.png";
cnt=0;
while ((! mapFile.eof()) && (cnt < IMMOBILE_AMT_PLANET))
{
// read in the map data
mapFile
.getline
(line
, sizeof(buffer
), ','); // X
int x = atoi(line);
mapFile
.getline
(line
, sizeof(buffer
), ','); // Y
int y = atoi(line);
mapFile
.getline
(line
, sizeof(buffer
), ','); // FRAME #
int frame = atoi(line);
mapFile
.getline
(line
, sizeof(buffer
), ','); // ANGLE
int rotation = atoi(line);
mapFile
.getline
(line
, sizeof(buffer
), '\n'); // grab the end of line
int Map = atoi(line); // rotation speed (if any)
immobile_planet[map][cnt] = new CPlanet(x,y,120,110,Filename,IMMOBILE_AMT_PLANET);
immobile_planet[map][cnt]->setFrame(frame-1);
immobile_planet[map][cnt]->setFacing(NORTH);
immobile_planet[map][cnt]->setMap(Map);
immobile_planet[map][cnt]->setAngle(rotation);
hitPlanet[map].surface[cnt] = false;
assert(immobile_planet
[map
][cnt
]);
cnt++;
}
mapFile.close();
}
// ------------------------------------------------------------------------
ifstream spaceFile("./Media/static_space_00.txt");
Filename = "./Media/Images/static_space.png";
cnt=0;
while ((! spaceFile.eof()) && (cnt < IMMOBILE_AMT_SPACE))
{
// read in the map data
spaceFile
.getline
(line
, sizeof(buffer
), ','); // X
int x = atoi(line);
spaceFile
.getline
(line
, sizeof(buffer
), ','); // Y
int y = atoi(line);
spaceFile
.getline
(line
, sizeof(buffer
), ','); // FRAME #
int frame = atoi(line);
spaceFile
.getline
(line
, sizeof(buffer
), ','); // ANGLE
int rotation = atoi(line);
spaceFile
.getline
(line
, sizeof(buffer
), '\n'); // grab the end of line
int map = atoi(line); // rotation speed (if any)
immobile_space[cnt] = new CPlanet(x,y,120,110,Filename,IMMOBILE_SPRITES_SPACE);
immobile_space[cnt]->setFrame(frame-1);
immobile_space[cnt]->setAngle(rotation);
immobile_space[cnt]->setMap(map);
hitPlanet[0].space[cnt] = false;
cnt++;
}
spaceFile.close();
// ------------------------------------------------------------------------
for (int map=0; map < NUM_MAPS_SYSTEM; map++)
{
sprintf(filename
,"./Media/static_system_0%d.txt",map
);
ifstream sysFile(filename);
// read in data from map file
// BITMAP SOURCE
Filename = "./Media/Images/static_system.png";
cnt=0;
while ((! sysFile.eof()) && (cnt < IMMOBILE_AMT_SYSTEM))
{
// read in the map data
sysFile
.getline
(line
, sizeof(buffer
), ','); // X
int x = atoi(line);
sysFile
.getline
(line
, sizeof(buffer
), ','); // Y
int y = atoi(line);
sysFile
.getline
(line
, sizeof(buffer
), ','); // FRAME #
int frame = atoi(line);
sysFile
.getline
(line
, sizeof(buffer
), ','); // ANGLE
int rotation = atoi(line);
sysFile
.getline
(line
, sizeof(buffer
), '\n'); // grab the end of line
int Map = atoi(line); // MAP (if not -1)
// Map > -1 , cnt = Planet # // indicate enemy occupied areas
if (Map > -1)
clearedArea[map][cnt] = false; // there will be enemies there now
immobile_system[map][cnt] = new CPlanet(x,y,120,110,Filename,IMMOBILE_AMT_SYSTEM);
immobile_system[map][cnt]->setFrame(frame-1); // 0 is the first frame!
immobile_system[map][cnt]->setAngle(rotation);
immobile_system[map][cnt]->setMap(Map);
assert(immobile_system
[map
][cnt
]);
hitPlanet
[map
].system[cnt
] = false;
cnt++;
}
sysFile.close();
}
};
void moveBullets()
{
for (int a=0; a < MAX_AMMO; a++)
Ammo[a]->doMoves(scalex); // only moves the active ones
for (int a=0; a < MAX_GUNS_AI; a++)
Ammo_AI[a]->doMoves(scalex); // only moves the active ones
};
// draw the active bullet sprites
void drawBullets()
{
int cnt = 0;
// PC bullets
for (int a=0; a < MAX_AMMO; a++)
for (int i=0; i < MAX_BULLETS; i++)
if (Ammo[a]->Bullets[i].isActive == true)
{ //draw the bullet sprite
cnt++; // keep track of number of bullets drawn
graphicsEngine.DrawTexture( Ammo[a]->Bullets[i].currPT.x-ScrollX,
Ammo[a]->Bullets[i].currPT.y-ScrollY,
Ammo[a]->getWidth(), Ammo[a]->getHeight(),
scalex, scaley,
Ammo[a]->Bullets[i].angle,
CPCOLOR_XRGB(255,255,255),
Ammo[a]->getTexture(),
& Ammo[a]->getRect(),
true);
}
// AI Bullets
for (int a=0; a < MAX_GUNS_AI; a++)
for (int i=0; i < MAX_BULLETS; i++)
if (Ammo_AI[a]->Bullets[i].isActive == true)
{ //draw the bullet sprite
cnt++; // keep track of number of bullets drawn
graphicsEngine.DrawTexture( Ammo_AI[a]->Bullets[i].currPT.x-ScrollX,
Ammo_AI[a]->Bullets[i].currPT.y-ScrollY,
Ammo_AI[a]->getWidth(), Ammo_AI[a]->getHeight(),
scalex, scaley,
Ammo_AI[a]->Bullets[i].angle,
CPCOLOR_XRGB(255,255,255),
Ammo_AI[a]->getTexture(),
& Ammo_AI[a]->getRect(),
true);
}
bulletsDrawn = cnt;
};
// draw the active bullet sprites (for players projectiles vs AI)
void bulletCollision(CShip *target)
{
int cnt = 0;
bool hit = false;
int hitCnt = 0;
for (int a=0; a < MAX_AMMO; a++)
for (int i=0; i < MAX_BULLETS; i++)
if (Ammo[a]->Bullets[i].isActive == true)
{
CPPOINT pt1 = Ammo[a]->Bullets[i].currPT;
int halfW = Ammo[a]->getWidth() / 2;
int halfH = Ammo[a]->getHeight() / 2;
CPPOINT center;
center.x = pt1.x + halfW;
center.y = pt1.y + halfH;
int radius1 = halfW;
// players location
CPPOINT pt2 = target->getAnchor();
int radius2 = target->getWidth() * 0.4f;
if ( circleCollision(center,radius1,pt2,radius2) )
{
// this bullet has collided
hitCnt++;
Ammo[a]->Bullets[i].isActive = false;
DAMAGE dType = Ammo[a]->getDmgType();
int dmg = Ammo[a]->getDmg();
if (target->applyDmg(dType,dmg))
{
// spawn new explosion
newExp(target->getAnchor());
// target is DEAD !!!
target->setSTATE(DEAD);
// TODO: BOOM SOUND
// target is dead, lets leave
bulletsHit += hitCnt;
return ;
// remaining bullets keep on moving
}
}
}
bulletsHit += hitCnt;
};
// checks AI bullets for collision (player sprite)
void bullet_AI_Collision(CShip *target)
{
// dont bother if target already dead
if (target->getSTATE() == DEAD)
return;
int cnt = 0;
bool hit = false;
int hitCnt = 0;
for (int a=0; a < MAX_GUNS_AI; a++)
for (int i=0; i < MAX_BULLETS; i++)
if (Ammo_AI[a]->Bullets[i].isActive == true)
{
CPPOINT pt1 = Ammo_AI[a]->Bullets[i].currPT;
int halfW = Ammo_AI[a]->getWidth() / 2;
int halfH = Ammo_AI[a]->getHeight() / 2;
CPPOINT center;
center.x = pt1.x + halfW;
center.y = pt1.y + halfH;
int radius1 = halfW;
// players location
CPPOINT pt2 = target->getAnchor();
int radius2 = target->getWidth() * 0.4f;
if ( circleCollision(center,radius1,pt2,radius2) )
{
// this bullet has collided
hitCnt++;
Ammo_AI[a]->Bullets[i].isActive = false;
DAMAGE dType = Ammo_AI[a]->getDmgType();
int dmg = Ammo_AI[a]->getDmg();
if (target->applyDmg(dType,dmg))
{
// spawn new explosion
newExp(target->getAnchor());
// target is DEAD !!!
target->setSTATE(DEAD);
// TODO: BOOM SOUND
// target dead
// dont worry about any more damage
bulletsHit += hitCnt;
return;
}
}
}
bulletsHit += hitCnt;
};
void Init_Guns()
{
// [5] //dmg speed
Ammo[0] = new CProjectile(1,ENERGY, 14,RANGE_MED, "./Media/Images/proj_blaster.png" ,30,30); // 24
Ammo[1] = new CProjectile(2,ENERGY, 20,RANGE_LONG, "./Media/Images/proj_laser.bmp" ,16,64); // 25
Ammo[2] = new CProjectile(3,KINETIC, 12,RANGE_SHORT,"./Media/Images/cannon.png" ,44,44); // 35
Ammo
[3] = new CProjectile
(2,EXPLODE, 12,RANGE_LONG
,"./Media/Images/missile.png" ,32,32); // 25
Ammo[4] = new CProjectile(4,ENERGY, 10,RANGE_SHORT,"./Media/Images/proj_torpedo.bmp" ,32,32); // 25
Ammo[3]->setupAnim(4,NORTH,4); // animated rocket frames
for (int i=0;i < MAX_AMMO; i++)
assert(Ammo
[i
]); // make sure all load successfully
// reload cycl energy per shot
Guns[0] = new CGuns(0, DELAY_SHORT, 1,"Blaster"); // blaster
Guns[1] = new CGuns(1, DELAY_SHORTEST, 2,"Laser"); // laser
Guns[2] = new CGuns(2, DELAY_MED, 3,"Cannon"); // cannon
Guns[3] = new CGuns(3, DELAY_LONG, 5,"Missile"); // missile
Guns[4] = new CGuns(4, DELAY_LONG, 5,"Torpedo"); // photon torpedo
for (int i=0;i < MAX_GUNS; i++)
assert(Guns
[i
]); // make sure all load successfully
//const int MAX_AI_GUNS;
//dmg
Ammo_AI[0] = new CProjectile(1,KINETIC, 9,RANGE_SHORT,"./Media/Images/mantabulletS.png" ,16,16); // 25
Ammo_AI[1] = new CProjectile(2,ENERGY , 12,RANGE_LONG ,"./Media/Images/mantabullet.png" ,32,32); // 25
Guns_AI[0] = new CGuns(1, DELAY_MED, 2,"manta bullet"); // AI blasters
Guns_AI[1] = new CGuns(2, DELAY_MED, 2,"boss bullet"); // AI blasters x 3
for (int i=0;i < MAX_GUNS_AI; i++)
{
assert(Guns_AI
[i
]); // make sure all load successfully
assert(Ammo_AI
[i
]); // make sure all load successfully
}
}
// performs basic FSM and then moves enemy ship
void EnemyAI()
{
int GUN_RANGE, distance;
DIRS chaseDIR, fleeDIR;
// default actions should be ; attack, shift l/r, shift back -- or move towards player/wander
// Enemy AI //
for (int i=0; i < NUM_ENEMIES; i++)
if (enemy[i]->getSTATE() != INACTIVE) // ignore the enemy if its INACTIVE
{
GUN_RANGE = Ammo[ enemy[i]->getAmmo() ]->getRange() * scalex; // 75% range in SYSTEM, 50% range in SPACE
distance = findDistance(enemy[i]->getAnchor(),player->getAnchor());
chaseDIR = getDirection(player->getAnchor() ,enemy[i]->getAnchor()); // used to CHASE
fleeDIR = getDirection(enemy[i]->getAnchor(),player->getAnchor()); // used to FLEE
// always move away if super close
if (distance <= TOO_CLOSE)
{
enemy[i]->setSpeed(0);
if (distance <= (TOO_CLOSE/2))
{
enemy[i]->setSTATE(FLEEING); // way too close, get away
enemy[i]->addSpeed(2);
}
}
switch ( enemy[i]->getSTATE() )
{
case FLEEING:
{
// flee until at a safe distance away
if (distance > (2*TOO_CLOSE))
{ // no longer need to flee
enemy[i]->setSTATE(ACTIVE);
}
else
{ // FLEE
enemy[i]->addSpeed(1); // move towards MAX speed (caps at max)
// face player
enemy[i]->setFacing(fleeDIR);
if ((rand() % 100) < 10) // 10% chance for random 45 degree turns
enemy
[i
]->turn(rand() % 2);
}
}; break;
case ACTIVE: // Moving around normally
{
if ((rand() % 100) < 10) // 10% chance for random 45 degree turns
enemy
[i
]->turn(rand() % 2);
// random +/- speed
enemy[i]->addSpeed(1);
// caps at MAX speed, so no harm in this
// change state if target visible
if (distance <= SIGHT_RANGE)
enemy[i]->setSTATE(SEARCHING); // sees player on radar
if (distance <= GUN_RANGE)
enemy[i]->setSTATE(ATTACKING);
}; break;
case SEARCHING:
{ // HEAD towards player - AI "Sees" the player on radar
enemy[i]->addSpeed(1); // move towards MAX speed (caps at max)
// face player
enemy[i]->setFacing(chaseDIR);
// change state if target visible
if (distance > SIGHT_RANGE)
enemy[i]->setSTATE(ACTIVE); // sees player on radar
if (distance <= GUN_RANGE)
enemy[i]->setSTATE(ATTACKING);
}; break;
case ATTACKING: // Attacking player
{
// make sure the target is still in range
if (distance > GUN_RANGE)
{
// unable to fire ... move first
enemy[i]->setSTATE(ACTIVE);
// this should make him head towards player
enemy[i]->setFacing(chaseDIR);
enemy[i]->addSpeed(2);
}
else
{ // close enough to fire
// see if ship has enough power to shoot, returns true if able to fire
// also checks if the gun is reloaded or not
if ( enemy[i]->canFire())
{
// try to match players speed
//enemy[i]->setSpeed(player->getSpeed());
enemy[i]->setSpeed(0); // stop moving and fire gun
// face player
enemy[i]->setFacing(chaseDIR);
Ammo_AI[0]->spawnBullet(enemy[i]->getAnchor(),enemy[i]->getFacing());
enemyBullets++;
// TODO: SOUND :: enemies guns firing at your
}
else
{
// shift r/l while still facing target
enemy[i]->addSpeed(1); // speed up a little first
enemy[i]->shift(); // then slide r/l to randomly avoid stuff
// keep current facing
}
} // distance
}; break; // CASE ..
} // end of SWITCH()
// perform the actual MOVE for enemy
enemy[i]->doMove();
// check boundaries
if ( enemy[i]->checkBounds(0,0,GAMEWORLDWIDTH,GAMEWORLDHEIGHT) ) // BOUNDARIES CHECK
{
// warp back to top left corner
enemy
[i
]->setX(300 + (rand() % 200)); // spawn point
enemy
[i
]->setY(100 + (rand() % 200));
enemy[i]->setFacing(SOUTH);
enemy[i]->setSpeed(1);
}
} // END ... Enemy AI code //
}; // end EnemyAI function //
// performs basic FSM and then moves enemy ship
void BossAI()
{
// Thw ANIM will be beaks added on top --
// not activated
if (boss->getSTATE() == INACTIVE)
return;
// died
if (boss->getSTATE() == DEAD)
{
deaths++;
if (deaths < lives)
{
// respawn, next color
boss->setSTATE(ACTIVE);
// create new boss
// but stay at same location
respawnBoss(false);
boss->setFrame(deaths);
return;
}
else // did boss just die? if so, make sure the planet is now "safe"
{
if (gameView == PLANET)
if ( clearedArea
[CURR_MAP
.system][CURR_MAP
.planet
] == false)
clearedArea
[CURR_MAP
.system][CURR_MAP
.planet
] = true;
return; // either way, exit
}
}
// Boss AI //
int GUN_RANGE=RANGE_LONG, distance, SIGHT = RANGE_LONG;
DIRS chaseDIR, fleeDIR;
GUN_RANGE = Ammo[ boss->getAmmo() ]->getRange() * scalex; // 75% range in SYSTEM, 50% range in SPACE
distance = findDistance(boss->getAnchor(),player->getAnchor());
chaseDIR = getDirection(player->getAnchor() ,boss->getAnchor()); // used to CHASE
fleeDIR = getDirection(boss->getAnchor(),player->getAnchor()); // used to FLEE
// always move away if super close
if (distance <= 300)
{
boss->setSTATE(FLEEING); // way too close, get away
boss->setSpeed(2);
};
if (distance <= 200)
{
boss->setSTATE(ATTACKING); // way too close, just attack
boss->setSpeed(0);
} ;
switch ( boss->getSTATE() )
{
case FLEEING:
{
// flee until at a safe distance away
if (distance > 400)
{ // no longer need to flee
boss->setSTATE(ACTIVE);
}
else
{ // FLEE
boss->addSpeed(1); // move towards MAX speed (caps at max)
// face player
boss->setFacing(fleeDIR);
if ((rand() % 100) < 1) // 10% chance for random 45 degree turns
}
}; break;
case ACTIVE: // Moving around normally
{
if ((rand() % 100) < 1) // 10% chance for random 45 degree turn
// random +/- speed
boss->addSpeed(1);
// caps at MAX speed, so no harm in this
// change state if target visible
if (distance <= 1000)
boss->setSTATE(SEARCHING); // sees player on radar
if (distance <= RANGE_LONG)
boss->setSTATE(ATTACKING);
}; break;
case SEARCHING:
{ // HEAD towards player - AI "Sees" the player on radar
boss->addSpeed(1); // move towards MAX speed (caps at max)
// face player
boss->setFacing(chaseDIR);
// change state if target visible
if (distance > SIGHT_RANGE)
boss->setSTATE(ACTIVE); // sees player on radar
if (distance <= GUN_RANGE)
boss->setSTATE(ATTACKING);
}; break;
case ATTACKING: // Attacking player
{
// make sure the target is still in range
if (distance > RANGE_LONG)
{
// unable to fire ... move first
boss->setSTATE(ACTIVE);
// this should make him head towards player
boss->setFacing(chaseDIR);
boss->addSpeed(2);
}
else
{ // close enough to fire
// see if ship has enough power to shoot, returns true if able to fire
// also checks if the gun is reloaded or not
if ( boss->canFire() )
{
// try to match players speed
//boss->setSpeed(player->getSpeed());
boss->setSpeed(0); // stop moving and fire gun
// face player
boss->setFacing(chaseDIR);
DIRS dir1=NW,dir2=chaseDIR,dir3=NE;
switch(boss->getFacing())
{
case NORTH : dir1=NW; dir3=NE; break; // dir1 = left, dir3=right
case NE : dir1=NORTH; dir3=EAST; break;
case NW : dir1=WEST; dir3=NORTH;break;
case EAST : dir1=NW; dir3=SE; break;
case WEST : dir1=SW; dir3=NW; break;
case SOUTH : dir1=SW; dir3=SE; break;
case SE : dir1=EAST; dir3=SOUTH;break;
case SW : dir1=SOUTH; dir3=WEST; break;
};
CPPOINT pt1,pt2=boss->getAnchor(),pt3;
pt1=pt2;
pt3=pt2;
switch(chaseDIR)
{
case NE:
case SW:
{
pt1.x -= 64;
pt3.x += 64;
pt1.y -= 64;
pt3.y += 64;
}; break;
case NW:
case SE:
{
pt1.x += 64;
pt3.x -= 64;
pt1.y += 64;
pt3.y -= 64;
}; break;
case WEST:
case EAST:
{
pt1.x -= 64;
pt3.x += 64;
}; break;
case NORTH:
case SOUTH:
{
pt1.y -= 64;
pt3.y += 64;
}; break;
}
// fire (3) bullet towards player
Ammo_AI[1]->spawnBullet( pt1, dir3 ); // towards right
Ammo_AI[1]->spawnBullet( pt2, dir2); // ahead
Ammo_AI[1]->spawnBullet( pt3, dir1); // towards left
enemyBullets+=3;
// TODO: SOUND :: enemies guns firing at your
}
} // distance
}; break; // CASE ..
} // end of SWITCH()
// perform the actual MOVE for enemy
boss->doMove(); // which doesnt animate the body
beeks->nextFrame();// animate the beeks tho
// check boundaries
if (boss->getX() < 0)
{
boss->setX(64);
boss->setSpeed(0);
};
if (boss->getX() > (GAMEWORLDWIDTH-128))
{
boss->setX(0); // ha ha -- GAMEWORLDWIDTH-128);
boss->setSpeed(0);
};
if (boss->getY() < 0)
{
boss->setY(1);
boss->setSpeed(0);
};
if (boss->getY() > (GAMEWORLDHEIGHT-128))
{
boss->setY(0); // GAMEWORLDHEIGHT-128);
boss->setSpeed(0);
};
}; // end EnemyAI function //
void moveDebris()
{
// move Debris (current view only)
switch(gameView)
{
case SPACE:
{
for (int i=0; i < DEBRIS_AMT_SPACE; i++)
debris_space[i]->doMove(); // moves and rotates
}; break;
{
for (int i=0; i < DEBRIS_AMT_SYSTEM; i++)
debris_system[i]->doMove(); // rotates only
}; break;
case PLANET:
{
for (int i=0; i < DEBRIS_AMT_PLANET; i++)
debris_planet[i]->doMove(); // static
}; break;
}
}
// check for collisions with moving debris ... and applies the effect there of
void checkDebris()
{
//track recent collision
if (gameView == SPACE) lastColl.space = currColl.space;
if (gameView == PLANET) lastColl.surface = currColl.surface;
// check for player vs. debris collisions
int temp = debrisCollision(player);
if (gameView == SPACE) currColl.space = temp; // resets to (0) if no collision
if (gameView == PLANET) currColl.surface = temp;
// ignore mid-air collisions on planets (clouds dont hurt)
if (temp > -1)
switch(gameView)
{
case PLANET:
{
lastColl.surface = temp;
}; break; // ignore collisions on planets
{
//if its a new collision, apply damage
player->applyDmg(ENERGY,1);
// see if you collided with a lost astronaut
if ( (debris_system[temp]->getFrame() == 1) || (debris_system[temp]->getFrame() == 3))
{
// you bumped into a lost astronaut
debris_system[temp]->nextFrame();
debris_system[temp]->randomSpawn();
astronauts++;
// full heal
player->fullHeal();
//mp3->OpenFile(".\\Media\\Sound\\teleport_activate.mp3",800, 0, 0);
//mp3->Play(); //remarked out by RP
en_sounds.teleport();
}
// save collision
}; break;
case SPACE:
{
//if its a new collision, apply damage
player->applyDmg(ENERGY,1);
// see if you collided with a lost astronaut
if (debris_space[temp]->getFrame() < 2)
{
// you bumped into a lost astronaut
debris_space[temp]->nextFrame();
debris_space[temp]->randomSpawn();
astronauts++;
// full heal
player->fullHeal();
// mp3->OpenFile(".\\Media\\Sound\\teleport_activate.mp3",800, 0, 0);
// mp3->Play(); //remarked out by RP
en_sounds.teleport();
}
// save collision
}; break;
}
// TODO: we can apply physics for collision if want to -- got the formula already --
// sure, if shields deflect a large collision - you bounce away
// NOTE: I have this algorithm in another program, too (ADV)
}
void createDebris()
{
// load the moving objects (asteroids and such)
for (int i=0;i < DEBRIS_AMT_SPACE;i++)
{
debris_space[i] = new CDebris(120,110,"./Media/Images/debris_space.png",DEBRIS_SPRITES_SPACE,GAMEWORLDWIDTH,GAMEWORLDHEIGHT);
hitDebris.space[i] = false;
}
for (int i=0;i < DEBRIS_AMT_SYSTEM;i++)
{
debris_system[i] = new CDebris(120,110,"./Media/Images/debris_system.png",DEBRIS_SPRITES_SYSTEM,GAMEWORLDWIDTH,GAMEWORLDHEIGHT);
}
for (int i=0;i < DEBRIS_AMT_PLANET;i++)
{
debris_planet[i] = new CDebris(120,110,"./Media/Images/debris_surface.png", DEBRIS_SPRITES_PLANET, GAMEWORLDWIDTH, GAMEWORLDHEIGHT);
hitDebris.surface[i] = false;
}
}
void drawBars()
{
// draw enemy health bars?
// scale the bar per the gameView
int sx = 32 / scalex;
int sy = 6 * scaley;
CPPOINT dest;
CPPOINT curr;
// Draw Players Health Bars
dest = player->getAnchor();
dest.x -= ScrollX; // + sx
dest.y -= ScrollY;
dest.y += (player->getHeight()/2) * scaley;
drawBar(dest.x,dest.y, player->getCur(LOC_SHIELD), player->getMax(LOC_SHIELD), 1); // SHIELDS
dest.y += sy;
drawBar(dest.x,dest.y, player->getCur(LOC_ARMOR) , player->getMax(LOC_ARMOR), 2); // ARMOR
dest.y += sy;
drawBar(dest.x,dest.y, player->getCur(LOC_HULL) , player->getMax(LOC_HULL), 5); // HULL
dest.y += sy;
drawBar(dest.x,dest.y, player->getSolar() , player->getSolarMax(), 6); // solar power
dest.y += sy;
if (player->isLoaded()) // gun reload
drawBar(dest.x,dest.y, 1,1,3);
else
drawBar(dest.x,dest.y, player->getGunDelay() , player->weapon->getReload(),3);
for (int i=0; i < NUM_ENEMIES; i++)
if ( (enemy[i]->getSTATE() != DEAD) && (enemy[i]->getSTATE() != INACTIVE) )
{
curr = enemy[i]->getAnchor();
curr.x -= ScrollX; // convert to window coord (not game coord)
curr.y -= ScrollY;
dest.x = enemy[i]->getX() - ScrollX;
dest.y = enemy[i]->getY() - ScrollY + ((enemy[i]->getHeight() / 2) *scaley);
// on-screen ?
if ((curr.x >= 0) && (curr.x <= SCREEN_WIDTH) && (curr.y >= 0) && (curr.y <= SCREEN_HEIGHT))
{ // should be visible on screen - so draw health bars
drawBar(dest.x,dest.y, enemy[i]->getHP(), enemy[i]->getMaxHP(), 5);
dest.y += sy;
drawBar(dest.x,dest.y, enemy[i]->getSolar(), enemy[i]->getSolarMax(), 6); // Power
dest.y += sy;
if ( enemy[i]->isLoaded() )
drawBar(dest.x,dest.y, 1, 1, 3);
else
drawBar(dest.x,dest.y, enemy[i]->getGunDelay(),enemy[i]->weapon->getReload(), 3);
}
}
}
void DrawBG(CPTexture& pSource)
{
CPRECT r1 = { ScrollX, ScrollY, ScrollX+SCREEN_WIDTH, ScrollY+SCREEN_HEIGHT };
CPRECT r2 = { 0, 0, SCREEN_WIDTH-1, SCREEN_HEIGHT-1 };
graphicsEngine.DrawStretchTexture(pSource, r1, r2);
};
void animExp()
{
for (int i=0;i < MAX_EXPLOSIONS;i++)
if (activeEXP[i] == true)
if (explosion[i]->nextFrame() == 1)
{ // animation complete
activeEXP[i] = false;
delete explosion[i];
// does that destroy it safely ?
}
}
//
void newExp(CPPOINT dest)
{
// find the next available one to use
int i=0;
while ((activeEXP[i] == true) && (i < MAX_EXPLOSIONS))
i++;
if (i >= MAX_EXPLOSIONS)
return; // quit
// make it ACTIVE duh
activeEXP[i] = true;
int Height=120;
int Width =120;
int Frames=12;
char* Filename = "./Media/Images/exp_red.png";
explosion[i] = new CSprite(dest.x,dest.y,Height, Width, Filename);
explosion[i]->setupAnim(Frames,EAST,4);
explosion[i]->setSTATE(ACTIVE);
en_sounds.explosion();
}
void drawExp()
{
for (int i=0;i < MAX_EXPLOSIONS;i++)
if (activeEXP[i] == true)
graphicsEngine.DrawTexture( explosion[i]->getX()-ScrollX,explosion[i]->getY()-ScrollY,
explosion[i]->getWidth(),explosion[i]->getHeight(),
scalex, scaley, explosion[i]->getAngle(),
CPCOLOR_XRGB(255,255,255),
explosion[i]->getTexture(),
&explosion[i]->getRect(),
false);
}
// sets up random enemy drones
void createDrones()
{
for (int i=0; i < NUM_ENEMIES; i++)
{
int aiGun = 0;// Guns[5] = AI Blasters
CPPOINT dest
= {rand()%2000+24,rand()%2000+24};
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);
enemy[i]->setupAnim(3,NORTH,3); // sprites per anim, initially heading, sprites per row on sheet
enemy[i]->setFrame(0);
enemy[i]->setSTATE(INACTIVE);
enemy[i]->setBorder(0,0,GAMEWORLDWIDTH - 16,GAMEWORLDHEIGHT - 16); // set border to game window
}
// RANDOMIZE
int Shield = 0;
int Armor
= rand()%6 +5; // 6-10
int Hull
= rand()%5 +8; // 8-12
//BOSS_ARMOR 8 // (- 1) for each life lost (max -7) = 1
//BOSS_HULL 10 // (- 1) for each life lost (max -7) = 3
int Speed = 2;
int bossGun = 1;// BOSS GUN
CPPOINT dest
= {rand()%800+1200,rand()%800+1200};
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);
boss->setupAnim(8,EAST,4); // sprites per anim, initially heading, sprites per row on sheet
boss->setDelay(6);
boss->setSTATE(ACTIVE);
boss->setBorder(0,0,GAMEWORLDWIDTH - 16,GAMEWORLDHEIGHT - 16); // set border to game window
boss->setFrame(0);
boss->setLastFrame(1);
boss->setAnimate(false);
beeks = new CSprite(900,900,256,256,"./Media/Images/jelly-beeks.png");
beeks->setupAnim(16,EAST,4);
beeks->setDelay(5);
beeks->setFrame(0);
}
void respawnDrones
(int
MAX = NUM_ENEMIES
)
{
// call this when you enter a new system or map
for (int i
=MAX; i
< NUM_ENEMIES
; i
++)
enemy[i]->setSTATE(INACTIVE); // be sure the others are ignored then
for (int i
=0; i
< MAX; i
++)
{
CPPOINT dest
= {rand()%1200+800,rand()%1200+800};
int Shield = 0;
int Armor
= rand()%4 +1; // 1-4
int Hull
= rand()%2 +1; // 1-2
int Speed = 9 - (Armor + Hull);
int Angle
= rand() % 360;
enemy[i]->setFrame(0);
enemy[i]->setSTATE(ACTIVE);
enemy[i]->setPT(dest);
enemy[i]->setMaxSpeed(Speed);
enemy[i]->setSpeed(Speed);
enemy[i]->setAngle(Angle);
enemy[i]->setupShip(Shield,Armor,Hull);
}
}
void respawnBoss(bool randLoc)
{
//spawns boss on far side of map
//when boss is destroyed this zone becomes clear
// areacleared[CURR_MAP.system][CURR_MAP.planet] = true;
// random new location
CPPOINT dest
= { rand()%1200+800,rand()%1200+800 };
if (! randLoc)
dest = boss->getPT(); // stay at same location
int Shield = 0;
int Armor
= rand()%6 + 5; // 5-10
int Hull
= rand()%5 + 8; // 8-12
int Speed = 2;
int Angle
= rand() % 360;
boss->setFrame(deaths);
boss->setDelay(16);
boss->setPT(dest);
boss->setSpeed(Speed);
boss->setAngle(Angle);
boss->setSTATE(ACTIVE);
boss->setupShip(Shield,Armor,Hull);
};
CPPOINT offsetPT(CPPOINT pt1, int Width, int Height,DIRS Facing)
{
CPPOINT dPT = pt1;
int halfW = Width / 2 * scalex;
int halfH = Height / 2 * scaley;
if ( (dir == NORTH
) || (dir == NE
) || (dir == NW
)) dPT
.y
-= halfH
;
if ( (dir == SOUTH
) || (dir == SE
) || (dir == SW
)) dPT
.y
+= halfH
;
if ( (dir == WEST
) || (dir == SW
) || (dir == NW
)) dPT
.x
-= halfW
;
if ( (dir == EAST
) || (dir == SE
) || (dir == NE
)) dPT
.x
+= halfW
;
return dPT;
}
void respawnPlayer()
{
// send player back to space station and heal them
gameView=SPACE;
// un-spawn the drones
respawnDrones(0); // sets them all to inactive
boss->setSTATE(INACTIVE);
deaths=0; // reset boss
// move to starting location
CPPOINT dest = { 105, 105 }; // GAMEWORLDWIDTH HEIGHT
player->setPT(dest);
ScrollX=0;ScrollY=0;
player->setSpeed(0);
player->fullHeal();
player->setSTATE(ACTIVE);
en_sounds.teleport();
}