diff options
Diffstat (limited to 'apps/plugins/bubbles.c')
-rw-r--r-- | apps/plugins/bubbles.c | 130 |
1 files changed, 75 insertions, 55 deletions
diff --git a/apps/plugins/bubbles.c b/apps/plugins/bubbles.c index d5d9987f68..ebf2051f1c 100644 --- a/apps/plugins/bubbles.c +++ b/apps/plugins/bubbles.c | |||
@@ -36,12 +36,13 @@ PLUGIN_HEADER | |||
36 | /* files */ | 36 | /* files */ |
37 | #define SCORE_FILE PLUGIN_GAMES_DIR "/bubbles.score" | 37 | #define SCORE_FILE PLUGIN_GAMES_DIR "/bubbles.score" |
38 | #define SAVE_FILE PLUGIN_GAMES_DIR "/bubbles.save" | 38 | #define SAVE_FILE PLUGIN_GAMES_DIR "/bubbles.save" |
39 | #define DATA_FILE PLUGIN_GAMES_DIR "/bubbles.data" | ||
39 | 40 | ||
40 | /* final game return status */ | 41 | /* final game return status */ |
41 | enum { | 42 | enum { |
42 | BB_LOSE, | 43 | BB_LOSE, |
43 | BB_QUIT, | 44 | BB_QUIT, |
44 | BB_QUIT_AND_SAVE, | 45 | BB_SAVE_AND_QUIT, |
45 | BB_USB, | 46 | BB_USB, |
46 | BB_END, | 47 | BB_END, |
47 | BB_WIN, | 48 | BB_WIN, |
@@ -1241,7 +1242,6 @@ struct tile { | |||
1241 | /* the game context struct | 1242 | /* the game context struct |
1242 | * score is the current score | 1243 | * score is the current score |
1243 | * level is the current level | 1244 | * level is the current level |
1244 | * highlevel is the highest level beaten | ||
1245 | * angle is the current cannon direction | 1245 | * angle is the current cannon direction |
1246 | * shots is the number of shots fired since last compression | 1246 | * shots is the number of shots fired since last compression |
1247 | * compress is the height of the compressor | 1247 | * compress is the height of the compressor |
@@ -1252,13 +1252,11 @@ struct tile { | |||
1252 | * elapsedlvl is level elapsed time in 1/100s of seconds | 1252 | * elapsedlvl is level elapsed time in 1/100s of seconds |
1253 | * elapsedshot is the shot elapsed time in 1/100s of seconds | 1253 | * elapsedshot is the shot elapsed time in 1/100s of seconds |
1254 | * startedshot is when the current shot began | 1254 | * startedshot is when the current shot began |
1255 | * resume denotes whether to resume the currently loaded game | ||
1256 | * playboard is the game playing board | 1255 | * playboard is the game playing board |
1257 | */ | 1256 | */ |
1258 | struct game_context { | 1257 | struct game_context { |
1259 | unsigned int score; | 1258 | unsigned int score; |
1260 | unsigned int level; | 1259 | unsigned int level; |
1261 | unsigned int highlevel; | ||
1262 | int angle; | 1260 | int angle; |
1263 | int shots; | 1261 | int shots; |
1264 | int compress; | 1262 | int compress; |
@@ -1276,6 +1274,8 @@ struct highscore highscores[NUM_SCORES]; | |||
1276 | 1274 | ||
1277 | /* used to denote available resume info */ | 1275 | /* used to denote available resume info */ |
1278 | static bool resume = false; | 1276 | static bool resume = false; |
1277 | static unsigned int highlevel = 0; /* the highest level beaten */ | ||
1278 | static unsigned int last_highlevel = 0; | ||
1279 | 1279 | ||
1280 | static void bubbles_init(struct game_context* bb); | 1280 | static void bubbles_init(struct game_context* bb); |
1281 | static bool bubbles_nextlevel(struct game_context* bb); | 1281 | static bool bubbles_nextlevel(struct game_context* bb); |
@@ -1291,7 +1291,6 @@ static void bubbles_anchored(struct game_context* bb, int row, int col); | |||
1291 | static int bubbles_fall(struct game_context* bb); | 1291 | static int bubbles_fall(struct game_context* bb); |
1292 | static int bubbles_checklevel(struct game_context* bb); | 1292 | static int bubbles_checklevel(struct game_context* bb); |
1293 | static void bubbles_recordscore(struct game_context* bb); | 1293 | static void bubbles_recordscore(struct game_context* bb); |
1294 | static void bubbles_savescores(struct game_context* bb); | ||
1295 | static bool bubbles_loadgame(struct game_context* bb); | 1294 | static bool bubbles_loadgame(struct game_context* bb); |
1296 | static void bubbles_savegame(struct game_context* bb); | 1295 | static void bubbles_savegame(struct game_context* bb); |
1297 | static inline void bubbles_setcolors(void); | 1296 | static inline void bubbles_setcolors(void); |
@@ -1326,15 +1325,14 @@ static void bubbles_init(struct game_context* bb) { | |||
1326 | static bool bubbles_nextlevel(struct game_context* bb) { | 1325 | static bool bubbles_nextlevel(struct game_context* bb) { |
1327 | int i, j, pos; | 1326 | int i, j, pos; |
1328 | 1327 | ||
1329 | /* save highest level */ | ||
1330 | if (bb->level > bb->highlevel) | ||
1331 | bb->highlevel = bb->level; | ||
1332 | |||
1333 | bb->level++; | 1328 | bb->level++; |
1334 | 1329 | ||
1335 | /* check if there are no more levels */ | 1330 | /* check if there are no more levels */ |
1336 | if(bb->level > NUM_LEVELS) return false; | 1331 | if(bb->level > NUM_LEVELS) return false; |
1337 | 1332 | ||
1333 | /* save highest level */ | ||
1334 | if (bb->level-1 > highlevel) | ||
1335 | highlevel = bb->level-1; | ||
1338 | 1336 | ||
1339 | /* set up the play board */ | 1337 | /* set up the play board */ |
1340 | rb->memset(bb->playboard, 0, sizeof(bb->playboard)); | 1338 | rb->memset(bb->playboard, 0, sizeof(bb->playboard)); |
@@ -2165,7 +2163,7 @@ static void bubbles_recordscore(struct game_context* bb) { | |||
2165 | 2163 | ||
2166 | int position; | 2164 | int position; |
2167 | 2165 | ||
2168 | position = highscore_update(bb->score, bb->level, "", | 2166 | position = highscore_update(bb->score, bb->level-1, "", |
2169 | highscores, NUM_SCORES); | 2167 | highscores, NUM_SCORES); |
2170 | if (position==0) | 2168 | if (position==0) |
2171 | rb->splash(HZ*2, "New High Score"); | 2169 | rb->splash(HZ*2, "New High Score"); |
@@ -2174,36 +2172,43 @@ static void bubbles_recordscore(struct game_context* bb) { | |||
2174 | } | 2172 | } |
2175 | 2173 | ||
2176 | /***************************************************************************** | 2174 | /***************************************************************************** |
2177 | * bubbles_loadscores() loads the high scores saved file. | 2175 | * bubbles_loaddata() loads highest level beaten. |
2178 | ******************************************************************************/ | 2176 | ******************************************************************************/ |
2179 | static void bubbles_loadscores(struct game_context* bb) { | 2177 | static void bubbles_loaddata(void) { |
2178 | int fd; | ||
2180 | 2179 | ||
2181 | int i; | 2180 | last_highlevel = highlevel = 0; |
2182 | int highlevel = 0; | 2181 | /* open data file */ |
2183 | /* highlevel and highscores */ | 2182 | fd = rb->open(DATA_FILE, O_RDONLY); |
2184 | highscore_load(SCORE_FILE, highscores, NUM_SCORES); | 2183 | if (fd < 0) return; |
2185 | 2184 | ||
2186 | /* level X in the high scores means one succeeded the level before (X-1) */ | 2185 | /* read in saved game */ |
2187 | for (i = 0; i < NUM_SCORES; i++) | 2186 | if (rb->read(fd, &highlevel, sizeof(highlevel)) < (long)sizeof(highlevel)) |
2188 | { | 2187 | { |
2189 | if (highscores[i].level-1 > highlevel) | 2188 | highlevel = 0; |
2190 | { | ||
2191 | highlevel = highscores[i].level-1; | ||
2192 | } | ||
2193 | } | 2189 | } |
2190 | if (highlevel >= NUM_LEVELS) | ||
2191 | highlevel = NUM_LEVELS-1; | ||
2192 | last_highlevel = highlevel; | ||
2194 | 2193 | ||
2195 | if (bb->highlevel < (unsigned)highlevel) | 2194 | rb->close(fd); |
2196 | bb->highlevel = highlevel; | ||
2197 | } | 2195 | } |
2198 | 2196 | ||
2199 | /***************************************************************************** | 2197 | /***************************************************************************** |
2200 | * bubbles_savescores() saves the high scores saved file. | 2198 | * bubbles_savedata() saves the current game state. |
2201 | ******************************************************************************/ | 2199 | ******************************************************************************/ |
2202 | static void bubbles_savescores(struct game_context* bb) { | 2200 | static void bubbles_savedata(void) { |
2201 | int fd; | ||
2203 | 2202 | ||
2204 | /* highscores */ | 2203 | if (last_highlevel >= highlevel) /* no need to save */ |
2205 | (void)bb; | 2204 | return; |
2206 | highscore_save(SCORE_FILE, highscores, NUM_SCORES+1); | 2205 | |
2206 | fd = rb->open(DATA_FILE, O_WRONLY|O_CREAT); | ||
2207 | if (fd < 0) return; | ||
2208 | |||
2209 | rb->write(fd, &highlevel, sizeof(highlevel)); | ||
2210 | |||
2211 | rb->close(fd); | ||
2207 | } | 2212 | } |
2208 | 2213 | ||
2209 | /***************************************************************************** | 2214 | /***************************************************************************** |
@@ -2225,6 +2230,9 @@ static bool bubbles_loadgame(struct game_context* bb) { | |||
2225 | } | 2230 | } |
2226 | 2231 | ||
2227 | rb->close(fd); | 2232 | rb->close(fd); |
2233 | |||
2234 | /* delete saved file */ | ||
2235 | rb->remove(SAVE_FILE); | ||
2228 | return ret; | 2236 | return ret; |
2229 | } | 2237 | } |
2230 | 2238 | ||
@@ -2266,8 +2274,8 @@ static inline void bubbles_setcolors(void) { | |||
2266 | * on usb connect and shutdown. | 2274 | * on usb connect and shutdown. |
2267 | ******************************************************************************/ | 2275 | ******************************************************************************/ |
2268 | static void bubbles_callback(void* param) { | 2276 | static void bubbles_callback(void* param) { |
2269 | struct game_context* bb = (struct game_context*) param; | 2277 | (void) param; |
2270 | bubbles_savescores(bb); | 2278 | highscore_save(SCORE_FILE, highscores, NUM_SCORES); |
2271 | } | 2279 | } |
2272 | 2280 | ||
2273 | /***************************************************************************** | 2281 | /***************************************************************************** |
@@ -2353,23 +2361,20 @@ static int bubbles_handlebuttons(struct game_context* bb, bool animblock, | |||
2353 | } | 2361 | } |
2354 | 2362 | ||
2355 | /***************************************************************************** | 2363 | /***************************************************************************** |
2356 | * bubbles() is the main game subroutine, it returns the final game status. | 2364 | * bubbles_menu() is the initial menu at the start of the game. |
2357 | ******************************************************************************/ | 2365 | ******************************************************************************/ |
2358 | static int bubbles(struct game_context* bb) { | 2366 | static int bubbles_menu(struct game_context* bb) { |
2359 | int buttonres; | 2367 | static unsigned int startlevel = 0; |
2360 | unsigned int startlevel = 0; | 2368 | int selected = resume?0:1; |
2361 | bool startgame = false; | 2369 | bool startgame = false; |
2362 | long timeout; | ||
2363 | 2370 | ||
2364 | /******************** | ||
2365 | * menu * | ||
2366 | ********************/ | ||
2367 | MENUITEM_STRINGLIST(menu,"Bubbles Menu",NULL, | 2371 | MENUITEM_STRINGLIST(menu,"Bubbles Menu",NULL, |
2368 | "Resume Game", "Start New Game", | 2372 | "Resume Game", "Start New Game", |
2369 | "Level", "High Scores", "Playback Control", | 2373 | "Level", "High Scores", "Playback Control", |
2370 | "Quit", "Quit and Save"); | 2374 | "Quit", "Save and Quit"); |
2375 | |||
2371 | while(!startgame){ | 2376 | while(!startgame){ |
2372 | switch (rb->do_menu(&menu, NULL, NULL, false)) | 2377 | switch (rb->do_menu(&menu, &selected, NULL, false)) |
2373 | { | 2378 | { |
2374 | case 0: /* resume game */ | 2379 | case 0: /* resume game */ |
2375 | if (!resume) | 2380 | if (!resume) |
@@ -2379,11 +2384,8 @@ static int bubbles(struct game_context* bb) { | |||
2379 | } | 2384 | } |
2380 | else | 2385 | else |
2381 | { | 2386 | { |
2382 | startlevel = bb->level - 1; | ||
2383 | startgame = true; | 2387 | startgame = true; |
2384 | } | 2388 | } |
2385 | /* delete saved file */ | ||
2386 | rb->remove(SAVE_FILE); | ||
2387 | break; | 2389 | break; |
2388 | case 1: /* new game */ | 2390 | case 1: /* new game */ |
2389 | bb->level = startlevel; | 2391 | bb->level = startlevel; |
@@ -2393,7 +2395,7 @@ static int bubbles(struct game_context* bb) { | |||
2393 | case 2: /* choose level */ | 2395 | case 2: /* choose level */ |
2394 | startlevel++; | 2396 | startlevel++; |
2395 | rb->set_int("Choose start level", "", UNIT_INT, &startlevel, | 2397 | rb->set_int("Choose start level", "", UNIT_INT, &startlevel, |
2396 | NULL, 1, 1, MIN(NUM_LEVELS,bb->highlevel+1), NULL); | 2398 | NULL, 1, 1, highlevel+1, NULL); |
2397 | startlevel--; | 2399 | startlevel--; |
2398 | break; | 2400 | break; |
2399 | case 3: /* High scores */ | 2401 | case 3: /* High scores */ |
@@ -2404,13 +2406,30 @@ static int bubbles(struct game_context* bb) { | |||
2404 | break; | 2406 | break; |
2405 | case 5: /* quit */ | 2407 | case 5: /* quit */ |
2406 | return BB_QUIT; | 2408 | return BB_QUIT; |
2407 | case 6: /* quit and save */ | 2409 | case 6: /* save and quit */ |
2408 | return BB_QUIT_AND_SAVE; | 2410 | return BB_SAVE_AND_QUIT; |
2409 | case MENU_ATTACHED_USB: | 2411 | case MENU_ATTACHED_USB: |
2410 | bubbles_callback(bb); | 2412 | bubbles_callback(bb); |
2411 | return BB_USB; | 2413 | return BB_USB; |
2412 | } | 2414 | } |
2413 | } | 2415 | } |
2416 | return 0; | ||
2417 | } | ||
2418 | |||
2419 | /***************************************************************************** | ||
2420 | * bubbles() is the main game subroutine, it returns the final game status. | ||
2421 | ******************************************************************************/ | ||
2422 | static int bubbles(struct game_context* bb) { | ||
2423 | int buttonres; | ||
2424 | long timeout; | ||
2425 | |||
2426 | /******************** | ||
2427 | * menu * | ||
2428 | ********************/ | ||
2429 | buttonres = bubbles_menu(bb); | ||
2430 | if(buttonres != 0) | ||
2431 | return buttonres; | ||
2432 | |||
2414 | /******************** | 2433 | /******************** |
2415 | * init * | 2434 | * init * |
2416 | ********************/ | 2435 | ********************/ |
@@ -2464,13 +2483,12 @@ enum plugin_status plugin_start(const void* parameter) { | |||
2464 | bool exit = false; | 2483 | bool exit = false; |
2465 | enum plugin_status ret = PLUGIN_OK; | 2484 | enum plugin_status ret = PLUGIN_OK; |
2466 | 2485 | ||
2467 | /* plugin init */ | ||
2468 | (void)parameter; | 2486 | (void)parameter; |
2469 | /* end of plugin init */ | ||
2470 | 2487 | ||
2471 | /* load files */ | 2488 | /* load files */ |
2472 | resume = bubbles_loadgame(&bb); | 2489 | resume = bubbles_loadgame(&bb); |
2473 | bubbles_loadscores(&bb); | 2490 | bubbles_loaddata(); |
2491 | highscore_load(SCORE_FILE, highscores, NUM_SCORES); | ||
2474 | rb->lcd_clear_display(); | 2492 | rb->lcd_clear_display(); |
2475 | 2493 | ||
2476 | /* start app */ | 2494 | /* start app */ |
@@ -2484,7 +2502,7 @@ enum plugin_status plugin_start(const void* parameter) { | |||
2484 | case BB_WIN: | 2502 | case BB_WIN: |
2485 | rb->splash(HZ*2, "You Win!"); | 2503 | rb->splash(HZ*2, "You Win!"); |
2486 | /* record high level */ | 2504 | /* record high level */ |
2487 | bb.highlevel = NUM_LEVELS; | 2505 | highlevel = NUM_LEVELS-1; |
2488 | /* record high score */ | 2506 | /* record high score */ |
2489 | bubbles_recordscore(&bb); | 2507 | bubbles_recordscore(&bb); |
2490 | break; | 2508 | break; |
@@ -2501,15 +2519,17 @@ enum plugin_status plugin_start(const void* parameter) { | |||
2501 | 2519 | ||
2502 | case BB_USB: | 2520 | case BB_USB: |
2503 | ret = PLUGIN_USB_CONNECTED; | 2521 | ret = PLUGIN_USB_CONNECTED; |
2522 | exit = true; | ||
2504 | break; | 2523 | break; |
2505 | 2524 | ||
2506 | case BB_QUIT_AND_SAVE: | 2525 | case BB_SAVE_AND_QUIT: |
2507 | rb->splash(HZ/2, "Saving Game and Scors"); | 2526 | rb->splash(HZ/2, "Saving Game ..."); |
2508 | bubbles_savescores(&bb); | ||
2509 | bubbles_savegame(&bb); | 2527 | bubbles_savegame(&bb); |
2510 | /* fall through */ | 2528 | /* fall through */ |
2511 | 2529 | ||
2512 | case BB_QUIT: | 2530 | case BB_QUIT: |
2531 | bubbles_savedata(); | ||
2532 | highscore_save(SCORE_FILE, highscores, NUM_SCORES); | ||
2513 | exit = true; | 2533 | exit = true; |
2514 | break; | 2534 | break; |
2515 | 2535 | ||