Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

sfcave.cpp

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 
00004 #include <time.h>
00005 #include <sys/timeb.h>
00006 
00007 #include <SDL/SDL.h>
00008 #include <SDL/SDL_gfxPrimitives.h>
00009 
00010 #include "constants.h"
00011 
00012 #include "sound.h"
00013 #include "menu.h"
00014 #include "help.h"
00015 #include "game.h"
00016 #include "terrain.h"
00017 #include "random.h"
00018 #include "sfcave.h"
00019 #include "font.h"
00020 #include "settings.h"
00021 #include "util.h"
00022 
00023 #include "sfcave_game.h"
00024 #include "gates_game.h"
00025 #include "fly_game.h"
00026 
00027 void start( int argc, char *argv[] )
00028 {
00029         SFCave *app = new SFCave( argc, argv );
00030         app->mainEventLoop();
00031         delete app;
00032 }
00033 
00034 #ifdef __cplusplus
00035 extern "C"
00036 #endif
00037 int main(int argc, char *argv[])
00038 {
00039         start( argc, argv );
00040         return 0;
00041 }
00042 
00043 
00044 SFCave :: SFCave( int argc, char *argv[] )
00045 {
00046     setupOK = false;
00047 
00048         // Load settings
00049         string diff = loadSetting( "GameDifficulty", "Easy" );
00050         string game = loadSetting( "GameType", "SFCave" );
00051         musicPath = loadSetting( "MusicPath", SOUND_PATH );
00052         musicType = loadSetting( "MusicType", "mod,ogg" );
00053         bool soundOn = loadBoolSetting( "SoundOn", true );
00054         bool musicOn = loadBoolSetting( "MusicOn", true );
00055         if ( musicPath[musicPath.size()-1] != '/' )
00056            musicPath += "/";
00057         printf( "musicPath %s\n", musicPath.c_str() );
00058 
00059     // Init main SDL Library
00060         initSDL( argc, argv );
00061 
00062         // Init font handler
00063         if ( !FontHandler::init() )
00064         {
00065            printf( "Unable to initialise fonts!\n" );
00066            return;
00067         }
00068 
00069         // Init SoundHandler
00070         if ( !SoundHandler :: init() )
00071                 printf("Unable to open audio!\n");
00072 
00073         SoundHandler :: setSoundsOn( soundOn );
00074         SoundHandler :: setMusicOn( musicOn );
00075 
00076         currentGame = Game::createGame( this, WIDTH, HEIGHT, game, diff );
00077         if ( !currentGame )
00078                 currentGame = new SFCaveGame( this, WIDTH, HEIGHT, 0 );
00079         currentGame->setSeed(-1);
00080 
00081         // Create menu
00082         menu = new Menu( this );
00083 
00084         // Create help screen
00085         help = new Help( this );
00086 
00087         maxFPS = 50;
00088         showFps = false;
00089         
00090         setupOK = true;
00091 }
00092 
00093 SFCave :: ~SFCave()
00094 {
00095         if ( currentGame )
00096                 delete currentGame;
00097 
00098         if ( menu )
00099                 delete menu;
00100 
00101         if ( help )
00102                 delete help;
00103 
00104         SDL_FreeSurface( screen );
00105         FontHandler::cleanUp();
00106         SoundHandler :: cleanUp();
00107 
00108         SDL_Quit();
00109 }
00110 
00111 
00112 void SFCave :: initSDL( int argc, char *argv[] )
00113 {
00114         const SDL_VideoInfo *info;
00115         Uint8  video_bpp;
00116         Uint32 videoflags;
00117 
00118         // Initialize SDL
00119         if ( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0 ) {
00120                 fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
00121                 exit(1);
00122         }
00123 
00124         video_bpp = 16;
00125 
00126         if ( !SDL_VideoModeOK(WIDTH, HEIGHT, video_bpp, SDL_DOUBLEBUF) )
00127                 printf( "No double buffering\n" );
00128 
00129         videoflags = SDL_HWSURFACE | SDL_SRCALPHA;
00130         while ( argc > 1 )
00131         {
00132                 --argc;
00133                 if ( strcmp(argv[argc-1], "-bpp") == 0 )
00134                 {
00135                         video_bpp = atoi(argv[argc]);
00136                         --argc;
00137                 }
00138                 else if ( strcmp(argv[argc], "-hw") == 0 )
00139                 {
00140                         videoflags |= SDL_HWSURFACE;
00141                 }
00142                 else if ( strcmp(argv[argc], "-warp") == 0 )
00143                 {
00144                         videoflags |= SDL_HWPALETTE;
00145                 }
00146                 else if ( strcmp(argv[argc], "-fullscreen") == 0 )
00147                 {
00148                         videoflags |= SDL_FULLSCREEN;
00149                 }
00150                 else if ( strcmp(argv[argc], "-h") == 0 )
00151                 {
00152                         fprintf(stderr,
00153                         "Usage: %s [-bpp N] [-warp] [-hw] [-fullscreen]\n",
00154                                                                 argv[0]);
00155                         exit(1);
00156                 }
00157         }
00158 
00159         // Set 240x320 video mode
00160         if ( (screen = SDL_SetVideoMode( WIDTH,HEIGHT,video_bpp,videoflags )) == NULL )
00161         {
00162                 printf( "Couldn't set %ix%i video mode: %s\n",WIDTH,HEIGHT,SDL_GetError() );
00163                 exit(2);
00164         }
00165 
00166         // Use alpha blending
00167         //SDL_SetAlpha(screen, SDL_RLEACCEL, 0);
00168 
00169         // Set title for window
00170         SDL_WM_SetCaption("SFCave","SFCave");
00171 }
00172 
00173 void SFCave :: mainEventLoop()
00174 {
00175     if ( !setupOK )
00176         return;
00177         
00178         // Wait for a keystroke
00179         finish = false;
00180         state = 0;
00181         state = STATE_CRASHED;
00182         changeState( STATE_MENU );
00183 
00184         FPS = 0;
00185         actualFPS = 0;
00186         time1 = 0;
00187 
00188         limitFPS = true;
00189         while ( !finish )
00190         {
00191                 // calc FPS
00192                 calcFPS();
00193 
00194         SDL_FillRect( screen, 0, 0 );
00195 
00196                 handleGameState( );
00197 
00198                 SDL_Flip( screen );
00199 
00200                 if ( limitFPS )
00201                         FPSDelay();
00202                 else
00203                         SDL_Delay( 5 );
00204 
00205                 handleEvents();
00206         }
00207 }
00208 
00209 
00210 void SFCave :: handleGameState()
00211 {
00212         switch( state )
00213         {
00214                 case STATE_MENU:
00215                         SDL_FillRect( screen, 0, 0 );
00216                         menu->draw( screen );
00217                         break;
00218                 case STATE_HELP:
00219                         SDL_FillRect( screen, 0, 0 );
00220                         help->update();
00221                         help->draw( screen );
00222                         break;
00223                 case STATE_NEWGAME:
00224                         currentGame->setReplay( false );
00225                         currentGame->init();
00226                         changeState( STATE_PLAYING );
00227                         break;
00228 
00229                 case STATE_REPLAY:
00230                         currentGame->setReplay( true );
00231                         currentGame->init();
00232                         changeState( STATE_PLAYING );
00233                         break;
00234 
00235                 case STATE_PLAYING:
00236                 case STATE_CRASHING:
00237                 case STATE_CRASHED:
00238                         currentGame->update( state );
00239                         currentGame->draw( screen );
00240                         break;
00241 
00242                 case STATE_QUIT:
00243                         finish = true;
00244                         break;
00245         }
00246 }
00247 
00248 void SFCave :: handleEvents()
00249 {
00250         SDL_Event event;
00251 
00252         // Check for events
00253         while ( SDL_PollEvent(&event) )
00254         {
00255                 switch (event.type)
00256                 {
00257                         case SDL_KEYDOWN:
00258                         case SDL_KEYUP:
00259                         {
00260                                 // Escape keypress quits the app
00261                                 if ( event.key.keysym.sym == SDLK_ESCAPE )
00262                                 {
00263                                         finish = true;
00264                                         break;
00265                                 }
00266 
00267                                 if ( state == STATE_MENU )
00268                                 {
00269                                         int rc = menu->handleKeys( event.key );
00270                                         if ( rc != -1 )
00271                                                 handleMenuSelect( rc );
00272                                 }
00273                                 else if ( state == STATE_HELP )
00274                                 {
00275                                         help->handleKeys( event.key );
00276                                 }
00277                                 else if ( state == STATE_CRASHED )
00278                                 {
00279                                         if ( event.type == SDL_KEYDOWN )
00280                                         {
00281                                                 if ( event.key.keysym.sym == SDLK_UP ||
00282                                                         event.key.keysym.sym == SDLK_DOWN ||
00283                                                         event.key.keysym.sym == SDLK_SPACE )
00284                                                         changeState( STATE_NEWGAME );
00285                                                 else if ( event.key.keysym.sym == SDLK_RETURN || event.key.keysym.sym == 0 )
00286                                                 {
00287                                                         changeState( STATE_MENU );
00288                                                         menu->resetToTopMenu();
00289                                                 }
00290                                                 else if ( event.key.keysym.sym == SDLK_r )
00291                                                 {
00292                                                         changeState( STATE_REPLAY );
00293                                                 }
00294                                                 else if ( event.key.keysym.sym == SDLK_s )
00295                                                 {
00296                                                         SoundHandler :: playSound( SND_EXPLOSION );
00297                                                 }
00298                                         }
00299                                 }
00300                                 else
00301                                 {
00302                                         switch ( event.key.keysym.sym )
00303                                         {
00304                                                 case SDLK_f:
00305                                                         if ( event.type == SDL_KEYDOWN )
00306                                                                 showFps = !showFps;
00307                                                         break;
00308                                                 case SDLK_l:
00309                                                         if ( event.type == SDL_KEYDOWN )
00310                                                                 limitFPS = !limitFPS;
00311                                                         break;
00312 
00313                                                 default:
00314                                                         currentGame->handleKeys( event.key );
00315                                                         break;
00316                                         }
00317                                 }
00318 
00319                                 break;
00320                         }
00321 
00322                         case SDL_QUIT:
00323                                 finish = true;
00324                                 break;
00325                         default:
00326                                 break;
00327                 }
00328         }
00329 }
00330 
00331 void SFCave :: changeState( int s )
00332 {
00333         if ( state != s )
00334                 currentGame->stateChanged( state, s );
00335 
00336     if ( state == STATE_MENU && s == STATE_HELP )
00337         help->init();
00338     if ( state == STATE_CRASHED && s == STATE_MENU )
00339         {
00340                 SoundHandler :: stopMusic( true );
00341 
00342                 string musicFile = chooseRandomFile( musicPath, musicType );
00343         SoundHandler :: setMusicVolume( 128 );
00344                 SoundHandler :: playMusic( musicFile );
00345         }
00346     else if ( state == STATE_MENU && (s == STATE_NEWGAME || s == STATE_REPLAY) )
00347     {
00348                 SoundHandler :: stopMusic( );
00349 
00350         // Start the in game music
00351         string musicFile = INGAME_MUSIC;
00352         SoundHandler :: playMusic( musicFile );
00353         SoundHandler :: setMusicVolume( 25 );
00354     }
00355 
00356         state = s;
00357 }
00358 
00359 
00360 void SFCave :: handleMenuSelect( int menuId )
00361 {
00362         switch( menuId )
00363         {
00364                 case MENU_STARTGAME:
00365                         changeState( STATE_NEWGAME );
00366                         break;
00367 
00368                 case MENU_HELP:
00369             changeState( STATE_HELP );
00370                         break;
00371 
00372                 case MENU_QUIT:
00373                         changeState( STATE_QUIT );
00374                         break;
00375 
00376                 case MENU_PLAY_REPLAY:
00377                         if ( currentGame->isReplayAvailable() )
00378                                 changeState( STATE_REPLAY );
00379                         else
00380                                 setMenuStatusText( "No replay available yet" );
00381                         break;
00382 
00383                 case MENU_LOAD_REPLAY:
00384                 {
00385                 string replayFile = getHomeDir() + "/" + currentGame->getGameName() + ".replay";
00386 
00387                         currentGame->loadReplay( replayFile );
00388 
00389                         break;
00390                 }
00391 
00392                 case MENU_SAVE_REPLAY:
00393                 {
00394 
00395                         if ( currentGame->isReplayAvailable() )
00396                         {
00397                                 string replayFile = getHomeDir() + "/" + currentGame->getGameName() + ".replay";
00398 
00399                                 currentGame->saveReplay( replayFile );
00400                         }
00401                         else
00402                                 setMenuStatusText( "No replay available yet" );
00403 
00404                         break;
00405                 }
00406                 case MENU_CLEAR_SCORES:
00407                         break;
00408 
00409                 case MENU_GAME_SFCAVE:
00410                         if ( currentGame->getGameName() != "SFCave" )
00411                         {
00412                                 int diff = currentGame->getDifficulty();
00413                                 delete currentGame;
00414                                 currentGame = new SFCaveGame( this, WIDTH, HEIGHT, 0 );
00415                                 currentGame->setDifficulty( diff );
00416 
00417                                 saveSetting( "GameType", "SFCave" );
00418                         }
00419                         break;
00420 
00421                 case MENU_GAME_GATES:
00422                         if ( currentGame->getGameName() != "Gates" )
00423                         {
00424                                 int diff = currentGame->getDifficulty();
00425                                 delete currentGame;
00426                                 currentGame = new GatesGame( this, WIDTH, HEIGHT, 0 );
00427                                 currentGame->setDifficulty( diff );
00428 
00429                                 saveSetting( "GameType", "Gates" );
00430                         }
00431                         break;
00432                         break;
00433 
00434                 case MENU_GAME_FLY:
00435                         if ( currentGame->getGameName() != "Fly" )
00436                         {
00437                                 int diff = currentGame->getDifficulty();
00438                                 delete currentGame;
00439                                 currentGame = new FlyGame( this, WIDTH, HEIGHT, 0 );
00440                                 currentGame->setDifficulty( diff );
00441 
00442                                 saveSetting( "GameType", "Fly" );
00443                         }
00444                         break;
00445 
00446                 case MENU_DIFFICULTY_EASY:
00447                         currentGame->setDifficulty( MENU_DIFFICULTY_EASY );
00448                         saveSetting( "GameDifficulty", "Easy" );
00449                         break;
00450 
00451                 case MENU_DIFFICULTY_NORMAL:
00452                         currentGame->setDifficulty( MENU_DIFFICULTY_NORMAL );
00453                         saveSetting( "GameDifficulty", "Medium" );
00454                         break;
00455 
00456                 case MENU_DIFFICULTY_HARD:
00457                         currentGame->setDifficulty( MENU_DIFFICULTY_HARD );
00458                         saveSetting( "GameDifficulty", "Hard" );
00459                         break;
00460 
00461                 case MENU_DIFFICULTY_CUSTOM:
00462                         currentGame->setDifficulty( MENU_DIFFICULTY_CUSTOM );
00463                         saveSetting( "GameDifficulty", "Custom" );
00464                         break;
00465 
00466                 case MENU_SOUND_ON:
00467                         SoundHandler :: setSoundsOn( true );
00468                         saveSetting( "SoundOn", "true" );
00469                         break;
00470 
00471                 case MENU_SOUND_OFF:
00472                         SoundHandler :: setSoundsOn( false );
00473                         saveSetting( "SoundOn", "false" );
00474                         break;
00475 
00476                 case MENU_MUSIC_ON:
00477                         SoundHandler :: setMusicOn( true );
00478                         saveSetting( "MusicOn", "true" );
00479                         break;
00480 
00481                 case MENU_MUSIC_OFF:
00482                         SoundHandler :: setMusicOn( false );
00483                         saveSetting( "MusicOn", "false" );
00484                         break;
00485 
00486         case MENU_CUSTOM_THRUST:
00487             customPlayerMenuVal = PLAYER_THRUST;
00488             origValue = currentGame->getPlayer()->getValue( customPlayerMenuVal );
00489                         setMenuStatusText( currentGame->getPlayer()->getValueString( customPlayerMenuVal ) );
00490             break;
00491         case MENU_CUSTOM_GRAVITY:
00492             customPlayerMenuVal = PLAYER_GRAVITY;
00493             origValue = currentGame->getPlayer()->getValue( customPlayerMenuVal );
00494                         setMenuStatusText( currentGame->getPlayer()->getValueString( customPlayerMenuVal ) );
00495             break;
00496         case MENU_CUSTOM_MAXSPEEDUP:
00497             customPlayerMenuVal = PLAYER_MAX_SPEED_UP;
00498             origValue = currentGame->getPlayer()->getValue( customPlayerMenuVal );
00499                         setMenuStatusText( currentGame->getPlayer()->getValueString( customPlayerMenuVal ) );
00500             break;
00501         case MENU_CUSTOM_MAXSPEEDDOWN:
00502             customPlayerMenuVal = PLAYER_MAX_SPEED_DOWN;
00503             origValue = currentGame->getPlayer()->getValue( customPlayerMenuVal );
00504                         setMenuStatusText( currentGame->getPlayer()->getValueString( customPlayerMenuVal ) );
00505             break;
00506         case MENU_CUSTOM_INCREASE:
00507             currentGame->getPlayer()->incValue( customPlayerMenuVal );
00508                         setMenuStatusText( currentGame->getPlayer()->getValueString( customPlayerMenuVal ) );
00509             break;
00510         case MENU_CUSTOM_DECREASE:
00511             currentGame->getPlayer()->decValue( customPlayerMenuVal );
00512                         setMenuStatusText( currentGame->getPlayer()->getValueString( customPlayerMenuVal ) );
00513             break;
00514         case MENU_CUSTOM_SAVE:
00515         {
00516             // save settings
00517             string key = currentGame->getGameName() + "_custom_player_" + currentGame->getPlayer()->getValueTypeString( customPlayerMenuVal );
00518                         saveSetting( key, currentGame->getPlayer()->getValue( customPlayerMenuVal ) );
00519 
00520             break;
00521         }
00522         case MENU_CUSTOM_CANCEL:
00523             currentGame->getPlayer()->setValue( customPlayerMenuVal, origValue );
00524             break;
00525 
00526                 default:
00527                         break;
00528         }
00529 }
00530 
00531 void SFCave :: setMenuStatusText( string statusText )
00532 {
00533         menu->setStatusText( statusText );
00534 }
00535 
00536 
00537 void SFCave :: saveSetting( string key, string val )
00538 {
00539         Settings cfg( "sfcave-sdl" );
00540         cfg.writeSetting( key, val );
00541 }
00542 
00543 void SFCave :: saveSetting( string key, int val )
00544 {
00545         Settings cfg( "sfcave-sdl" );
00546         cfg.writeSetting( key, val );
00547 }
00548 
00549 void SFCave :: saveSetting( string key, long val )
00550 {
00551         Settings cfg( "sfcave-sdl" );
00552         cfg.writeSetting( key, val );
00553 }
00554 
00555 void SFCave :: saveSetting( string key, double val )
00556 {
00557         Settings cfg( "sfcave-sdl" );
00558         cfg.writeSetting( key, val );
00559 }
00560 
00561 string SFCave :: loadSetting( string key, string defaultVal )
00562 {
00563         string val;
00564         Settings cfg( "sfcave-sdl" );
00565         cfg.readSetting( key, val );
00566 
00567         if ( val == "" )
00568                 val = defaultVal;
00569 
00570         return val;
00571 }
00572 
00573 bool SFCave :: loadBoolSetting( string key, bool defaultVal )
00574 {
00575         bool val = defaultVal;
00576         Settings cfg( "sfcave-sdl" );
00577         cfg.readSetting( key, val );
00578 
00579         return val;
00580 }
00581 
00582 int SFCave :: loadIntSetting( string key, int defaultVal )
00583 {
00584         int val = defaultVal;
00585         Settings cfg( "sfcave-sdl" );
00586         cfg.readSetting( key, val );
00587 
00588         return val;
00589 }
00590 
00591 double SFCave :: loadDoubleSetting( string key, double defaultVal )
00592 {
00593         double val = defaultVal;
00594         Settings cfg( "sfcave-sdl" );
00595         cfg.readSetting( key, val );
00596 
00597         return val;
00598 }
00599 
00600 
00601 void SFCave :: calcFPS()
00602 {
00603         struct timeb tp;
00604         ftime( &tp );
00605         start =(tp.time%10000)*10000 + tp.millitm;
00606         if ( start - time1 >= 1000 )
00607         {
00608                 actualFPS = FPS;
00609                 FPS = 0;
00610                 time1 = start;
00611         }
00612         else
00613                 FPS ++;
00614 }
00615 
00616 void SFCave :: FPSDelay()
00617 {
00618         struct timeb tp;
00619         // Slow down polling - limit to x FPS
00620         ftime( &tp );
00621         end = abs((tp.time%10000)*10000 + tp.millitm);
00622         if ( end-start < (1000/maxFPS) )
00623         {
00624                 if ( (1000/maxFPS)-(end-start) > 500 )
00625                 {
00626                         // Should never happen but in case it does sleep for 5 seconds
00627                         printf( "WARNING WILL ROBINSON! delay = %ld - start %ld, end %ld\n", (1000/maxFPS)-(end-start), start, end );
00628                         SDL_Delay( 5 );
00629                 }
00630                 else
00631                         SDL_Delay((1000/maxFPS)-(end-start) );
00632         }
00633 }

Generated on Sat Nov 5 16:17:25 2005 for OPIE by  doxygen 1.4.2