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

menu.cpp

Go to the documentation of this file.
00001 #include <SDL/SDL_image.h>
00002 #include <SDL/SDL_rotozoom.h>
00003 
00004 #include "constants.h"
00005 #include "sfcave.h"
00006 #include "game.h"
00007 #include "menu.h"
00008 #include "font.h"
00009 #include "starfield.h"
00010 
00011 MenuOption :: MenuOption( string text, int id )
00012 {
00013         menuText = text;
00014         menuId = id;
00015         nextMenu = 0;
00016         highlighted = false;
00017 }
00018 
00019 MenuOption :: ~MenuOption()
00020 {
00021 }
00022 
00023 
00024 int MenuOption :: draw( SDL_Surface *screen, int y )
00025 {
00026         if ( highlighted )
00027         {
00028                 int x = (240 - FontHandler::TextWidth( FONT_MENU_HIGHLIGHTED, (const char *)menuText.c_str() ))/2;
00029                 FontHandler::draw( screen, FONT_MENU_HIGHLIGHTED, (const char *)menuText.c_str(), x, y );
00030                 return FontHandler::FontHeight( FONT_MENU_HIGHLIGHTED );
00031         }
00032         else
00033         {
00034                 int x = (240 - FontHandler::TextWidth( FONT_MENU_UNHIGHLIGHTED, (const char *)menuText.c_str() ))/2;
00035                 FontHandler::draw( screen, FONT_MENU_UNHIGHLIGHTED, (const char *)menuText.c_str(), x, y );
00036                 return FontHandler::FontHeight( FONT_MENU_UNHIGHLIGHTED );
00037         }
00038 }
00039 
00040 void MenuOption :: setNextMenu( Menu *item, bool down )
00041 {
00042         nextMenu = item;
00043         downMenuTree = down;
00044 }
00045 
00046 
00047 
00048 //----------------- Menu Class -------------
00049 
00050 SDL_Surface * Menu :: sfcaveTextImage;
00051 Menu *Menu :: mainMenu;
00052 Menu *Menu :: currentMenu;
00053 
00054 // This is the Master Menu constructor
00055 Menu :: Menu( SFCave *p )
00056 {
00057         parent = p;
00058         parentMenu = 0;
00059         statusText = "";
00060 
00061 //      listItems.setAutoDelete( TRUE );
00062 
00063         SDL_Surface *tmp = IMG_Load( IMAGES_PATH "sfcave_text.bmp" );
00064         sfcaveTextImage = SDL_CreateRGBSurface(SDL_SWSURFACE, tmp->w, tmp->h, 32,
00065                                                0x000000ff,0x0000ff00, 0x00ff0000, 0xff000000);
00066     SDL_BlitSurface(tmp, NULL, sfcaveTextImage, NULL);
00067         SDL_FreeSurface(tmp);
00068 
00069         // Create menu structure
00070         // Top level menu has 5 items - Start Game, Replays, Options, Help, and Quit
00071         // Replays, Option menu items hav submenus
00072         MenuOption *replayMenu = 0;
00073         MenuOption *optionsMenu = 0;
00074         MenuOption *item = 0;
00075         addMenuOption( "Start Game", MENU_STARTGAME );
00076         replayMenu = addMenuOption( "Replays", MENU_REPLAYS );
00077         optionsMenu = addMenuOption( "Options", MENU_OPTIONS );
00078         addMenuOption( "Help", MENU_HELP );
00079         addMenuOption( "Quit", MENU_QUIT );
00080 
00081         // Now deal with the Replays Menu
00082         Menu *replay = new Menu( this );
00083         replay->addMenuOption( "Play Replay", MENU_PLAY_REPLAY );
00084         replay->addMenuOption( "Load Replay", MENU_LOAD_REPLAY );
00085         replay->addMenuOption( "Save Replay", MENU_SAVE_REPLAY );
00086         item = replay->addMenuOption( "Back", MENU_BACK );
00087         item->setNextMenu( this, false );
00088         replayMenu->setNextMenu( replay );
00089 
00090         // Now deal with the Options Menu       currentMenu->currentMenuOption->setHighlighted( false );
00091         listItems.front()->highlight( true );
00092 
00093         Menu *options = new Menu( this );
00094         MenuOption *typeMenu = 0;
00095         MenuOption *difficultyMenu = 0;
00096         MenuOption *soundsMenu = 0;
00097         typeMenu = options->addMenuOption( "Game Type", MENU_GAME_TYPE );
00098         difficultyMenu = options->addMenuOption( "Difficulty", MENU_DIFFICULTY );
00099         soundsMenu = options->addMenuOption( "Sound", MENU_SOUNDS );
00100         options->addMenuOption( "Clear Scores", MENU_CLEAR_SCORES );
00101         item = options->addMenuOption( "Back", MENU_BACK );
00102         item->setNextMenu( this, false );
00103         optionsMenu->setNextMenu( options );
00104 
00105         // Game Type menu
00106         Menu *gameType = new Menu( options );
00107         item = gameType->addMenuOption( "SFCave", MENU_GAME_SFCAVE );
00108         item->setNextMenu( options );
00109         item = gameType->addMenuOption( "Gates", MENU_GAME_GATES );
00110         item->setNextMenu( options );
00111         item = gameType->addMenuOption( "Fly", MENU_GAME_FLY );
00112         item->setNextMenu( options );
00113         item = gameType->addMenuOption( "Back", MENU_BACK );
00114         item->setNextMenu( options );
00115         typeMenu->setNextMenu( gameType );
00116 
00117         // Game Difficulty menu
00118         MenuOption *customMenu = 0;
00119         Menu *gameDifficulty = new Menu( options );
00120         item = gameDifficulty->addMenuOption( "Easy", MENU_DIFFICULTY_EASY );
00121         item->setNextMenu( options, false );
00122         item = gameDifficulty->addMenuOption( "Normal", MENU_DIFFICULTY_NORMAL );
00123         item->setNextMenu( options, false );
00124         item = gameDifficulty->addMenuOption( "Hard", MENU_DIFFICULTY_HARD );
00125         item->setNextMenu( options, false );
00126         customMenu = gameDifficulty->addMenuOption( "Custom", MENU_DIFFICULTY_CUSTOM );
00127         item = gameDifficulty->addMenuOption( "Back", MENU_BACK );
00128         item->setNextMenu( options, false );
00129         difficultyMenu->setNextMenu( gameDifficulty );
00130 
00131         // Sounds Menu
00132         Menu *sounds = new Menu( options );
00133         sounds->addMenuOption( "Sound On", MENU_SOUND_ON );
00134         sounds->addMenuOption( "Sound Off", MENU_SOUND_OFF );
00135         sounds->addMenuOption( "Music On", MENU_MUSIC_ON );
00136         sounds->addMenuOption( "Music Off", MENU_MUSIC_OFF );
00137         item = sounds->addMenuOption( "Back", MENU_BACK );
00138         item->setNextMenu( options, false );
00139         soundsMenu->setNextMenu( sounds );
00140         
00141         // Custom Menu
00142         Menu *custom = new Menu( gameDifficulty );
00143         Menu *updown = new Menu( custom );
00144         item = custom->addMenuOption( "Thrust", MENU_CUSTOM_THRUST );
00145         item->setNextMenu( updown );
00146         item = custom->addMenuOption( "Gravity", MENU_CUSTOM_GRAVITY );
00147         item->setNextMenu( updown );
00148         item = custom->addMenuOption( "Max Speed Up", MENU_CUSTOM_MAXSPEEDUP );
00149         item->setNextMenu( updown );
00150         item = custom->addMenuOption( "Max Speed Down", MENU_CUSTOM_MAXSPEEDDOWN );
00151         item->setNextMenu( updown );
00152         item = custom->addMenuOption( "Back", MENU_BACK );
00153         item->setNextMenu( gameDifficulty, false );
00154         customMenu->setNextMenu( custom );
00155 
00156     // Up down menu
00157         item = updown->addMenuOption( "Increase", MENU_CUSTOM_INCREASE );
00158         item = updown->addMenuOption( "Decrease", MENU_CUSTOM_DECREASE );
00159         item = updown->addMenuOption( "Save", MENU_CUSTOM_SAVE );
00160         item->setNextMenu( custom, false );
00161         item = updown->addMenuOption( "Cancel", MENU_CUSTOM_CANCEL );
00162         item->setNextMenu( custom, false );
00163 
00164         // Set static variables for menu selection up
00165         mainMenu = this;
00166         currentMenuOption = 0;
00167 
00168         resetToTopMenu();
00169 
00170         angle = 0;
00171 
00172         stars = new StarField;
00173 }
00174 
00175 // This is a private constructor used for creating sub menus - only called by the Master Menu
00176 Menu :: Menu( Menu *p )
00177 {
00178         parentMenu = p;
00179 //      listItems.setAutoDelete( TRUE );
00180         currentMenuOption = 0;
00181 }
00182 
00183 Menu :: ~Menu()
00184 {
00185         if ( this == mainMenu )
00186         {
00187                 SDL_FreeSurface( sfcaveTextImage );
00188                 delete stars;
00189         }
00190 }
00191 
00192 void Menu :: draw( SDL_Surface *screen )
00193 {
00194         // draw stafield
00195         stars->draw( screen );
00196         stars->move( );
00197 
00198         // Draw the spinning SFCave logo
00199         SDL_Surface *rotozoom_pic;
00200         SDL_Rect dest;
00201 
00202         angle += 2;
00203         if ( angle > 359 )
00204                 angle = 0;
00205         if ((rotozoom_pic=rotozoomSurface (sfcaveTextImage, angle*1, 1, SMOOTHING_ON))!=NULL)
00206         {
00207                 dest.x = (screen->w - rotozoom_pic->w)/2;
00208                 dest.y = 10;
00209                 dest.w = rotozoom_pic->w;
00210                 dest.h = rotozoom_pic->h;
00211                 SDL_BlitSurface( rotozoom_pic, NULL, screen, &dest );
00212                 SDL_FreeSurface(rotozoom_pic);
00213         }
00214 
00215         // Draw what game is selected
00216         char text[100];
00217         sprintf( text, "Current Game: %s", (const char *)parent->getCurrentGame()->getGameName().c_str() );
00218 //      Menu::scoreFont.PutString( screen, (240 - Menu::scoreFont.TextWidth( (const char *)text ))/2, 120, (const char *)text );
00219         FontHandler::draw( screen, FONT_WHITE_TEXT, (const char *)text, (240 - FontHandler::TextWidth( FONT_WHITE_TEXT,(const char *)text ))/2, 120 );
00220         sprintf( text, "Difficulty: %s", (const char *)parent->getCurrentGame()->getGameDifficultyText().c_str() );
00221 //      Menu::scoreFont.PutString( screen, (240 - Menu::scoreFont.TextWidth( (const char *)text ))/2, 120 + Menu::scoreFont.FontHeight()+2, (const char *)text );
00222         FontHandler::draw( screen, FONT_WHITE_TEXT, (const char *)text, (240 - FontHandler::TextWidth( FONT_WHITE_TEXT,(const char *)text ))/2, 120 + FontHandler::FontHeight( FONT_WHITE_TEXT ) );
00223 
00224         if ( statusText != "" )
00225                 FontHandler::draw( screen, FONT_WHITE_TEXT, (const char *)statusText.c_str(), (240 - FontHandler::TextWidth( FONT_WHITE_TEXT,(const char *)statusText.c_str() ))/2, 120 + (2*FontHandler::FontHeight( FONT_WHITE_TEXT ))+6 );
00226 //              Menu::scoreFont.PutString( screen, (240 - Menu::scoreFont.TextWidth( (const char *)statusText ))/2, 120 + (Menu::scoreFont.FontHeight()*2)+6, (const char *)statusText );
00227 
00228 
00229         // Loop round each menu option and draw it
00230         int y = 155;
00231         list<MenuOption *>::iterator it;
00232         for ( it = currentMenu->listItems.begin(); it != currentMenu->listItems.end() ; ++it )
00233         {
00234                 y += (*it)->draw( screen, y ) + 2;
00235         }
00236 }
00237 
00238 int Menu :: handleKeys( SDL_KeyboardEvent &key )
00239 {
00240         if ( key.type != SDL_KEYDOWN )
00241                 return -1;
00242 
00243         switch( key.keysym.sym )
00244         {
00245                 case SDLK_DOWN:
00246                 {
00247                         // Move to next menu item
00248                         currentMenu->currentMenuOption->highlight( false );
00249 
00250                         list<MenuOption *>::iterator it;
00251                         for ( it = currentMenu->listItems.begin(); it != currentMenu->listItems.end() ; ++it )
00252                         {
00253                                 if ( (*it) == currentMenu->currentMenuOption )
00254                                 {
00255                                         it++;
00256                                         break;
00257                                 }
00258                         }
00259 
00260                         if ( it == currentMenu->listItems.end() )
00261                                 it = currentMenu->listItems.begin();
00262 
00263                         currentMenu->currentMenuOption = *it;
00264                         currentMenu->currentMenuOption->highlight( true );
00265 
00266                         break;
00267                 }
00268                 case SDLK_UP:
00269                 {
00270                         // Move to previous menu item
00271                         currentMenu->currentMenuOption->highlight( false );
00272                         list<MenuOption *>::iterator it;
00273                         bool reachedBeginning = false;
00274                         for ( it = (currentMenu->listItems).end()--;  ; --it )
00275                         {
00276                                 if ( (*it) == currentMenu->currentMenuOption )
00277                                 {
00278 
00279                                         if ( it == currentMenu->listItems.begin( ) )
00280                                         {
00281                                                 reachedBeginning = true;
00282                                                 break;
00283                                         }
00284                                         else
00285                                                 it--;
00286                                         break;
00287                                 }
00288 
00289                         }
00290 
00291                         if ( reachedBeginning )
00292                                 currentMenu->currentMenuOption = currentMenu->listItems.back();
00293                         else
00294                                 currentMenu->currentMenuOption = *it;
00295 
00296                         currentMenu->currentMenuOption->highlight( true );
00297 
00298                         break;
00299                 }
00300                 case SDLK_LEFT:
00301                         if ( currentMenu->parentMenu != 0 )
00302                         {
00303                 statusText = "";
00304                                 currentMenu = currentMenu->parentMenu;
00305 
00306                                 return -1;
00307                         }
00308                         break;
00309 
00310                 case SDLK_RETURN:
00311                 case SDLK_SPACE:
00312                 {
00313                 statusText = "";
00314                         // select menu item
00315                         int id = currentMenu->currentMenuOption->getMenuId();
00316 
00317                         // if the current item has a child menu then move to that menu
00318                         Menu *next = currentMenu->currentMenuOption->getNextMenu();
00319                         if ( next != 0 )
00320                         {
00321                                 bool down = currentMenu->currentMenuOption->isDownMenuTree();
00322                                 currentMenu = next;
00323                                 if ( down )
00324                                         initCurrentMenu();
00325                         }
00326 
00327                         return id;
00328 
00329                         break;
00330                 }
00331 
00332                 default:
00333                         break;
00334         }
00335 
00336         return -1;
00337 }
00338 
00339 MenuOption *Menu :: addMenuOption( string text, int id )
00340 {
00341         MenuOption *item = new MenuOption( text, id );
00342 
00343         listItems.push_back( item );
00344 
00345         return item;
00346 }
00347 
00348 void Menu :: resetToTopMenu()
00349 {
00350         currentMenu = mainMenu;
00351         initCurrentMenu();
00352 }
00353 
00354 void Menu :: initCurrentMenu()
00355 {
00356         if ( currentMenu->currentMenuOption != 0 )
00357                 currentMenu->currentMenuOption->highlight( false );
00358         currentMenu->currentMenuOption = currentMenu->listItems.front();
00359         currentMenu->currentMenuOption->highlight( true );
00360 }

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