00001 #include <stdio.h>
00002 #include <time.h>
00003
00004 #include <SDL/SDL.h>
00005 #include <SDL/SDL_image.h>
00006
00007 #include "font.h"
00008
00009 #include "constants.h"
00010 #include "game.h"
00011 #include "player.h"
00012 #include "random.h"
00013 #include "sound.h"
00014 #include "stringtokenizer.h"
00015
00016 #include "sfcave_game.h"
00017 #include "gates_game.h"
00018 #include "fly_game.h"
00019 #include "starfield.h"
00020
00021 Game :: Game( SFCave *p, int w, int h, int diff )
00022 {
00023 parent = p;
00024 sHeight = h;
00025 sWidth = w;
00026 difficulty = diff;
00027 replayIt = 0;
00028 replay = false;
00029 terrain = 0;
00030 player = 0;
00031 thrustChannel = -1;
00032 }
00033
00034 Game :: ~Game()
00035 {
00036 if ( terrain )
00037 delete terrain;
00038
00039 if ( player )
00040 delete player;
00041
00042 replayList.clear();
00043 }
00044
00045 void Game :: init()
00046 {
00047 if ( replay )
00048 {
00049 setSeed( currentSeed );
00050 replayIt = replayList.begin();
00051 }
00052 else
00053 {
00054 setSeed( -1 );
00055 replayList.clear();
00056 }
00057
00058 score = 0;
00059 nrFrames = 0;
00060 press = false;
00061
00062
00063 string key = getGameName() + "_" + getGameDifficultyText() + "_highscore";
00064 highScore = atoi( parent->loadSetting( key, "0" ).c_str() );
00065
00066 terrain->initTerrain();
00067 player->init();
00068 }
00069
00070 void Game :: handleKeys( SDL_KeyboardEvent &key )
00071 {
00072 if ( !replay &&
00073 (key.keysym.sym == SDLK_SPACE ||
00074 key.keysym.sym == SDLK_KP_ENTER ||
00075 key.keysym.sym == SDLK_RETURN ||
00076 key.keysym.sym == SDLK_UP) )
00077 {
00078 if ( key.type == SDL_KEYDOWN )
00079 {
00080 if ( !press )
00081 replayList.push_back( nrFrames );
00082 press = true;
00083 }
00084 else
00085 {
00086 if ( press )
00087 replayList.push_back( nrFrames );
00088 press = false;
00089
00090 }
00091 }
00092 }
00093
00094
00095
00096 string Game :: getGameDifficultyText()
00097 {
00098 string ret;
00099
00100 if ( difficulty == MENU_DIFFICULTY_EASY )
00101 ret = "Easy";
00102 else if ( difficulty == MENU_DIFFICULTY_NORMAL )
00103 ret = "Medium";
00104 else if ( difficulty == MENU_DIFFICULTY_HARD )
00105 ret = "Hard";
00106 else if ( difficulty == MENU_DIFFICULTY_CUSTOM )
00107 ret = "Custom";
00108
00109 return ret;
00110 }
00111
00112 void Game :: setDifficulty( string diff )
00113 {
00114 if ( diff == "Easy" )
00115 difficulty = MENU_DIFFICULTY_EASY;
00116 else if ( diff == "Medium" )
00117 difficulty = MENU_DIFFICULTY_NORMAL;
00118 else if ( diff == "Hard" )
00119 difficulty = MENU_DIFFICULTY_HARD;
00120 else if ( diff == "Custom" )
00121 difficulty = MENU_DIFFICULTY_CUSTOM;
00122
00123 init();
00124 }
00125
00126 void Game :: setDifficulty( int diff )
00127 {
00128 difficulty = diff;
00129 init();
00130 }
00131
00132 void Game :: update( int state )
00133 {
00134 nrFrames ++;
00135
00136 if ( score > highScore )
00137 highScore = score;
00138
00139
00140 if ( state == STATE_PLAYING )
00141 {
00142 if ( replay )
00143 {
00144 while( replayIt != replayList.end() && (*replayIt) == nrFrames-1 )
00145 {
00146 press = !press;
00147 replayIt ++;
00148 }
00149 }
00150
00151 if ( press && thrustChannel == -1 )
00152 thrustChannel = SoundHandler :: playSound( SND_THRUST, -1, -1, false );
00153
00154 if ( !press &&thrustChannel != -1 )
00155 {
00156 SoundHandler :: stopSound( thrustChannel, true, 300 );
00157 thrustChannel = -1;
00158 }
00159 }
00160
00161 if ( state == STATE_CRASHING || state == STATE_CRASHED )
00162 {
00163
00164 if ( player->updateCrashing() )
00165 parent->changeState( STATE_CRASHED );
00166
00167 }
00168 }
00169
00170 void Game :: preDraw( SDL_Surface *screen )
00171 {
00172 }
00173
00174 void Game :: draw( SDL_Surface *screen )
00175 {
00176 char tmp[100];
00177 string scoreText;
00178 sprintf( tmp, "Score: %06ld High Score: %06ld", score, highScore );
00179 FontHandler::draw( screen, FONT_WHITE_TEXT, tmp, 3, 10 );
00180
00181 if ( parent->getState() == STATE_CRASHED )
00182 {
00183 string crashText;
00184 crashText = "Game Over";
00185 int x = (240 - FontHandler::TextWidth( FONT_WHITE_TEXT, (const char *)crashText.c_str() )) / 2;
00186 FontHandler::draw( screen, FONT_WHITE_TEXT, (const char *)crashText.c_str(), x, 150 );
00187
00188 int fontHeight = FontHandler::FontHeight( FONT_WHITE_TEXT );
00189 crashText = "Press Middle Button to play again";
00190 x = (240 - FontHandler::TextWidth( FONT_WHITE_TEXT, (const char *)crashText.c_str() )) / 2;
00191 FontHandler::draw( screen, FONT_WHITE_TEXT, (const char *)crashText.c_str(), x, 150 + fontHeight );
00192
00193 crashText = "or OK for menu";
00194 x = (240 - FontHandler::TextWidth( FONT_WHITE_TEXT, (const char *)crashText.c_str() )) / 2;
00195 FontHandler::draw( screen, FONT_WHITE_TEXT, (const char *)crashText.c_str(), x, 150 + 2*fontHeight );
00196 }
00197
00198 if ( parent->showFPS() )
00199 {
00200 sprintf( tmp, "FPS : %d", parent->getFPS() );
00201 FontHandler::draw( screen, FONT_WHITE_TEXT, tmp, 20, 300 );
00202 }
00203 }
00204
00205 void Game :: stateChanged( int from, int to )
00206 {
00207 if ( from != STATE_CRASHING && to == STATE_CRASHING )
00208 {
00209
00210 SoundHandler :: stopSound( -1, false );
00211 SoundHandler :: playSound( SND_EXPLOSION );
00212
00213
00214 printf( "Got Highscore = %d\n", gotHighScore() );
00215 if ( gotHighScore() )
00216 {
00217 string key = getGameName() + "_" + getGameDifficultyText() + "_highscore";
00218 parent->saveSetting( key, getHighScore() );
00219 }
00220
00221 }
00222 }
00223
00224 void Game :: setSeed( int seed )
00225 {
00226 if ( seed == -1 )
00227 currentSeed = ((unsigned long) time((time_t *) NULL));
00228 else
00229 currentSeed = seed;
00230 PutSeed( currentSeed );
00231 }
00232
00233 void Game :: saveReplay( string file )
00234 {
00235 FILE *out;
00236 out = fopen( file.c_str(), "w" );
00237 if ( !out )
00238 {
00239 printf( "Couldn't write to /home/root/%s\n", file.c_str() );
00240 parent->setMenuStatusText( "Couldn't save replay file" );
00241 return;
00242 }
00243
00244
00245
00246 string val;
00247 char tmp[20];
00248 sprintf( tmp, "%d %d ", currentSeed, difficulty );
00249 val = tmp;
00250
00251 list<int>::iterator it = replayList.begin();
00252 while( it != replayList.end() )
00253 {
00254 sprintf( tmp, "%d ", *it );
00255 val += tmp;
00256
00257 it++;
00258 }
00259 val += "\n";
00260
00261 string line;
00262 sprintf( tmp, "%d\n", val.length() );
00263 line = tmp;
00264 fwrite( line.c_str(), 1, line.length(), out );
00265
00266 fwrite( val.c_str(), 1, val.length(), out );
00267
00268 fclose( out );
00269 }
00270
00271 void Game :: loadReplay( string file )
00272 {
00273
00274 FILE *in = fopen( (const char *)file.c_str(), "r" );
00275
00276 if ( in == 0 )
00277 {
00278 printf( "Couldn't load replay file %s!\n", (const char *)file.c_str() );
00279 parent->setMenuStatusText( "Couldn't load replay file" );
00280 return;
00281 }
00282
00283
00284 char line[10+1];
00285 fgets( line, 10, in );
00286
00287 int length = -1;
00288 sscanf( line, "%d", &length );
00289 char *data = new char[length+1];
00290
00291 fread( data, 1, length, in );
00292
00293 string sep = " ";
00294
00295 StringTokenizer st( data, sep );
00296
00297
00298 vector<string>::iterator it = st.begin();
00299 currentSeed = atoi( (*it).c_str() );
00300 ++it;
00301 difficulty = atoi( (*it).c_str() );
00302 ++it;
00303
00304 replayList.clear();
00305 for ( ; it != st.end(); ++it )
00306 {
00307 int v = atoi( (*it).c_str() );
00308 replayList.push_back( v );
00309 }
00310
00311 delete data;
00312
00313 fclose( in );
00314 }
00315
00316
00317 Game *Game :: createGame( SFCave *p, int w, int h, string game, string difficulty )
00318 {
00319 Game *g;
00320
00321 if ( game == "SFCave" )
00322 g = new SFCaveGame( p, w, h, 0 );
00323 else if ( game == "Gates" )
00324 g = new GatesGame( p, w, h, 0 );
00325 else if ( game == "Fly" )
00326 g = new FlyGame( p, w, h, 0 );
00327
00328 if ( g )
00329 g->setDifficulty( difficulty );
00330
00331 return g;
00332 }