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 #include <math.h>
00004 #include <time.h>
00005 
00006 #include <opie2/oapplicationfactory.h>
00007 #include <qpe/qpeapplication.h>
00008 #include <qpe/config.h>
00009 #include <qpe/global.h>
00010 
00011 #include <qdir.h>
00012 
00013 #include "helpwindow.h"
00014 #include "sfcave.h"
00015 
00016 #define CAPTION "SFCave 1.13 by AndyQ"
00017 
00018 #define UP_THRUST               0.6
00019 #define NO_THRUST               0.8
00020 #define MAX_DOWN_THRUST         4.0
00021 #define MAX_UP_THRUST           -3.5
00022 
00023 // States
00024 #define STATE_BOSS              0
00025 #define STATE_RUNNING           1
00026 #define STATE_CRASHING          2
00027 #define STATE_CRASHED           3
00028 #define STATE_NEWGAME           4
00029 #define STATE_MENU              5
00030 #define STATE_REPLAY            6
00031 
00032 // Menus
00033 #define MENU_MAIN_MENU          0
00034 #define MENU_OPTIONS_MENU       1
00035 #define MENU_REPLAY_MENU        2
00036 
00037 // Main Menu Options
00038 #define MENU_START_GAME         0
00039 #define MENU_REPLAY             1
00040 #define MENU_OPTIONS            2
00041 #define MENU_HELP               3
00042 #define MENU_QUIT               4
00043 
00044 // Option Menu Options
00045 #define MENU_GAME_TYPE          0
00046 #define MENU_GAME_DIFFICULTY    1
00047 #define MENU_CLEAR_HIGHSCORES   2
00048 #define MENU_BACK               3
00049 
00050 // Replay Menu Options
00051 #define MENU_REPLAY_START       0
00052 #define MENU_REPLAY_LOAD        1
00053 #define MENU_REPLAY_SAVE        2
00054 #define MENU_REPLAY_BACK        3
00055 
00056 
00057 #define NR_GAME_DIFFICULTIES    3
00058 #define NR_GAME_TYPES           3
00059 
00060 #define DIFICULTY_EASY          0
00061 #define DIFICULTY_NORMAL        1
00062 #define DIFICULTY_HARD          2
00063 #define EASY                    "Easy"
00064 #define NORMAL                  "Normal"
00065 #define HARD                    "Hard"
00066 
00067 #define SFCAVE_GAME_TYPE        0
00068 #define GATES_GAME_TYPE         1
00069 #define FLY_GAME_TYPE           2
00070 #define SFCAVE_GAME             "SFCave"
00071 #define GATES_GAME              "Gates"
00072 #define FLY_GAME                "Fly"
00073 #define CURRENT_GAME_TYPE       gameTypes[currentGameType]
00074 #define CURRENT_GAME_DIFFICULTY difficultyOption[currentGameDifficulty];
00075 
00076 QString SFCave::dificultyOption[] = { EASY, NORMAL, HARD };
00077 QString SFCave::gameTypes[] = { SFCAVE_GAME, GATES_GAME, FLY_GAME };
00078 
00079 QString SFCave::menuOptions[NR_MENUS][MAX_MENU_OPTIONS] = { { "Start Game", "Replays", "Options", "Help", "Quit", "", "", "" },
00080                                     { "Game Type - %s", "Game Difficulty - %s", "Clear High Scores for this game", "Back", "", "", "", "" },
00081                                     { "Play Reply", "Load Replay", "Save Replay", "Back", "", "", "", "" } };
00082 
00083 int SFCave::nrMenuOptions[NR_MENUS] = { 5, 4, 4 };
00084 int SFCave ::currentMenuOption[NR_MENUS] = { 0, 0, 0 };
00085                                     
00086 #define UP_THRUST               0.6
00087 #define NO_THRUST               0.8
00088 #define MAX_DOWN_THRUST         4.0
00089 #define MAX_UP_THRUST           -3.5
00090 double SFCave::UpThrustVals[3][3]               = {{ 0.6,   0.6, 0.6 },     // SFCave
00091                                                    { 0.6,   0.6, 0.8 },     // Gates
00092                                                    { 0.4,   0.7, 1.0 } };   // Fly
00093                                                    
00094 double SFCave::DownThrustVals[3][3]             = {{ 0.8,   0.8, 0.8 },     // SFCave
00095                                                    { 0.8,   0.8, 1.0 },     // Gates
00096                                                    { 0.4,   0.7, 1.0 } };   // Fly
00097                                                    
00098 double SFCave::MaxUpThrustVals[3][3]            = {{ -3.5, -3.5, -3.5 },    // SFCave
00099                                                    { -3.5, -4.0, -5.0 },    // Gates
00100                                                    { -3.5, -4.0, -5.0 } };  // Fly
00101                                                    
00102 double SFCave::MaxDownThrustVals[3][3]          = {{ 4.0,   4.0, 4.0 },     // SFCave
00103                                                    { 4.0,   5.0, 5.5 },     // Gates
00104                                                    { 3.5,   4.0, 5.0 } };   // Fly
00105 
00106 int SFCave::flyEasyScores[7][3] = { { 0, 10, 5 },
00107                                    { 10, 20, 3 },
00108                                    { 20, 30, 2 },
00109                                    { 30, 40, 1 },
00110                                    { 50, 70, -2 },
00111                                    { 70, 300, -5 },
00112                                    { -1, -1, -1 } };
00113 int SFCave::flyNormalScores[7][3] = { { 0, 10, 5 },
00114                                      { 10, 20, 3 },
00115                                      { 20, 30, 2 },
00116                                      { 30, 40, 1 },
00117                                      { 50, 70, -2 },
00118                                      { 70, 300, -5 },
00119                                      { -1, -1, -1 } };
00120 int SFCave::flyHardScores[7][3] = { { 0, 20, 5 },
00121                                    { 20, 40, 3 },
00122                                    { 40, 100, 1 },
00123                                    { 100, 150, -2 },
00124                                    { 150, 300, -5 },
00125                                    { -1, -1, -1 } };
00126 
00127 int SFCave::initialGateGaps[]           = { 75, 50, 25 };
00128 
00129 
00130 #define FLYSCORES( x, y )  (*(flyScores + ((x)*3) + y))
00131 bool movel;
00132 
00133 
00134 OPIE_EXPORT_APP( Opie::Core::OApplicationFactory<SFCave> )
00135 
00136 SFCave :: SFCave( QWidget *w, const char *name, WFlags fl )
00137     : QMainWindow( w, name, fl )
00138 
00139 {
00140     showMaximized();
00141     movel = true;
00142     int spd = 3;
00143     
00144     
00145     replayIt = 0;
00146 
00147     replayFile = Global::applicationFileName("sfcave", "replay");
00148 
00149     sWidth = width();
00150     sHeight = height();
00151     segSize = sWidth/(MAPSIZE-1)+1;
00152 
00153     currentMenuNr = 0;
00154     currentGameType = 0;
00155     currentGameDifficulty = 0;
00156 
00157     setCaption( CAPTION );
00158     showScoreZones = false;
00159 
00160 #ifdef QWS
00161     Config cfg( "sfcave" );
00162     cfg.setGroup( "settings" );
00163     QString key = "highScore_";
00164 
00165     for ( int i = 0 ; i < 3 ; ++i )
00166     {
00167         for ( int j = 0 ; j < 3 ; ++j )
00168             highestScore[i][j] = cfg.readNumEntry( key + gameTypes[i] + "_" + dificultyOption[j], 0 );
00169     }
00170     
00171     currentGameType = cfg.readNumEntry( "gameType", 0 );
00172     currentGameDifficulty = cfg.readNumEntry( "difficulty", 0 );
00173 #endif
00174     speed = spd; // Change to 2 for PC
00175     press = false;
00176     showEyeCandy = false;
00177 
00178     offscreen = new QPixmap( sWidth, sHeight );
00179     offscreen->fill( Qt::black );
00180 
00181 //    setUp();
00182     crashLineLength = -1;
00183     state = STATE_MENU;
00184     prevState = STATE_MENU;
00185 
00186     gameTimer = new QTimer( this, "game timer" );
00187     connect( gameTimer, SIGNAL( timeout() ),
00188              this, SLOT( run() ) );
00189              
00190     QTimer::singleShot(0, this, SLOT(start()));
00191 }
00192 
00193 SFCave :: ~SFCave()
00194 {
00195 }
00196 
00197 void SFCave :: start()
00198 {
00199     gameTimer->start( 10 );
00200 
00201 }
00202 
00203 void SFCave :: setSeed( int seed )
00204 {
00205     if ( seed == -1 )
00206         currentSeed = ((unsigned long) time((time_t *) NULL));
00207     else
00208         currentSeed = seed;
00209     PutSeed( currentSeed );
00210 }
00211     
00212 int SFCave :: nextInt( int range )
00213 {
00214     int val = (int)(Random( ) * range);
00215 
00216     return val;
00217     
00218 }
00219 
00220 void SFCave :: setUp()
00221 {
00222     score = 0;
00223     offset = 0;
00224     nrFrames = 0;
00225     dir = 1;
00226     thrust = 0;
00227     startScoring = false;
00228     press = false;
00229 
00230     if ( CURRENT_GAME_TYPE == SFCAVE_GAME )
00231     {
00232         thrustUp = UpThrustVals[SFCAVE_GAME_TYPE][currentGameDifficulty];;
00233         noThrust = DownThrustVals[SFCAVE_GAME_TYPE][currentGameDifficulty];;
00234         maxUpThrust = MaxUpThrustVals[SFCAVE_GAME_TYPE][currentGameDifficulty];;
00235         maxDownThrust = MaxDownThrustVals[SFCAVE_GAME_TYPE][currentGameDifficulty];;
00236 
00237         if ( currentGameDifficulty == DIFICULTY_EASY )
00238             gateDistance = 100;
00239         else if ( currentGameDifficulty == DIFICULTY_NORMAL )
00240             gateDistance = 60;
00241         else
00242             gateDistance = 40;
00243     }
00244     else if ( CURRENT_GAME_TYPE == GATES_GAME )
00245     {
00246         thrustUp = UpThrustVals[GATES_GAME_TYPE][currentGameDifficulty];;
00247         noThrust = DownThrustVals[GATES_GAME_TYPE][currentGameDifficulty];;
00248         maxUpThrust = MaxUpThrustVals[GATES_GAME_TYPE][currentGameDifficulty];;
00249         maxDownThrust = MaxDownThrustVals[GATES_GAME_TYPE][currentGameDifficulty];;
00250         gateDistance = 75;
00251         nextGate = nextInt( 50 ) + gateDistance;
00252     }
00253     else
00254     {
00255         thrustUp = UpThrustVals[FLY_GAME_TYPE][currentGameDifficulty];
00256         noThrust = DownThrustVals[FLY_GAME_TYPE][currentGameDifficulty];
00257         maxUpThrust = MaxUpThrustVals[FLY_GAME_TYPE][currentGameDifficulty];
00258         maxDownThrust = MaxDownThrustVals[FLY_GAME_TYPE][currentGameDifficulty];
00259 
00260         if ( currentGameDifficulty == DIFICULTY_EASY )
00261             flyScores = (int*)flyEasyScores;
00262         else if ( currentGameDifficulty == DIFICULTY_NORMAL )
00263             flyScores = (int*)flyNormalScores;
00264         else
00265             flyScores = (int*)flyHardScores;
00266     }
00267     
00268     crashLineLength = 0;
00269     lastGateBottomY = 0;
00270 
00271     user.setRect( 50, sWidth/2, 4, 4 );
00272 
00273     blockWidth = 20;
00274     blockHeight = 70;
00275     gapHeight = initialGateGaps[currentGameDifficulty];
00276 
00277     for ( int i = 0 ; i < TRAILSIZE ; ++i )
00278     {
00279         trail[i].setX( -1 );
00280         trail[i].setY( 0 );
00281     }
00282 
00283     if ( CURRENT_GAME_TYPE != FLY_GAME )
00284     {
00285         maxHeight = 50;
00286         
00287         mapTop[0] = (int)(nextInt(50)) + 5;
00288         mapBottom[0] = (int)(nextInt(50)) + 5;
00289         for ( int i = 1 ; i < MAPSIZE ; ++i )
00290             setPoint( i );
00291     }
00292     else
00293     {
00294         maxHeight = 100;
00295 
00296         for ( int i = 0 ; i < MAPSIZE ; ++i )
00297             mapBottom[i] = sHeight - 10;
00298     }
00299     for ( int i = 0 ; i < BLOCKSIZE ; ++i )
00300         blocks[i].setY( -1 );
00301 
00302 }
00303 
00304 void SFCave :: run()
00305 {
00306     switch ( state )
00307     {
00308         case STATE_MENU:
00309             displayMenu();
00310             break;
00311         case STATE_NEWGAME:
00312             setSeed( -1 );
00313             setUp();
00314             draw();
00315             state = STATE_RUNNING;
00316             replay = false;
00317             replayList.clear();
00318             break;
00319         case STATE_REPLAY:
00320             setSeed( currentSeed );
00321             setUp();
00322             draw();
00323             state = STATE_RUNNING;
00324             replay = true;
00325             if ( replayIt )
00326                 delete replayIt;
00327             replayIt = new QListIterator<int>( replayList );
00328             break;
00329         case STATE_BOSS:
00330             drawBoss();
00331             break;
00332 
00333         case STATE_CRASHING:
00334         case STATE_CRASHED:
00335             press = false;
00336             draw();
00337             break;
00338 
00339         case STATE_RUNNING:
00340         {
00341             if ( nrFrames % 2 == 0 )
00342                 handleKeys();
00343 
00344             // Apply Game rules
00345             nrFrames ++;
00346 
00347             if ( replay )
00348             {
00349                 while( replayIt->current() && *(replayIt->current()) == nrFrames )
00350                 {
00351                     press = !press;
00352                     ++(*replayIt);
00353                 }
00354             }
00355             
00356             if ( CURRENT_GAME_TYPE == SFCAVE_GAME )
00357                 handleGameSFCave();
00358             else if ( CURRENT_GAME_TYPE == GATES_GAME )
00359                 handleGameGates();
00360             else if ( CURRENT_GAME_TYPE == FLY_GAME )
00361                 handleGameFly();
00362 
00363             draw();
00364             break;
00365         }
00366     }
00367 }
00368 
00369 void SFCave :: handleGameSFCave()
00370 {
00371     // Update score
00372     if ( nrFrames % 5 == 0 )
00373         score ++;
00374 
00375     if ( nrFrames % 500 == 0 )
00376     {
00377         if ( maxHeight < sHeight - 100 )
00378         {
00379             maxHeight += 10;
00380 
00381             // Reduce block height
00382             if ( maxHeight > sHeight - 150 )
00383                 blockHeight -= 5;
00384         }
00385     }
00386 
00387     if ( nrFrames % gateDistance == 0 )
00388         addBlock();
00389 
00390     if ( checkCollision() )
00391     {
00392         if ( score > highestScore[currentGameType][currentGameDifficulty] )
00393         {
00394             highestScore[currentGameType][currentGameDifficulty] = score;
00395             saveScore();
00396         }
00397         state = STATE_CRASHING;
00398     }
00399     else
00400     {
00401         moveLandscape();
00402     }
00403 
00404 }
00405 
00406 
00407 void SFCave :: handleGameGates()
00408 {
00409     // Update score
00410     if ( nrFrames % 5 == 0 )
00411         score ++;
00412 
00413     // Slightly random gap distance
00414     if ( nrFrames >= nextGate )
00415     {
00416         nextGate = nrFrames + nextInt( 50 ) + gateDistance;
00417         addGate();
00418     }
00419 
00420     if ( nrFrames % 500 == 0 )
00421     {
00422         if ( gapHeight > 75 )
00423             gapHeight -= 5;
00424     }
00425 
00426     if ( checkCollision() )
00427     {
00428         if ( score > highestScore[currentGameType][currentGameDifficulty] )
00429         {
00430             highestScore[currentGameType][currentGameDifficulty] = score;
00431             saveScore();
00432         }
00433         state = STATE_CRASHING;
00434     }
00435     else
00436     {
00437         moveLandscape();
00438     }
00439 
00440 }
00441 
00442 void SFCave :: handleGameFly()
00443 {
00444     int diff = mapBottom[10] - user.y();
00445 
00446     if ( nrFrames % 4 == 0 )
00447     {
00448         if ( !startScoring )
00449         {
00450             if ( diff < 40 )
00451                 startScoring = true;
00452         }
00453 
00454         if ( startScoring )
00455         {
00456             // Update score
00457             // get distance between landscape and ship
00458 
00459             // the closer the difference is to 0 means more points
00460             for ( int i = 0 ; i < 10 && FLYSCORES( i, 0 ) != -1 ; ++i )
00461             {
00462                 if ( FLYSCORES( i, 0 ) <= diff && FLYSCORES(i, 1 ) > diff )
00463                 {
00464                     score += FLYSCORES( i, 2 );
00465                     break;
00466                 }
00467             }
00468         }
00469     }
00470 
00471     if ( checkFlyGameCollision() )
00472     {
00473         if ( score > highestScore[currentGameType][currentGameDifficulty] )
00474         {
00475             highestScore[currentGameType][currentGameDifficulty] = score;
00476             saveScore();
00477         }
00478         state = STATE_CRASHING;
00479     }
00480     else
00481     {
00482         moveFlyGameLandscape();
00483     }
00484 }
00485 
00486 bool SFCave :: checkFlyGameCollision()
00487 {
00488     if ( (user.y() + user.width()) >= mapBottom[11] )
00489         return true;
00490 
00491     return false;
00492 }
00493 
00494 void SFCave :: moveFlyGameLandscape()
00495 {
00496     offset++;
00497 
00498     if ( offset >= segSize )
00499     {
00500         offset = 0;
00501         for ( int i = 0 ; i < MAPSIZE-speed ; ++i )
00502             mapBottom[i] = mapBottom[i+speed];
00503 
00504         for ( int i = speed ; i > 0 ; --i )
00505             setFlyPoint( MAPSIZE-i );
00506     }
00507 }
00508 
00509 void SFCave :: setFlyPoint( int point )
00510 {
00511     static int fly_difficulty_levels[] = { 5, 10, 15 };
00512     if ( nextInt(100) >= 75 )
00513         dir *= -1;
00514 
00515     int prevPoint = mapBottom[point-1];
00516     
00517     int nextPoint = prevPoint + (dir * nextInt( fly_difficulty_levels[currentGameDifficulty] ) );
00518 
00519     if ( nextPoint > sHeight )
00520     {
00521         nextPoint = sHeight;
00522         dir *= -1;
00523     }
00524     else if ( nextPoint < maxHeight )
00525     {
00526         nextPoint = maxHeight;
00527         dir *= 1;
00528     }
00529 
00530     mapBottom[point] = nextPoint;
00531 }
00532 
00533 bool SFCave :: checkCollision()
00534 {
00535     if ( (user.y() + user.width()) >= mapBottom[11] || user.y() <= mapTop[11] )
00536         return true;
00537 
00538     for ( int i = 0 ; i < BLOCKSIZE ; ++i )
00539     {
00540         if ( blocks[i].y() != -1 )
00541         {
00542             if ( blocks[i].intersects( user ) )
00543                 return true;
00544         }
00545     }
00546     return false;
00547 }
00548 
00549 void SFCave :: moveLandscape()
00550 {
00551     offset++;
00552 
00553     if ( offset >= segSize )
00554     {
00555         offset = 0;
00556         for ( int i = 0 ; i < MAPSIZE-speed ; ++i )
00557         {
00558             mapTop[i] = mapTop[i+speed];
00559             mapBottom[i] = mapBottom[i+speed];
00560         }
00561 
00562         for ( int i = speed ; i > 0 ; --i )
00563             setPoint( MAPSIZE-i );
00564     }
00565 
00566     for ( int i = 0 ; i < BLOCKSIZE ; ++i )
00567     {
00568         if ( blocks[i].y() != -1 )
00569         {
00570             blocks[i].moveBy( -speed, 0 );
00571             if ( blocks[i].x() + blocks[i].width() < 0 )
00572                 blocks[i].setY( -1 );
00573         }
00574     }
00575 }
00576 
00577 void SFCave :: addBlock()
00578 {
00579     for ( int i = 0 ; i < BLOCKSIZE ; ++i )
00580     {
00581         if ( blocks[i].y() == -1 )
00582         {
00583             int x = sWidth;
00584 
00585             int y = mapTop[50] + (int)(nextInt(mapBottom[50] - mapTop[50] - blockHeight));
00586 
00587             blocks[i].setRect( x, y, blockWidth, blockHeight );
00588 
00589             break;
00590         }
00591     }
00592 }
00593 
00594 void SFCave :: addGate()
00595 {
00596     for ( int i = 0 ; i < BLOCKSIZE ; ++i )
00597     {
00598         if ( blocks[i].y() == -1 )
00599         {
00600             int x1 = sWidth;
00601             int y1 = mapTop[50];
00602             int b1Height = nextInt(mapBottom[50] - mapTop[50] - gapHeight);
00603 
00604             // See if height between last gate and this one is too big
00605             if ( b1Height - 100 > lastGateBottomY )
00606                 b1Height -= 25;
00607             else if ( b1Height + 100 < lastGateBottomY )
00608                 b1Height += 25;
00609             lastGateBottomY = b1Height;
00610 
00611 
00612             int x2 = sWidth;
00613             int y2 = y1 + b1Height + gapHeight;
00614             int b2Height = mapBottom[50] - y2;
00615             
00616 
00617             blocks[i].setRect( x1, y1, blockWidth, b1Height );
00618             blocks[i+1].setRect( x2, y2, blockWidth, b2Height );
00619 
00620             break;
00621         }
00622     }
00623 }
00624 
00625 void SFCave :: setPoint( int point )
00626 {
00627     if ( nextInt(100) >= 80 )
00628         dir *= -1;
00629 
00630     mapTop[point] = mapTop[point-1] + (dir * nextInt( 5 ) );
00631     if ( mapTop[point] < 0 )
00632     {
00633         mapTop[point] = 0;
00634         dir *= -1;
00635     }
00636     else if ( mapTop[point] >= maxHeight )
00637     {
00638         mapTop[point] = maxHeight;
00639         dir *= -1;
00640     }
00641 
00642 //    mapBottom[point] = sHeight - (maxHeight - mapBottom[point]);
00643     mapBottom[point] = sHeight - (maxHeight - mapTop[point]);
00644 }
00645 
00646 void SFCave :: drawBoss()
00647 {
00648     offscreen->fill( Qt::black );
00649 
00650     bitBlt( this, 0, 0, offscreen, 0, 0, sWidth, sHeight, Qt::CopyROP, true );
00651 }
00652 
00653 void SFCave :: draw()
00654 {
00655     //printf( "Paint\n" );
00656     offscreen->fill( Qt::black );
00657 
00658     QPainter p( offscreen );
00659     QFontMetrics fm = p.fontMetrics();
00660     p.setPen( Qt::white );
00661 
00662     for ( int i = 0 ; i < MAPSIZE -3; ++i )
00663     {
00664         // Only display top landscape if not running FLY_GAME
00665         if ( CURRENT_GAME_TYPE != FLY_GAME )
00666             p.drawLine( (i*segSize) - (offset*speed), mapTop[i], ((i+1)*segSize)-(offset*speed), mapTop[i+1] );
00667             
00668         p.drawLine( (i*segSize) - (offset*speed), mapBottom[i], ((i+1)*segSize)-(offset*speed), mapBottom[i+1] );
00669 
00670         if ( CURRENT_GAME_TYPE == FLY_GAME && showScoreZones )
00671         {
00672             p.setPen( Qt::blue );
00673             for ( int j = 1 ; j < 10 && FLYSCORES( j, 0 ) != -1 ; ++j )
00674             {
00675                 if ( FLYSCORES( j, 2 ) < 0 )
00676                     p.setPen( Qt::red );
00677 
00678                 p.drawLine( (i*segSize) - (offset*speed), mapBottom[i]-FLYSCORES( j, 0 ), ((i+1)*segSize)-(offset*speed), mapBottom[i+1]-FLYSCORES( j, 0 ) );
00679             }
00680 
00681             p.setPen( Qt::white );
00682         }        
00683     }
00684 
00685     // Uncomment this to show user segment (usful for checking collision boundary with landscape
00686 //    p.setPen( Qt::red );
00687 //    p.drawLine( (11*segSize) - (offset*speed), 0, ((11)*segSize)-(offset*speed), sHeight );
00688 //    p.setPen( Qt::white );
00689     
00690     // Draw user
00691     p.drawRect( user );
00692 
00693     // Draw trails
00694     for ( int i = 0 ; i < TRAILSIZE ; ++i )
00695         if ( trail[i].x() >= 0 )
00696         {
00697             if ( showEyeCandy )
00698                 p.setPen( Qt::white.light((int)(100.0-3*(user.x()/100.0)* (user.x()-trail[i].x())) ) );
00699             p.drawRect( trail[i].x(), trail[i].y(), 2, 2 );
00700         }
00701 
00702     p.setPen( Qt::white );
00703     // Draw blocks
00704     for ( int i = 0 ; i < BLOCKSIZE ; ++i )
00705         if ( blocks[i].y() != -1 )
00706         {
00707             p.fillRect( blocks[i], Qt::black );
00708             p.drawRect( blocks[i] );
00709         }
00710 
00711     // draw score
00712     QString s;
00713     s.sprintf( "score %06d   high score %06d", score, highestScore[currentGameType][currentGameDifficulty] );
00714     p.drawText( 5, 10, s );
00715 
00716 
00717     if ( state == STATE_CRASHING || state == STATE_CRASHED )
00718     {
00719         // add next crash line
00720 
00721         if ( crashLineLength != -1 )
00722         {
00723             for ( int i = 0 ; i < 36 ; ++i )
00724             {
00725                 int x = (int)(user.x() + (crashLineLength+nextInt(10)) * cos( (M_PI/180) * (10.0 * i) ) );
00726                 int y = (int)(user.y() + (crashLineLength+nextInt(10)) * sin( (M_PI/180) * (10.0 * i) ) );            p.drawLine( user.x(), user.y(), x, y );
00727             }
00728         }
00729 
00730         if ( state == STATE_CRASHING && crashLineLength >= 15 ) //|| crashLineLength == -1) )
00731             state = STATE_CRASHED;
00732 
00733         if ( state == STATE_CRASHED )
00734         {
00735             QString text = "Press up or down to start";
00736             p.drawText( (sWidth/2) - (fm.width( text )/2), 120, text );
00737 
00738             text = "Press OK for menu";
00739             p.drawText( (sWidth/2) - (fm.width( text )/2), 135, text );
00740 /*
00741             text = "Press r to replay";
00742             p.drawText( (sWidth/2) - (fm.width( text )/2), 150, text );
00743                                                            
00744             text = "Press s to save the replay";
00745             p.drawText( (sWidth/2) - (fm.width( text )/2), 165, text );
00746 
00747             text = "Press r to load a saved replay";
00748             p.drawText( (sWidth/2) - (fm.width( text )/2), 180, text );
00749 */
00750         }
00751         else
00752             crashLineLength ++;
00753     }
00754 
00755     p.end();
00756     bitBlt( this, 0, 0, offscreen, 0, 0, sWidth, sHeight, Qt::CopyROP, true );
00757     //printf( "endpaint\n" );
00758 }
00759 
00760 void SFCave :: handleKeys()
00761 {
00762     // Find enpty trail and move others
00763     bool done = false;
00764     for ( int i = 0 ; i < TRAILSIZE ; ++i )
00765     {
00766         if ( trail[i].x() < 0 )
00767         {
00768             if ( !done )
00769             {
00770                 trail[i].setX( user.x() - 5 );
00771                 trail[i].setY( user.y() );
00772                 done = true;
00773             }
00774         }
00775         else
00776         {
00777             trail[i].setX( trail[i].x() - (2) );
00778         }
00779     }
00780 
00781     if ( speed <= 3 )
00782     {
00783         if ( press )
00784             thrust -= thrustUp;
00785         else
00786             thrust += noThrust;
00787 
00788         if ( thrust > maxDownThrust )
00789             thrust = maxDownThrust;
00790         else if ( thrust < maxUpThrust )
00791             thrust = maxUpThrust;
00792     }
00793     else
00794     {
00795         if ( press )
00796             thrust -= 0.5;
00797         else
00798             thrust += 0.8;
00799 
00800         if ( thrust > 5.0 )
00801             thrust = 5.0;
00802         else if ( thrust < -3.5 )
00803             thrust = -3.5;
00804     }
00805     user.moveBy( 0, (int)thrust );
00806 }
00807 
00808 void SFCave :: keyPressEvent( QKeyEvent *e )
00809 {
00810     if ( state == STATE_MENU )
00811         handleMenuKeys( e );
00812     else
00813     {
00814         switch( e->key() )
00815         {
00816             case Qt::Key_Up:
00817             case Qt::Key_F9:
00818             case Qt::Key_Space:
00819                 if ( state == STATE_RUNNING )
00820                 {
00821                     if ( !replay && !press )
00822                     {
00823                         press = true;
00824                         replayList.append( new int( nrFrames ) );
00825                     }
00826                 }
00827                 else if ( state == STATE_CRASHED )
00828                 {
00829                     if ( e->key() == Key_Up )
00830                         state = STATE_NEWGAME;
00831                 }
00832                 
00833                 break;
00834             case Qt::Key_M:
00835             case Qt::Key_Return:
00836             case Qt::Key_Enter:
00837                 if ( state == STATE_CRASHED )
00838                 {
00839                     state = STATE_MENU;
00840                     currentMenuNr = 0;
00841                     currentMenuOption[currentMenuNr] = 0;
00842                 }
00843                 break;
00844 
00845             case Qt::Key_Z:
00846                 showScoreZones = !showScoreZones;
00847                 break;
00848                 
00849            default:
00850                 e->ignore();
00851                 break;
00852         }
00853     }
00854 }
00855 
00856 void SFCave :: keyReleaseEvent( QKeyEvent *e )
00857 {
00858     if ( state == STATE_MENU )
00859     {
00860     }
00861     else
00862     {
00863         switch( e->key() )
00864         {
00865             case Qt::Key_F9:
00866             case Qt::Key_Space:
00867             case Qt::Key_Up:
00868                 if ( state == STATE_RUNNING )
00869                 {
00870                     if ( !replay && press )
00871                     {
00872                         press = false;
00873                         replayList.append( new int( nrFrames ) );
00874                     }
00875                 }
00876                 break;
00877 
00878             case Qt::Key_E:
00879                 showEyeCandy = !showEyeCandy;
00880                 break;
00881                 
00882             case Qt::Key_R:
00883                 if ( state == STATE_CRASHED )
00884                     state = STATE_REPLAY;
00885                 break;
00886 
00887             case Qt::Key_Down:
00888                 if ( state == STATE_CRASHED )
00889                     state = STATE_NEWGAME;
00890                 break;
00891 
00892             case Qt::Key_S:
00893                 if ( state == STATE_CRASHED )
00894                     saveReplay();
00895                 break;
00896 
00897             case Qt::Key_L:
00898                 if ( state == STATE_CRASHED )
00899                     loadReplay();
00900                 break;
00901            default:
00902                 e->ignore();
00903                 break;
00904         }
00905     }
00906 
00907 }
00908 
00909 
00910 void SFCave :: saveScore()
00911 {
00912 #ifdef QWS
00913     Config cfg( "sfcave" );
00914     cfg.setGroup( "settings" );
00915     QString key = "highScore_";
00916 
00917     cfg.writeEntry( key + gameTypes[currentGameType] + "_" + dificultyOption[currentGameDifficulty], highestScore[currentGameType][currentGameDifficulty] );
00918     key += CURRENT_GAME_TYPE;
00919     cfg.writeEntry( key, highestScore[currentGameType] );
00920 #endif
00921 }
00922 
00923 void SFCave :: saveReplay()
00924 {
00925     FILE *out;
00926     out = fopen( QFile::encodeName(replayFile).data(), "w" );
00927     if ( !out )
00928     {
00929         printf( "Couldn't write to %s\n", QFile::encodeName(replayFile).data() );
00930         return;
00931     }
00932 
00933     // Build up string of values
00934     // Format is:: <landscape seed> <game type> <difficulty> <framenr> <framenr>.......
00935     QString val;
00936     val.sprintf( "%d %d %d ", currentSeed, currentGameType, currentGameDifficulty );
00937     
00938     QListIterator<int> it( replayList );
00939     while( it.current() )
00940     {
00941         QString tmp;
00942         tmp.sprintf( "%d ", (*it.current()) );
00943         val += tmp;
00944 
00945         ++it;
00946     }
00947     val += "\n";
00948 
00949     QString line;
00950     line.sprintf( "%d\n", val.length() );
00951     fwrite( (const char *)line, 1, line.length(), out );
00952 
00953     fwrite( (const char *)val, 1, val.length(), out );
00954    
00955     fclose( out );
00956 
00957     printf( "Replay saved to %s\n", QFile::encodeName(replayFile).data() );
00958 
00959 }
00960 
00961 void SFCave :: loadReplay()
00962 {
00963     FILE *in = fopen( QFile::encodeName(replayFile).data() , "r" );
00964 
00965     if ( in == 0 )
00966     {
00967         printf( "Couldn't load replay file!\n" );
00968         return;
00969     }   
00970 
00971     // Read next line - contains the size of the options
00972     char line[10+1];
00973     fgets( line, 10, in );
00974 
00975     int length = -1;
00976     sscanf( line, "%d", &length );
00977     char *data = new char[length+1];
00978 
00979     fread( data, 1, length, in );
00980 //    printf( "data - %s", data );
00981 
00982     QString sep  = " ";
00983     QStringList list = QStringList::split( sep, QString( data ) );
00984     
00985     // print it out
00986     QStringList::Iterator it = list.begin();
00987     currentSeed = (*it).toInt();
00988     ++it;
00989     currentGameType = (*it).toInt();
00990     ++it;
00991     currentGameDifficulty = (*it).toInt();
00992     ++it;
00993 
00994     replayList.clear();
00995     for ( ; it != list.end(); ++it )
00996     {
00997         int v = (*it).toInt();
00998         replayList.append( new int( v ) );
00999     }
01000 
01001     delete data;
01002 
01003     fclose( in );
01004     
01005     printf( "Replay loaded from %s\n", QFile::encodeName(replayFile).data() );
01006 }
01007 
01008 
01009 //--------------- MENU CODE ---------------------
01010 void SFCave :: handleMenuKeys( QKeyEvent *e )
01011 {
01012     switch( e->key() )
01013     {
01014         case Qt::Key_Down:
01015             currentMenuOption[currentMenuNr] ++;
01016             if ( menuOptions[currentMenuNr][currentMenuOption[currentMenuNr]] == "" )
01017                 currentMenuOption[currentMenuNr] = 0;
01018             break;
01019         case Qt::Key_Up:
01020             currentMenuOption[currentMenuNr] --;
01021             if ( currentMenuOption[currentMenuNr] < 0 )
01022                 currentMenuOption[currentMenuNr] = nrMenuOptions[currentMenuNr]-1;
01023             break;
01024 
01025         case Qt::Key_Left:
01026             if ( currentMenuNr == MENU_OPTIONS_MENU )
01027             {
01028                 if ( currentMenuOption[currentMenuNr] == MENU_GAME_TYPE )
01029                 {
01030                     currentGameType --;
01031                     if ( currentGameType < 0 )
01032                         currentGameType = NR_GAME_TYPES - 1;
01033                 }
01034                 else if ( currentMenuOption[currentMenuNr] == MENU_GAME_DIFFICULTY )
01035                 {
01036                     currentGameDifficulty --;
01037                     if ( currentGameDifficulty < 0 )
01038                         currentGameDifficulty = NR_GAME_DIFFICULTIES - 1;
01039                 }
01040             }
01041             break;
01042 
01043         case Qt::Key_Right:
01044             if ( currentMenuNr == MENU_OPTIONS_MENU )
01045             {
01046                 if ( currentMenuOption[currentMenuNr] == MENU_GAME_TYPE )
01047                 {
01048                     currentGameType ++;
01049                     if ( currentGameType == NR_GAME_TYPES )
01050                         currentGameType = 0;
01051                 }
01052                 else if ( currentMenuOption[currentMenuNr] == MENU_GAME_DIFFICULTY )
01053                 {
01054                     currentGameDifficulty ++;
01055                     if ( currentGameDifficulty == NR_GAME_DIFFICULTIES )
01056                         currentGameDifficulty = 0;
01057                 }
01058             }
01059             break;
01060 
01061         case Qt::Key_Space:
01062         case Qt::Key_Return:
01063         case Qt::Key_Enter:
01064             dealWithMenuSelection();
01065             break;
01066     }
01067 }
01068 
01069 void SFCave :: displayMenu()
01070 {
01071     offscreen->fill( Qt::black );
01072 
01073     QPainter p( offscreen );
01074     p.setPen( Qt::white );
01075 
01076     QFont f( "Helvetica", 16 );
01077     p.setFont( f );
01078 
01079     QFontMetrics fm = p.fontMetrics();
01080 
01081     QString text = "SFCave";
01082     p.drawText( (sWidth/2) - (fm.width( text )/2), 60, text );
01083 
01084     text = "Written by Andy Qua";
01085     p.drawText( (sWidth/2) - (fm.width( text )/2), 85, text );
01086 
01087     // Draw options
01088     int pos = 140;
01089     for ( int i = 0 ; menuOptions[currentMenuNr][i] != "" ; ++i, pos += 25 )
01090     {
01091         if ( currentMenuOption[currentMenuNr] == i )
01092             p.setPen( Qt::yellow );
01093         else
01094             p.setPen( Qt::white );
01095 
01096         QString text;
01097         if ( menuOptions[currentMenuNr][i].find( "%s" ) != -1 )
01098         {
01099             QString val;
01100             if ( i == MENU_GAME_TYPE )
01101                 val = gameTypes[currentGameType];
01102             else
01103                 val = dificultyOption[currentGameDifficulty];
01104 
01105             text.sprintf( (const char *)menuOptions[currentMenuNr][i], (const char *)val );
01106         }
01107         else
01108             text = menuOptions[currentMenuNr][i];
01109 
01110         p.drawText( (sWidth/2) - (fm.width( text )/2), pos, text );
01111     }
01112 
01113     p.end();
01114     bitBlt( this, 0, 0, offscreen, 0, 0, sWidth, sHeight, Qt::CopyROP, true );
01115 }
01116 
01117 void SFCave :: dealWithMenuSelection()
01118 {
01119     switch( currentMenuNr )
01120     {
01121         case MENU_MAIN_MENU:
01122         {
01123             switch( currentMenuOption[currentMenuNr] )
01124             {
01125                 case MENU_START_GAME:
01126                     state = STATE_NEWGAME;
01127                     break;
01128 
01129                 case MENU_REPLAY:
01130                     currentMenuNr = MENU_REPLAY_MENU;
01131                     currentMenuOption[currentMenuNr] = 0;
01132                     break;
01133 
01134                 case MENU_OPTIONS:
01135                     currentMenuNr = MENU_OPTIONS_MENU;
01136                     currentMenuOption[currentMenuNr] = 0;
01137                     break;
01138 
01139                 case MENU_HELP:
01140                 {
01141                     // Display Help Menu
01142                     HelpWindow *win = new HelpWindow(  );
01143                     QPEApplication::showWidget( win );
01144                     break;
01145                 }
01146 
01147                 case MENU_QUIT:
01148                     QApplication::exit();
01149                     break;
01150             }
01151 
01152             break;
01153         }
01154 
01155         case MENU_OPTIONS_MENU:
01156         {
01157             switch( currentMenuOption[currentMenuNr] )
01158             {
01159                 case MENU_GAME_TYPE:
01160                     break;
01161 
01162                 case MENU_GAME_DIFFICULTY:
01163                     break;
01164 
01165                 case MENU_CLEAR_HIGHSCORES:
01166                     for ( int i = 0 ; i < 3 ; ++i )
01167                         highestScore[currentGameType][i] = 0;
01168                     break;
01169 
01170                 case MENU_BACK:
01171                     currentMenuNr = MENU_MAIN_MENU;
01172 
01173 #ifdef QWS
01174                     Config cfg( "sfcave" );
01175                     cfg.setGroup( "settings" );
01176                     cfg.writeEntry( "difficulty", currentGameDifficulty );
01177                     cfg.writeEntry( "gameType", currentGameType );
01178 #endif
01179                     break;
01180             }
01181 
01182             break;
01183         }
01184 
01185         case MENU_REPLAY_MENU:
01186         {
01187             switch( currentMenuOption[currentMenuNr] )
01188             {
01189                 case MENU_REPLAY_START:
01190                     if ( currentSeed != 0 )
01191                         state = STATE_REPLAY;
01192                         // Display No Replay
01193                     break;
01194 
01195                 case MENU_REPLAY_LOAD:
01196                     loadReplay();
01197                     break;
01198 
01199                 case MENU_REPLAY_SAVE:
01200                     saveReplay();
01201                     break;
01202 
01203                 case MENU_REPLAY_BACK:
01204                     currentMenuNr = MENU_MAIN_MENU;
01205                     break;
01206 
01207             }
01208         }
01209     }
01210 }
01211 

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