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
00049
00050 SDL_Surface * Menu :: sfcaveTextImage;
00051 Menu *Menu :: mainMenu;
00052 Menu *Menu :: currentMenu;
00053
00054
00055 Menu :: Menu( SFCave *p )
00056 {
00057 parent = p;
00058 parentMenu = 0;
00059 statusText = "";
00060
00061
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
00070
00071
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
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
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
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
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
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
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
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
00165 mainMenu = this;
00166 currentMenuOption = 0;
00167
00168 resetToTopMenu();
00169
00170 angle = 0;
00171
00172 stars = new StarField;
00173 }
00174
00175
00176 Menu :: Menu( Menu *p )
00177 {
00178 parentMenu = p;
00179
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
00195 stars->draw( screen );
00196 stars->move( );
00197
00198
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
00216 char text[100];
00217 sprintf( text, "Current Game: %s", (const char *)parent->getCurrentGame()->getGameName().c_str() );
00218
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
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
00227
00228
00229
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
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
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
00315 int id = currentMenu->currentMenuOption->getMenuId();
00316
00317
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 }