Index: apps/plugins/bubbles.c =================================================================== --- apps/plugins/bubbles.c (Revision 21052) +++ apps/plugins/bubbles.c (Arbeitskopie) @@ -29,13 +29,19 @@ #include "lib/pluginlib_actions.h" #include "lib/fixedpoint.h" #include "lib/playback_control.h" +#include "lib/highscore.h" PLUGIN_HEADER /* files */ -#define SCORE_FILE PLUGIN_GAMES_DIR "/bubbles.score" +#define HIGH_SCORE PLUGIN_GAMES_DIR "/bubbles.score" #define SAVE_FILE PLUGIN_GAMES_DIR "/bubbles.save" +#define MAX_HIGH_SCORES 5 +struct highscore Highest[MAX_HIGH_SCORES]; + +#define MARGIN 5 + /* final game return status */ #define BB_NONE 5 #define BB_WIN 4 @@ -50,7 +56,6 @@ #define BB_LEVEL_HEIGHT 10 /* various amounts */ -#define NUM_SCORES 10 #define NUM_LEVELS 100 #define NUM_QUEUE 2 #define NUM_BUBBLES 8 @@ -1223,20 +1228,9 @@ bool delete; }; -/* the highscore struct - * level is the highscore level - * score is the highscore score - */ -struct highscore { - unsigned int level; - unsigned int score; -}; - /* the game context struct * 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 @@ -1248,14 +1242,11 @@ * elapsedshot is the shot elapsed time in 1/100s of seconds * startedshot is when the current shot began * resume denotes whether to resume the currently loaded game - * dirty denotes whether the high scores are out of sync with the saved file * playboard is the game playing board */ struct game_context { unsigned int score; unsigned int level; - unsigned int highlevel; - struct highscore highscores[NUM_SCORES]; int angle; int shots; int compress; @@ -1267,7 +1258,6 @@ long elapsedshot; long startedshot; bool resume; - bool dirty; struct tile playboard[BB_HEIGHT][BB_WIDTH]; }; @@ -1284,12 +1274,10 @@ static void bubbles_anchored(struct game_context* bb, int row, int col); static int bubbles_fall(struct game_context* bb); static int bubbles_checklevel(struct game_context* bb); -static int bubbles_recordscore(struct game_context* bb); -static void bubbles_savescores(struct game_context* bb); +static void bubbles_show_highscores(int p); static bool bubbles_loadgame(struct game_context* bb); static void bubbles_savegame(struct game_context* bb); -static void bubbles_setcolors(void); -static void bubbles_callback(void* param); +static inline void bubbles_setcolors(void); static int bubbles_handlebuttons(struct game_context* bb, bool animblock, int timeout); static int bubbles(struct game_context* bb); @@ -1321,7 +1309,10 @@ bb->level++; /* check if there are no more levels */ - if(bb->level > NUM_LEVELS) return false; + if(bb->level > NUM_LEVELS) { + bb->level--; + return false; + } /* set up the play board */ rb->memset(bb->playboard, 0, sizeof(bb->playboard)); @@ -2118,103 +2109,62 @@ } /***************************************************************************** -* bubbles_recordscore() inserts a high score into the high scores list and -* returns the high score position. +* bubbles_show_highscores() shows the high score table. ******************************************************************************/ -static int bubbles_recordscore(struct game_context* bb) { - int i; - int position = 0; - unsigned int currentscore, currentlevel; - unsigned int tempscore, templevel; +static void bubbles_show_highscores(int p) +{ +#if LCD_DEPTH >= 2 + rb->lcd_set_background(LCD_BLACK); + rb->lcd_set_foreground(LCD_WHITE); +#endif + rb->button_clear_queue(); + rb->lcd_clear_display(); - if(bb->score > 0) { - currentlevel = bb->level-1; - currentscore = bb->score; - - for(i=0; i= bb->highscores[i].score) { - if(!position) { - position = i+1; - bb->dirty = true; - } - templevel = bb->highscores[i].level; - tempscore = bb->highscores[i].score; - bb->highscores[i].level = currentlevel; - bb->highscores[i].score = currentscore; - currentlevel = templevel; - currentscore = tempscore; - } - } + int w, h; + char str[30]; + rb->lcd_setfont(FONT_UI); + rb->font_getstringsize("High Scores", &w, &h, FONT_UI); + /* check wether it fits on screen */ + if ((4*h + h*(MAX_HIGH_SCORES-1) + MARGIN) > LCD_HEIGHT) { + rb->lcd_setfont(FONT_SYSFIXED); + rb->font_getstringsize("High Scores", &w, &h, FONT_SYSFIXED); } + rb->lcd_putsxy(LCD_WIDTH/2-w/2, MARGIN, "High Scores"); + rb->lcd_putsxy(LCD_WIDTH/4-w/4,2*h, "Score"); + rb->lcd_putsxy(LCD_WIDTH*3/4-w/4,2*h, "Level"); - return position; - } - -/***************************************************************************** -* bubbles_loadscores() loads the high scores saved file. -******************************************************************************/ -static void bubbles_loadscores(struct game_context* bb) { - int fd; - - bb->dirty = false; - - /* clear high scores */ - bb->highlevel = 0; - rb->memset(bb->highscores, 0, sizeof(bb->highscores)); - - /* open scores file */ - fd = rb->open(SCORE_FILE, O_RDONLY); - if(fd < 0) return; - - /* read in high scores */ - rb->read(fd, &bb->highlevel, sizeof(bb->highlevel)); - if(rb->read(fd, bb->highscores, sizeof(bb->highscores)) <= 0) { - /* scores are bad, reset */ - rb->memset(bb->highscores, 0, sizeof(bb->highscores)); + int i; + for (i = 1; i<=MAX_HIGH_SCORES; i++) + { + rb->snprintf (str, sizeof (str), "%d)", i); + rb->lcd_putsxy (MARGIN,3*h + h*(i-1), str); + rb->snprintf (str, sizeof (str), "%d", Highest[i-1].score); + rb->lcd_putsxy (LCD_WIDTH/4-w/4,3*h + h*(MAX_HIGH_SCORES-i), str); + rb->snprintf (str, sizeof (str), "%d", (Highest[i-1].level)); + rb->lcd_putsxy (LCD_WIDTH*3/4-w/4,3*h + h*(MAX_HIGH_SCORES-i), str); } +#ifdef HAVE_LCD_COLOR + rb->lcd_set_foreground(LCD_RGBPACK(245,0,0)); + rb->snprintf (str, sizeof (str), "%d)", MAX_HIGH_SCORES-p+1); + rb->lcd_putsxy (MARGIN,3*h + h*(MAX_HIGH_SCORES-p), str); + rb->snprintf (str, sizeof (str), "%d", Highest[p-1].score); + rb->lcd_putsxy (LCD_WIDTH/4-w/4,3*h + h*(MAX_HIGH_SCORES-p), str); + rb->snprintf (str, sizeof (str), "%d", Highest[p-1].level); + rb->lcd_putsxy (LCD_WIDTH*3/4-w/4,3*h + h*(MAX_HIGH_SCORES-p), str); + rb->lcd_set_foreground(LCD_WHITE); +#else + (void)p; +#endif + rb->lcd_update(); - if( bb->highlevel >= NUM_LEVELS ) - bb->highlevel = NUM_LEVELS - 1; + rb->button_get(true); - rb->close(fd); -} + rb->lcd_setfont(FONT_SYSFIXED); -/***************************************************************************** -* bubbles_savescores() saves the high scores saved file. -******************************************************************************/ -static void bubbles_savescores(struct game_context* bb) { - int fd; - - /* write out the high scores to the save file */ - fd = rb->open(SCORE_FILE, O_WRONLY|O_CREAT); - rb->write(fd, &bb->highlevel, sizeof(bb->highlevel)); - rb->write(fd, bb->highscores, sizeof(bb->highscores)); - rb->close(fd); - bb->dirty = false; + bubbles_setcolors(); } -/***************************************************************************** -* bubbles_displaycores() displays the high scores -******************************************************************************/ -static char * scores_get_name(int selected_item, void * data, - char * buffer, size_t buffer_len) -{ - struct game_context* bb = (struct game_context*)data; - rb->snprintf(buffer, buffer_len, "#%02d: %d, Lvl %d", - selected_item+1, - bb->highscores[selected_item].score, - bb->highscores[selected_item].level); - return buffer; -} -static void bubbles_displayscores(struct game_context* bb) { - struct simplelist_info info; - rb->simplelist_info_init(&info, "High Scores", NUM_SCORES, (void*)bb); - info.hide_selection = true; - info.get_name = scores_get_name; - rb->simplelist_show_list(&info); -} - /***************************************************************************** * bubbles_loadgame() loads the saved game and returns load success. ******************************************************************************/ @@ -2282,22 +2232,13 @@ #ifdef HAVE_LCD_COLOR rb->lcd_set_background(LCD_RGBPACK(181,181,222)); rb->lcd_set_foreground(LCD_BLACK); +#elif LCD_DEPTH >= 2 + rb->lcd_set_background(LCD_WHITE); + rb->lcd_set_foreground(LCD_BLACK); #endif } /***************************************************************************** -* bubbles_callback() is the default event handler callback which is called -* on usb connect and shutdown. -******************************************************************************/ -static void bubbles_callback(void* param) { - struct game_context* bb = (struct game_context*) param; - if(bb->dirty) { - rb->splash(HZ/2, "Saving high scores..."); - bubbles_savescores(bb); - } -} - -/***************************************************************************** * bubbles_handlebuttons() handles button events during a game. ******************************************************************************/ static int bubbles_handlebuttons(struct game_context* bb, bool animblock, @@ -2372,8 +2313,7 @@ break; default: - if(rb->default_event_handler_ex(button, bubbles_callback, - (void*) bb) == SYS_USB_CONNECTED) + if (rb->default_event_handler (button) == SYS_USB_CONNECTED) return BB_USB; break; } @@ -2389,6 +2329,7 @@ unsigned int startlevel = 0; bool startgame = false; long timeout; + unsigned int highlevel=1; bubbles_setcolors(); @@ -2400,7 +2341,7 @@ ********************/ MENUITEM_STRINGLIST(menu,"Bubbles Menu",NULL, "Start New Game", "Resume Game", - "Level", "Display High Scores", "Playback Control", + "Level", "High Scores", "Playback Control", "Quit"); while(!startgame){ switch (rb->do_menu(&menu, NULL, NULL, false)) @@ -2418,11 +2359,15 @@ break; case 2: /* choose level */ startlevel++; - rb->set_int("Choose start level", "", UNIT_INT, &startlevel, NULL, 1, 1, bb->highlevel+1, NULL); + if (Highest[MAX_HIGH_SCORES-1].level!=0) { + highlevel= Highest[MAX_HIGH_SCORES-1].level; + } + rb->set_int("Choose start level", "", UNIT_INT, &startlevel, + NULL, 1, 1, highlevel, NULL); startlevel--; break; case 3: /* High scores */ - bubbles_displayscores(bb); + bubbles_show_highscores(MAX_HIGH_SCORES); break; case 4: /* Playback Control */ playback_control(NULL); @@ -2430,7 +2375,6 @@ case 5: /* quit */ return BB_QUIT; case MENU_ATTACHED_USB: - bubbles_callback(bb); return BB_USB; } } @@ -2485,6 +2429,7 @@ enum plugin_status plugin_start(const void* parameter) { struct game_context bb; bool exit = false; + bool highscore_changed = false; int position; /* plugin init */ @@ -2492,8 +2437,7 @@ /* end of plugin init */ /* load files */ - rb->splash(0, "Loading..."); - bubbles_loadscores(&bb); + highscore_load(HIGH_SCORE,Highest,MAX_HIGH_SCORES); rb->lcd_clear_display(); /* start app */ @@ -2506,15 +2450,13 @@ switch(bubbles(&bb)){ case BB_WIN: rb->splash(HZ*2, "You Win!"); - /* record high level */ - if( NUM_LEVELS-1 > bb.highlevel) { - bb.highlevel = NUM_LEVELS-1; - bb.dirty = true; + position=highscore_update(bb.score,bb.level,Highest,MAX_HIGH_SCORES); + if (position==MAX_HIGH_SCORES) { + rb->splash(HZ*2, "New High Score"); } - - /* record high score */ - if((position = bubbles_recordscore(&bb))) { - rb->splashf(HZ*2, "New high score #%d!", position); + if (position!=0) { + bubbles_show_highscores(position); + highscore_changed = true; } break; @@ -2524,16 +2466,14 @@ case BB_END: if(!bb.resume) { - /* record high level */ - if(bb.level-1 > bb.highlevel) { - bb.highlevel = bb.level-1; - bb.dirty = true; - } - - /* record high score */ - if((position = bubbles_recordscore(&bb))) { - rb->splashf(HZ*2, "New high score #%d!", position); - } + position=highscore_update(bb.score,bb.level,Highest,MAX_HIGH_SCORES); + if (position==MAX_HIGH_SCORES) { + rb->splash(HZ*2, "New High Score"); + } + if (position!=0) { + bubbles_show_highscores(position); + highscore_changed = true; + } } break; @@ -2542,10 +2482,6 @@ return PLUGIN_USB_CONNECTED; case BB_QUIT: - if(bb.dirty) { - rb->splash(HZ/2, "Saving high scores..."); - bubbles_savescores(&bb); - } exit = true; break; @@ -2553,7 +2489,9 @@ break; } } - + if (highscore_changed) { + highscore_save(HIGH_SCORE,Highest,MAX_HIGH_SCORES); + } rb->lcd_setfont(FONT_UI); return PLUGIN_OK; }