From 322fae42992040a30416ddd1587fd96dbca0a5e7 Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Sun, 2 Aug 2009 16:41:30 +0000 Subject: A bit of rework in bubbles: *) Change saving mechanism: always save into RAM on any exit button, and offer an additional quit item in the game menu (so that 1 item doesn't save -> no disk spinup) *) Change loading mechanism: always load on entering the game, but delete the save file still on actually resuming (that fixes weirdnesses with the level choosing menu item) *) Remove the highscores from the bubbles struct. *) Swap the "Start New Game" and "Resume Game" menu items to help against accidental deletion of progress. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22116 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/bubbles.c | 189 ++++++++++++++++++++++++++----------------------- 1 file changed, 102 insertions(+), 87 deletions(-) diff --git a/apps/plugins/bubbles.c b/apps/plugins/bubbles.c index 4ed15bd124..1f1e3ac905 100644 --- a/apps/plugins/bubbles.c +++ b/apps/plugins/bubbles.c @@ -38,12 +38,15 @@ PLUGIN_HEADER #define SAVE_FILE PLUGIN_GAMES_DIR "/bubbles.save" /* final game return status */ -#define BB_NONE 5 -#define BB_WIN 4 -#define BB_END 3 -#define BB_USB 2 -#define BB_QUIT 1 -#define BB_LOSE 0 +enum { + BB_LOSE, + BB_QUIT, + BB_QUIT_AND_SAVE, + BB_USB, + BB_END, + BB_WIN, + BB_NONE, +}; /* play board dimension */ #define BB_HEIGHT 12 @@ -1223,7 +1226,6 @@ struct tile { * score is the current score * level is the current level * highlevel is the highest level beaten - * highscores is the list of high scores * angle is the current cannon direction * shots is the number of shots fired since last compression * compress is the height of the compressor @@ -1240,8 +1242,7 @@ struct tile { struct game_context { unsigned int score; unsigned int level; - struct highscore highlevel; - struct highscore highscores[NUM_SCORES]; + unsigned int highlevel; int angle; int shots; int compress; @@ -1252,10 +1253,14 @@ struct game_context { long elapsedlvl; long elapsedshot; long startedshot; - bool resume; struct tile playboard[BB_HEIGHT][BB_WIDTH]; }; +struct highscore highscores[NUM_SCORES]; + +/* used to denote available resume info */ +static bool resume = false; + static void bubbles_init(struct game_context* bb); static bool bubbles_nextlevel(struct game_context* bb); static void bubbles_getonboard(struct game_context* bb); @@ -1288,8 +1293,9 @@ static void bubbles_init(struct game_context* bb) { rb->srand(*rb->current_tick); /* check for resumed game */ - if(bb->resume) { - bb->resume = false; + if (resume) + { + resume = false; return; } @@ -1304,11 +1310,16 @@ static void bubbles_init(struct game_context* bb) { static bool bubbles_nextlevel(struct game_context* bb) { int i, j, pos; + /* save highest level */ + if (bb->level > bb->highlevel) + bb->highlevel = bb->level; + bb->level++; /* check if there are no more levels */ if(bb->level > NUM_LEVELS) return false; + /* set up the play board */ rb->memset(bb->playboard, 0, sizeof(bb->playboard)); for(i=0; iscore, bb->level, "", - bb->highscores, NUM_SCORES); + highscores, NUM_SCORES); if (position==0) rb->splash(HZ*2, "New High Score"); if (position != -1) - highscore_show(position, bb->highscores, NUM_SCORES); + highscore_show(position, highscores, NUM_SCORES); } /***************************************************************************** @@ -2124,11 +2135,21 @@ static void bubbles_recordscore(struct game_context* bb) { ******************************************************************************/ static void bubbles_loadscores(struct game_context* bb) { + int i; + int highlevel = 0; /* highlevel and highscores */ - highscore_load(SCORE_FILE, &bb->highlevel, NUM_SCORES+1); + highscore_load(SCORE_FILE, highscores, NUM_SCORES); + + for (i = 0; i < NUM_SCORES; i++) + { + if (highscores[i].level >= highlevel) + { + highlevel = highscores[i].level+1; + } + } - if( bb->highlevel.level >= NUM_LEVELS ) - bb->highlevel.level = NUM_LEVELS - 1; + if (bb->highlevel < (unsigned)highlevel) + bb->highlevel = highlevel; } /***************************************************************************** @@ -2136,8 +2157,9 @@ static void bubbles_loadscores(struct game_context* bb) { ******************************************************************************/ static void bubbles_savescores(struct game_context* bb) { - /* highlevel and highscores */ - highscore_save(SCORE_FILE, &bb->highlevel, NUM_SCORES+1); + /* highscores */ + (void)bb; + highscore_save(SCORE_FILE, highscores, NUM_SCORES+1); } /***************************************************************************** @@ -2145,35 +2167,22 @@ static void bubbles_savescores(struct game_context* bb) { ******************************************************************************/ static bool bubbles_loadgame(struct game_context* bb) { int fd; - bool loaded = false; + bool ret = true; /* open game file */ fd = rb->open(SAVE_FILE, O_RDONLY); - if(fd < 0) return loaded; + if(fd < 0) return false; /* read in saved game */ - while(true) { - if(rb->read(fd, &bb->score, sizeof(bb->score)) <= 0) break; - if(rb->read(fd, &bb->level, sizeof(bb->level)) <= 0) break; - if(rb->read(fd, &bb->angle, sizeof(bb->angle)) <= 0) break; - if(rb->read(fd, &bb->shots, sizeof(bb->shots)) <= 0) break; - if(rb->read(fd, &bb->compress, sizeof(bb->compress)) <= 0) break; - if(rb->read(fd, &bb->onboardcnt, sizeof(bb->onboardcnt)) <= 0) break; - if(rb->read(fd, bb->onboard, sizeof(bb->onboard)) <= 0) break; - if(rb->read(fd, &bb->nextinq, sizeof(bb->nextinq)) <= 0) break; - if(rb->read(fd, bb->queue, sizeof(bb->queue)) <= 0) break; - if(rb->read(fd, &bb->elapsedlvl, sizeof(bb->elapsedlvl)) <= 0) break; - if(rb->read(fd, bb->playboard, sizeof(bb->playboard)) <= 0) break; - bb->resume = true; - loaded = true; - break; + if(rb->read(fd, bb, sizeof(struct game_context)) + < (long)sizeof(struct game_context)) + { + ret = false; } + DEBUGF("highlevel: %d\n", bb->highlevel); rb->close(fd); - - /* delete saved file */ - rb->remove(SAVE_FILE); - return loaded; + return ret; } /***************************************************************************** @@ -2182,22 +2191,22 @@ static bool bubbles_loadgame(struct game_context* bb) { static void bubbles_savegame(struct game_context* bb) { int fd; + if (!resume) /* nothing to save */ + return; /* write out the game state to the save file */ fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT); - rb->write(fd, &bb->score, sizeof(bb->score)); - rb->write(fd, &bb->level, sizeof(bb->level)); - rb->write(fd, &bb->angle, sizeof(bb->angle)); - rb->write(fd, &bb->shots, sizeof(bb->shots)); - rb->write(fd, &bb->compress, sizeof(bb->compress)); - rb->write(fd, &bb->onboardcnt, sizeof(bb->onboardcnt)); - rb->write(fd, bb->onboard, sizeof(bb->onboard)); - rb->write(fd, &bb->nextinq, sizeof(bb->nextinq)); - rb->write(fd, bb->queue, sizeof(bb->queue)); - rb->write(fd, &bb->elapsedlvl, sizeof(bb->elapsedlvl)); - rb->write(fd, bb->playboard, sizeof(bb->playboard)); + if (fd < 0) + { + rb->splash(HZ/2, "Failed to save game"); + return; + } + if (rb->write(fd, bb, sizeof(struct game_context)) <= 0) + { + rb->splash(HZ/2, "Failed to save game"); + } + DEBUGF("highlevel: %d\n", bb->highlevel); rb->close(fd); - bb->resume = true; } /***************************************************************************** @@ -2280,14 +2289,12 @@ static int bubbles_handlebuttons(struct game_context* bb, bool animblock, break; case BUBBLES_RESUME: /* save and end the game */ + case BUBBLES_QUIT: /* end the game */ if(!animblock) { - rb->splash(HZ/2, "Saving game..."); - bubbles_savegame(bb); + resume = true; return BB_END; } break; - case BUBBLES_QUIT: /* end the game */ - return BB_END; case ACTION_UNKNOWN: case ACTION_NONE: /* no button pressed */ @@ -2312,44 +2319,51 @@ static int bubbles(struct game_context* bb) { bool startgame = false; long timeout; - /* don't resume by default */ - bb->resume = false; - /******************** * menu * ********************/ MENUITEM_STRINGLIST(menu,"Bubbles Menu",NULL, - "Start New Game", "Resume Game", + "Resume Game", "Start New Game", "Level", "High Scores", "Playback Control", - "Quit"); + "Quit", "Quit and Save"); while(!startgame){ switch (rb->do_menu(&menu, NULL, NULL, false)) { - case 0: /* new game */ - bb->level = startlevel; - startgame = true; - break; - case 1: /* resume game */ - if(!bubbles_loadgame(bb)) { - rb->splash(HZ*2, "Nothing to resume"); - } else { + case 0: /* resume game */ + if (!resume) + { + rb->splash(HZ/2, "Nothing to resume"); + break; + } + else + { + startlevel = bb->level - 1; startgame = true; } + /* delete saved file */ + rb->remove(SAVE_FILE); + break; + case 1: /* new game */ + bb->level = startlevel; + startgame = true; + resume = false; break; case 2: /* choose level */ startlevel++; rb->set_int("Choose start level", "", UNIT_INT, &startlevel, - NULL, 1, 1, bb->highlevel.level+1, NULL); + NULL, 1, 1, bb->highlevel+1, NULL); startlevel--; break; case 3: /* High scores */ - highscore_show(NUM_SCORES, bb->highscores, NUM_SCORES); + highscore_show(NUM_SCORES, highscores, NUM_SCORES); break; case 4: /* Playback Control */ playback_control(NULL); break; case 5: /* quit */ return BB_QUIT; + case 6: /* quit and save */ + return BB_QUIT_AND_SAVE; case MENU_ATTACHED_USB: bubbles_callback(bb); return BB_USB; @@ -2404,14 +2418,16 @@ static int bubbles(struct game_context* bb) { * plugin entry point. ******************************************************************************/ enum plugin_status plugin_start(const void* parameter) { - struct game_context bb; + static struct game_context bb; bool exit = false; + enum plugin_status ret = PLUGIN_OK; /* plugin init */ (void)parameter; /* end of plugin init */ /* load files */ + resume = bubbles_loadgame(&bb); bubbles_loadscores(&bb); rb->lcd_clear_display(); @@ -2426,35 +2442,34 @@ enum plugin_status plugin_start(const void* parameter) { case BB_WIN: rb->splash(HZ*2, "You Win!"); /* record high level */ - if( NUM_LEVELS-1 > bb.highlevel.level) { - bb.highlevel.level = NUM_LEVELS-1; + if( NUM_LEVELS-1 > bb.highlevel) { + bb.highlevel = NUM_LEVELS-1; } /* record high score */ bubbles_recordscore(&bb); break; case BB_LOSE: + resume = false; rb->splash(HZ*2, "Game Over"); + /* record high score */ + bubbles_recordscore(&bb); /* fall through to BB_END */ case BB_END: - if(!bb.resume) { - /* record high level */ - if((int)bb.level-1 > bb.highlevel.level) { - bb.highlevel.score = -1; - highscore_update(0, bb.level-1, "", &bb.highlevel, 1); - } - /* record high score */ - bubbles_recordscore(&bb); - } break; case BB_USB: - rb->lcd_setfont(FONT_UI); - return PLUGIN_USB_CONNECTED; + ret = PLUGIN_USB_CONNECTED; + break; - case BB_QUIT: + case BB_QUIT_AND_SAVE: + rb->splash(HZ/2, "Saving Game and Scors"); bubbles_savescores(&bb); + bubbles_savegame(&bb); + /* fall through */ + + case BB_QUIT: exit = true; break; @@ -2464,7 +2479,7 @@ enum plugin_status plugin_start(const void* parameter) { } rb->lcd_setfont(FONT_UI); - return PLUGIN_OK; + return ret; } #endif -- cgit v1.2.3