/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2002 Frederic Dang Ngoc * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include "plugin.h" #ifdef HAVE_LCD_BITMAP PLUGIN_HEADER /* file which contains the levels */ #define STAR_LEVELS_FILE "/.rockbox/star/levels.txt" /* title of the game */ #define STAR_TITLE "Star" /* font used to display title */ #define STAR_TITLE_FONT 2 /* size of a level in file */ #define STAR_LEVEL_SIZE ((STAR_WIDTH + 1) * STAR_HEIGHT + 1) /* size of the game board */ #define STAR_WIDTH 16 #define STAR_HEIGHT 9 /* number of level */ #define STAR_LEVEL_COUNT 20 /* values of object in the board */ #define STAR_VOID '.' #define STAR_WALL '*' #define STAR_STAR 'o' #define STAR_BALL 'X' #define STAR_BLOCK 'x' /* sleep time between two frames */ #if (LCD_HEIGHT == 240) && (LCD_WIDTH == 320) /* iPod 5G LCD is *slow* */ #define STAR_SLEEP ; #elif (LCD_HEIGHT == 128) && (LCD_WIDTH == 160) #define STAR_SLEEP rb->sleep(0); #else #define STAR_SLEEP rb->sleep(1); #endif /* value of ball and block control */ #define STAR_CONTROL_BALL 0 #define STAR_CONTROL_BLOCK 1 /* variable button definitions */ #if CONFIG_KEYPAD == RECORDER_PAD #define STAR_QUIT BUTTON_OFF #define STAR_UP BUTTON_UP #define STAR_DOWN BUTTON_DOWN #define STAR_TOGGLE_CONTROL BUTTON_ON #define STAR_TOGGLE_CONTROL2 BUTTON_PLAY #define STAR_LEVEL_UP BUTTON_F3 #define STAR_LEVEL_DOWN BUTTON_F1 #define STAR_LEVEL_REPEAT BUTTON_F2 #define STAR_MENU_RUN BUTTON_PLAY #define STAR_MENU_RUN2 BUTTON_RIGHT #define STAR_MENU_RUN3 BUTTON_ON #elif CONFIG_KEYPAD == ONDIO_PAD #define STAR_QUIT BUTTON_OFF #define STAR_UP BUTTON_UP #define STAR_DOWN BUTTON_DOWN #define STAR_TOGGLE_CONTROL_PRE BUTTON_MENU #define STAR_TOGGLE_CONTROL (BUTTON_MENU | BUTTON_REL) #define STAR_LEVEL_UP (BUTTON_MENU | BUTTON_RIGHT) #define STAR_LEVEL_DOWN (BUTTON_MENU | BUTTON_LEFT) #define STAR_LEVEL_REPEAT (BUTTON_MENU | BUTTON_UP) #define STAR_MENU_RUN BUTTON_RIGHT #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ (CONFIG_KEYPAD == IRIVER_H300_PAD) #define STAR_QUIT BUTTON_OFF #define STAR_UP BUTTON_UP #define STAR_DOWN BUTTON_DOWN #define STAR_TOGGLE_CONTROL BUTTON_MODE #define STAR_TOGGLE_CONTROL2 BUTTON_SELECT #define STAR_LEVEL_UP (BUTTON_ON | BUTTON_RIGHT) #define STAR_LEVEL_DOWN (BUTTON_ON | BUTTON_LEFT) #define STAR_LEVEL_REPEAT (BUTTON_ON | BUTTON_SELECT) #define STAR_MENU_RUN BUTTON_RIGHT #define STAR_MENU_RUN2 BUTTON_SELECT #define STAR_RC_QUIT BUTTON_RC_STOP #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ (CONFIG_KEYPAD == IPOD_3G_PAD) #define STAR_QUIT (BUTTON_SELECT | BUTTON_MENU) #define STAR_UP BUTTON_MENU #define STAR_DOWN BUTTON_PLAY #define STAR_TOGGLE_CONTROL_PRE BUTTON_SELECT #define STAR_TOGGLE_CONTROL (BUTTON_SELECT | BUTTON_REL) #define STAR_LEVEL_UP (BUTTON_SELECT | BUTTON_RIGHT) #define STAR_LEVEL_DOWN (BUTTON_SELECT | BUTTON_LEFT) #define STAR_LEVEL_REPEAT (BUTTON_SELECT | BUTTON_PLAY) #define STAR_MENU_RUN BUTTON_RIGHT #define STAR_MENU_RUN2 BUTTON_SELECT #elif (CONFIG_KEYPAD == IAUDIO_X5_PAD) #define STAR_QUIT BUTTON_POWER #define STAR_UP BUTTON_UP #define STAR_DOWN BUTTON_DOWN #define STAR_TOGGLE_CONTROL_PRE BUTTON_SELECT #define STAR_TOGGLE_CONTROL (BUTTON_SELECT | BUTTON_REL) #define STAR_LEVEL_UP (BUTTON_PLAY | BUTTON_UP) #define STAR_LEVEL_DOWN (BUTTON_PLAY | BUTTON_DOWN) #define STAR_LEVEL_REPEAT (BUTTON_PLAY | BUTTON_RIGHT) #define STAR_MENU_RUN BUTTON_REC #elif (CONFIG_KEYPAD == GIGABEAT_PAD) #define STAR_QUIT BUTTON_A #define STAR_UP BUTTON_UP #define STAR_DOWN BUTTON_DOWN #define STAR_TOGGLE_CONTROL_PRE BUTTON_MENU #define STAR_TOGGLE_CONTROL (BUTTON_MENU | BUTTON_REL) #define STAR_LEVEL_UP (BUTTON_POWER | BUTTON_UP) #define STAR_LEVEL_DOWN (BUTTON_POWER | BUTTON_DOWN) #define STAR_LEVEL_REPEAT (BUTTON_POWER | BUTTON_RIGHT) #define STAR_MENU_RUN BUTTON_RIGHT #elif (CONFIG_KEYPAD == IRIVER_H10_PAD) #define STAR_QUIT BUTTON_POWER #define STAR_UP BUTTON_SCROLL_UP #define STAR_DOWN BUTTON_SCROLL_DOWN #define STAR_TOGGLE_CONTROL_PRE BUTTON_REW #define STAR_TOGGLE_CONTROL (BUTTON_REW | BUTTON_REL) #define STAR_LEVEL_UP (BUTTON_PLAY | BUTTON_SCROLL_UP) #define STAR_LEVEL_DOWN (BUTTON_PLAY | BUTTON_SCROLL_DOWN) #define STAR_LEVEL_REPEAT (BUTTON_PLAY | BUTTON_RIGHT) #define STAR_MENU_RUN BUTTON_FF #endif /* function returns because of USB? */ static bool usb_detected = false; /* position of the ball */ static int ball_x, ball_y; /* position of the block */ static int block_x, block_y; /* number of stars to get to finish the level */ static int star_count; /* the object we control : ball or block */ static int control; /* the current board */ static char board[STAR_HEIGHT][STAR_WIDTH]; #if LCD_DEPTH > 1 extern const fb_data star_tiles[]; /* size of a tile */ #if LCD_WIDTH >= 320 && defined( HAVE_LCD_COLOR ) # define STAR_TILE_SIZE 20 #elif LCD_WIDTH >= 220 && defined( HAVE_LCD_COLOR ) # define STAR_TILE_SIZE 13 #else # define STAR_TILE_SIZE 10 #endif /* left and top margin */ #define STAR_OFFSET_X ( ( LCD_WIDTH - STAR_WIDTH * STAR_TILE_SIZE ) / 2 ) #define STAR_OFFSET_Y ( ( LCD_HEIGHT - ( STAR_HEIGHT + 1 ) * STAR_TILE_SIZE ) / 2 ) #define wall 0 #define space 1 #define block 2 #define star 3 #define ball 4 #else /* left and top margin */ #define STAR_OFFSET_X 8 #define STAR_OFFSET_Y 0 /* size of a tile */ #define STAR_TILE_SIZE 6 /* bitmap of the wall */ static unsigned char wall_bmp[STAR_TILE_SIZE] = {0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55}; /* bitmap of the star */ static unsigned char star_bmp[STAR_TILE_SIZE] = {0x00, 0x0c, 0x12, 0x12, 0x0c, 0x00}; /* bitmap of the ball */ static unsigned char ball_bmp[STAR_TILE_SIZE] = {0x00, 0x0c, 0x1e, 0x1a, 0x0c, 0x00}; /* bitmap of the block */ static unsigned char block_bmp[STAR_TILE_SIZE] = {0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00}; #endif /* bitmap of the arrow animation */ static unsigned char arrow_bmp[4][7] = { {0x7f, 0x7f, 0x3e, 0x3e, 0x1c, 0x1c, 0x08}, {0x3e, 0x3e, 0x1c, 0x1c, 0x08, 0x08, 0x08}, {0x1c, 0x1c, 0x1c, 0x1c, 0x08, 0x08, 0x08}, {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08} }; /* sequence of the bitmap arrow to follow to do one turn */ static unsigned char anim_arrow[8] = {0, 1, 2, 3, 2, 1, 0}; /* current_level */ static int current_level = 0; /* char font size */ static int char_width = -1; static int char_height = -1; static struct plugin_api* rb; /* this arrays contains a group of levels loaded into memory */ static unsigned char* levels = "****************\n" "*X**........o*x*\n" "*..........o.***\n" "*.......**o....*\n" "*...**.o......**\n" "**.o..o.....o..*\n" "*.o......o**.o.*\n" "*.....**o.....o*\n" "****************\n" "\n" ".*..*.*.*...*.**\n" "*...o.........X*\n" "...*o..*o...o...\n" "*.*.o.....o..*.*\n" "......*...o...*.\n" "*....*x*..o....*\n" "...*..*.*...*oo*\n" "*.............*.\n" ".*..*........*..\n" "\n" "****************\n" "*...........o*x*\n" "*...**......**X*\n" "*...*o.........*\n" "*.o.....o**...o*\n" "*.*o..o..o*..o**\n" "*.**o.*o..o.o***\n" "*o....**o......*\n" "****************\n" "\n" "****************\n" "*............*x*\n" "*.....*........*\n" "**o*o.o*o*o*o*o*\n" "*.*.*o.o*.*.*.**\n" "**o*o*o.o*o*o*o*\n" "*.....*........*\n" "*...*.......*X.*\n" "****************\n" "\n" ".**************.\n" "*X..*...*..*...*\n" "*..*o.*.o..o.*.*\n" "**......*..*...*\n" "*o.*o*........**\n" "**.....*.o.*...*\n" "*o*..*.*.*...*x*\n" "*...*....o*..*o*\n" ".**************.\n" "\n" "....************\n" "...*...o...*o.o*\n" "..*....o....*.**\n" ".*.....o.......*\n" "*X.....o.......*\n" "**.....o..*...**\n" "*......o....*..*\n" "*x.*...o..**o..*\n" "****************\n" "\n" "****************\n" "*..............*\n" ".**.***..*o.**o*\n" ".*o..*o.*.*.*.*.\n" "..*..*..***.**..\n" ".**..*..*o*.*o**\n" "*..............*\n" "*..X*o....x..*o*\n" "****************\n" "\n" "***************.\n" "*..o**.........*\n" "*..*o..**.o....*\n" "*..o**.*.*o....*\n" "**.....**..*o*.*\n" "**.*.......o*o.*\n" "*oxo*...o..*X*.*\n" "**.............*\n" ".***************\n" "\n" "..*.***********.\n" ".*o*o......*..X*\n" "*o.o*....o....*.\n" ".*.*..o**..o*..*\n" "*..*o.*oxo....o*\n" "*.....o**.....*.\n" "*o*o.........*..\n" "*...........*...\n" ".***********....\n" "\n" "....***********.\n" "*****.o........*\n" "*...x.***o.o*.o*\n" "*.o...*o.*o...*.\n" "*.....*..o..*.o*\n" "*o*o..*.o*..*X*.\n" ".*o...***..***..\n" "*.........*.*.*.\n" ".*********..*..*\n" "\n" "****************\n" "*......*......X*\n" "*..*oo.....oo.**\n" "**...o...**...o*\n" "*o....*o*oo..***\n" "**.**....**....*\n" "*o..o*.o....x.o*\n" "**o***....*...**\n" "***************.\n" "\n" "**.....**..****.\n" "*X*****o.***.o**\n" "*....oo.....o..*\n" "*.**..**o..*o*.*\n" "*.*.o.*.*o.**..*\n" "*.**..**...*x*.*\n" "*.....o........*\n" "*........o.....*\n" "****************\n" "\n" ".**************.\n" "*.X*........o.**\n" "*.*...*o...o**.*\n" "*.......o....*.*\n" "*.o..........*o*\n" "*.*......o.....*\n" "**......o.o..*o*\n" "*x..*....o.*.*.*\n" ".**************.\n" "\n" "****************\n" "*o*o........o*o*\n" "*.o*X......**..*\n" "*.x........o...*\n" "*........o*....*\n" "*......o.......*\n" "*.o*........*..*\n" "*o*o........o*o*\n" "****************\n" "\n" ".******.********\n" "*.....o*.....o.*\n" "*.*.o.*..*...o.*\n" "*..X*...*oo.*o.*\n" ".*.*...*.o..x*.*\n" "*o.......*..*o.*\n" ".*......o.....*.\n" "*o............o*\n" "****************\n" "\n" "****************\n" "**.x*o.o......o*\n" "*o.Xo*o.......**\n" "**.***........**\n" "**.....o*o*....*\n" "*oo.......o*o..*\n" "**.o....****o..*\n" "**o*..*........*\n" "****************\n" "\n" "****************\n" "*.o*........*X.*\n" "*.*..o*oo*o..*.*\n" "*....*o**o*.o..*\n" "*.o*.......o*..*\n" "*..o*o....o*...*\n" "*.*..*.**o*..*.*\n" "*....o.*o...x..*\n" "****************\n" "\n" "****************\n" "*.o....o..x*...*\n" "*..*o*o...*o...*\n" "*...*o*....*o..*\n" "*...o..*...o*o.*\n" "*.*o*...*.o*...*\n" "*.o*o.*.o.*....*\n" "*o*X..*.....*..*\n" "****************\n" "\n" "****************\n" "*o...**.....**o*\n" "*.*..*......*o.*\n" "*.o*...o**..o..*\n" "*.*....*o......*\n" "*....*...o*....*\n" "*.**.o*.**o..*x*\n" "*.o*.*o.....**X*\n" "****************\n" "\n" "****************\n" "*...o*o........*\n" "**o..o*.**o...**\n" "*.*.*.o...*..*.*\n" "*.x.*..**..*.Xo*\n" "*.*..*...o.*.*.*\n" "**...o**.*o..o**\n" "*........o*o...*\n" "****************"; /** * Display text. */ static void star_display_text(char *str, bool waitkey) { int chars_by_line; int lines_by_screen; int chars_for_line; int current_line = 0; int first_char_index = 0; char *ptr_char; char *ptr_line; int i; char line[255]; int key; bool go_on; rb->lcd_clear_display(); chars_by_line = LCD_WIDTH / char_width; lines_by_screen = LCD_HEIGHT / char_height; do { ptr_char = str + first_char_index; chars_for_line = 0; i = 0; ptr_line = line; while (i < chars_by_line) { switch (*ptr_char) { case '\t': case ' ': *(ptr_line++) = ' '; case '\n': case '\0': chars_for_line = i; break; default: *(ptr_line++) = *ptr_char; } if (*ptr_char == '\n' || *ptr_char == '\0') break; ptr_char++; i++; } if (chars_for_line == 0) chars_for_line = i; line[chars_for_line] = '\0'; /* test if we have cutted a word. If it is the case we don't have to */ /* skip the space */ if (i == chars_by_line && chars_for_line == chars_by_line) first_char_index += chars_for_line; else first_char_index += chars_for_line + 1; /* print the line on the screen */ rb->lcd_putsxy(0, current_line * char_height, line); /* if the number of line showed on the screen is equals to the */ /* maximum number of line we can show, we wait for a key pressed to */ /* clear and show the remaining text. */ current_line++; if (current_line == lines_by_screen || *ptr_char == '\0') { current_line = 0; rb->lcd_update(); go_on = false; while (waitkey && !go_on) { key = rb->button_get(true); switch (key) { case STAR_QUIT: case BUTTON_LEFT: case STAR_DOWN: go_on = true; break; default: if (rb->default_event_handler(key) == SYS_USB_CONNECTED) { usb_detected = true; go_on = true; break; } } } rb->lcd_clear_display(); } } while (*ptr_char != '\0'); } /** * Do a pretty transition from one level to another. */ static void star_transition_update(void) { int center_x = LCD_WIDTH / 2; int lcd_demi_width = LCD_WIDTH / 2; int center_y = LCD_HEIGHT / 2; int x; int y = 0; int var_y = 0; for (x = 1 ; x < lcd_demi_width ; x++) { var_y += LCD_HEIGHT; if (var_y > LCD_WIDTH) { var_y -= LCD_WIDTH; y++; } rb->lcd_update_rect(center_x - x, center_y - y, x * 2, y * 2); STAR_SLEEP } rb->lcd_update(); } /** * Display information board of the current level. */ static void star_display_board_info(void) { int label_offset_y = label_offset_y = LCD_HEIGHT - char_height - ( STAR_TILE_SIZE - char_height ) / 2 ; char str_info[32]; rb->snprintf(str_info, sizeof(str_info), "L:%02d S:%02d C:", current_level, star_count); rb->lcd_putsxy(0, label_offset_y, str_info); #if LCD_DEPTH > 1 if( control == STAR_CONTROL_BALL ) rb->lcd_bitmap_part( star_tiles, 0, ball*STAR_TILE_SIZE, STAR_TILE_SIZE, 107, label_offset_y - ( STAR_TILE_SIZE - char_height ) / 2 - 2, STAR_TILE_SIZE, STAR_TILE_SIZE); else rb->lcd_bitmap_part( star_tiles, 0, block*STAR_TILE_SIZE, STAR_TILE_SIZE, 107, label_offset_y - ( STAR_TILE_SIZE - char_height ) / 2 - 2, STAR_TILE_SIZE, STAR_TILE_SIZE); rb->lcd_update_rect(0, label_offset_y - ( STAR_TILE_SIZE - char_height ) / 2 - 2, LCD_WIDTH, STAR_TILE_SIZE ); #else if (control == STAR_CONTROL_BALL) rb->lcd_mono_bitmap (ball_bmp, 103, label_offset_y + 1, STAR_TILE_SIZE, STAR_TILE_SIZE); else rb->lcd_mono_bitmap (block_bmp, 103, label_offset_y + 1, STAR_TILE_SIZE, STAR_TILE_SIZE); rb->lcd_update_rect(0, label_offset_y, LCD_WIDTH, char_height); #endif } /** * Load a level into board array. */ static int star_load_level(int current_level) { int x, y; char *ptr_tab; ptr_tab = levels + current_level * STAR_LEVEL_SIZE; control = STAR_CONTROL_BALL; star_count = 0; rb->lcd_clear_display(); for (y = 0 ; y < STAR_HEIGHT ; y++) { for (x = 0 ; x < STAR_WIDTH ; x++) { board[y][x] = *ptr_tab; switch (*ptr_tab) { #if LCD_DEPTH > 1 # define DRAW_TILE( a ) \ rb->lcd_bitmap_part( star_tiles, 0, \ a*STAR_TILE_SIZE, STAR_TILE_SIZE, \ STAR_OFFSET_X + x * STAR_TILE_SIZE, \ STAR_OFFSET_Y + y * STAR_TILE_SIZE, \ STAR_TILE_SIZE, STAR_TILE_SIZE); #else # define DRAW_TILE( a ) \ rb->lcd_mono_bitmap ( a ## _bmp, \ STAR_OFFSET_X + x * STAR_TILE_SIZE, \ STAR_OFFSET_Y + y * STAR_TILE_SIZE, \ STAR_TILE_SIZE, STAR_TILE_SIZE); #endif case STAR_VOID: #if LCD_DEPTH > 1 DRAW_TILE( space ); #endif break; case STAR_WALL: DRAW_TILE( wall ); break; case STAR_STAR: DRAW_TILE( star ); star_count++; break; case STAR_BALL: ball_x = x; ball_y = y; DRAW_TILE( ball ); break; case STAR_BLOCK: block_x = x; block_y = y; DRAW_TILE( block ); break; } ptr_tab++; } ptr_tab++; } star_display_board_info(); star_transition_update(); return 1; } /** * Run the game. */ static int star_run_game(void) { int move_x = 0; int move_y = 0; int i; int key; int lastkey = BUTTON_NONE; int label_offset_y; label_offset_y = LCD_HEIGHT - char_height; if (!star_load_level(current_level)) return 0; while (true) { move_x = 0; move_y = 0; while ((move_x == 0) && (move_y == 0)) { key = rb->button_get(true); switch (key) { #ifdef STAR_RC_QUIT case STAR_RC_QUIT: #endif case STAR_QUIT: return -1; case BUTTON_LEFT: move_x = -1; break; case BUTTON_RIGHT: move_x = 1; break; case STAR_UP: move_y = -1; break; case STAR_DOWN: move_y = 1; break; case STAR_LEVEL_DOWN: if (current_level > 0) { current_level--; star_load_level(current_level); } break; case STAR_LEVEL_REPEAT: star_load_level(current_level); break; case STAR_LEVEL_UP: if (current_level < STAR_LEVEL_COUNT - 1) { current_level++; star_load_level(current_level); } break; case STAR_TOGGLE_CONTROL: #ifdef STAR_TOGGLE_CONTROL_PRE if (lastkey != STAR_TOGGLE_CONTROL_PRE) break; #endif #ifdef STAR_TOGGLE_CONTROL2 case STAR_TOGGLE_CONTROL2: #endif if (control == STAR_CONTROL_BALL) control = STAR_CONTROL_BLOCK; else control = STAR_CONTROL_BALL; star_display_board_info(); break; default: if (rb->default_event_handler(key) == SYS_USB_CONNECTED) { usb_detected = true; return 0; } break; } if (key != BUTTON_NONE) lastkey = key; } if (control == STAR_CONTROL_BALL) { board[ball_y][ball_x] = STAR_VOID; while ((board[ball_y + move_y][ball_x + move_x] == STAR_VOID || board[ball_y + move_y][ball_x + move_x] == STAR_STAR)) { for (i = 0 ; i <= STAR_TILE_SIZE ; i++) { #if LCD_DEPTH > 1 rb->lcd_bitmap_part( star_tiles, 0, space * STAR_TILE_SIZE, STAR_TILE_SIZE, STAR_OFFSET_X + ball_x * STAR_TILE_SIZE, STAR_OFFSET_Y + ball_y * STAR_TILE_SIZE, STAR_TILE_SIZE, STAR_TILE_SIZE); rb->lcd_bitmap_part( star_tiles, 0, ball * STAR_TILE_SIZE, STAR_TILE_SIZE, STAR_OFFSET_X + ball_x * STAR_TILE_SIZE + move_x * i, STAR_OFFSET_Y + ball_y * STAR_TILE_SIZE + move_y * i, STAR_TILE_SIZE, STAR_TILE_SIZE); rb->lcd_update_rect( STAR_OFFSET_X + ball_x * STAR_TILE_SIZE + move_x * (i>0?i-1:0), STAR_OFFSET_Y + ball_y * STAR_TILE_SIZE + move_y * (i>0?i-1:0), STAR_TILE_SIZE+(i>0?0:1), STAR_TILE_SIZE+(i>0?0:1)); #else rb->lcd_mono_bitmap( ball_bmp, STAR_OFFSET_X + ball_x * STAR_TILE_SIZE + move_x * i, STAR_OFFSET_Y + ball_y * STAR_TILE_SIZE + move_y * i, STAR_TILE_SIZE, STAR_TILE_SIZE); rb->lcd_update_rect( STAR_OFFSET_X + ball_x * STAR_TILE_SIZE + move_x * i, STAR_OFFSET_Y + ball_y * STAR_TILE_SIZE + move_y * i, STAR_TILE_SIZE, STAR_TILE_SIZE); #endif STAR_SLEEP } ball_x += move_x; ball_y += move_y; if (board[ball_y][ball_x] == STAR_STAR) { board[ball_y][ball_x] = STAR_VOID; star_count--; star_display_board_info(); } } board[ball_y][ball_x] = STAR_BALL; } else { board[block_y][block_x] = STAR_VOID; while (board[block_y + move_y][block_x + move_x] == STAR_VOID) { for (i = 0 ; i <= STAR_TILE_SIZE ; i++) { #if LCD_DEPTH > 1 rb->lcd_bitmap_part( star_tiles, 0, space * STAR_TILE_SIZE, STAR_TILE_SIZE, STAR_OFFSET_X + block_x * STAR_TILE_SIZE, STAR_OFFSET_Y + block_y * STAR_TILE_SIZE, STAR_TILE_SIZE, STAR_TILE_SIZE); rb->lcd_bitmap_part( star_tiles, 0, block * STAR_TILE_SIZE, STAR_TILE_SIZE, STAR_OFFSET_X + block_x * STAR_TILE_SIZE + move_x * i, STAR_OFFSET_Y + block_y * STAR_TILE_SIZE + move_y * i, STAR_TILE_SIZE, STAR_TILE_SIZE); rb->lcd_update_rect( STAR_OFFSET_X + block_x * STAR_TILE_SIZE + move_x * (i>0?i-1:0), STAR_OFFSET_Y + block_y * STAR_TILE_SIZE + move_y * (i>0?i-1:0), STAR_TILE_SIZE+(i>0?0:1), STAR_TILE_SIZE+(i>0?0:1)); #else rb->lcd_mono_bitmap( block_bmp, STAR_OFFSET_X + block_x * STAR_TILE_SIZE + move_x * i, STAR_OFFSET_Y + block_y * STAR_TILE_SIZE + move_y * i, STAR_TILE_SIZE, STAR_TILE_SIZE); rb->lcd_update_rect( STAR_OFFSET_X + block_x * STAR_TILE_SIZE + move_x * i, STAR_OFFSET_Y + block_y * STAR_TILE_SIZE + move_y * i, STAR_TILE_SIZE, STAR_TILE_SIZE); #endif STAR_SLEEP } block_x += move_x; block_y += move_y; } board[block_y][block_x] = STAR_BLOCK; } if (star_count == 0) { current_level++; if (current_level == STAR_LEVEL_COUNT) { rb->lcd_clear_display(); star_display_text("Congratulation !", true); rb->lcd_update(); return 1; } star_load_level(current_level); } } } /** * Display the choose level screen. */ static int star_choose_level(void) { int level = current_level; int key = BUTTON_NONE; char str_info[32]; int lastkey = BUTTON_NONE; while (true) { rb->lcd_clear_display(); rb->snprintf(str_info, sizeof(str_info), "Level:%02d / %02d", level,STAR_LEVEL_COUNT); rb->lcd_putsxy(0, 0, str_info); rb->lcd_update(); key = rb->button_get(true); switch (key) { case STAR_QUIT: case BUTTON_LEFT: return -1; break; case STAR_MENU_RUN: #ifdef STAR_MENU_RUN2 case STAR_MENU_RUN2: #endif #ifdef STAR_MENU_RUN3 case STAR_MENU_RUN3: #endif current_level=level; return star_run_game(); break; case STAR_UP: case BUTTON_REPEAT | STAR_UP: if(level< STAR_LEVEL_COUNT - 1) level++; break; case STAR_DOWN: case BUTTON_REPEAT | STAR_DOWN: if(level> 0) level--; break; default: if (rb->default_event_handler(key) == SYS_USB_CONNECTED) { usb_detected = true; return 0; } break; } if (key != BUTTON_NONE) lastkey = key; } } /** * Display the choice menu. */ static int star_menu(void) { int move_y; int menu_y = 0; int i = 0; bool refresh = true; char anim_state = 0; unsigned char *menu[5] = {"Play", "Choose Level", "Information", "Keys", "Exit"}; int menu_count = sizeof(menu) / sizeof(unsigned char *); int menu_offset_y; int key; menu_offset_y = LCD_HEIGHT - char_height * menu_count; while (true) { if (refresh) { rb->lcd_clear_display(); rb->lcd_putsxy((LCD_WIDTH - char_width * rb->strlen(STAR_TITLE)) / 2, 0, STAR_TITLE); for (i = 0 ; i < menu_count ; i++) { rb->lcd_putsxy(15, menu_offset_y + char_height * i, menu[i]); } rb->lcd_update(); refresh = false; } move_y = 0; rb->lcd_mono_bitmap(arrow_bmp[anim_arrow[(anim_state & 0x38) >> 3]], 2, menu_offset_y + menu_y * char_height, 7, 8); rb->lcd_update_rect (2, menu_offset_y + menu_y * 8, 8, 8); STAR_SLEEP anim_state++; key = rb->button_get(false); switch (key) { #ifdef STAR_RC_QUIT case STAR_RC_QUIT: #endif case STAR_QUIT: return PLUGIN_OK; case STAR_UP: if (menu_y > 0) { move_y = -1; #if LCD_DEPTH > 1 int oldforeground = rb->lcd_get_foreground(); rb->lcd_set_foreground(LCD_BLACK); #endif rb->lcd_fillrect(0,menu_offset_y + char_height * menu_y - 2, 15, char_height + 3); #if LCD_DEPTH > 1 rb->lcd_set_foreground(oldforeground); #endif } break; case STAR_DOWN: if (menu_y < menu_count-1) { move_y = 1; #if LCD_DEPTH > 1 int oldforeground = rb->lcd_get_foreground(); rb->lcd_set_foreground(LCD_BLACK); #endif rb->lcd_fillrect(0,menu_offset_y + char_height * menu_y - 1, 15, char_height + 2); #if LCD_DEPTH > 1 rb->lcd_set_foreground(oldforeground); #endif } break; case STAR_MENU_RUN: #ifdef STAR_MENU_RUN2 case STAR_MENU_RUN2: #endif #ifdef STAR_MENU_RUN3 case STAR_MENU_RUN3: #endif refresh = true; switch (menu_y) { case 0: star_run_game(); break; case 1: star_choose_level(); break; case 2: #if LCD_DEPTH > 1 star_display_text( "INFO\n\n" "Take all the stars to go to the next level. " "You can toggle control with the block to " "use it as a mobile wall. The block cannot " "take stars.", true); #else star_display_text( "INFO\n\n" "Take all the \"o\"s to go to the next level. " "You can toggle control with the block to " "use it as a mobile wall. The block cannot " "take \"o\".", true); #endif break; case 3: #if CONFIG_KEYPAD == RECORDER_PAD star_display_text("KEYS\n\n" "[ON] Toggle Ctl.\n" "[OFF] Exit\n" "[F1] Prev. level\n" "[F2] Reset level\n" "[F3] Next level", true); #elif CONFIG_KEYPAD == ONDIO_PAD star_display_text("KEYS\n\n" "[MODE] Toggle Ctl\n" "[OFF] Exit\n" "[M <] Prev. level\n" "[M ^] Reset level\n" "[M >] Next level", true); #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) star_display_text("KEYS\n\n" "[MODE/SELECT] Toggle Ctrl\n" "[OFF] Exit\n" "[ON + LEFT] Prev. level\n" "[ON + SELECT] Reset level\n" "[ON + RIGHT] Next level", true); #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) star_display_text("KEYS\n\n" "[SELECT] Toggle Ctl\n" "[S + MENU] Exit\n" "[S <] Prev. level\n" "[S + PLAY] Reset level\n" "[S >] Next level", true); #elif CONFIG_KEYPAD == IAUDIO_X5_PAD star_display_text("KEYS\n\n" "[SELECT] Toggle Ctl\n" "[POWER] Exit\n" "[PLAY+DOWN] Prev. level\n" "[PLAY+RIGHT] Reset level\n" "[PLAY+UP] Next level", true); #elif CONFIG_KEYPAD == GIGABEAT_PAD star_display_text("KEYS\n\n" "[MENU] Toggle Ctl\n" "[A] Exit\n" "[PWR+DOWN] Prev. level\n" "[PWR+RIGHT] Reset level\n" "[PWR+UP] Next level", true); #endif break; case 4: return PLUGIN_OK; } if (usb_detected) return PLUGIN_USB_CONNECTED; break; default: if (rb->default_event_handler(key) == SYS_USB_CONNECTED) return PLUGIN_USB_CONNECTED; break; } for (i = 0 ; i < char_height ; i++) { rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); rb->lcd_fillrect (2, menu_offset_y, 8, menu_count * 8); rb->lcd_set_drawmode(DRMODE_FG); rb->lcd_mono_bitmap(arrow_bmp[anim_arrow[(anim_state & 0x38) >> 3]], 2, menu_offset_y + menu_y * 8 + move_y * i, 7, 8); rb->lcd_update_rect(2, menu_offset_y, 8, menu_count * 8); anim_state++; STAR_SLEEP } rb->lcd_set_drawmode(DRMODE_SOLID); menu_y += move_y; } } /** * Main entry point */ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) { (void)parameter; rb = api; /* get the size of char */ rb->lcd_setfont(FONT_SYSFIXED); if (char_width == -1) rb->lcd_getstringsize("a", &char_width, &char_height); #if LCD_DEPTH > 1 rb->lcd_set_background( LCD_BLACK ); rb->lcd_set_foreground( LCD_WHITE ); #endif /* display choice menu */ return star_menu(); } #endif