1156 lines
34 KiB
C++
1156 lines
34 KiB
C++
/***************************************************************************
|
|
alienBlaster
|
|
Copyright (C) 2004
|
|
Paul Grathwohl, Arne Hormann, Daniel Kuehn, Soenke Schwardt
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2, or (at your option)
|
|
any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
***************************************************************************/
|
|
using namespace std;
|
|
|
|
#include "racer.h"
|
|
#include "surfaceDB.h"
|
|
#include "shot.h"
|
|
#include "shots.h"
|
|
#include "items.h"
|
|
#include "item.h"
|
|
#include "font.h"
|
|
#include "boundingBox.h"
|
|
#include "enemys.h"
|
|
#include "enemy.h"
|
|
#include "mixer.h"
|
|
#include "global.h"
|
|
#include "banners.h"
|
|
#include "shieldGlow.h"
|
|
|
|
Racer::Racer( string fnSprite, int whichPlayer, Vector2D startpos , int newShipType) {
|
|
|
|
spriteRacerBase = surfaceDB.loadSurface( fnSprite );
|
|
drawRectBase.w = spriteRacerBase->w;
|
|
drawRectBase.h = spriteRacerBase->h;
|
|
playerNr = whichPlayer;
|
|
pos = startpos;
|
|
shipType = newShipType;
|
|
|
|
// init weaponary and specials
|
|
timeLastShotPrimary = SDL_GetTicks();
|
|
timeLastShotSecondary = SDL_GetTicks();
|
|
lastDumbfireWasLeft = false;
|
|
timeLastHeatseekerUsed = SDL_GetTicks();
|
|
timeLastNukeUsed = SDL_GetTicks();
|
|
lastHeatseekerWasLeft = false;
|
|
deflectorActive = false;
|
|
deflectorTimeLeft = -1;
|
|
|
|
for ( int i = 0; i < NR_SECONDARY_WEAPONS; i++ ) {
|
|
secondaryWeaponsAvailability[ i ] = false;
|
|
}
|
|
for ( int i = 0; i < NR_SPECIALS; i++ ) {
|
|
specialsAvailability[ i ] = 0;
|
|
}
|
|
specialsAvailability[ SPECIAL_NONE ] = 1; // this one is always present
|
|
|
|
// assign values dependant on shiptype
|
|
switch (shipType) {
|
|
case LIGHT_FIGHTER:
|
|
{
|
|
maxShield = LIGHT_FIGHTER_MAX_SHIELD;
|
|
maxDamage = LIGHT_FIGHTER_MAX_DAMAGE;
|
|
shield = maxShield;
|
|
damage = maxDamage;
|
|
maxVel = LIGHT_FIGHTER_VEL_MAX;
|
|
spriteShadow = surfaceDB.loadSurface( FN_LIGHT_FIGHTER_SHADOW, true );
|
|
shieldGlow = new ShieldGlow( LIGHT_FIGHTER );
|
|
if ( playerNr == 0 ) {
|
|
spriteFighterIcon = surfaceDB.loadSurface( FN_LIGHT_FIGHTER_1_SMALL );
|
|
} else {
|
|
spriteFighterIcon = surfaceDB.loadSurface( FN_LIGHT_FIGHTER_2_SMALL );
|
|
}
|
|
if ( arcadeGame ) {
|
|
secondaryWeaponsAvailability[ SHOT_DUMBFIRE_DOUBLE-100 ] = true;
|
|
secondaryWeaponsAvailability[ SHOT_KICK_ASS_ROCKET-100 ] = true;
|
|
secondaryWeaponsAvailability[ SHOT_HELLFIRE-100 ] = true;
|
|
secondaryWeaponsAvailability[ SHOT_MACHINE_GUN-100 ] = true;
|
|
secondaryWeaponsAvailability[ SHOT_ENERGY_BEAM-100 ] = true;
|
|
primaryShotType = SHOT_TRIPLE;
|
|
activeSecondary = SHOT_HELLFIRE;
|
|
activeSpecial = SPECIAL_NUKE; switchSpecials(); // init specials
|
|
} else {
|
|
secondaryWeaponsAvailability[ 0 ] = true; // Dumbfire is always available
|
|
primaryShotType = SHOT_NORMAL;
|
|
activeSecondary = SHOT_DUMBFIRE;
|
|
activeSpecial = SPECIAL_NUKE; switchSpecials(); // init specials
|
|
}
|
|
break;
|
|
}
|
|
case HEAVY_FIGHTER:
|
|
{
|
|
maxShield = HEAVY_FIGHTER_MAX_SHIELD;
|
|
maxDamage = HEAVY_FIGHTER_MAX_DAMAGE;
|
|
shield = maxShield;
|
|
damage = maxDamage;
|
|
maxVel = HEAVY_FIGHTER_VEL_MAX;
|
|
spriteShadow = surfaceDB.loadSurface( FN_HEAVY_FIGHTER_SHADOW, true );
|
|
shieldGlow = new ShieldGlow( HEAVY_FIGHTER );
|
|
if ( playerNr == 0 ) {
|
|
spriteFighterIcon = surfaceDB.loadSurface( FN_HEAVY_FIGHTER_1_SMALL );
|
|
} else {
|
|
spriteFighterIcon = surfaceDB.loadSurface( FN_HEAVY_FIGHTER_2_SMALL );
|
|
}
|
|
if ( arcadeGame ) {
|
|
secondaryWeaponsAvailability[ SHOT_HF_DUMBFIRE_DOUBLE-100 ] = true;
|
|
secondaryWeaponsAvailability[ SHOT_HF_KICK_ASS_ROCKET-100 ] = true;
|
|
secondaryWeaponsAvailability[ SHOT_HF_LASER-100 ] = true;
|
|
primaryShotType = SHOT_HF_QUINTO;
|
|
activeSecondary = SHOT_HF_KICK_ASS_ROCKET;
|
|
activeSpecial = SPECIAL_NUKE; switchSpecials(); // init specials
|
|
} else {
|
|
// Dumbfire is always available
|
|
secondaryWeaponsAvailability[ SHOT_HF_DUMBFIRE-100 ] = true;
|
|
specialsAvailability[ SPECIAL_DEFLECTOR ] = 1;
|
|
primaryShotType = SHOT_HF_NORMAL;
|
|
activeSecondary = SHOT_HF_DUMBFIRE;
|
|
specialsAvailability[ SPECIAL_NUKE ] = 1;
|
|
activeSpecial = SPECIAL_NUKE; switchSpecials(); // init specials
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
spriteHPStat = surfaceDB.loadSurface( FN_HITPOINTS_STAT );
|
|
pixPerHP = spriteHPStat->w / (maxDamage + maxShield);
|
|
|
|
shieldDamageEndTime = 0;
|
|
shieldDamageActive = false;
|
|
|
|
if ( whichPlayer == 0 ) {
|
|
font = new Font( FN_FONT_NUMBERS_LEFT );
|
|
} else {
|
|
font = new Font( FN_FONT_NUMBERS_RIGHT );
|
|
}
|
|
fontSize = font->getCharWidth();
|
|
|
|
sndShotPrimary = Mixer::mixer().loadSample( FN_SOUND_SHOT_PRIMARY );
|
|
sndShotSecondary = Mixer::mixer().loadSample( FN_SOUND_SHOT_SECONDARY );
|
|
|
|
spriteSpecials = surfaceDB.loadSurface( FN_ICONS_SPECIALS );
|
|
spriteSecondaryWeapons = surfaceDB.loadSurface( FN_ICONS_SECONDARY_WEAPONS );
|
|
|
|
spriteDeflector = surfaceDB.loadSurface( FN_HEAVY_FIGHTER_DEFLECTOR, true );
|
|
drawRectDeflector.w = spriteDeflector->w;
|
|
drawRectDeflector.h = spriteDeflector->h;
|
|
|
|
boundaryRect =
|
|
new RectangleGeo(Vector2D(spriteRacerBase->w/(2*RACER_IMAGE_CNT), spriteRacerBase->h/2),
|
|
Vector2D(320-spriteRacerBase->w/(2*RACER_IMAGE_CNT), 200-spriteRacerBase->h/2));
|
|
|
|
boundingBox = new BoundingBox( lroundf(pos.getX() - (spriteRacerBase->w / RACER_IMAGE_CNT) * 0.45),
|
|
lroundf(pos.getY() - spriteRacerBase->h * 0.45),
|
|
lroundf((spriteRacerBase->w / RACER_IMAGE_CNT) * 0.9),
|
|
lroundf(spriteRacerBase->h * 0.9) );
|
|
|
|
shipAngle = -90;
|
|
vel = Vector2D(0,0);
|
|
thrust = false;
|
|
backwards = false;
|
|
left = false;
|
|
right = false;
|
|
fireWeapons = false;
|
|
useSpecial = false;
|
|
|
|
points = 0;
|
|
|
|
timeLastMove = SDL_GetTicks();
|
|
}
|
|
|
|
|
|
Racer::~Racer() {
|
|
delete boundaryRect;
|
|
delete boundingBox;
|
|
if (font) delete font;
|
|
delete shieldGlow;
|
|
}
|
|
|
|
|
|
Vector2D Racer::move( int dT ) {
|
|
// TODO: move this to a correct place
|
|
if ( deflectorActive ) {
|
|
deflectorTimeLeft -= dT;
|
|
if (deflectorTimeLeft < 0) deflectorActive = false;
|
|
}
|
|
|
|
Vector2D oldPos = pos;
|
|
|
|
if ( thrust ) {
|
|
pos += Vector2D( 0, -maxVel ) * dT / 1000.0;
|
|
}
|
|
if ( backwards ) {
|
|
pos += Vector2D( 0, maxVel ) * dT / 1000.0;
|
|
}
|
|
if ( left ) {
|
|
pos += Vector2D( -maxVel, 0 ) * dT / 1000.0;
|
|
}
|
|
if ( right ) {
|
|
pos += Vector2D( maxVel, 0 ) * dT / 1000.0;
|
|
}
|
|
|
|
clipWorld();
|
|
|
|
updateBoundingBox();
|
|
|
|
return oldPos;
|
|
}
|
|
|
|
|
|
void Racer::clipWorld() {
|
|
int left = lroundf(pos.getX()) - (spriteRacerBase->w / (2*RACER_IMAGE_CNT));
|
|
int top = lroundf(pos.getY()) - (spriteRacerBase->h / 2);
|
|
int right = lroundf(pos.getX()) + (spriteRacerBase->w / (2*RACER_IMAGE_CNT));
|
|
int bottom = lroundf(pos.getY()) + (spriteRacerBase->h / 2);
|
|
if ( left <= 1 ) {
|
|
pos.setX( 1 + spriteRacerBase->w / (2*RACER_IMAGE_CNT) );
|
|
} else if ( right >= SCREEN_WIDTH - 1 ) {
|
|
pos.setX( SCREEN_WIDTH - 2 - spriteRacerBase->w / (2*RACER_IMAGE_CNT));
|
|
}
|
|
if ( top <= 1 ) {
|
|
pos.setY( 1 + spriteRacerBase->h / 2 );
|
|
} else if ( bottom >= SCREEN_HEIGHT - 1 ) {
|
|
pos.setY( SCREEN_HEIGHT - 2 - spriteRacerBase->h / 2 );
|
|
}
|
|
}
|
|
|
|
|
|
void Racer::drawStats( SdlCompat_AcceleratedSurface *screen ) {
|
|
SDL_Rect srcR, destR;
|
|
|
|
int indent = 5;
|
|
|
|
if ( playerNr == 1 ) {
|
|
indent = screen->w -
|
|
( 7 + 3 * fontSize + (spriteSpecials->w / (NR_SPECIALS-1)) ) -
|
|
( 5 + spriteSecondaryWeapons->w / NR_SECONDARY_WEAPONS );
|
|
}
|
|
|
|
int x = indent;
|
|
|
|
// draw Secondary Weapon
|
|
srcR.x = (activeSecondary - SHOT_DUMBFIRE) * spriteSecondaryWeapons->w / NR_SECONDARY_WEAPONS;
|
|
srcR.y = 0;
|
|
srcR.w = spriteSecondaryWeapons->w / NR_SECONDARY_WEAPONS;
|
|
srcR.h = spriteSecondaryWeapons->h;
|
|
destR.x = x;
|
|
destR.y = 25;
|
|
destR.w = spriteSecondaryWeapons->w / NR_SECONDARY_WEAPONS;
|
|
x += destR.w + 5;
|
|
destR.h = spriteSecondaryWeapons->h;
|
|
SDL_BlitSurface( spriteSecondaryWeapons, &srcR, screen, &destR );
|
|
|
|
// draw active special and amount of it
|
|
if ( activeSpecial != SPECIAL_NONE ) {
|
|
int pixPerSpecial = spriteSpecials->w / (NR_SPECIALS - 1);
|
|
srcR.y = 0;
|
|
srcR.w = pixPerSpecial;
|
|
srcR.h = spriteSpecials->h;
|
|
srcR.x = (activeSpecial - SPECIAL_NUKE) * pixPerSpecial;
|
|
destR.x = x;
|
|
destR.y = 25;
|
|
destR.w = pixPerSpecial;
|
|
x += pixPerSpecial + 2;
|
|
destR.h = spriteSpecials->h;
|
|
SDL_BlitSurface( spriteSpecials, &srcR, screen, &destR );
|
|
int digitCnt = 1;
|
|
int i=1;
|
|
while ( specialsAvailability[ activeSpecial ] >= i*10 ) {
|
|
digitCnt++;
|
|
i *= 10;
|
|
}
|
|
font->drawInt( screen, x, 25,
|
|
specialsAvailability[ activeSpecial ], digitCnt, 0);
|
|
}
|
|
|
|
if ( !onePlayerGame ) {
|
|
// draw Icon
|
|
switch (playerNr) {
|
|
case 0: indent = 10 + spriteHPStat->w; break;
|
|
case 1: indent = screen->w - (20 + spriteHPStat->w + spriteFighterIcon->w); break;
|
|
default: break;
|
|
}
|
|
destR.x = indent;
|
|
destR.w = spriteFighterIcon->w;
|
|
destR.y = 2;
|
|
destR.h = spriteFighterIcon->h;
|
|
SDL_BlitSurface( spriteFighterIcon, 0, screen, &destR );
|
|
}
|
|
|
|
// draw shields and damage
|
|
switch (playerNr) {
|
|
case 0: indent = 5; break;
|
|
case 1: indent = screen->w - (15 + spriteHPStat->w); break;
|
|
default: break;
|
|
}
|
|
|
|
// draw damage
|
|
srcR.x = 0;
|
|
srcR.y = 0;
|
|
srcR.w = lroundf(damage * pixPerHP);
|
|
srcR.h = spriteHPStat->h;
|
|
destR.x = indent;
|
|
destR.w = srcR.w;
|
|
destR.y = 5;
|
|
destR.h = spriteHPStat->h;
|
|
SDL_BlitSurface( spriteHPStat, &srcR, screen, &destR );
|
|
// draw shield
|
|
destR.x = indent + srcR.w;
|
|
srcR.x = spriteHPStat->w / 2;
|
|
srcR.w = lroundf(shield * pixPerHP);
|
|
destR.w = srcR.w;
|
|
destR.h = spriteHPStat->h;
|
|
SDL_BlitSurface( spriteHPStat, &srcR, screen, &destR );
|
|
}
|
|
|
|
|
|
void Racer::drawShadow( SdlCompat_AcceleratedSurface *screen ) {
|
|
SDL_Rect destR;
|
|
destR.x = lroundf(pos.getX()) - (spriteShadow->w / 2) - 10;
|
|
destR.y = lroundf(pos.getY()) - (spriteShadow->h / 2) + 10;
|
|
destR.w = spriteShadow->w;
|
|
destR.h = spriteShadow->h;
|
|
SDL_BlitSurface( spriteShadow, 0, screen, &destR );
|
|
}
|
|
|
|
|
|
void Racer::drawRacer( SdlCompat_AcceleratedSurface *screen ) {
|
|
|
|
SDL_Rect srcR;
|
|
SDL_Rect destR;
|
|
|
|
destR.x = lroundf(pos.getX()) - (spriteRacerBase->w / (2*RACER_IMAGE_CNT));
|
|
destR.y = lroundf(pos.getY()) - (spriteRacerBase->h / 2);
|
|
destR.w = spriteRacerBase->w / RACER_IMAGE_CNT;
|
|
destR.h = spriteRacerBase->h;
|
|
|
|
int idx = 0; // normal pos
|
|
if ( !left && !right && !thrust && !backwards ) idx = 0; //stop
|
|
else if ( left && !right && !thrust && !backwards ) idx = 1; // left
|
|
else if ( !left && right && !thrust && !backwards ) idx = 2; // right
|
|
else if ( !left && !right && thrust && !backwards ) idx = 3; // forward
|
|
else if ( !left && !right && !thrust && backwards ) idx = 4; // backward
|
|
else if ( left && !right && thrust && !backwards ) idx = 5; // left-forward
|
|
else if ( !left && right && thrust && !backwards ) idx = 6; // right-forward
|
|
else if ( left && !right && !thrust && backwards ) idx = 7; // left-backward
|
|
else if ( !left && right && !thrust && backwards ) idx = 8; // right-backward
|
|
srcR.x = idx * (spriteRacerBase->w / RACER_IMAGE_CNT);
|
|
srcR.y = 0;
|
|
srcR.w = (spriteRacerBase->w / RACER_IMAGE_CNT);
|
|
srcR.h = spriteRacerBase->h;
|
|
|
|
SDL_BlitSurface( spriteRacerBase, &srcR, screen, &destR );
|
|
|
|
if ( shieldDamageActive ) {
|
|
int shieldGlowTimeLeft = shieldDamageEndTime - SDL_GetTicks();
|
|
if ( shieldGlowTimeLeft < 0 ) {
|
|
shieldDamageActive = false;
|
|
} else {
|
|
shieldGlow->draw( screen, pos, RACER_SHIELD_DAMAGE_LIFETIME - shieldGlowTimeLeft );
|
|
}
|
|
}
|
|
|
|
if ( deflectorActive ) {
|
|
drawRectDeflector.x = lroundf(pos.getX()) - spriteDeflector->w / 2;
|
|
drawRectDeflector.y = lroundf(pos.getY()) - spriteDeflector->h / 2;
|
|
SDL_BlitSurface( spriteDeflector, 0, screen, &drawRectDeflector );
|
|
}
|
|
}
|
|
|
|
|
|
void Racer::switchSecondary() {
|
|
int newActive = (activeSecondary-100 + 1) % NR_SECONDARY_WEAPONS;
|
|
while ( newActive != activeSecondary-100 &&
|
|
secondaryWeaponsAvailability[ newActive ] == false ) {
|
|
newActive = (newActive + 1) % NR_SECONDARY_WEAPONS;
|
|
}
|
|
activeSecondary = (ShotTypes)(newActive+100);
|
|
|
|
if ( activeSecondary == SHOT_DUMBFIRE &&
|
|
secondaryWeaponsAvailability[ SHOT_DUMBFIRE_DOUBLE - 100 ] ) {
|
|
activeSecondary = SHOT_DUMBFIRE_DOUBLE;
|
|
}
|
|
// same for heavy-fighter
|
|
if ( activeSecondary == SHOT_HF_DUMBFIRE &&
|
|
secondaryWeaponsAvailability[ SHOT_HF_DUMBFIRE_DOUBLE - 100 ] ) {
|
|
activeSecondary = SHOT_HF_DUMBFIRE_DOUBLE;
|
|
}
|
|
|
|
// TODO: ugly workaround...
|
|
if ( activeSecondary == SHOT_KICK_ASS_ROCKET ||
|
|
activeSecondary == SHOT_HF_KICK_ASS_ROCKET ) {
|
|
timeLastShotSecondary -= RACER_COOLDOWN_KICK_ASS_ROCKET / 2;
|
|
}
|
|
}
|
|
|
|
void Racer::switchSpecials() {
|
|
int newActive = activeSpecial + 1;
|
|
if ( newActive == NR_SPECIALS ) newActive = 1;
|
|
for(int i=0; i < NR_SPECIALS-1; ++i) {
|
|
// Only Sönke knows what the following does ;-)
|
|
if (specialsAvailability[ ((activeSpecial + i) % (NR_SPECIALS-1))+1 ] != 0) {
|
|
activeSpecial = (SpecialTypes)(((activeSpecial + i) % (NR_SPECIALS-1))+1);
|
|
return;
|
|
}
|
|
}
|
|
activeSpecial = SPECIAL_NONE;
|
|
}
|
|
|
|
|
|
void Racer::shootPrimary() {
|
|
if ( fireWeapons ) {
|
|
|
|
switch ( primaryShotType ) {
|
|
case SHOT_NORMAL:
|
|
{
|
|
if ( (SDL_GetTicks() - RACER_COOLDOWN_SHOT_NORMAL) > timeLastShotPrimary ) {
|
|
Shot *shot =
|
|
new Shot( SHOT_NORMAL, playerNr,
|
|
pos + Vector2D(0, -spriteRacerBase->h / 2),
|
|
-90 + (rand() % SPREAD_ANGLE_SHOT_NORMAL) -
|
|
SPREAD_ANGLE_SHOT_NORMAL / 2 );
|
|
shots->addShot( shot );
|
|
Mixer::mixer().playSample( sndShotPrimary, 0 );
|
|
timeLastShotPrimary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
case SHOT_NORMAL_HEAVY:
|
|
{
|
|
if ( SDL_GetTicks() - RACER_COOLDOWN_SHOT_NORMAL_HEAVY > timeLastShotPrimary ) {
|
|
Shot *shot =
|
|
new Shot( SHOT_NORMAL_HEAVY, playerNr,
|
|
pos + Vector2D(0, -spriteRacerBase->h / 2), -90 );
|
|
shots->addShot( shot );
|
|
Mixer::mixer().playSample( sndShotPrimary, 0 );
|
|
timeLastShotPrimary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
case SHOT_DOUBLE:
|
|
{
|
|
if ( SDL_GetTicks() - RACER_COOLDOWN_SHOT_DOUBLE > timeLastShotPrimary ) {
|
|
Shot *shot1 =
|
|
new Shot( SHOT_DOUBLE, playerNr, pos + Vector2D(-8,-2), -95 );
|
|
Shot *shot2 =
|
|
new Shot( SHOT_DOUBLE, playerNr, pos + Vector2D(8,-2), -85 );
|
|
shots->addShot(shot1);
|
|
shots->addShot(shot2);
|
|
Mixer::mixer().playSample( sndShotPrimary, 0 );
|
|
timeLastShotPrimary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
case SHOT_DOUBLE_HEAVY:
|
|
{
|
|
if ( SDL_GetTicks() - RACER_COOLDOWN_SHOT_DOUBLE_HEAVY > timeLastShotPrimary ) {
|
|
Shot *shot1 =
|
|
new Shot( SHOT_DOUBLE_HEAVY, playerNr, pos + Vector2D(-8,-2), -95 );
|
|
Shot *shot2 =
|
|
new Shot( SHOT_DOUBLE_HEAVY, playerNr, pos + Vector2D(8,-2), -85 );
|
|
shots->addShot(shot1);
|
|
shots->addShot(shot2);
|
|
Mixer::mixer().playSample( sndShotPrimary, 0 );
|
|
timeLastShotPrimary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
case SHOT_TRIPLE:
|
|
{
|
|
if ( SDL_GetTicks() - RACER_COOLDOWN_SHOT_TRIPLE > timeLastShotPrimary ) {
|
|
Shot *shot1 =
|
|
new Shot( SHOT_TRIPLE, playerNr, pos + Vector2D(-8, -2), -100 );
|
|
Shot *shot2 =
|
|
new Shot( SHOT_TRIPLE, playerNr, pos + Vector2D(0, -spriteRacerBase->h / 2), -90 );
|
|
Shot *shot3 =
|
|
new Shot( SHOT_TRIPLE, playerNr, pos + Vector2D(8, -2), -80 );
|
|
shots->addShot(shot1);
|
|
shots->addShot(shot2);
|
|
shots->addShot(shot3);
|
|
Mixer::mixer().playSample( sndShotPrimary, 0 );
|
|
timeLastShotPrimary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
|
|
// HEAVY FIGHTER SHOTS
|
|
case SHOT_HF_NORMAL:
|
|
{
|
|
if ( (SDL_GetTicks() - RACER_COOLDOWN_SHOT_HF_NORMAL) > timeLastShotPrimary ) {
|
|
Shot *shot =
|
|
new Shot( SHOT_HF_NORMAL, playerNr,
|
|
pos + Vector2D(0, -spriteRacerBase->h / 2), -90 );
|
|
shots->addShot( shot );
|
|
Mixer::mixer().playSample( sndShotPrimary, 0 );
|
|
timeLastShotPrimary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
case SHOT_HF_DOUBLE:
|
|
{
|
|
if ( (SDL_GetTicks() - RACER_COOLDOWN_SHOT_HF_DOUBLE) > timeLastShotPrimary ) {
|
|
Shot *shot = new Shot( SHOT_HF_DOUBLE, playerNr, pos + Vector2D(-12, -12), -90 );
|
|
shots->addShot( shot );
|
|
shot = new Shot( SHOT_HF_DOUBLE, playerNr, pos + Vector2D(12, -12), -90 );
|
|
shots->addShot( shot );
|
|
Mixer::mixer().playSample( sndShotPrimary, 0 );
|
|
timeLastShotPrimary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
case SHOT_HF_TRIPLE:
|
|
{
|
|
if ( (SDL_GetTicks() - RACER_COOLDOWN_SHOT_HF_TRIPLE) > timeLastShotPrimary ) {
|
|
Shot *shot = new Shot( SHOT_HF_TRIPLE, playerNr, pos + Vector2D(-12, -12), -103 );
|
|
shots->addShot( shot );
|
|
shot = new Shot( SHOT_HF_TRIPLE, playerNr,
|
|
pos + Vector2D(0, -spriteRacerBase->h / 2), -90 );
|
|
shots->addShot( shot );
|
|
shot = new Shot( SHOT_HF_TRIPLE, playerNr, pos + Vector2D(12, -12), -77 );
|
|
shots->addShot( shot );
|
|
Mixer::mixer().playSample( sndShotPrimary, 0 );
|
|
timeLastShotPrimary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
case SHOT_HF_QUATTRO:
|
|
{
|
|
if ( (SDL_GetTicks() - RACER_COOLDOWN_SHOT_HF_QUATTRO) > timeLastShotPrimary ) {
|
|
Shot *shot = new Shot( SHOT_HF_QUATTRO, playerNr, pos + Vector2D(-30, -15), -100 );
|
|
shots->addShot( shot );
|
|
shot = new Shot( SHOT_HF_QUATTRO, playerNr, pos + Vector2D(-12, -12), -90 );
|
|
shots->addShot( shot );
|
|
shot = new Shot( SHOT_HF_QUATTRO, playerNr, pos + Vector2D(12, -12), -90 );
|
|
shots->addShot( shot );
|
|
shot = new Shot( SHOT_HF_QUATTRO, playerNr, pos + Vector2D(30, -15), -80 );
|
|
shots->addShot( shot );
|
|
Mixer::mixer().playSample( sndShotPrimary, 0 );
|
|
timeLastShotPrimary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
case SHOT_HF_QUINTO:
|
|
{
|
|
if ( (SDL_GetTicks() - RACER_COOLDOWN_SHOT_HF_QUINTO) > timeLastShotPrimary ) {
|
|
Shot *shot = new Shot( SHOT_HF_QUINTO, playerNr, pos + Vector2D(-30, -15), -110 );
|
|
shots->addShot( shot );
|
|
shot = new Shot( SHOT_HF_QUINTO, playerNr, pos + Vector2D(-12, -12), -100 );
|
|
shots->addShot( shot );
|
|
shot = new Shot( SHOT_HF_QUINTO, playerNr,
|
|
pos + Vector2D(0, -spriteRacerBase->h / 2), -90 );
|
|
shots->addShot( shot );
|
|
shot = new Shot( SHOT_HF_QUINTO, playerNr, pos + Vector2D(12, -12), -80 );
|
|
shots->addShot( shot );
|
|
shot = new Shot( SHOT_HF_QUINTO, playerNr, pos + Vector2D(30, -15), -70 );
|
|
shots->addShot( shot );
|
|
Mixer::mixer().playSample( sndShotPrimary, 0 );
|
|
timeLastShotPrimary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
cout << "Racer::shootPrimary: unexpected primaryShotType: "
|
|
<< primaryShotType << endl;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void Racer::shootSecondary() {
|
|
if ( fireWeapons ) {
|
|
|
|
switch ( activeSecondary ) {
|
|
|
|
case SHOT_DUMBFIRE:
|
|
{
|
|
if ( SDL_GetTicks() - RACER_COOLDOWN_DUMBFIRE > timeLastShotSecondary ) {
|
|
Shot *shot =
|
|
new Shot( SHOT_DUMBFIRE, playerNr, pos + Vector2D(0, -5), -90 );
|
|
shots->addShot(shot);
|
|
Mixer::mixer().playSample( sndShotSecondary, 0 );
|
|
timeLastShotSecondary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
case SHOT_DUMBFIRE_DOUBLE:
|
|
{
|
|
if ( SDL_GetTicks() - RACER_COOLDOWN_DUMBFIRE_DOUBLE > timeLastShotSecondary ) {
|
|
Shot *shot;
|
|
if ( lastDumbfireWasLeft ) {
|
|
shot = new Shot( SHOT_DUMBFIRE_DOUBLE, playerNr, pos + Vector2D(15,-3), -90 );
|
|
} else {
|
|
shot = new Shot( SHOT_DUMBFIRE_DOUBLE, playerNr, pos + Vector2D(-15,-3), -90 );
|
|
}
|
|
lastDumbfireWasLeft = !lastDumbfireWasLeft;
|
|
shots->addShot(shot);
|
|
Mixer::mixer().playSample( sndShotSecondary, 0 );
|
|
timeLastShotSecondary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
case SHOT_KICK_ASS_ROCKET:
|
|
{
|
|
if ( SDL_GetTicks() - RACER_COOLDOWN_KICK_ASS_ROCKET > timeLastShotSecondary ) {
|
|
Shot *shot =
|
|
new Shot( SHOT_KICK_ASS_ROCKET, playerNr, pos, -90 );
|
|
shots->addShot(shot);
|
|
Mixer::mixer().playSample( sndShotSecondary, 0 );
|
|
timeLastShotSecondary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
case SHOT_HELLFIRE:
|
|
{
|
|
if ( SDL_GetTicks() - RACER_COOLDOWN_HELLFIRE > timeLastShotSecondary ) {
|
|
Shot *shot1 =
|
|
new Shot( SHOT_HELLFIRE, playerNr, pos + Vector2D(-15, -3), -180 );
|
|
Shot *shot2 =
|
|
new Shot( SHOT_HELLFIRE, playerNr, pos + Vector2D(15, -3), 0 );
|
|
shots->addShot(shot1);
|
|
shots->addShot(shot2);
|
|
Mixer::mixer().playSample( sndShotSecondary, 0 );
|
|
timeLastShotSecondary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
case SHOT_MACHINE_GUN:
|
|
{
|
|
if ( SDL_GetTicks() - RACER_COOLDOWN_MACHINE_GUN > timeLastShotSecondary ) {
|
|
|
|
int idxNearestEnemy1 = 0;
|
|
float distFarestY1 = -1;
|
|
int idxNearestEnemy2 = 0;
|
|
float distFarestY2 = -1;
|
|
float angle1 = -90;
|
|
float angle2 = -90;
|
|
float maxDistY = pos.getY() + 40; // only enemys in or already in the screen
|
|
for ( unsigned int i = 0; i < enemys->getNrEnemys(); i++ ) {
|
|
// angle of the vector from the racer position to the enemy
|
|
float angleEnemy = (enemys->getEnemy(i)->getPos() - pos).getDirection();
|
|
if ( -90 <= angleEnemy && angleEnemy < -60 ) {
|
|
float distY = pos.getY() - enemys->getEnemy(i)->getPos().getY();
|
|
if ( distFarestY1 < distY && distY < maxDistY ) {
|
|
distFarestY1 = distY;
|
|
idxNearestEnemy1 = i;
|
|
angle2 = angleEnemy + 5;
|
|
}
|
|
} else {
|
|
if ( -120 < angleEnemy && angleEnemy < -90 ) {
|
|
float distY = pos.getY() - enemys->getEnemy(i)->getPos().getY();
|
|
if ( distFarestY2 < distY && distY < maxDistY ) {
|
|
distFarestY2 = distY;
|
|
idxNearestEnemy2 = i;
|
|
angle1 = angleEnemy - 5;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Shot *shot1 =
|
|
new Shot( SHOT_MACHINE_GUN, playerNr,
|
|
pos + Vector2D(-3, -spriteRacerBase->h/2), angle1 );
|
|
Shot *shot2 =
|
|
new Shot( SHOT_MACHINE_GUN, playerNr,
|
|
pos + Vector2D(+3, -spriteRacerBase->h/2), angle2 );
|
|
shots->addShot(shot1);
|
|
shots->addShot(shot2);
|
|
Mixer::mixer().playSample( sndShotSecondary, 0 );
|
|
timeLastShotSecondary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
case SHOT_ENERGY_BEAM:
|
|
{
|
|
if ( SDL_GetTicks() - RACER_COOLDOWN_ENERGY_BEAM > timeLastShotSecondary ) {
|
|
Shot *shot =
|
|
new Shot( SHOT_ENERGY_BEAM, playerNr, pos + Vector2D(-1, -10), -90 );
|
|
shots->addShot(shot);
|
|
Mixer::mixer().playSample( sndShotSecondary, 0 );
|
|
timeLastShotSecondary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
|
|
// HEAVY FIGHTER SHOTS
|
|
case SHOT_HF_DUMBFIRE:
|
|
{
|
|
if ( SDL_GetTicks() - RACER_COOLDOWN_HF_DUMBFIRE > timeLastShotSecondary ) {
|
|
Shot *shot =
|
|
new Shot( SHOT_HF_DUMBFIRE, playerNr, pos + Vector2D(-30, -5), -90 );
|
|
shots->addShot(shot);
|
|
shot =
|
|
new Shot( SHOT_HF_DUMBFIRE, playerNr, pos + Vector2D(30, -5), -90 );
|
|
shots->addShot(shot);
|
|
Mixer::mixer().playSample( sndShotSecondary, 0 );
|
|
timeLastShotSecondary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
case SHOT_HF_DUMBFIRE_DOUBLE:
|
|
{
|
|
if ( SDL_GetTicks() - RACER_COOLDOWN_HF_DUMBFIRE_DOUBLE > timeLastShotSecondary ) {
|
|
Shot *shot =
|
|
new Shot( SHOT_HF_DUMBFIRE_DOUBLE, playerNr, pos + Vector2D(-30, -5), -90 );
|
|
shots->addShot(shot);
|
|
shot =
|
|
new Shot( SHOT_HF_DUMBFIRE_DOUBLE, playerNr, pos + Vector2D(30, -5), -90 );
|
|
shots->addShot(shot);
|
|
Mixer::mixer().playSample( sndShotSecondary, 0 );
|
|
timeLastShotSecondary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
case SHOT_HF_KICK_ASS_ROCKET:
|
|
{
|
|
if ( SDL_GetTicks() - RACER_COOLDOWN_HF_KICK_ASS_ROCKET > timeLastShotSecondary ) {
|
|
Shot *shot1 =
|
|
new Shot( SHOT_HF_KICK_ASS_ROCKET, playerNr, pos + Vector2D(-30,0), -90 );
|
|
shots->addShot(shot1);
|
|
Shot *shot2 =
|
|
new Shot( SHOT_HF_KICK_ASS_ROCKET, playerNr, pos + Vector2D(30,0), -90 );
|
|
shots->addShot(shot2);
|
|
Mixer::mixer().playSample( sndShotSecondary, 0 );
|
|
timeLastShotSecondary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
case SHOT_HF_LASER:
|
|
{
|
|
if ( SDL_GetTicks() - RACER_COOLDOWN_HF_LASER > timeLastShotSecondary ) {
|
|
Shot *shot1 =
|
|
new Shot( SHOT_HF_LASER, playerNr, pos + Vector2D(-30,-10), -90 );
|
|
shots->addShot(shot1);
|
|
Shot *shot2 =
|
|
new Shot( SHOT_HF_LASER, playerNr, pos + Vector2D(30,-10), -90 );
|
|
shots->addShot(shot2);
|
|
Mixer::mixer().playSample( sndShotSecondary, 0 );
|
|
timeLastShotSecondary = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
cout << "Racer::shootSecondary: unexpected activeSecondary: "
|
|
<< activeSecondary << endl;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void Racer::shootSpecial() {
|
|
if ( useSpecial ) {
|
|
|
|
switch ( activeSpecial ) {
|
|
|
|
case SPECIAL_HEATSEEKER:
|
|
{
|
|
if ( SDL_GetTicks() - RACER_COOLDOWN_SPECIAL_HEATSEEKER > timeLastHeatseekerUsed &&
|
|
specialsAvailability[ SPECIAL_HEATSEEKER ] > 0 ) {
|
|
Shot *shot;
|
|
if ( lastHeatseekerWasLeft ) {
|
|
shot = new Shot( SPECIAL_SHOT_HEATSEEKER, playerNr, pos + Vector2D(15,-3), -90 );
|
|
} else {
|
|
shot = new Shot( SPECIAL_SHOT_HEATSEEKER, playerNr, pos + Vector2D(-15,-3), -90 );
|
|
}
|
|
lastHeatseekerWasLeft = !lastHeatseekerWasLeft;
|
|
shots->addShot(shot);
|
|
Mixer::mixer().playSample( sndShotSecondary, 0 );
|
|
timeLastHeatseekerUsed = SDL_GetTicks();
|
|
specialsAvailability[ SPECIAL_HEATSEEKER ]--;
|
|
}
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool Racer::collidesWith( const Vector2D &shotPosOld, const Vector2D &shotPosNew ) {
|
|
return boundingBox->overlaps(shotPosOld, shotPosNew);
|
|
}
|
|
|
|
bool Racer::collidesWith( BoundingBox *box ) {
|
|
return boundingBox->overlaps( box );
|
|
}
|
|
|
|
bool Racer::collidesWith( const Circle &circle ) {
|
|
return boundingBox->overlaps( circle );
|
|
}
|
|
|
|
bool Racer::collidesWithAsCircle( const Circle &circle ) {
|
|
return ( (circle.getRadius() + (spriteRacerBase->w / RACER_IMAGE_CNT)/2) > circle.getCenter().distanceTo( pos ) );
|
|
}
|
|
|
|
bool Racer::collidesWithAsCircle( BoundingBox *box ) {
|
|
return ( box->overlaps( Circle( pos, spriteRacerBase->h >> 1 ) ) );
|
|
}
|
|
|
|
BoundingBox *Racer::getBoundingBox() {
|
|
return boundingBox;
|
|
}
|
|
|
|
|
|
bool Racer::isDead() {
|
|
return (damage < 0);
|
|
}
|
|
|
|
|
|
void Racer::receiveDamage( float amount ) {
|
|
if ( lroundf(shield) >= amount ) {
|
|
shield -= amount;
|
|
shieldDamageActive = true;
|
|
shieldDamageEndTime = SDL_GetTicks() + RACER_SHIELD_DAMAGE_LIFETIME;
|
|
return;
|
|
}
|
|
amount -= shield;
|
|
shield = 0;
|
|
damage -= amount;
|
|
}
|
|
|
|
void Racer::doDamage( ShotTypes shotType ) {
|
|
|
|
switch (shotType) {
|
|
case ENEMY_SHOT_NORMAL:
|
|
{
|
|
receiveDamage( DAMAGE_ENEMY_SHOT_NORMAL );
|
|
break;
|
|
}
|
|
case ENEMY_SHOT_TANK_ROCKET:
|
|
{
|
|
receiveDamage( DAMAGE_ENEMY_SHOT_TANK_ROCKET );
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
cout << "Racer::doDamage: unexpected shotType: " << shotType << endl;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Racer::rechargeShield ( int dT ) {
|
|
float amount;
|
|
if ( shipType == LIGHT_FIGHTER ) {
|
|
amount = LIGHT_FIGHTER_SHIELD_RECHARGE * dT / 100000.0;
|
|
} else {
|
|
amount = HEAVY_FIGHTER_SHIELD_RECHARGE * dT / 100000.0;
|
|
}
|
|
if (shield + amount < maxShield) shield += amount;
|
|
else shield = maxShield;
|
|
}
|
|
|
|
void Racer::receivePoints( float amount ) {
|
|
float oldPoints = points;
|
|
points += amount;
|
|
|
|
if ( arcadeGame ) {
|
|
// time for a health item?
|
|
for ( int i = 0; i < NR_ARCACE_POINTS_FOR_HEALTH_ITEM; i++ ) {
|
|
if ( oldPoints < ARCADE_POINTS_FOR_HEALTH_ITEM[ i ] &&
|
|
ARCADE_POINTS_FOR_HEALTH_ITEM[ i ] <= points ) {
|
|
Item *health = new Item( Vector2D( SCREEN_WIDTH / 2, -30 ),
|
|
Vector2D( 0, 30 ),
|
|
ITEM_HEALTH );
|
|
items->addItem( health );
|
|
banners->addBanner( BANNER_HEALTH, BANNER_MODE_FLY_FROM_LEFT, BANNER_BONUS_NONE );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
Vector2D Racer::setVel( const Vector2D &newVel ) {
|
|
Vector2D temp = vel;
|
|
vel = newVel;
|
|
if ( vel.getLength() >= getActVelMax() ) {
|
|
vel.setLength(getActVelMax());
|
|
}
|
|
return temp;
|
|
}
|
|
|
|
|
|
void Racer::setPos( const Vector2D &newPos ) {
|
|
pos = newPos;
|
|
updateBoundingBox();
|
|
}
|
|
|
|
|
|
void Racer::updateBoundingBox() {
|
|
boundingBox->moveUpperBound( lroundf(pos.getY() - spriteRacerBase->h * 0.45) );
|
|
boundingBox->moveLeftBound( lroundf(pos.getX() - (spriteRacerBase->w / RACER_IMAGE_CNT) * 0.45) );
|
|
}
|
|
|
|
|
|
void Racer::pickUpItems() {
|
|
for ( unsigned int i = 0; i < items->getNrItems(); i++ ) {
|
|
Item *item = items->getItem(i);
|
|
if ( !item->isExpired() && boundingBox->overlaps( item->getBoundingBox() ) ) {
|
|
switch (item->getType()) {
|
|
case ITEM_PRIMARY_UPGRADE:
|
|
{
|
|
int newPrimaryShotType = primaryShotType + 1;
|
|
if ( shipType == LIGHT_FIGHTER && newPrimaryShotType <= SHOT_TRIPLE )
|
|
primaryShotType = (ShotTypes)newPrimaryShotType;
|
|
else if ( shipType == HEAVY_FIGHTER && newPrimaryShotType <= SHOT_HF_QUINTO )
|
|
primaryShotType = (ShotTypes)newPrimaryShotType;
|
|
item->pickedUp();
|
|
addBannerItemCollected( BANNER_ITEM_PRIMARY_UPGRADE_COLLECTED );
|
|
break;
|
|
}
|
|
case ITEM_DUMBFIRE_DOUBLE:
|
|
{
|
|
if ( shipType == LIGHT_FIGHTER ) {
|
|
secondaryWeaponsAvailability[ SHOT_DUMBFIRE_DOUBLE - 100 ] = true;
|
|
if (activeSecondary == SHOT_DUMBFIRE ) activeSecondary = SHOT_DUMBFIRE_DOUBLE;
|
|
} else {
|
|
secondaryWeaponsAvailability[ SHOT_HF_DUMBFIRE_DOUBLE - 100 ] = true;
|
|
if (activeSecondary == SHOT_HF_DUMBFIRE ) activeSecondary = SHOT_HF_DUMBFIRE_DOUBLE;
|
|
}
|
|
item->pickedUp();
|
|
addBannerItemCollected( BANNER_ITEM_DUMBFIRE_DOUBLE_COLLECTED );
|
|
break;
|
|
}
|
|
case ITEM_KICK_ASS_ROCKET:
|
|
{
|
|
if ( shipType == LIGHT_FIGHTER )
|
|
secondaryWeaponsAvailability[ SHOT_KICK_ASS_ROCKET - 100 ] = true;
|
|
else
|
|
secondaryWeaponsAvailability[ SHOT_HF_KICK_ASS_ROCKET - 100 ] = true;
|
|
item->pickedUp();
|
|
addBannerItemCollected( BANNER_ITEM_KICK_ASS_ROCKET_COLLECTED );
|
|
break;
|
|
}
|
|
case ITEM_HELLFIRE:
|
|
{
|
|
if ( shipType == LIGHT_FIGHTER ) {
|
|
secondaryWeaponsAvailability[ SHOT_HELLFIRE - 100 ] = true;
|
|
item->pickedUp();
|
|
addBannerItemCollected( BANNER_ITEM_HELLFIRE_COLLECTED );
|
|
}
|
|
break;
|
|
}
|
|
case ITEM_MACHINE_GUN:
|
|
{
|
|
if ( shipType == LIGHT_FIGHTER ) {
|
|
secondaryWeaponsAvailability[ SHOT_MACHINE_GUN - 100 ] = true;
|
|
item->pickedUp();
|
|
addBannerItemCollected( BANNER_ITEM_MACHINE_GUN_COLLECTED );
|
|
}
|
|
break;
|
|
}
|
|
case ITEM_HEALTH:
|
|
{
|
|
if ( arcadeGame ) {
|
|
repair( ITEM_HEALTH_REPAIR_AMOUNT );
|
|
} else {
|
|
if ( shipType == LIGHT_FIGHTER )
|
|
repair( ITEM_HEALTH_REPAIR_AMOUNT );
|
|
else repair( ITEM_HEALTH_REPAIR_AMOUNT * ITEM_HEALTH_REPAIR_FACTOR_HEAVY_FIGHTER );
|
|
}
|
|
item->pickedUp();
|
|
addBannerItemCollected( BANNER_ITEM_HEALTH_COLLECTED );
|
|
break;
|
|
}
|
|
case ITEM_HEATSEEKER:
|
|
{
|
|
specialsAvailability[ SPECIAL_HEATSEEKER ] += ITEM_HEATSEEKER_AMMO;
|
|
activeSpecial = SPECIAL_HEATSEEKER;
|
|
item->pickedUp();
|
|
addBannerItemCollected( BANNER_ITEM_HEATSEEKER_COLLECTED );
|
|
break;
|
|
}
|
|
case ITEM_NUKE:
|
|
{
|
|
specialsAvailability[ SPECIAL_NUKE ] += ITEM_NUKE_AMMO;
|
|
if ( activeSpecial == SPECIAL_NONE ) {
|
|
activeSpecial = SPECIAL_NUKE;
|
|
}
|
|
item->pickedUp();
|
|
addBannerItemCollected( BANNER_ITEM_NUKE_COLLECTED );
|
|
break;
|
|
}
|
|
case ITEM_DEFLECTOR:
|
|
{
|
|
if (shipType == HEAVY_FIGHTER ) {
|
|
specialsAvailability[ SPECIAL_DEFLECTOR ] += ITEM_DEFLECTOR_AMMO;
|
|
if ( activeSpecial == SPECIAL_NONE ) {
|
|
activeSpecial = SPECIAL_DEFLECTOR;
|
|
}
|
|
item->pickedUp();
|
|
addBannerItemCollected( BANNER_ITEM_DEFLECTOR_COLLECTED );
|
|
}
|
|
break;
|
|
}
|
|
case ITEM_ENERGY_BEAM:
|
|
{
|
|
if ( shipType == LIGHT_FIGHTER ) {
|
|
secondaryWeaponsAvailability[ SHOT_ENERGY_BEAM - 100 ] = true;
|
|
item->pickedUp();
|
|
addBannerItemCollected( BANNER_ITEM_ENERGY_BEAM_COLLECTED );
|
|
}
|
|
break;
|
|
}
|
|
case ITEM_LASER:
|
|
{
|
|
if ( shipType == HEAVY_FIGHTER ) {
|
|
secondaryWeaponsAvailability[ SHOT_HF_LASER - 100 ] = true;
|
|
addBannerItemCollected( BANNER_ITEM_LASER_COLLECTED );
|
|
item->pickedUp();
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
cout << "pickUpItems: unexpected itemType: " << item->getType() << endl;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
float Racer::getActVelMax() {
|
|
return maxVel;
|
|
}
|
|
|
|
|
|
void Racer::repair( float amount ) {
|
|
float possibleDamageAdd = maxDamage - damage;
|
|
if ( possibleDamageAdd >= amount ) {
|
|
damage += amount;
|
|
} else {
|
|
damage += possibleDamageAdd;
|
|
amount -= possibleDamageAdd;
|
|
shield += amount;
|
|
}
|
|
if ( shield > maxShield ) shield = maxShield;
|
|
}
|
|
|
|
|
|
void Racer::specialKeyDown() {
|
|
switch ( activeSpecial ) {
|
|
case SPECIAL_NUKE:
|
|
{
|
|
if ( timeLastNukeUsed + RACER_COOLDOWN_SPECIAL_NUKE < SDL_GetTicks() ) {
|
|
shots->addShot( new Shot( SPECIAL_SHOT_NUKE,
|
|
playerNr, pos,
|
|
(Vector2D( SCREEN_WIDTH / 2.0,
|
|
SCREEN_HEIGHT / 2.0 ) - pos).getDirection() ) );
|
|
specialsAvailability[ SPECIAL_NUKE ]--;
|
|
timeLastNukeUsed = SDL_GetTicks();
|
|
}
|
|
break;
|
|
}
|
|
case SPECIAL_DEFLECTOR:
|
|
{
|
|
if ( !deflectorActive ) {
|
|
deflectorActive = true;
|
|
deflectorTimeLeft = ITEM_DEFLECTOR_DURATION;
|
|
specialsAvailability[ SPECIAL_DEFLECTOR ]--;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if ( specialsAvailability[ activeSpecial ] == 0 ) {
|
|
switchSpecials();
|
|
}
|
|
}
|
|
|
|
void Racer::specialKeyUp() {
|
|
if ( specialsAvailability[ activeSpecial ] == 0 ) {
|
|
switchSpecials();
|
|
}
|
|
}
|
|
|
|
void Racer::handlePlayerEvent( PlayerEvent pEvent, bool keyDown ) {
|
|
switch (pEvent) {
|
|
case PE_UP: if ( keyDown ) thrust = true; else thrust = false; break;
|
|
case PE_DOWN: if ( keyDown ) backwards = true; else backwards = false; break;
|
|
case PE_LEFT: if ( keyDown ) left = true; else left = false; break;
|
|
case PE_RIGHT: if ( keyDown ) right = true; else right = false; break;
|
|
case PE_FIRE_SPECIALS:// PE_FIRE_WEAPONS:
|
|
if ( keyDown ) fireWeapons = true; else fireWeapons = false; break;
|
|
case PE_CHOOSE_WEAPON_SECONDARY:
|
|
{
|
|
if ( !keyDown ) {
|
|
switchSecondary();
|
|
}
|
|
break;
|
|
}
|
|
case PE_CHOOSE_WEAPON_SPECIALS:
|
|
{
|
|
if ( !keyDown ) {
|
|
switchSpecials();
|
|
}
|
|
break;
|
|
}
|
|
case PE_FIRE_WEAPONS: // PE_FIRE_SPECIALS:
|
|
{
|
|
if ( keyDown ) {
|
|
useSpecial = true;
|
|
specialKeyDown();
|
|
} else {
|
|
useSpecial = false;
|
|
specialKeyUp();
|
|
break;
|
|
}
|
|
}
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
|
|
void Racer::addBannerItemCollected( BannerTexts text ) {
|
|
if ( onePlayerGame ) {
|
|
banners->addBanner( text,
|
|
BANNER_MODE_ITEM_COLLECTED_SINGLE_PLAYER,
|
|
BANNER_BONUS_NONE );
|
|
} else {
|
|
if ( playerNr == 0 ) {
|
|
banners->addBanner( text,
|
|
BANNER_MODE_ITEM_COLLECTED_PLAYER_ONE,
|
|
BANNER_BONUS_NONE );
|
|
} else {
|
|
banners->addBanner( text,
|
|
BANNER_MODE_ITEM_COLLECTED_PLAYER_TWO,
|
|
BANNER_BONUS_NONE );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|