summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/plugins/snake.c352
1 files changed, 161 insertions, 191 deletions
diff --git a/apps/plugins/snake.c b/apps/plugins/snake.c
index 54d1d5dce3..87b68d2055 100644
--- a/apps/plugins/snake.c
+++ b/apps/plugins/snake.c
@@ -34,7 +34,7 @@ dir is the current direction of the snake - 0=up, 1=right, 2=down, 3=left;
34 34
35#include "plugin.h" 35#include "plugin.h"
36#ifdef HAVE_LCD_BITMAP 36#ifdef HAVE_LCD_BITMAP
37#include "lib/highscore.h" 37#include "lib/configfile.h"
38#include "lib/playback_control.h" 38#include "lib/playback_control.h"
39 39
40PLUGIN_HEADER 40PLUGIN_HEADER
@@ -154,9 +154,6 @@ PLUGIN_HEADER
154 154
155#define SNAKE_RC_QUIT BUTTON_REC 155#define SNAKE_RC_QUIT BUTTON_REC
156 156
157#elif (CONFIG_KEYPAD == COWOND2_PAD)
158#define SNAKE_QUIT BUTTON_POWER
159
160#elif CONFIG_KEYPAD == CREATIVEZVM_PAD 157#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
161#define SNAKE_QUIT BUTTON_BACK 158#define SNAKE_QUIT BUTTON_BACK
162#define SNAKE_LEFT BUTTON_LEFT 159#define SNAKE_LEFT BUTTON_LEFT
@@ -173,6 +170,14 @@ PLUGIN_HEADER
173#define SNAKE_DOWN BUTTON_DOWN 170#define SNAKE_DOWN BUTTON_DOWN
174#define SNAKE_PLAYPAUSE BUTTON_MENU 171#define SNAKE_PLAYPAUSE BUTTON_MENU
175 172
173#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
174#define SNAKE_QUIT BUTTON_REC
175#define SNAKE_LEFT BUTTON_LEFT
176#define SNAKE_RIGHT BUTTON_RIGHT
177#define SNAKE_UP BUTTON_UP
178#define SNAKE_DOWN BUTTON_DOWN
179#define SNAKE_PLAYPAUSE BUTTON_PLAY
180
176#elif CONFIG_KEYPAD == MROBE500_PAD 181#elif CONFIG_KEYPAD == MROBE500_PAD
177#define SNAKE_QUIT BUTTON_POWER 182#define SNAKE_QUIT BUTTON_POWER
178#define SNAKE_RC_QUIT BUTTON_RC_DOWN 183#define SNAKE_RC_QUIT BUTTON_RC_DOWN
@@ -183,13 +188,8 @@ PLUGIN_HEADER
183#elif (CONFIG_KEYPAD == ONDAVX777_PAD) 188#elif (CONFIG_KEYPAD == ONDAVX777_PAD)
184#define SNAKE_QUIT BUTTON_POWER 189#define SNAKE_QUIT BUTTON_POWER
185 190
186#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD 191#elif CONFIG_KEYPAD == COWOND2_PAD
187#define SNAKE_QUIT BUTTON_REC 192#define SNAKE_QUIT BUTTON_POWER
188#define SNAKE_LEFT BUTTON_LEFT
189#define SNAKE_RIGHT BUTTON_RIGHT
190#define SNAKE_UP BUTTON_UP
191#define SNAKE_DOWN BUTTON_DOWN
192#define SNAKE_PLAYPAUSE BUTTON_PLAY
193 193
194#else 194#else
195#error No keymap defined! 195#error No keymap defined!
@@ -218,44 +218,44 @@ PLUGIN_HEADER
218 218
219#define BOARD_WIDTH (LCD_WIDTH/4) 219#define BOARD_WIDTH (LCD_WIDTH/4)
220#define BOARD_HEIGHT (LCD_HEIGHT/4) 220#define BOARD_HEIGHT (LCD_HEIGHT/4)
221#define NUM_SCORES 5
222#define SCORE_FILE PLUGIN_GAMES_DIR "/snake.score"
223 221
224static int board[BOARD_WIDTH][BOARD_HEIGHT],snakelength; 222static int board[BOARD_WIDTH][BOARD_HEIGHT],snakelength;
225static int score,level=1; 223static unsigned int score,hiscore=0,level=1;
226static int dir,dead=0,quit=0; 224static int dir;
227static bool apple; 225static bool apple, dead;
228 226
229static struct highscore highscores[NUM_SCORES]; 227#define CONFIG_FILE_NAME "snake.cfg"
228static struct configdata config[] = {
229 {TYPE_INT, 0, 10, { .int_p = &level }, "level", NULL},
230 {TYPE_INT, 0, 10000, { .int_p = &hiscore }, "hiscore", NULL},
231};
230 232
231void die (void) 233static void snake_die (void)
232{ 234{
233 char pscore[17]; 235 char pscore[17];
234 rb->lcd_clear_display(); 236 rb->lcd_clear_display();
235 rb->snprintf(pscore,sizeof(pscore),"Your score: %d",score); 237 rb->snprintf(pscore,sizeof(pscore),"Your score: %d",score);
236 rb->lcd_puts(0,0,"Oops..."); 238 rb->lcd_puts(0,0,"Oops...");
237 rb->lcd_puts(0,1, pscore); 239 rb->lcd_puts(0,1, pscore);
238 if (highscore_update(score, level, "", highscores, NUM_SCORES) == 0) { 240 if (score>hiscore) {
241 hiscore=score;
239 rb->lcd_puts(0,2,"New High Score!"); 242 rb->lcd_puts(0,2,"New High Score!");
240 } 243 }
241 else { 244 else {
242 rb->snprintf(pscore, sizeof(pscore), 245 rb->snprintf(pscore,sizeof(pscore),"High Score: %d",hiscore);
243 "High Score: %d", highscores[0].score);
244 rb->lcd_puts(0,2,pscore); 246 rb->lcd_puts(0,2,pscore);
245 } 247 }
246 rb->lcd_update(); 248 rb->lcd_update();
247 rb->sleep(3*HZ); 249 rb->sleep(3*HZ);
248 dead=1; 250 dead=true;
249} 251}
250 252
251void colission (short x, short y) 253static void snake_colission (short x, short y)
252{ 254{
253 if (x==BOARD_WIDTH || x<0 || y==BOARD_HEIGHT || y<0) 255 if (x==BOARD_WIDTH || x<0 || y==BOARD_HEIGHT || y<0) {
254 { 256 snake_die();
255 die();
256 return; 257 return;
257 } 258 }
258
259 switch (board[x][y]) { 259 switch (board[x][y]) {
260 case 0: 260 case 0:
261 break; 261 break;
@@ -265,12 +265,12 @@ void colission (short x, short y)
265 apple=false; 265 apple=false;
266 break; 266 break;
267 default: 267 default:
268 die(); 268 snake_die();
269 break; 269 break;
270 } 270 }
271} 271}
272 272
273void move_head (short x, short y) 273static void snake_move_head (short x, short y)
274{ 274{
275 switch (dir) { 275 switch (dir) {
276 case 0: 276 case 0:
@@ -286,14 +286,36 @@ void move_head (short x, short y)
286 x-=1; 286 x-=1;
287 break; 287 break;
288 } 288 }
289 colission (x,y); 289 snake_colission (x,y);
290 if (dead) 290 if (dead)
291 return; 291 return;
292 board[x][y]=1; 292 board[x][y]=1;
293 rb->lcd_fillrect(x*4,y*4,4,4); 293 rb->lcd_fillrect(x*4,y*4,4,4);
294} 294}
295 295
296void frame (void) 296static void snake_redraw (void)
297{
298 short x,y;
299 rb->lcd_clear_display();
300 for (x=0; x<BOARD_WIDTH; x++) {
301 for (y=0; y<BOARD_HEIGHT; y++) {
302 switch (board[x][y]) {
303 case -1:
304 rb->lcd_fillrect((x*4)+1,y*4,2,4);
305 rb->lcd_fillrect(x*4,(y*4)+1,4,2);
306 break;
307 case 0:
308 break;
309 default:
310 rb->lcd_fillrect(x*4,y*4,4,4);
311 break;
312 }
313 }
314 }
315 rb->lcd_update();
316}
317
318static void snake_frame (void)
297{ 319{
298 short x,y,head=0; 320 short x,y,head=0;
299 for (x=0; x<BOARD_WIDTH; x++) { 321 for (x=0; x<BOARD_WIDTH; x++) {
@@ -301,7 +323,7 @@ void frame (void)
301 switch (board[x][y]) { 323 switch (board[x][y]) {
302 case 1: 324 case 1:
303 if (!head) { 325 if (!head) {
304 move_head(x,y); 326 snake_move_head(x,y);
305 if (dead) 327 if (dead)
306 return; 328 return;
307 board[x][y]++; 329 board[x][y]++;
@@ -328,92 +350,116 @@ void frame (void)
328 rb->lcd_update(); 350 rb->lcd_update();
329} 351}
330 352
331void redraw (void) 353static void snake_game_init(void) {
332{
333 short x,y; 354 short x,y;
334 rb->lcd_clear_display(); 355 rb->lcd_clear_display();
356
335 for (x=0; x<BOARD_WIDTH; x++) { 357 for (x=0; x<BOARD_WIDTH; x++) {
336 for (y=0; y<BOARD_HEIGHT; y++) { 358 for (y=0; y<BOARD_HEIGHT; y++) {
337 switch (board[x][y]) { 359 board[x][y]=0;
338 case -1:
339 rb->lcd_fillrect((x*4)+1,y*4,2,4);
340 rb->lcd_fillrect(x*4,(y*4)+1,4,2);
341 break;
342 case 0:
343 break;
344 default:
345 rb->lcd_fillrect(x*4,y*4,4,4);
346 break;
347 }
348 } 360 }
349 } 361 }
350 rb->lcd_update(); 362 apple=false;
363 dead=false;
364 snakelength=4;
365 score=0;
366 board[11][7]=1;
351} 367}
352 368
353void game_pause (void) { 369static void snake_choose_level(void)
354 int button; 370{
355 rb->lcd_clear_display(); 371 rb->set_int("Snake Speed", "", UNIT_INT, &level, NULL, 1, 1, 9, NULL);
356 rb->lcd_putsxy(3,12,"Game Paused"); 372}
357#if CONFIG_KEYPAD == RECORDER_PAD 373
358 rb->lcd_putsxy(3,22,"[Play] to resume"); 374static bool _ingame;
359#elif CONFIG_KEYPAD == ONDIO_PAD 375static int snake_menu_cb(int action, const struct menu_item_ex *this_item)
360 rb->lcd_putsxy(3,22,"[Mode] to resume"); 376{
361#endif 377 if(action == ACTION_REQUEST_MENUITEM
362 rb->lcd_putsxy(3,32,"[Off] to quit"); 378 && !_ingame && ((intptr_t)this_item)==0)
363 rb->lcd_update(); 379 return ACTION_EXIT_MENUITEM;
364 while (1) { 380 return action;
365 button=rb->button_get(true); 381}
366 switch (button) { 382
367#ifdef SNAKE_RC_QUIT 383static int snake_game_menu(bool ingame)
368 case SNAKE_RC_QUIT: 384{
369#endif 385 rb->button_clear_queue();
370 case SNAKE_QUIT: 386 int choice = 0;
371 dead=1; 387
372 quit=1; 388 _ingame = ingame;
373 return; 389
374 case SNAKE_PLAYPAUSE: 390 MENUITEM_STRINGLIST(main_menu,"Snake Menu",snake_menu_cb,
375 redraw(); 391 "Resume Game",
376 rb->sleep(HZ/2); 392 "Start New Game",
377 return; 393 "Snake Speed",
394 "High Score",
395 "Playback Control",
396 "Quit");
397
398 while (true) {
399 choice = rb->do_menu(&main_menu, &choice, NULL, false);
400 switch (choice) {
401 case 0:
402 snake_redraw();
403 return 0;
404 case 1:
405 snake_game_init();
406 return 0;
407 case 2:
408 snake_choose_level();
409 break;
410 case 3:
411 rb->splashf(HZ*2, "High Score: %d", hiscore);
412 break;
413 case 4:
414 playback_control(NULL);
415 break;
416 case 5:
417 return 1;
418 case MENU_ATTACHED_USB:
419 return 1;
378 default: 420 default:
379 if (rb->default_event_handler(button)==SYS_USB_CONNECTED) {
380 dead = 1;
381 quit = 2;
382 return;
383 }
384 break; 421 break;
385 } 422 }
386 } 423 }
387} 424}
388 425
389 426static int snake_game_loop (void) {
390void game (void) {
391 int button; 427 int button;
392 short x,y; 428 short x,y;
393 while (1) { 429 bool pause = false;
394 frame(); 430
395 if (dead) 431 if (snake_game_menu(false)==1)
396 return; 432 return 1;
397 if (!apple) { 433
398 do { 434 while (true) {
399 x=rb->rand() % BOARD_WIDTH; 435 if (!pause) {
400 y=rb->rand() % BOARD_HEIGHT; 436 snake_frame();
401 } while (board[x][y]); 437 if (dead) {
402 apple=true; 438 if (snake_game_menu(false)==1)
403 board[x][y]=-1; 439 return 1;
404 rb->lcd_fillrect((x*4)+1,y*4,2,4); 440 }
405 rb->lcd_fillrect(x*4,(y*4)+1,4,2); 441 if (!apple) {
406 } 442 do {
443 x=rb->rand() % BOARD_WIDTH;
444 y=rb->rand() % BOARD_HEIGHT;
445 } while (board[x][y]);
446 apple=true;
447 board[x][y]=-1;
448 rb->lcd_fillrect((x*4)+1,y*4,2,4);
449 rb->lcd_fillrect(x*4,(y*4)+1,4,2);
450 }
407 451
408 rb->sleep(HZ/level); 452 rb->sleep(HZ/level);
453 }
409 454
410 button=rb->button_get(false); 455 button=rb->button_get(false);
411 456
412#ifdef HAS_BUTTON_HOLD 457#ifdef HAS_BUTTON_HOLD
413 if (rb->button_hold()) 458 if (rb->button_hold()) {
414 button = SNAKE_PLAYPAUSE; 459 pause = true;
460 rb->splash (HZ, "Paused");
461 }
415#endif 462#endif
416
417 switch (button) { 463 switch (button) {
418 case SNAKE_UP: 464 case SNAKE_UP:
419 if (dir!=2) dir=0; 465 if (dir!=2) dir=0;
@@ -427,113 +473,37 @@ void game (void) {
427 case SNAKE_LEFT: 473 case SNAKE_LEFT:
428 if (dir!=1) dir=3; 474 if (dir!=1) dir=3;
429 break; 475 break;
476 case SNAKE_PLAYPAUSE:
477 pause = !pause;
478 if (pause)
479 rb->splash (HZ, "Paused");
480 else
481 snake_redraw();
482 break;
430#ifdef SNAKE_RC_QUIT 483#ifdef SNAKE_RC_QUIT
431 case SNAKE_RC_QUIT: 484 case SNAKE_RC_QUIT:
432#endif 485#endif
433 case SNAKE_QUIT: 486 case SNAKE_QUIT:
434 quit = 1; 487 pause = false;
435 return; 488 if (snake_game_menu(true)==1)
436 case SNAKE_PLAYPAUSE: 489 return 1;
437 game_pause();
438 break;
439 default:
440 if (rb->default_event_handler(button)==SYS_USB_CONNECTED) {
441 quit = 2;
442 return;
443 }
444 break;
445 }
446 }
447}
448
449void game_init(void) {
450 int selection=0;
451 short x,y;
452 bool menu_quit = false;
453
454 for (x=0; x<BOARD_WIDTH; x++) {
455 for (y=0; y<BOARD_HEIGHT; y++) {
456 board[x][y]=0;
457 }
458 }
459 dead=0;
460 apple=false;
461 snakelength=4;
462 score=0;
463 board[11][7]=1;
464
465#if LCD_DEPTH > 1
466 fb_data *backdrop = rb->lcd_get_backdrop();
467#endif
468
469 MENUITEM_STRINGLIST(menu, "Snake Menu", NULL,
470 "Start New Game", "Starting Level",
471 "High Scores",
472 "Playback Control", "Quit");
473
474 rb->button_clear_queue();
475
476 while (!menu_quit) {
477 switch(rb->do_menu(&menu, &selection, NULL, false))
478 {
479 case 0:
480 menu_quit = true; /* start playing */
481 break; 490 break;
482
483 case 1:
484 rb->set_int("Starting Level", "", UNIT_INT, &level, NULL,
485 1, 1, 9, NULL );
486 break;
487
488 case 2:
489#if LCD_DEPTH > 1
490 rb->lcd_set_backdrop(NULL);
491#endif
492 highscore_show(NUM_SCORES, highscores, NUM_SCORES, true);
493
494 rb->lcd_setfont(FONT_UI);
495#if LCD_DEPTH > 1
496 rb->lcd_set_backdrop(backdrop);
497#ifdef HAVE_LCD_COLOR
498 rb->lcd_set_background(rb->global_settings->bg_color);
499 rb->lcd_set_foreground(rb->global_settings->fg_color);
500#endif
501#endif
502 break;
503
504 case 3:
505 playback_control(NULL);
506 break;
507
508 case MENU_ATTACHED_USB:
509 quit = 2;
510 menu_quit = true;
511 break;
512
513 default: 491 default:
514 quit = 1; /* quit program */ 492 if (rb->default_event_handler (button) == SYS_USB_CONNECTED)
515 menu_quit = true; 493 return PLUGIN_USB_CONNECTED;
516 break; 494 break;
517
518 } 495 }
519 } 496 }
520} 497}
521 498
522enum plugin_status plugin_start(const void* parameter) 499enum plugin_status plugin_start(const void* parameter)
523{ 500{
524 (void)(parameter); 501 (void)parameter;
525 502
526 highscore_load(SCORE_FILE, highscores, NUM_SCORES); 503 configfile_load(CONFIG_FILE_NAME,config,2,0);
527 while(!quit) 504 rb->lcd_clear_display();
528 { 505 snake_game_loop();
529 game_init(); 506 configfile_save(CONFIG_FILE_NAME,config,2,0);
530 if(quit) 507 return PLUGIN_OK;
531 break;
532 rb->lcd_clear_display();
533 game();
534 }
535 highscore_save(SCORE_FILE, highscores, NUM_SCORES);
536 return (quit==1)?PLUGIN_OK:PLUGIN_USB_CONNECTED;
537} 508}
538
539#endif 509#endif