964 lines
25 KiB
C++
964 lines
25 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <sstream>
|
|
#include <android/log.h>
|
|
|
|
#include "SDL.h"
|
|
#include "mixer.h"
|
|
#include "game.h"
|
|
#include "surfaceDB.h"
|
|
#include "racers.h"
|
|
#include "racer.h"
|
|
#include "video.h"
|
|
#include "shots.h"
|
|
#include "shot.h"
|
|
#include "items.h"
|
|
#include "explosions.h"
|
|
#include "explosion.h"
|
|
#include "enemys.h"
|
|
#include "font.h"
|
|
#include "mixer.h"
|
|
#include "input.h"
|
|
#include "wrecks.h"
|
|
#include "wreck.h"
|
|
#include "global.h"
|
|
#include "settings.h"
|
|
#include "intro.h"
|
|
#include "setDifficulty.h"
|
|
#include "menuArcadeMode.h"
|
|
#include "asstring.h"
|
|
#include "sonic.h"
|
|
#include "banners.h"
|
|
#include "banner.h"
|
|
#include "smokePuffs.h"
|
|
#include "background.h"
|
|
#include "options.h"
|
|
|
|
Racers *racers = NULL;
|
|
Enemys *enemys = NULL;
|
|
Shots *shots = NULL;
|
|
Explosions *explosions = NULL;
|
|
Items *items = NULL;
|
|
Wrecks *wrecks = NULL;
|
|
Banners *banners = NULL;
|
|
SmokePuffs *smokePuffs = NULL;
|
|
Options *levelConf = NULL;
|
|
|
|
bool scrollingOn;
|
|
bool nukeIsInPlace;
|
|
bool playMusicOn;
|
|
bool onePlayerGame;
|
|
bool arcadeGame;
|
|
int difficultyLevel;
|
|
float actBackgroundPos;
|
|
|
|
Game::Game() {
|
|
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 1");
|
|
videoserver = new Video();
|
|
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 2");
|
|
screen = 0;
|
|
screen = videoserver->init();
|
|
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 3");
|
|
settings = new Settings();
|
|
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 4");
|
|
intro = new Intro( screen );
|
|
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 5");
|
|
setDifficulty = new SetDifficulty( screen );
|
|
menuArcadeMode = new MenuArcadeMode( screen );
|
|
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 6");
|
|
|
|
pauseSprite = surfaceDB.loadSurface( FN_PAUSED );
|
|
youLoseSprite = surfaceDB.loadSurface( FN_YOU_LOSE );
|
|
youWinSprite = surfaceDB.loadSurface( FN_YOU_WIN );
|
|
// for arcadeMode
|
|
gameOverSprite = surfaceDB.loadSurface( FN_GAME_OVER );
|
|
|
|
nukeEffectSurface = surfaceDB.loadSurface( FN_NUKE_EFFECT );
|
|
|
|
bossAlarm = Mixer::mixer().loadSample( FN_SOUND_BOSS_ALARM, 60 );
|
|
|
|
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 7");
|
|
|
|
fontTime = new Font( FN_FONT_NUMBERS_TIME );
|
|
fontSizeTime = fontTime->getCharWidth();
|
|
|
|
racers = 0;
|
|
explosions = 0;
|
|
enemys = 0;
|
|
shots = 0;
|
|
items = 0;
|
|
wrecks = 0;
|
|
banners = 0;
|
|
smokePuffs = 0;
|
|
// needed for calculating fps
|
|
frameCnt = 0;
|
|
tickCnt = 0;
|
|
|
|
gameState = GS_INTRO;
|
|
paused = true;
|
|
sdlTicks = SDL_GetTicks();
|
|
gameActRuntime = 0;
|
|
timeNukeEnd = 0;
|
|
timePauseOn = 0;
|
|
timeMinibossOn = 0;
|
|
|
|
scrollingOn = true;
|
|
showAllShipStats = false;
|
|
playMusicOn = true;
|
|
onePlayerGame = false;
|
|
arcadeGame = false;
|
|
difficultyLevel = 1;
|
|
|
|
sonic1 = new Sonic();
|
|
sonic2 = new Sonic();
|
|
|
|
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 8");
|
|
|
|
background = new Background();
|
|
loadLevel( FN_LEVEL_ONE_PLAYER );
|
|
|
|
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 9");
|
|
|
|
SdlCompat_AcceleratedSurface *loadingSprite = surfaceDB.loadSurface( FN_LOADING );
|
|
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 10");
|
|
SDL_Rect dest;
|
|
dest.x = (SCREEN_WIDTH - loadingSprite->w ) / 2;
|
|
dest.y = (SCREEN_HEIGHT - loadingSprite->h ) / 2;
|
|
dest.w = loadingSprite->w;
|
|
dest.h = loadingSprite->h;
|
|
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 11");
|
|
SDL_BlitSurface( loadingSprite, 0, screen, &dest );
|
|
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 12");
|
|
SDL_Flip( screen );
|
|
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 13");
|
|
initAllSurfaces();
|
|
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", "Game() 14");
|
|
}
|
|
|
|
Game::~Game(){
|
|
if (videoserver) delete videoserver;
|
|
if (settings) delete settings;
|
|
if (intro) delete intro;
|
|
if (setDifficulty) delete setDifficulty;
|
|
if (racers) delete racers;
|
|
if (shots) delete shots;
|
|
if (explosions) delete explosions;
|
|
if (enemys) delete enemys;
|
|
if (items) delete items;
|
|
if (wrecks) delete wrecks;
|
|
if (fontTime) delete fontTime;
|
|
if (sonic1) delete sonic1;
|
|
if (sonic2) delete sonic2;
|
|
if (banners) delete banners;
|
|
if (smokePuffs) delete smokePuffs;
|
|
}
|
|
|
|
void Game::initNewGame() {
|
|
parseGlobalConfigValues( difficultyLevel );
|
|
|
|
if (racers) delete racers;
|
|
if (shots) delete shots;
|
|
if (explosions) delete explosions;
|
|
if (enemys) delete enemys;
|
|
if (items) delete items;
|
|
if (wrecks) delete wrecks;
|
|
if (sonic1) delete sonic1;
|
|
if (sonic2) delete sonic2;
|
|
if (banners) delete banners;
|
|
if (smokePuffs) delete smokePuffs;
|
|
|
|
banners = new Banners();
|
|
smokePuffs = new SmokePuffs();
|
|
|
|
racers = new Racers();
|
|
Racer *racer;
|
|
|
|
if ( !arcadeGame ) {
|
|
if ( onePlayerGame ) {
|
|
loadLevel( FN_LEVEL_ONE_PLAYER );
|
|
if ( setDifficulty->getPlayerOneLightFighter() ) {
|
|
racer = new Racer( FN_LIGHT_FIGHTER_1, 0,
|
|
Vector2D(320,350), LIGHT_FIGHTER );
|
|
} else {
|
|
racer = new Racer( FN_HEAVY_FIGHTER_1, 0,
|
|
Vector2D(320,350), HEAVY_FIGHTER );
|
|
}
|
|
racers->addRacer(racer);
|
|
}
|
|
// two players
|
|
else {
|
|
loadLevel( FN_LEVEL_TWO_PLAYER );
|
|
if ( setDifficulty->getPlayerOneLightFighter() ) {
|
|
racer = new Racer( FN_LIGHT_FIGHTER_1, 0,
|
|
Vector2D(250,350), LIGHT_FIGHTER );
|
|
} else {
|
|
racer = new Racer( FN_HEAVY_FIGHTER_1, 0,
|
|
Vector2D(250,350), HEAVY_FIGHTER );
|
|
}
|
|
racers->addRacer(racer);
|
|
|
|
if ( setDifficulty->getPlayerTwoLightFighter() ) {
|
|
racer = new Racer( FN_LIGHT_FIGHTER_2, 1,
|
|
Vector2D(390,350), LIGHT_FIGHTER );
|
|
} else {
|
|
racer = new Racer( FN_HEAVY_FIGHTER_2, 1,
|
|
Vector2D(390,350), HEAVY_FIGHTER );
|
|
}
|
|
racers->addRacer(racer);
|
|
}
|
|
}
|
|
// arcade game
|
|
else {
|
|
loadLevel( FN_LEVEL_ARCADEMODE );
|
|
if ( menuArcadeMode->getPlayerOneLightFighter() ) {
|
|
racer = new Racer( FN_LIGHT_FIGHTER_1, 0,
|
|
Vector2D(320,350), LIGHT_FIGHTER );
|
|
} else {
|
|
racer = new Racer( FN_HEAVY_FIGHTER_1, 0,
|
|
Vector2D(320,350), HEAVY_FIGHTER );
|
|
}
|
|
racers->addRacer(racer);
|
|
}
|
|
|
|
racers->getKeyActionMaps();
|
|
|
|
explosions = new Explosions();
|
|
enemys = new Enemys();
|
|
shots = new Shots();
|
|
items = new Items();
|
|
wrecks = new Wrecks();
|
|
|
|
gameActRuntime = 0;
|
|
paused = true;
|
|
bossTime = false;
|
|
bossNukeEffect = false;
|
|
bossExplosion = Mixer::mixer().loadSample( FN_SOUND_EXPLOSION_BOSS );
|
|
|
|
minibossAlreadyKilled = false;
|
|
minibossTime = false;
|
|
timeMinibossOn = SDL_GetTicks();
|
|
timeLastUpdate = SDL_GetTicks();
|
|
timeNukeEnd = SDL_GetTicks();
|
|
timePauseOn = SDL_GetTicks();
|
|
actBackgroundPos = 0;
|
|
|
|
scrollingOn = true;
|
|
nukeIsInPlace = false;
|
|
|
|
sonic1 = new Sonic();
|
|
sonic2 = new Sonic();
|
|
sonic1->setActive( false );
|
|
sonic2->setActive( false );
|
|
}
|
|
|
|
void Game::run(){
|
|
while( gameState != GS_QUIT ) {
|
|
switch (gameState) {
|
|
case GS_SCREENSHOTS:
|
|
{
|
|
intro->showScreenshots();
|
|
gameState = GS_INTRO;
|
|
break;
|
|
}
|
|
case GS_INTRO:
|
|
{
|
|
intro->run( gameState );
|
|
break;
|
|
}
|
|
case GS_SET_DIFFICULTY:
|
|
{
|
|
setDifficulty->run( gameState, onePlayerGame);
|
|
break;
|
|
}
|
|
case GS_ARCADE_MODE_SETUP:
|
|
{
|
|
menuArcadeMode->run( gameState );
|
|
break;
|
|
}
|
|
case GS_ARCADE_MODE_FINISHED:
|
|
{
|
|
menuArcadeMode->run( gameState, racers->getPointsArcadeMode() );
|
|
break;
|
|
}
|
|
case GS_OPTIONS:
|
|
{
|
|
options();
|
|
break;
|
|
}
|
|
case GS_ROUNDFINISHED:
|
|
{
|
|
roundFinished();
|
|
break;
|
|
}
|
|
case GS_BOSS_KILLED:
|
|
{
|
|
bossKilled();
|
|
break;
|
|
}
|
|
case GS_PLAYON:
|
|
{
|
|
initNewGame();
|
|
if ( playMusicOn ) Mixer::mixer().playMusic( MUSIC_PLAYON, -1, 1000 );
|
|
playOn();
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*********************************/
|
|
/**** PlayOn *********************/
|
|
/*********************************/
|
|
|
|
void Game::playOn() {
|
|
int A = SDL_GetTicks();
|
|
frameCnt = 0;
|
|
tickCnt = 0;
|
|
{
|
|
std::ostringstream logout;
|
|
logout << "frameCnt: " << frameCnt << " tickCnt: " << tickCnt
|
|
<< " SDL_GetTicks()=" << A;
|
|
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", logout.str().c_str());
|
|
}
|
|
|
|
|
|
while ( gameState == GS_PLAYON ) {
|
|
handleEventsPlayOn();
|
|
if (!paused) {
|
|
updateGameState();
|
|
}
|
|
drawPlayOn();
|
|
// miniboss
|
|
if ( minibossTime && enemys->minibossDead() ) minibossAlreadyKilled = true;
|
|
if (!minibossAlreadyKilled && !arcadeGame && !paused && !minibossTime &&
|
|
(unsigned int)GAME_LENGTH / 2 <= gameActRuntime) {
|
|
generateMiniboss();
|
|
}
|
|
if ( minibossTime && enemys->bossDead() ) minibossKilled();
|
|
// endboss
|
|
if (!arcadeGame && !paused && !bossTime && !minibossTime &&
|
|
(unsigned int)GAME_LENGTH < gameActRuntime) {
|
|
enemys->bossTime(1); // generates the boss
|
|
bossTime = true;
|
|
Mixer::mixer().playSample( bossAlarm , 0, true );
|
|
if ( playMusicOn ) Mixer::mixer().playMusic( MUSIC_BOSS1, -1, 0 );
|
|
}
|
|
if ( bossTime && enemys->bossDead() ) gameState = GS_BOSS_KILLED;
|
|
if ( racers->bothPlayersLost() ) gameState = GS_ROUNDFINISHED;
|
|
}
|
|
|
|
{
|
|
std::ostringstream logout;
|
|
|
|
int B = SDL_GetTicks();
|
|
logout << "frameCnt: " << frameCnt << " tickCnt: " << tickCnt
|
|
<< " SDL_GetTicks()=" << B << endl;
|
|
logout << "Milliseconds: " << B-A << endl;
|
|
logout << "Frames/sec : " << (float)frameCnt / ((float)(B-A) / 1000.0) << endl;
|
|
logout << "ms/Frame : " << (float)tickCnt / (float)frameCnt << endl;
|
|
__android_log_print(ANDROID_LOG_INFO, "Alien Blaster", logout.str().c_str());
|
|
}
|
|
}
|
|
|
|
|
|
void Game::pause() {
|
|
if (paused) {
|
|
Uint32 timePaused = SDL_GetTicks() - timePauseOn;
|
|
timeLastUpdate += timePaused;
|
|
} else {
|
|
timePauseOn = SDL_GetTicks();
|
|
}
|
|
paused = !paused;
|
|
}
|
|
|
|
|
|
void Game::handleEventsPlayOn() {
|
|
SDL_Event event;
|
|
|
|
while (SDL_PollEvent(&event)) {
|
|
switch(event.type) {
|
|
case SDL_JOYBUTTONDOWN:
|
|
case SDL_KEYDOWN:
|
|
case SDL_MOUSEBUTTONDOWN: {
|
|
if (paused) pause();
|
|
racers->handleEvent(input.translate(event), input.isPressed(event));
|
|
break;
|
|
}
|
|
case SDL_KEYUP: {
|
|
switch(event.key.keysym.sym) {
|
|
case SDLK_F10: {
|
|
pause();
|
|
break;
|
|
}
|
|
case SDLK_F5: {
|
|
videoserver->toggleFullscreen();
|
|
break;
|
|
}
|
|
case SDLK_F6: {
|
|
showAllShipStats = !showAllShipStats;
|
|
break;
|
|
}
|
|
case SDLK_ESCAPE: {
|
|
gameState = GS_INTRO;
|
|
break;
|
|
}
|
|
case SDLK_F1: {
|
|
if (!paused) pause();
|
|
settings->settingsDialog(screen);
|
|
racers->getKeyActionMaps();
|
|
pause();
|
|
break;
|
|
}
|
|
case SDLK_F7: {
|
|
if ( playMusicOn ) {
|
|
playMusicOn = false;
|
|
Mixer::mixer().stopMusic();
|
|
} else {
|
|
playMusicOn = true;
|
|
if ( bossTime ) Mixer::mixer().playMusic( MUSIC_BOSS1, -1, 1000 );
|
|
else Mixer::mixer().playMusic( MUSIC_PLAYON, -1, 1000 );
|
|
}
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
}
|
|
case SDL_JOYAXISMOTION:
|
|
case SDL_JOYBUTTONUP:
|
|
case SDL_MOUSEBUTTONUP:
|
|
racers->handleEvent(input.translate(event), input.isPressed(event));
|
|
break;
|
|
case SDL_QUIT: {
|
|
gameState = GS_QUIT;
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// what to do in one tick
|
|
void Game::updateGameState() {
|
|
int dT = SDL_GetTicks() - timeLastUpdate;
|
|
timeLastUpdate += dT;
|
|
if ( !minibossTime ) gameActRuntime += dT;
|
|
|
|
if ( nukeIsInPlace ) handleNuke();
|
|
|
|
enemys->generateEnemys( dT );
|
|
explosions->updateExplosions( dT );
|
|
|
|
smokePuffs->update( dT );
|
|
shots->moveAndCollide( dT );
|
|
wrecks->updateWrecks( dT );
|
|
enemys->updateEnemys( dT );
|
|
if ( !arcadeGame ) items->generate( dT );
|
|
items->update( dT );
|
|
|
|
racers->moveAndCollide( dT );
|
|
racers->pickUpItems();
|
|
racers->shoot();
|
|
if ( !arcadeGame ) racers->rechargeShield( dT );
|
|
|
|
enemys->deleteExpiredEnemys();
|
|
shots->expireShots();
|
|
items->expireItems();
|
|
explosions->expireExplosions();
|
|
wrecks->expireWrecks();
|
|
racers->expireRacers();
|
|
smokePuffs->expireSmokePuffs();
|
|
sonicDeflectorEffect();
|
|
|
|
banners->update( dT );
|
|
banners->expireBanners();
|
|
|
|
if ( scrollingOn ) actBackgroundPos -= SCROLL_SPEED * dT / 1000.0;
|
|
|
|
if ( arcadeGame ) {
|
|
racers->receivePointsArcade( ARCADE_POINTS_PER_TEN_SECONDS * dT / 10000.0 );
|
|
}
|
|
}
|
|
|
|
void Game::handleNuke() {
|
|
sonic1->setActive( false );
|
|
sonic2->setActive( false );
|
|
|
|
enemys->doNukeDamage();
|
|
shots->deleteAllShots();
|
|
timeNukeEnd = SDL_GetTicks() + NUKE_EFFECT_DURATION;
|
|
nukeIsInPlace = false;
|
|
}
|
|
|
|
void Game::sonicDeflectorEffect() {
|
|
for ( unsigned int i = 0; i < racers->getNrRacers(); i++) {
|
|
if ( racers->getRacer(i)->getShipType() == LIGHT_FIGHTER ) {
|
|
Shot* nearestRocket = shots->getNearestRocket( racers->getRacer(i)->getPos() );
|
|
// a rocket exists and it is in range of the sonic
|
|
if ( nearestRocket != NULL &&
|
|
(nearestRocket->getPos() - racers->getRacer(i)->getPos()).getLength() <
|
|
RACER_SONIC_ACTIVATION_DIST ) {
|
|
// activate the correct sonic
|
|
if (i == 0) {
|
|
sonic1->setPos( racers->getRacer(i)->getPos(), nearestRocket->getPos() );
|
|
nearestRocket->deflectedBySonicFromPlayer1 = true;
|
|
} else {
|
|
sonic2->setPos( racers->getRacer(i)->getPos(), nearestRocket->getPos() );
|
|
nearestRocket->deflectedBySonicFromPlayer2 = true;
|
|
}
|
|
// no rocket is in sonic-range
|
|
} else {
|
|
// deactivate the sonic
|
|
if (i == 0) {
|
|
sonic1->setActive( false );
|
|
} else {
|
|
sonic2->setActive( false );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Game::drawPlayOn() {
|
|
drawBackground();
|
|
wrecks->draw(screen);
|
|
enemys->drawGroundEnemys(screen);
|
|
shots->drawShadows(screen);
|
|
racers->drawShadows(screen);
|
|
enemys->drawShadows(screen);
|
|
explosions->drawGroundExplosions(screen);
|
|
|
|
smokePuffs->draw(screen);
|
|
|
|
sonic1->draw(screen);
|
|
sonic2->draw(screen);
|
|
|
|
shots->drawGroundShots(screen);
|
|
shots->drawGroundAirShots(screen);
|
|
items->draw(screen);
|
|
enemys->drawAirEnemys(screen);
|
|
racers->drawRacers(screen);
|
|
shots->drawAirShots(screen);
|
|
explosions->drawAirExplosions(screen);
|
|
|
|
|
|
if ( showAllShipStats ) enemys->drawAllStats(screen);
|
|
else {
|
|
if ( bossTime ) {
|
|
enemys->drawBossStats(screen);
|
|
fontTime->drawStr( screen, (screen->w / 2), 5, "BOSS", FONT_ALIGN_CENTERED );
|
|
}
|
|
}
|
|
|
|
if ( SDL_GetTicks() < timeNukeEnd ) {
|
|
drawNukeEffect();
|
|
}
|
|
|
|
racers->drawStats(screen);
|
|
|
|
banners->draw(screen);
|
|
if ( !arcadeGame && !bossTime && !minibossTime ) drawTime();
|
|
else {
|
|
if ( bossTime || minibossTime ) {
|
|
fontTime->drawStr( screen, (screen->w / 2), 5, "BOSS", FONT_ALIGN_CENTERED );
|
|
}
|
|
else {
|
|
drawPointsArcadeMode();
|
|
}
|
|
}
|
|
|
|
if (paused) drawPaused();
|
|
|
|
SDL_Flip( screen );
|
|
|
|
frameCnt++;
|
|
}
|
|
|
|
void Game::drawBackground() {
|
|
background->draw(screen, (int) (actBackgroundPos + 0.5) );
|
|
}
|
|
|
|
|
|
void Game::drawTime() {
|
|
Uint32 timeToDraw;
|
|
timeToDraw = (GAME_LENGTH - gameActRuntime) / 1000;
|
|
if ( timeToDraw > 0 ) {
|
|
int digitCnt = 1;
|
|
Uint32 i=1;
|
|
while ( timeToDraw >= i*10 ) {
|
|
digitCnt++;
|
|
i *= 10;
|
|
}
|
|
fontTime->drawInt(screen, (screen->w / 2) - (fontSizeTime * digitCnt) / 2, 5,
|
|
timeToDraw, digitCnt, 0);
|
|
}
|
|
}
|
|
|
|
|
|
void Game::drawPointsArcadeMode() {
|
|
int pointsToDraw = racers->getPointsArcadeMode();
|
|
if ( pointsToDraw < 0 ) return;
|
|
|
|
int digitCnt = 1;
|
|
int i=1;
|
|
while ( pointsToDraw >= i*10 ) {
|
|
digitCnt++;
|
|
i *= 10;
|
|
}
|
|
fontTime->drawInt( screen, (screen->w / 2) - (fontSizeTime * digitCnt) / 2, 10,
|
|
pointsToDraw, digitCnt, 0);
|
|
}
|
|
|
|
|
|
|
|
void Game::drawPaused() {
|
|
SDL_Rect r;
|
|
r.x = screen->w/2 - pauseSprite->w/2;
|
|
r.y = screen->h/2 - pauseSprite->h/2;
|
|
r.w = pauseSprite->w;
|
|
r.h = pauseSprite->h;
|
|
SDL_BlitSurface( pauseSprite, 0, screen, &r );
|
|
}
|
|
|
|
|
|
void Game::drawNukeEffect() {
|
|
// effect-process: transparent -> nearly opaque -> transparent
|
|
int timeFromMaximum = (NUKE_EFFECT_DURATION / 2) - (timeNukeEnd - SDL_GetTicks());
|
|
timeFromMaximum = abs(timeFromMaximum);
|
|
|
|
SDL_SetAlpha( nukeEffectSurface, SDL_SRCALPHA,
|
|
lroundf(((NUKE_EFFECT_DURATION / 2) - timeFromMaximum) * 128.0 /
|
|
(NUKE_EFFECT_DURATION / 2)) );
|
|
|
|
SDL_BlitSurface( nukeEffectSurface, 0, screen, 0 );
|
|
|
|
/*
|
|
int randRange = (int)
|
|
(( ((NUKE_EFFECT_DURATION / 2.0) - timeFromMaximum) * NUKE_QUAKE_EFFECT /
|
|
(NUKE_EFFECT_DURATION / 2.0 ) ) + 0.5);
|
|
|
|
int randX, randY;
|
|
if ( randRange == 0 ) randRange = 1;
|
|
randX = (rand() % randRange) - randRange / 2;
|
|
randY = (rand() % randRange) - randRange / 2;
|
|
|
|
SDL_Rect src, dest;
|
|
if ( randX < 0 ) {
|
|
src.x = -randX;
|
|
src.w = screen->w + randX;
|
|
dest.x = 0;
|
|
dest.w = screen->w + randX;
|
|
} else {
|
|
src.x = 0;
|
|
src.w = screen->w - randX;
|
|
dest.x = randX;
|
|
dest.w = screen->w - randX;
|
|
}
|
|
if ( randY < 0 ) {
|
|
src.y = -randY;
|
|
src.h = screen->h + randY;
|
|
dest.y = 0;
|
|
dest.h = screen->h + randY;
|
|
} else {
|
|
src.y = 0;
|
|
src.h = screen->h - randY;
|
|
dest.y = randY;
|
|
dest.h = screen->h - randY;
|
|
}
|
|
|
|
SDL_BlitSurface( screen, &src, screen, &dest );
|
|
*/
|
|
}
|
|
|
|
|
|
// not in use - not needed anymore
|
|
void Game::timeManagement() {
|
|
Uint32 sdlTicksNew = SDL_GetTicks();
|
|
tickCnt += sdlTicksNew - sdlTicks;
|
|
// 25 Frames per Second is wanted
|
|
// we needed less than 40 ms -> wait till the 40 ms are over
|
|
while ( sdlTicks + 40 > sdlTicksNew ) {
|
|
sdlTicksNew = SDL_GetTicks();
|
|
}
|
|
sdlTicks = sdlTicksNew;
|
|
}
|
|
|
|
|
|
|
|
/***********************************/
|
|
/** Options ************************/
|
|
/***********************************/
|
|
|
|
void Game::options() {}
|
|
|
|
|
|
/************************************/
|
|
/** Round Finished ******************/
|
|
/************************************/
|
|
|
|
void Game::roundFinished() {
|
|
drawRoundFinished();
|
|
SDL_Flip( screen );
|
|
while (gameState == GS_ROUNDFINISHED ) {
|
|
handleEventsRoundFinished();
|
|
}
|
|
}
|
|
|
|
void Game::handleEventsRoundFinished() {
|
|
SDL_Event event;
|
|
|
|
while (SDL_PollEvent(&event)) {
|
|
switch(event.type) {
|
|
case SDL_KEYUP:
|
|
{
|
|
switch(event.key.keysym.sym) {
|
|
case SDLK_ESCAPE:
|
|
case SDLK_SPACE:
|
|
case SDLK_RETURN:
|
|
{
|
|
if ( arcadeGame ) gameState = GS_ARCADE_MODE_FINISHED;
|
|
else gameState = GS_INTRO;
|
|
break;
|
|
}
|
|
case SDLK_F5:
|
|
{
|
|
videoserver->toggleFullscreen();
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case SDL_QUIT:
|
|
{
|
|
if ( arcadeGame ) gameState = GS_ARCADE_MODE_FINISHED;
|
|
else gameState = GS_INTRO;
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Game::drawRoundFinished() {
|
|
SDL_Rect r;
|
|
|
|
if ( arcadeGame ) {
|
|
r.x = screen->w/2 - gameOverSprite->w / 2;
|
|
r.y = screen->h/2 - gameOverSprite->h / 2;
|
|
r.w = gameOverSprite->w;
|
|
r.h = gameOverSprite->h;
|
|
SDL_BlitSurface( gameOverSprite, 0, screen, &r );
|
|
|
|
fontTime->drawStr( screen, screen->w/2, screen->h/2 + gameOverSprite->h/2 + 50,
|
|
"SCORE: " + asString( racers->getPointsArcadeMode() ),
|
|
FONT_ALIGN_CENTERED );
|
|
fontTime->drawStr( screen, screen->w/2, screen->h/2 + gameOverSprite->h/2 + 100,
|
|
"Kill Rate: " + asString(enemys->getNrEnemysKilled())
|
|
+ "/" + asString(enemys->getNrEnemysGenerated()),
|
|
FONT_ALIGN_CENTERED );
|
|
}
|
|
|
|
// normal game
|
|
else {
|
|
if ( racers->bothPlayersLost() ) {
|
|
r.x = screen->w/2 - youLoseSprite->w / 2;
|
|
r.y = screen->h/2 - youLoseSprite->h / 2;
|
|
r.w = youLoseSprite->w;
|
|
r.h = youLoseSprite->h;
|
|
SDL_BlitSurface( youLoseSprite, 0, screen, &r );
|
|
} else {
|
|
r.x = screen->w/2 - youWinSprite->w / 2;
|
|
r.y = screen->h/2 - youWinSprite->h / 2;
|
|
r.w = youWinSprite->w;
|
|
r.h = youWinSprite->h;
|
|
SDL_BlitSurface( youWinSprite, 0, screen, &r );
|
|
fontTime->drawStr(screen, screen->w/2, screen->h/2 + youWinSprite->h/2 + 50,
|
|
"Kill Rate: " + asString(enemys->getNrEnemysKilled())
|
|
+ ":" + asString(enemys->getNrEnemysGenerated()),
|
|
FONT_ALIGN_CENTERED);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/************************************/
|
|
/** Miniboss ***********************/
|
|
/************************************/
|
|
|
|
void Game::generateMiniboss() {
|
|
scrollingOn = false;
|
|
minibossTime = true;
|
|
enemys->bossTime(2); // generates the miniboss
|
|
Mixer::mixer().playSample( bossAlarm , 0, true );
|
|
if ( playMusicOn ) Mixer::mixer().playMusic( MUSIC_BOSS1, -1, 0 );
|
|
}
|
|
|
|
void Game::minibossKilled() {
|
|
scrollingOn = true;
|
|
minibossTime = false;
|
|
if ( playMusicOn ) Mixer::mixer().playMusic( MUSIC_PLAYON, -1, 0 );
|
|
}
|
|
|
|
|
|
/************************************/
|
|
/** Boss Killed *********************/
|
|
/************************************/
|
|
|
|
void Game::bossKilled() {
|
|
int BOSS_EXPLOSION_DURATION = 3000;
|
|
int startOfBossExplosion = SDL_GetTicks();
|
|
int actualTime;
|
|
bool bossExplosionSound = false;
|
|
timeNukeEnd = SDL_GetTicks() + BOSS_EXPLOSION_DURATION + NUKE_EFFECT_DURATION;
|
|
|
|
while ( gameState == GS_BOSS_KILLED ) {
|
|
actualTime = SDL_GetTicks();
|
|
updateBossKilled();
|
|
if ( (actualTime - startOfBossExplosion) < BOSS_EXPLOSION_DURATION ) {
|
|
// explosions
|
|
Explosion *newExplosion =
|
|
new Explosion( FN_EXPLOSION_ENEMY,
|
|
Vector2D( rand() % SCREEN_WIDTH, rand() % 150 ),
|
|
Vector2D( 0, 0 ),
|
|
EXPLOSION_NORMAL_GROUND );
|
|
explosions->addExplosion( newExplosion );
|
|
}
|
|
else if ( (actualTime - startOfBossExplosion) < (BOSS_EXPLOSION_DURATION + NUKE_EFFECT_DURATION) ) {
|
|
// nuke effect
|
|
if ( !bossExplosionSound ) {
|
|
Mixer::mixer().playSample( bossExplosion, 0, true );
|
|
bossExplosionSound = false;
|
|
enemys->doNukeDamage();
|
|
enemys->deleteExpiredEnemys();
|
|
shots->deleteAllShots();
|
|
items->deleteAllItems();
|
|
wrecks->deleteAllWrecks();
|
|
Wreck *newWreck = new Wreck( Vector2D( SCREEN_WIDTH / 2, 70 ), WRECK_BOSS_1_DESTROYED);
|
|
wrecks->addWreck( newWreck );
|
|
bossNukeEffect = true;
|
|
}
|
|
}
|
|
else {
|
|
bossNukeEffect = false;
|
|
}
|
|
if ( (actualTime - startOfBossExplosion) > (BOSS_EXPLOSION_DURATION + NUKE_EFFECT_DURATION + 4000) ) {
|
|
gameState = GS_ROUNDFINISHED;
|
|
}
|
|
drawBossKilled();
|
|
handleEventsBossKilled();
|
|
}
|
|
}
|
|
|
|
void Game::handleEventsBossKilled() {
|
|
SDL_Event event;
|
|
|
|
while (SDL_PollEvent(&event)) {
|
|
switch(event.type) {
|
|
case SDL_KEYUP: {
|
|
switch(event.key.keysym.sym) {
|
|
case SDLK_ESCAPE:
|
|
case SDLK_SPACE:
|
|
case SDLK_RETURN:
|
|
{
|
|
gameState = GS_INTRO;
|
|
break;
|
|
}
|
|
case SDLK_F5:
|
|
{
|
|
videoserver->toggleFullscreen();
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
break;
|
|
}
|
|
case SDL_QUIT:
|
|
{
|
|
gameState = GS_INTRO;
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Game::drawBossKilled() {
|
|
drawBackground();
|
|
wrecks->draw(screen);
|
|
enemys->drawGroundEnemys(screen);
|
|
shots->drawShadows(screen);
|
|
racers->drawShadows(screen);
|
|
enemys->drawShadows(screen);
|
|
explosions->drawGroundExplosions(screen);
|
|
shots->drawGroundShots(screen);
|
|
shots->drawGroundAirShots(screen);
|
|
items->draw(screen);
|
|
enemys->drawAirEnemys(screen);
|
|
racers->drawRacers(screen);
|
|
shots->drawAirShots(screen);
|
|
explosions->drawAirExplosions(screen);
|
|
if ( bossNukeEffect ) drawNukeEffect();
|
|
racers->drawStats(screen);
|
|
SDL_Flip( screen );
|
|
}
|
|
|
|
void Game::updateBossKilled() {
|
|
int dT = SDL_GetTicks() - timeLastUpdate;
|
|
timeLastUpdate += dT;
|
|
explosions->updateExplosions( dT );
|
|
explosions->expireExplosions();
|
|
}
|
|
|
|
|
|
void Game::loadLevel( string fn ) {
|
|
if (levelConf) {
|
|
delete levelConf;
|
|
}
|
|
levelConf = new Options( fn );
|
|
|
|
// load background tiles
|
|
background->clearTileList();
|
|
int cnt = 0;
|
|
if (!levelConf->getInt( LVL_BACKG_TILE_CNT, cnt )) {
|
|
cout << "ERROR: " << fn << " contains no '" << LVL_BACKG_TILE_CNT << "' keyword!" << endl;
|
|
exit(0);
|
|
}
|
|
for(int i=0; i < cnt; i++) {
|
|
string tilename;
|
|
if (levelConf->getStr( LVL_BACKG_TILE + asString( i ), tilename ) ) {
|
|
background->addTile( tilename );
|
|
}
|
|
}
|
|
int len = SCREEN_WIDTH;
|
|
levelConf->getInt( LVL_BACKG_LENGTH, len );
|
|
background->generateBackground( len );
|
|
}
|