1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Thomas Martitz 2009-08-02 16:41:30 +00:00
parent 1060326f02
commit 322fae4299

View file

@ -38,12 +38,15 @@ PLUGIN_HEADER
#define SAVE_FILE PLUGIN_GAMES_DIR "/bubbles.save" #define SAVE_FILE PLUGIN_GAMES_DIR "/bubbles.save"
/* final game return status */ /* final game return status */
#define BB_NONE 5 enum {
#define BB_WIN 4 BB_LOSE,
#define BB_END 3 BB_QUIT,
#define BB_USB 2 BB_QUIT_AND_SAVE,
#define BB_QUIT 1 BB_USB,
#define BB_LOSE 0 BB_END,
BB_WIN,
BB_NONE,
};
/* play board dimension */ /* play board dimension */
#define BB_HEIGHT 12 #define BB_HEIGHT 12
@ -1223,7 +1226,6 @@ struct tile {
* score is the current score * score is the current score
* level is the current level * level is the current level
* highlevel is the highest level beaten * highlevel is the highest level beaten
* highscores is the list of high scores
* angle is the current cannon direction * angle is the current cannon direction
* shots is the number of shots fired since last compression * shots is the number of shots fired since last compression
* compress is the height of the compressor * compress is the height of the compressor
@ -1240,8 +1242,7 @@ struct tile {
struct game_context { struct game_context {
unsigned int score; unsigned int score;
unsigned int level; unsigned int level;
struct highscore highlevel; unsigned int highlevel;
struct highscore highscores[NUM_SCORES];
int angle; int angle;
int shots; int shots;
int compress; int compress;
@ -1252,10 +1253,14 @@ struct game_context {
long elapsedlvl; long elapsedlvl;
long elapsedshot; long elapsedshot;
long startedshot; long startedshot;
bool resume;
struct tile playboard[BB_HEIGHT][BB_WIDTH]; 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 void bubbles_init(struct game_context* bb);
static bool bubbles_nextlevel(struct game_context* bb); static bool bubbles_nextlevel(struct game_context* bb);
static void bubbles_getonboard(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); rb->srand(*rb->current_tick);
/* check for resumed game */ /* check for resumed game */
if(bb->resume) { if (resume)
bb->resume = false; {
resume = false;
return; return;
} }
@ -1304,11 +1310,16 @@ static void bubbles_init(struct game_context* bb) {
static bool bubbles_nextlevel(struct game_context* bb) { static bool bubbles_nextlevel(struct game_context* bb) {
int i, j, pos; int i, j, pos;
/* save highest level */
if (bb->level > bb->highlevel)
bb->highlevel = bb->level;
bb->level++; bb->level++;
/* check if there are no more levels */ /* check if there are no more levels */
if(bb->level > NUM_LEVELS) return false; if(bb->level > NUM_LEVELS) return false;
/* set up the play board */ /* set up the play board */
rb->memset(bb->playboard, 0, sizeof(bb->playboard)); rb->memset(bb->playboard, 0, sizeof(bb->playboard));
for(i=0; i<BB_LEVEL_HEIGHT; i++) { for(i=0; i<BB_LEVEL_HEIGHT; i++) {
@ -2112,11 +2123,11 @@ static void bubbles_recordscore(struct game_context* bb) {
int position; int position;
position = highscore_update(bb->score, bb->level, "", position = highscore_update(bb->score, bb->level, "",
bb->highscores, NUM_SCORES); highscores, NUM_SCORES);
if (position==0) if (position==0)
rb->splash(HZ*2, "New High Score"); rb->splash(HZ*2, "New High Score");
if (position != -1) 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) { static void bubbles_loadscores(struct game_context* bb) {
int i;
int highlevel = 0;
/* highlevel and highscores */ /* highlevel and highscores */
highscore_load(SCORE_FILE, &bb->highlevel, NUM_SCORES+1); highscore_load(SCORE_FILE, highscores, NUM_SCORES);
if( bb->highlevel.level >= NUM_LEVELS ) for (i = 0; i < NUM_SCORES; i++)
bb->highlevel.level = NUM_LEVELS - 1; {
if (highscores[i].level >= highlevel)
{
highlevel = highscores[i].level+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) { static void bubbles_savescores(struct game_context* bb) {
/* highlevel and highscores */ /* highscores */
highscore_save(SCORE_FILE, &bb->highlevel, NUM_SCORES+1); (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) { static bool bubbles_loadgame(struct game_context* bb) {
int fd; int fd;
bool loaded = false;
bool ret = true;
/* open game file */ /* open game file */
fd = rb->open(SAVE_FILE, O_RDONLY); fd = rb->open(SAVE_FILE, O_RDONLY);
if(fd < 0) return loaded; if(fd < 0) return false;
/* read in saved game */ /* read in saved game */
while(true) { if(rb->read(fd, bb, sizeof(struct game_context))
if(rb->read(fd, &bb->score, sizeof(bb->score)) <= 0) break; < (long)sizeof(struct game_context))
if(rb->read(fd, &bb->level, sizeof(bb->level)) <= 0) break; {
if(rb->read(fd, &bb->angle, sizeof(bb->angle)) <= 0) break; ret = false;
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;
} }
DEBUGF("highlevel: %d\n", bb->highlevel);
rb->close(fd); rb->close(fd);
return ret;
/* delete saved file */
rb->remove(SAVE_FILE);
return loaded;
} }
/***************************************************************************** /*****************************************************************************
@ -2182,22 +2191,22 @@ static bool bubbles_loadgame(struct game_context* bb) {
static void bubbles_savegame(struct game_context* bb) { static void bubbles_savegame(struct game_context* bb) {
int fd; int fd;
if (!resume) /* nothing to save */
return;
/* write out the game state to the save file */ /* write out the game state to the save file */
fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT); fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT);
rb->write(fd, &bb->score, sizeof(bb->score)); if (fd < 0)
rb->write(fd, &bb->level, sizeof(bb->level)); {
rb->write(fd, &bb->angle, sizeof(bb->angle)); rb->splash(HZ/2, "Failed to save game");
rb->write(fd, &bb->shots, sizeof(bb->shots)); return;
rb->write(fd, &bb->compress, sizeof(bb->compress)); }
rb->write(fd, &bb->onboardcnt, sizeof(bb->onboardcnt)); if (rb->write(fd, bb, sizeof(struct game_context)) <= 0)
rb->write(fd, bb->onboard, sizeof(bb->onboard)); {
rb->write(fd, &bb->nextinq, sizeof(bb->nextinq)); rb->splash(HZ/2, "Failed to save game");
rb->write(fd, bb->queue, sizeof(bb->queue)); }
rb->write(fd, &bb->elapsedlvl, sizeof(bb->elapsedlvl)); DEBUGF("highlevel: %d\n", bb->highlevel);
rb->write(fd, bb->playboard, sizeof(bb->playboard));
rb->close(fd); rb->close(fd);
bb->resume = true;
} }
/***************************************************************************** /*****************************************************************************
@ -2280,14 +2289,12 @@ static int bubbles_handlebuttons(struct game_context* bb, bool animblock,
break; break;
case BUBBLES_RESUME: /* save and end the game */ case BUBBLES_RESUME: /* save and end the game */
case BUBBLES_QUIT: /* end the game */
if(!animblock) { if(!animblock) {
rb->splash(HZ/2, "Saving game..."); resume = true;
bubbles_savegame(bb);
return BB_END; return BB_END;
} }
break; break;
case BUBBLES_QUIT: /* end the game */
return BB_END;
case ACTION_UNKNOWN: case ACTION_UNKNOWN:
case ACTION_NONE: /* no button pressed */ case ACTION_NONE: /* no button pressed */
@ -2312,44 +2319,51 @@ static int bubbles(struct game_context* bb) {
bool startgame = false; bool startgame = false;
long timeout; long timeout;
/* don't resume by default */
bb->resume = false;
/******************** /********************
* menu * * menu *
********************/ ********************/
MENUITEM_STRINGLIST(menu,"Bubbles Menu",NULL, MENUITEM_STRINGLIST(menu,"Bubbles Menu",NULL,
"Start New Game", "Resume Game", "Resume Game", "Start New Game",
"Level", "High Scores", "Playback Control", "Level", "High Scores", "Playback Control",
"Quit"); "Quit", "Quit and Save");
while(!startgame){ while(!startgame){
switch (rb->do_menu(&menu, NULL, NULL, false)) switch (rb->do_menu(&menu, NULL, NULL, false))
{ {
case 0: /* new game */ case 0: /* resume game */
bb->level = startlevel; if (!resume)
startgame = true; {
break; rb->splash(HZ/2, "Nothing to resume");
case 1: /* resume game */ break;
if(!bubbles_loadgame(bb)) { }
rb->splash(HZ*2, "Nothing to resume"); else
} else { {
startlevel = bb->level - 1;
startgame = true; startgame = true;
} }
/* delete saved file */
rb->remove(SAVE_FILE);
break;
case 1: /* new game */
bb->level = startlevel;
startgame = true;
resume = false;
break; break;
case 2: /* choose level */ case 2: /* choose level */
startlevel++; startlevel++;
rb->set_int("Choose start level", "", UNIT_INT, &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--; startlevel--;
break; break;
case 3: /* High scores */ case 3: /* High scores */
highscore_show(NUM_SCORES, bb->highscores, NUM_SCORES); highscore_show(NUM_SCORES, highscores, NUM_SCORES);
break; break;
case 4: /* Playback Control */ case 4: /* Playback Control */
playback_control(NULL); playback_control(NULL);
break; break;
case 5: /* quit */ case 5: /* quit */
return BB_QUIT; return BB_QUIT;
case 6: /* quit and save */
return BB_QUIT_AND_SAVE;
case MENU_ATTACHED_USB: case MENU_ATTACHED_USB:
bubbles_callback(bb); bubbles_callback(bb);
return BB_USB; return BB_USB;
@ -2404,14 +2418,16 @@ static int bubbles(struct game_context* bb) {
* plugin entry point. * plugin entry point.
******************************************************************************/ ******************************************************************************/
enum plugin_status plugin_start(const void* parameter) { enum plugin_status plugin_start(const void* parameter) {
struct game_context bb; static struct game_context bb;
bool exit = false; bool exit = false;
enum plugin_status ret = PLUGIN_OK;
/* plugin init */ /* plugin init */
(void)parameter; (void)parameter;
/* end of plugin init */ /* end of plugin init */
/* load files */ /* load files */
resume = bubbles_loadgame(&bb);
bubbles_loadscores(&bb); bubbles_loadscores(&bb);
rb->lcd_clear_display(); rb->lcd_clear_display();
@ -2426,35 +2442,34 @@ enum plugin_status plugin_start(const void* parameter) {
case BB_WIN: case BB_WIN:
rb->splash(HZ*2, "You Win!"); rb->splash(HZ*2, "You Win!");
/* record high level */ /* record high level */
if( NUM_LEVELS-1 > bb.highlevel.level) { if( NUM_LEVELS-1 > bb.highlevel) {
bb.highlevel.level = NUM_LEVELS-1; bb.highlevel = NUM_LEVELS-1;
} }
/* record high score */ /* record high score */
bubbles_recordscore(&bb); bubbles_recordscore(&bb);
break; break;
case BB_LOSE: case BB_LOSE:
resume = false;
rb->splash(HZ*2, "Game Over"); rb->splash(HZ*2, "Game Over");
/* record high score */
bubbles_recordscore(&bb);
/* fall through to BB_END */ /* fall through to BB_END */
case 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; break;
case BB_USB: case BB_USB:
rb->lcd_setfont(FONT_UI); ret = PLUGIN_USB_CONNECTED;
return PLUGIN_USB_CONNECTED; break;
case BB_QUIT_AND_SAVE:
rb->splash(HZ/2, "Saving Game and Scors");
bubbles_savescores(&bb);
bubbles_savegame(&bb);
/* fall through */
case BB_QUIT: case BB_QUIT:
bubbles_savescores(&bb);
exit = true; exit = true;
break; break;
@ -2464,7 +2479,7 @@ enum plugin_status plugin_start(const void* parameter) {
} }
rb->lcd_setfont(FONT_UI); rb->lcd_setfont(FONT_UI);
return PLUGIN_OK; return ret;
} }
#endif #endif