Index: apps/plugins/SOURCES =================================================================== --- apps/plugins/SOURCES (revision 20667) +++ apps/plugins/SOURCES (working copy) @@ -3,6 +3,7 @@ credits.c cube.c dict.c +fingersofrock.c jackpot.c keybox.c logo.c Index: apps/plugins/CATEGORIES =================================================================== --- apps/plugins/CATEGORIES (revision 20667) +++ apps/plugins/CATEGORIES (working copy) @@ -20,6 +20,7 @@ disktidy,apps doom,games euroconverter,apps +fingersofrock,games fire,demos fireworks,demos firmware_flash,apps Index: apps/plugins/fingersofrock.c =================================================================== --- apps/plugins/fingersofrock.c (revision 0) +++ apps/plugins/fingersofrock.c (revision 0) @@ -0,0 +1,1098 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id:$ + * + * Copyright (C) 2008 by Tony Huynh + * + * 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" +#include "lib/playback_control.h" +#include "lib/helper.h" + +PLUGIN_HEADER + +/* variable button definitions */ +#if (CONFIG_KEYPAD == SANSA_C200_PAD) || \ + (CONFIG_KEYPAD == SANSA_E200_PAD) || \ + (CONFIG_KEYPAD == MROBE100_PAD) || \ + (CONFIG_KEYPAD == GIGABEAT_S_PAD) || \ + (CONFIG_KEYPAD == GIGABEAT_F_PAD) || \ + (CONFIG_KEYPAD == GIGABEAT_PAD) || \ + (CONFIG_KEYPAD == COWOND2_PAD) || \ + (CONFIG_KEYPAD == CREATIVEZVM_PAD) || \ + (CONFIG_KEYPAD == IAUDIO_X5M5_PAD) +#define FOR_UP BUTTON_UP +#define FOR_LEFT BUTTON_LEFT +#define FOR_RIGHT BUTTON_RIGHT +#define FOR_DOWN BUTTON_DOWN +#define FOR_EXIT BUTTON_POWER + +#elif (CONFIG_KEYPAD == RECORDER_PAD) || \ + (CONFIG_KEYPAD == ARCHOS_AV300_PAD) || \ + (CONFIG_KEYPAD == ONDIO_PAD) || \ + (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ + (CONFIG_KEYPAD == IRIVER_H300_PAD) +#define FOR_UP BUTTON_UP +#define FOR_LEFT BUTTON_LEFT +#define FOR_RIGHT BUTTON_RIGHT +#define FOR_DOWN BUTTON_DOWN +#define FOR_EXIT BUTTON_OFF + +#elif CONFIG_KEYPAD == IRIVER_H10_PAD +#define FOR_UP BUTTON_SCROLL_UP +#define FOR_LEFT BUTTON_LEFT +#define FOR_RIGHT BUTTON_RIGHT +#define FOR_DOWN BUTTON_SCROLL_DOWN +#define FOR_EXIT BUTTON_POWER + +#elif (CONFIG_KEYPAD == PLAYER_PAD) +#define FOR_UP BUTTON_PLAY +#define FOR_LEFT BUTTON_LEFT +#define FOR_RIGHT BUTTON_RIGHT +#define FOR_DOWN BUTTON_STOP +#define FOR_EXIT BUTTON_ON + +#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ + (CONFIG_KEYPAD == IPOD_3G_PAD) || \ + (CONFIG_KEYPAD == IPOD_1G2G_PAD) +#define FOR_UP BUTTON_MENU +#define FOR_LEFT BUTTON_LEFT +#define FOR_RIGHT BUTTON_RIGHT +#define FOR_DOWN BUTTON_PLAY +#define FOR_EXIT BUTTON_SELECT + +#elif (ONFIG_KEYPAD == IRIVER_H10_PAD) +#define FOR_UP BUTTON_FF +#define FOR_LEFT BUTTON_LEFT +#define FOR_RIGHT BUTTON_RIGHT +#define FOR_DOWN BUTTON_REW +#define FOR_EXIT BUTTON_POWER + +#elif (CONFIG_KEYPAD == IRIVER_IFP7XX_PAD) +#define FOR_UP BUTTON_FF +#define FOR_LEFT BUTTON_LEFT +#define FOR_RIGHT BUTTON_RIGHT +#define FOR_DOWN BUTTON_REW +#define FOR_EXIT (BUTTON_MODE|BUTTON_EQ) + +#elif CONFIG_KEYPAD == IRIVER_H10_PAD +#define FOR_UP BUTTON_UP +#define FOR_LEFT BUTTON_LEFT +#define FOR_RIGHT BUTTON_RIGHT +#define FOR_DOWN BUTTON_DOWN +#define FOR_EXIT (BUTTON_OFF|BUTTON_ON) + + +#else +/* Guess and hope for the best */ +#warning No key mapping. Please add one. +#define FOR_UP BUTTON_UP +#define FOR_LEFT BUTTON_LEFT +#define FOR_RIGHT BUTTON_RIGHT +#define FOR_DOWN BUTTON_DOWN +#define FOR_EXIT BUTTON_OFF + + +#endif + + + + +# define ARROW_SPACING 4 /* Pixels between arrows */ + +# define HORIZONTAL 0 +# define VERTICAL 1 + +/* if the width is at least 1/4 larger than the height, rotate the screen */ +# if LCD_WIDTH > LCD_HEIGHT + # define ARROW_DIRECTION HORIZONTAL + # define ARROW_SIZE ((LCD_HEIGHT-(4*ARROW_SPACING))/4) + # define MAX_ARROWS (10+(LCD_WIDTH/ARROW_SIZE*2)) /*size of buffer*/ + # define HP_BAR_WIDTH 5 + # define HP_BAR_HEIGHT LCD_HEIGHT + /*arrow (spawn) positions + / |--| U ^ | + / |hp| R > | <----- ARROWS + / | | L < | + / |__| D V \ + / / \ \_____ + / / \ \ + / Perfect Almost Miss-threshold */ + + # define UP_ARROW_Y (ARROW_SPACING/2) + # define RIGHT_ARROW_Y (UP_ARROW_Y + ARROW_SPACING + ARROW_SIZE) + # define LEFT_ARROW_Y (RIGHT_ARROW_Y + ARROW_SPACING + ARROW_SIZE) + # define DOWN_ARROW_Y (LEFT_ARROW_Y + ARROW_SPACING + ARROW_SIZE) + + # define FRAME_ARROW_X HP_BAR_WIDTH + # define SPAWN_ARROW_X LCD_WIDTH + +# else + # define ARROW_DIRECTION VERTICAL + # define ARROW_SIZE ((LCD_WIDTH-(4*ARROW_SPACING))/4) + # define MAX_ARROWS (10+(LCD_HEIGHT-(4*ARROW_SPACING)/ARROW_SIZE*2)) /*size of buffer*/ + # define HP_BAR_WIDTH LCD_WIDTH + # define HP_BAR_HEIGHT 5 + /*arrow (spawn) positions + / ------- + / | HP | + / ------- + / < ^ V > + / L U D R + / + / /\ + / //\\ + / || + / || + / ARROWS */ + + # define LEFT_ARROW_X (ARROW_SPACING/2) + # define UP_ARROW_X (LEFT_ARROW_X + ARROW_SPACING + ARROW_SIZE) + # define DOWN_ARROW_X (UP_ARROW_X + ARROW_SPACING + ARROW_SIZE) + # define RIGHT_ARROW_X (DOWN_ARROW_X + ARROW_SPACING + ARROW_SIZE) + + # define FRAME_ARROW_Y HP_BAR_HEIGHT + # define SPAWN_ARROW_Y LCD_HEIGHT +# endif + +/* +- Pixels when checking collision with frame */ +# define PRESS_PERFECT_BUFFER (ARROW_SIZE/4) +# define PRESS_GOOD_BUFFER (ARROW_SIZE/2) +# define PRESS_MISS_BUFFER ARROW_SIZE + +/* pixels per frame */ +/* We dont vary this as difficulty increases, as incresing this too much would */ +/* make it impossible to hit an arrow (rigged ><) */ +# define ARROW_SPEED 2 +# define MAX_HP 100 + + +/* min fps. automaticaly increases with score */ +static int min_fps = 28; + +/* maximum fps can automaticaly increase with score */ +static int max_fps = 50; + +/* max number of arrows active at one time */ +static int arrow_count = 0; +/* number of arrows active at one time */ +static int max_arrow_count = MAX_ARROWS; + + +/* from robotfindskitten.c */ +static const unsigned int red = 0; +static const unsigned int green = 1; +static const unsigned int blue = 2; +static const unsigned int yellow = 3; +static const unsigned int black = 4; +static const unsigned int white = 5; +static const unsigned int grey = 6; +static const unsigned int orange = 7; +static const unsigned int pink = 8; +static const unsigned int colours[9] = { +#if LCD_DEPTH >= 16 + /* these are "pure" colours, because i think they look better like this =]*/ + /* colours taken from image posted by Gman */ + LCD_RGBPACK(255, 0, 0), /* red */ + LCD_RGBPACK(0, 220, 0), /* green */ + LCD_RGBPACK(52, 20, 255), /* blue */ + LCD_RGBPACK(251, 254, 6), /* yellow */ + LCD_RGBPACK(0, 0, 0), /* black */ + LCD_RGBPACK(255, 255, 255), /* white */ + LCD_RGBPACK(128, 128, 150), /* grey-ish */ + LCD_RGBPACK(254, 134, 5), /* orange */ + LCD_RGBPACK(219, 63, 196) /* pink */ +#endif +}; + +void setColour(unsigned int colour){ + #if LCD_DEPTH >= 16 + rb->lcd_set_foreground(colours[colour]); + #endif +} + + +/* Possible directions arrows can have */ +enum directions{ LEFT, RIGHT, UP, DOWN, NONE }; +/* Action state of the arrows */ +enum arrow_state{ ACTIVE, MISSED, OFF }; +/* Used to help display messages to player, such as "Perfect" */ +enum accuracy_message{ PERFECT, GOOD, MISS, IGNORE }; +/* Used as return values for th menu */ +enum menu_selection{ NEW_GAME, RESUME, EXIT, USB }; +/* Difficulty levels */ +enum difficulties{ + EXTREME = 0, + HARD = 1, + NORMAL = 2, + EASY = 3 +}; + + +struct Arrow{ + /* since the rest of the code is so wasteful, thought i would */ + /* try to be economical... =( */ + #if ARROW_DIRECTION == VERTICAL + short x; + float y; + #else + float x; + short y; + #endif + int direction; + int state; +}; + + +/* If val is greater than limit, limit is returned, else val is returned */ +inline int limit(int val, int limit){ return (valstate = ACTIVE; +#if ARROW_DIRECTION == VERTICAL + arrow->y = SPAWN_ARROW_Y; + switch( rb->rand() % 4 ){ + /* Left */ + case 0: + arrow->x = LEFT_ARROW_X; + arrow->direction = LEFT; + break; + + /* Up */ + case 1: + arrow->x = UP_ARROW_X; + arrow->direction = UP; + break; + + /* Down */ + case 2: + arrow->x = DOWN_ARROW_X; + arrow->direction = DOWN; + break; + + /* Right */ + case 3: + arrow->x = RIGHT_ARROW_X; + arrow->direction = RIGHT; + break; + } +#else + arrow->x = SPAWN_ARROW_X; + switch( rb->rand() % 4 ){ + /* Left */ + case 0: + arrow->y = LEFT_ARROW_Y; + arrow->direction = LEFT; + break; + + /* Up */ + case 1: + arrow->y = UP_ARROW_Y; + arrow->direction = UP; + break; + + /* Down */ + case 2: + arrow->y = DOWN_ARROW_Y; + arrow->direction = DOWN; + break; + + /* Right */ + case 3: + arrow->y = RIGHT_ARROW_Y; + arrow->direction = RIGHT; + break; + } +#endif +} + + +int handleInput(struct Arrow *arrow){ + #if ARROW_DIRECTION == VERTICAL + /* approaching frame */ + if( arrow->y > FRAME_ARROW_Y ){ + if( arrow->y < FRAME_ARROW_Y+PRESS_MISS_BUFFER ){ + if( arrow->y < FRAME_ARROW_Y+PRESS_GOOD_BUFFER ){ + if( arrow->y < FRAME_ARROW_Y+PRESS_PERFECT_BUFFER ){ + arrow->state = OFF; + arrow_count--; + return PERFECT; + } + arrow->state = OFF; + arrow_count--; + return GOOD; + } + arrow->state = MISSED; + arrow_count--; + return MISS; + } + return IGNORE; + } else { + /* leaving frame */ + if( arrow->y < FRAME_ARROW_Y-PRESS_MISS_BUFFER ){ + if( arrow->y < FRAME_ARROW_Y-PRESS_GOOD_BUFFER ){ + if( arrow->y < FRAME_ARROW_Y-PRESS_PERFECT_BUFFER ){ + arrow->state = OFF; + arrow_count--; + return PERFECT; + } + arrow->state = OFF; + arrow_count--; + return GOOD; + } + arrow->state = MISSED; + arrow_count--; + return MISS; + } + return IGNORE; + } + #else + /* approaching frame */ + if( arrow->x > FRAME_ARROW_X ){ + if( arrow->x < FRAME_ARROW_X+PRESS_MISS_BUFFER ){ + if( arrow->x < FRAME_ARROW_X+PRESS_GOOD_BUFFER ){ + if( arrow->x < FRAME_ARROW_X+PRESS_PERFECT_BUFFER ){ + arrow->state = OFF; + arrow_count--; + return PERFECT; + } + arrow->state = OFF; + arrow_count--; + return GOOD; + } + arrow->state = MISSED; + arrow_count--; + return MISS; + } + return IGNORE; + } else { + /* leaving frame */ + if( arrow->x < FRAME_ARROW_X-PRESS_MISS_BUFFER ){ + if( arrow->x < FRAME_ARROW_X-PRESS_GOOD_BUFFER ){ + if( arrow->x < FRAME_ARROW_X-PRESS_PERFECT_BUFFER ){ + arrow->state = OFF; + arrow_count--; + return PERFECT; + } + arrow->state = OFF; + arrow_count--; + return GOOD; + } + arrow->state = MISSED; + arrow_count--; + return MISS; + } + return IGNORE; + } + #endif +} + + +int awardPoints(int hitAccuracy){ + switch(hitAccuracy){ + case PERFECT: return 5; + case GOOD: return 2; + case MISS: return 0; + case IGNORE: return 0; + default: + rb->splash(HZ*2, "Bad Arrow"); + return 0; + } +} + + +int awardHp(int hitAccuracy){ + switch(hitAccuracy){ + case PERFECT: return 8; + case GOOD: return 4; + case MISS: return -4 ; + case IGNORE: return 0; + default: + rb->splash(HZ*2, "Bad Arrow"); + return 0; + } +} + + +/* Taken from pong.c */ +void show_score(unsigned int score){ + static char buffer[20]; + int w,h; + + rb->snprintf(buffer, sizeof(buffer), "%d", score); + rb->lcd_getstringsize((unsigned char *)buffer, &w, &h); + rb->lcd_putsxy( LCD_WIDTH-w, LCD_HEIGHT-h, (unsigned char *)buffer); +} + + +void show_fps(unsigned int fps){ + static char buffer[20]; + int w,h; + + rb->snprintf(buffer, sizeof(buffer), "%d", fps); + rb->lcd_getstringsize((unsigned char *)buffer, &w, &h); + rb->lcd_putsxy( 0, 0, (unsigned char *)buffer); +} + + +void showAccuracy(int hitAccuracy){ + static char buffer[20]; + int w,h; + + switch( hitAccuracy ){ + case PERFECT: + rb->snprintf(buffer, sizeof(buffer), "Perfect!"); + rb->lcd_getstringsize((unsigned char *)buffer, &w, &h); + break; + + case GOOD: + rb->snprintf(buffer, sizeof(buffer), "Good"); + rb->lcd_getstringsize((unsigned char *)buffer, &w, &h); + break; + + case MISS: + rb->snprintf(buffer, sizeof(buffer), "Miss"); + rb->lcd_getstringsize((unsigned char *)buffer, &w, &h); + break; + } + + rb->lcd_putsxy( (LCD_WIDTH/2)-(w/2), (LCD_HEIGHT/2)-(h/2), + (unsigned char *)buffer); +} + + +void draw_basic_arrow( int direction, + signed int x, signed int y, + unsigned int w, unsigned int h ){ + switch( direction ){ + case LEFT: + /* tip */ + rb->lcd_drawline( x+(w/2), y, x, y+(h/2) ); + rb->lcd_drawline( x, y+(h/2), x+(w/2), y+h ); + /* mid : */ + rb->lcd_drawline( x+(w/2), y, x+(w/2), y+(h/3) ); + rb->lcd_drawline( x+(w/2), y+(h*2/3), x+(w/2), y+h ); + /* end */ + rb->lcd_drawline( x+(w/2), y+(h/3), x+w, y+(h/3) ); + rb->lcd_drawline( x+(w/2), y+(h*2/3), x+w, y+(h*2/3) ); + rb->lcd_drawline( x+w, y+(h/3), x+w, y+(h*2/3) ); + break; + + case UP: + /* tip */ + rb->lcd_drawline( x+(w/2), y, x, y+(h/2) ); + rb->lcd_drawline( x+(w/2), y, x+w, y+(h/2) ); + /* mid */ + rb->lcd_drawline( x, y+(h/2), x+(w/3), y+(h/2) ); + rb->lcd_drawline( x+(w*2/3), y+(h/2), x+w, y+(h/2) ); + /* end */ + rb->lcd_drawline( x+(w/3), y+(h/2), x+(w/3), y+h ); + rb->lcd_drawline( x+(w*2/3), y+(h/2), x+(w*2/3), y+h ); + rb->lcd_drawline( x+(w/3), y+h, x+(w*2/3), y+h ); + break; + + case DOWN: + /* tip */ + rb->lcd_drawline( x, y+(h/2), x+(w/2), y+h ); + rb->lcd_drawline( x+w, y+(h/2), x+(w/2), y+h ); + /* mid */ + rb->lcd_drawline( x, y+(h/2), x+(w/3), y+(h/2) ); + rb->lcd_drawline( x+(w*2/3), y+(h/2), x+w, y+(h/2) ); + /* end */ + rb->lcd_drawline( x+(w/3), y, x+(w/3), y+(h/2) ); + rb->lcd_drawline( x+(w*2/3), y, x+(w*2/3), y+(h/2) ); + rb->lcd_drawline( x+(w/3), y, x+(w*2/3), y ); + break; + + case RIGHT: + /* tip */ + rb->lcd_drawline( x+(w/2), y, x+w, y+(h/2) ); + rb->lcd_drawline( x+(w/2), y+h, x+w, y+(h/2) ); + /* mid */ + rb->lcd_drawline( x+(w/2), y, x+(w/2), y+(h/3) ); + rb->lcd_drawline( x+(w/2), y+(h*2/3), x+(w/2), y+h ); + /* end */ + rb->lcd_drawline( x, y+(h/3), x+(w/2), y+(h/3) ); + rb->lcd_drawline( x, y+(h*2/3), x+(w/2), y+(h*2/3) ); + rb->lcd_drawline( x, y+(h/3), x, y+(h*2/3) ); + break; + default: + rb->splash(HZ*2, "Bad Arrow"); + } +} + + +/* Hopefully, in the future there will be a variety of */ +/* in-built arrows for users to choose from. Users will also be able to */ +/* load custom images to use as arrows */ +/* Image strip, accompanied by info file(detailing width/height) */ +void draw_arrow1( unsigned int direction, + signed int x, signed int y, + unsigned int w, unsigned int h ){ + switch( direction ){ + case LEFT: + draw_basic_arrow( LEFT, x, y, w, h); + draw_basic_arrow( LEFT, x+1, y+1, w-2, h-2); + draw_basic_arrow( LEFT, x+2, y+2, w-4, h-4); + break; + + case UP: + draw_basic_arrow( UP, x, y, w, h); + draw_basic_arrow( UP, x+1, y+1, w-2, h-2); + draw_basic_arrow( UP, x+2, y+2, w-4, h-4); + break; + + case DOWN: + draw_basic_arrow( DOWN, x, y, w, h); + draw_basic_arrow( DOWN, x+1, y+1, w-2, h-2); + draw_basic_arrow( DOWN, x+2, y+2, w-4, h-4); + break; + + case RIGHT: + draw_basic_arrow( RIGHT, x, y, w, h); + draw_basic_arrow( RIGHT, x+1, y+1, w-2, h-2); + draw_basic_arrow( RIGHT, x+2, y+2, w-4, h-4); + return; + default: + rb->splash(HZ*2, "Bad Arrow"); + } +} + + +/* displays dislaimer */ +void display_disclaimer(){ + rb->lcd_clear_display(); + rb->splash(HZ*3, "Rockbox will not be responsible for button \ + damage resulting from the use of this plugin"); + rb->lcd_clear_display(); +} + + +/* sets max speed/no arrows depeneding on difficulty */ +void set_difficulty(int difficulty){ + switch(difficulty){ + case EASY: + #if defined(DEBUG) || defined(SIMULATOR) + rb->debugf("Diff = easy\n"); + #endif + min_fps = 27; + max_fps = 37; + max_arrow_count = MAX_ARROWS/4; + break; + default: + case NORMAL: + #if defined(DEBUG) || defined(SIMULATOR) + rb->debugf("Diff = normal\n"); + #endif + min_fps = 37; + max_fps = 47; + max_arrow_count = MAX_ARROWS/2; + break; + case HARD: + #if defined(DEBUG) || defined(SIMULATOR) + rb->debugf("Diff = hard\n"); + #endif + min_fps = 47; + max_fps = 57; + max_arrow_count = (3*MAX_ARROWS)/4; + break; + case EXTREME: + #if defined(DEBUG) || defined(SIMULATOR) + rb->debugf("Diff = extreme\n"); + #endif + min_fps = 57; + max_fps = 70; /* i doubt any cpus can handle this speed =/ */ + max_arrow_count = MAX_ARROWS; + #ifdef HAVE_LCD_COLOR + rb->lcd_set_foreground(LCD_WHITE); + rb->lcd_set_background(LCD_BLACK); + + char buffer[20]; + int w,h; + rb->snprintf(buffer, sizeof(buffer), "EXTREME!!!"); + rb->lcd_getstringsize((unsigned char *)buffer, &w, &h); + + rb->lcd_clear_display(); + rb->lcd_set_foreground(LCD_WHITE); + rb->lcd_set_background(colours[red]); + rb->lcd_putsxy( (LCD_WIDTH/2)-(w/2), (LCD_HEIGHT/2)-(h/2), + (unsigned char *)buffer); + rb->lcd_update(); + rb->sleep(HZ/10); + + rb->lcd_clear_display(); + rb->lcd_set_foreground(colours[red]); + rb->lcd_set_background(LCD_WHITE); + rb->lcd_putsxy( (LCD_WIDTH/2)-(w/2), (LCD_HEIGHT/2)-(h/2), + (unsigned char *)buffer); + rb->lcd_update(); + rb->sleep(HZ/10); + + rb->lcd_clear_display(); + rb->lcd_set_foreground(LCD_WHITE); + rb->lcd_set_background(colours[red]); + rb->lcd_putsxy( (LCD_WIDTH/2)-(w/2), (LCD_HEIGHT/2)-(h/2), + (unsigned char *)buffer); + rb->lcd_update(); + rb->sleep(HZ/10); + + rb->lcd_clear_display(); + rb->lcd_set_foreground(colours[red]); + rb->lcd_set_background(LCD_WHITE); + rb->lcd_putsxy( (LCD_WIDTH/2)-(w/2), (LCD_HEIGHT/2)-(h/2), + (unsigned char *)buffer); + rb->lcd_update(); + rb->sleep(HZ/10); + + rb->lcd_set_foreground(LCD_WHITE); + rb->lcd_set_background(LCD_BLACK); + #endif + + break; + } +} + + +/* Adapted from chopper.c =] */ +/* val is an int used for new difficulty */ +static int menu(int start_selected) +{ + static const struct opt_items levels[4] = { + { "EXTREME", -1 }, + { "Hard", -1 }, + { "Normal", -1 }, + { "Easy", -1 }, + }; + + MENUITEM_STRINGLIST(menu,"Fingers of Rock Menu",NULL,"New Game","Resume","Difficulty","Playback Control","Disclaimer","Quit"); + +#ifdef HAVE_LCD_COLOR + rb->lcd_set_foreground(LCD_WHITE); + rb->lcd_set_background(LCD_BLACK); +#elif LCD_DEPTH == 2 + rb->lcd_set_foreground(LCD_BLACK); + rb->lcd_set_background(LCD_WHITE); +#endif + + rb->lcd_clear_display(); + + int res = 0; + bool menu_quit = false; + while (!menu_quit) { + switch(rb->do_menu(&menu, &start_selected, NULL, false)) { + case 0: + /* New Game */ + menu_quit=true; + res = NEW_GAME; + rb->splash(HZ*1, "Ready"); + rb->lcd_clear_display(); + rb->splash(HZ*1, "Set"); + rb->lcd_clear_display(); + rb->splash(HZ*1, "GO!"); + break; + case 1: + /* Resume */ + menu_quit=true; + res = RESUME; + break; + case 2: + /* Difficulty */ + menu_quit=false; + int diff = NORMAL; + rb->set_option("Difficulty", &diff, INT, levels, 4, NULL); + set_difficulty(diff); + break; + case 3: + /* Playerback control */ + menu_quit=false; + playback_control(NULL); + break; + case 4: + /* Disclaimer */ + menu_quit=false; + display_disclaimer(); + break; + case 5: + /* Quit */ + menu_quit=true; + res = EXIT; + break; + case MENU_ATTACHED_USB: + /* USB Plugged in */ + menu_quit=true; + res = USB; + break; + } + } + return res; +} + + + +enum plugin_status plugin_start(const void* parameter){ + (void)parameter; + + #ifndef HAVE_LCD_BITMAP + rb->splash(HZ*2, "incompatible lcd"); + return PLUGIN_OK; + #endif + + #if LCD_DEPTH > 1 + rb->lcd_set_drawmode(DRMODE_SOLID); + #else + rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + #endif + + #if LCD_DEPTH>=2 + rb->lcd_set_backdrop(NULL); + #endif + + rb->lcd_setfont (FONT_SYSFIXED); + /* Turn off backlight timeout */ + backlight_force_on(); /* backlight control in lib/helper.c */ + rb->srand (*rb->current_tick); + /* boost cpu */ + #ifdef HAVE_ADJUSTABLE_CPU_FREQ + rb->cpu_boost(true); + #endif + + + rb->splash(HZ*1, "Fingers Of Rock"); + rb->lcd_clear_display(); + + + /* used for loops*/ + int i = 0; + /* Ticks, at the start of a cycle */ + int sTime; + + /* arrows */ + struct Arrow arrows[MAX_ARROWS]; + for( i = 0; i < MAX_ARROWS; ++i ){ + arrows[i].x = 0; + arrows[i].y = 0; + arrows[i].direction = NONE; + arrows[i].state = OFF; + } + + /* Current Hit accuracy (used for displaying messages such as "Perfect!") */ + int hitAccuracy; + /* previous hit hit acc. */ + int prevAccuracy; + /* am = accuracy message */ + int amMaxTime = HZ; + int amTimeLeft = 0; + + /* Difficulty */ + int difficulty = NORMAL; + set_difficulty(difficulty); + + /* Score and HP */ + int hp = MAX_HP; + float percentHP = 100; + unsigned int score = 0; + + /* Used to collect button input */ + long button; + + + + + + /* Game Loop */ + bool run_menu = true; + bool done = false; + int res = 0; + while ( !done ){ + while( run_menu ){ + switch( menu(0) ){ + case NEW_GAME: + run_menu = false; + break; + case RESUME: + rb->splash(HZ*1, "Nothing to resume"); + break; + case EXIT: + return PLUGIN_OK; + case USB: + return PLUGIN_USB_CONNECTED; + } + } + + sTime = *rb->current_tick; + + hitAccuracy = IGNORE; + /* Check input */ + button = rb->button_get_w_tmo (1); + if( button & FOR_LEFT ){ + for( i = 0; i < MAX_ARROWS; ++i ){ + if( (arrows[i].state == ACTIVE) || (arrows[i].direction == LEFT) ){ + hitAccuracy = handleInput(&arrows[i]); + score += awardPoints( hitAccuracy ); + hp += awardHp( hitAccuracy ); + if( hitAccuracy != IGNORE ){ + prevAccuracy = hitAccuracy; + amTimeLeft = amMaxTime; + } + } + } + } + + if( button & FOR_UP ){ + for( i = 0; i < MAX_ARROWS; ++i ){ + if( (arrows[i].state == ACTIVE) || (arrows[i].direction == UP) ){ + hitAccuracy = handleInput(&arrows[i]); + score += awardPoints( hitAccuracy ); + hp += awardHp( hitAccuracy ); + if( hitAccuracy != IGNORE ){ + prevAccuracy = hitAccuracy; + amTimeLeft = amMaxTime; + } + } + } + } + + if( button & FOR_DOWN ){ + for( i = 0; i < MAX_ARROWS; ++i ){ + if( (arrows[i].state == ACTIVE) || (arrows[i].direction == DOWN) ){ + hitAccuracy = handleInput(&arrows[i]); + score += awardPoints( hitAccuracy ); + hp += awardHp( hitAccuracy ); + if( hitAccuracy != IGNORE ){ + prevAccuracy = hitAccuracy; + amTimeLeft = amMaxTime; + } + } + } + } + + if( button & FOR_RIGHT ){ + for( i = 0; i < MAX_ARROWS; ++i ){ + if( (arrows[i].state == ACTIVE) || (arrows[i].direction == RIGHT)){ + hitAccuracy = handleInput(&arrows[i]); + score += awardPoints( hitAccuracy ); + hp += awardHp( hitAccuracy ); + if( hitAccuracy != IGNORE ){ + prevAccuracy = hitAccuracy; + amTimeLeft = amMaxTime; + } + } + } + } + + if( button & FOR_EXIT ){ + /* Open menu */ + run_menu = true; + while( run_menu ){ + switch( menu(1) ){ + case NEW_GAME: + run_menu = false; + for( i = 0; i < MAX_ARROWS; ++i ){ + arrows[i].x = 0; + arrows[i].y = 0; + arrows[i].direction = NONE; + arrows[i].state = OFF; + arrow_count = 0; + } + amTimeLeft = 0; + /* Score and HP */ + hp = MAX_HP; + percentHP = 100; + score = 0; + break; + case RESUME: + run_menu = false; + break; + case EXIT: + done = true; + run_menu = false; + res = PLUGIN_OK; + break; + case USB: + done = true; + run_menu = false; + res = PLUGIN_USB_CONNECTED; + break; + } + } + } + + if ( rb->default_event_handler(button) == SYS_USB_CONNECTED ) + done = true; + + /* spawn arrow */ + if( arrow_count < max_arrow_count ){ + if( rb->rand()/10 > rb->rand() ){ + for ( i = 0; i < MAX_ARROWS; ++i){ + if ( arrows[i].state == OFF ){ + deploy_arrow(&arrows[i]); + arrow_count++; + break; + } + } + } + } + + /* move arrows */ + for ( i = 0; i < MAX_ARROWS; ++i){ + if ( arrows[i].state != OFF ){ + #if ARROW_DIRECTION == VERTICAL + arrows[i].y -= ARROW_SPEED; + /* check if it has moved off the screen */ + if( arrows[i].y < FRAME_ARROW_Y-PRESS_MISS_BUFFER ){ + if( arrows[i].state == ACTIVE ){ + hp -= 15; + } + arrows[i].state = OFF; + arrow_count--; + } + #else + arrows[i].x -= ARROW_SPEED; + /* check if it has moved off the screen */ + if( arrows[i].x < FRAME_ARROW_X-PRESS_MISS_BUFFER ){ + if( arrows[i].state == ACTIVE ){ + hp -= 15; + } + arrows[i].state = OFF; + arrow_count--; + } + #endif + } + } + + + /* clear display and redraw frame */ + #if LCD_DEPTH >= 16 + rb->lcd_set_background(colours[white]); + #endif + rb->lcd_clear_display(); + + setColour(black); + show_score(score); + + /* draw accuracy messeges */ + setColour(red); + if( amTimeLeft > 0 ){ + showAccuracy( prevAccuracy ); + } + + /* draw hp bar */ + if( hp > MAX_HP/4 ){ + setColour(blue); + } else { + setColour(red); + } + + percentHP = ((float)hp/MAX_HP); + if(percentHP>1){percentHP=1;} + #if ARROW_DIRECTION == VERTICAL + /* arrows run up */ + /* bar is horizontal, drains to left */ + rb->lcd_fillrect(0,0,percentHP*HP_BAR_WIDTH,HP_BAR_HEIGHT); + #else + /* arrows run across, horizontal */ + /* Bar is vertical, drains down */ + rb->lcd_fillrect(0,HP_BAR_HEIGHT-(percentHP*HP_BAR_HEIGHT),HP_BAR_WIDTH,HP_BAR_HEIGHT); + #endif + + /* draw arrow frames */ + #if ARROW_DIRECTION == VERTICAL + setColour(orange); + draw_arrow1( LEFT, LEFT_ARROW_X, FRAME_ARROW_Y, + ARROW_SIZE, ARROW_SIZE); + setColour(yellow); + draw_arrow1( UP, UP_ARROW_X, FRAME_ARROW_Y, + ARROW_SIZE, ARROW_SIZE); + setColour(blue); + draw_arrow1( DOWN, DOWN_ARROW_X, FRAME_ARROW_Y, + ARROW_SIZE, ARROW_SIZE); + setColour(pink); + draw_arrow1( RIGHT, RIGHT_ARROW_X, FRAME_ARROW_Y, + ARROW_SIZE, ARROW_SIZE); + #else + setColour(orange); + draw_arrow1( LEFT, FRAME_ARROW_X, LEFT_ARROW_Y, + ARROW_SIZE, ARROW_SIZE); + setColour(yellow); + draw_arrow1( UP, FRAME_ARROW_X, UP_ARROW_Y, + ARROW_SIZE, ARROW_SIZE); + setColour(blue); + draw_arrow1( DOWN, FRAME_ARROW_X, DOWN_ARROW_Y, + ARROW_SIZE, ARROW_SIZE); + setColour(pink); + draw_arrow1( RIGHT, FRAME_ARROW_X, RIGHT_ARROW_Y, + ARROW_SIZE, ARROW_SIZE); + #endif + + /* draw arrows */ + for ( i = 0; i < MAX_ARROWS; ++i){ + if ( arrows[i].state != OFF ){ + if( arrows[i].state == ACTIVE ){ + setColour(green); + } else { + /* missed */ + setColour(grey); + } + switch( arrows[i].direction ){ + case LEFT: + draw_arrow1( LEFT, arrows[i].x, arrows[i].y, + ARROW_SIZE, ARROW_SIZE); + break; + case UP: + draw_arrow1( UP, arrows[i].x, arrows[i].y, + ARROW_SIZE, ARROW_SIZE); + break; + case DOWN: + draw_arrow1( DOWN, arrows[i].x, arrows[i].y, + ARROW_SIZE, ARROW_SIZE); + break; + case RIGHT: + draw_arrow1( RIGHT, arrows[i].x, arrows[i].y, + ARROW_SIZE, ARROW_SIZE); + break; + } + } + } + + + if( amTimeLeft > 0 ){ + amTimeLeft -= *rb->current_tick-sTime; + } + + /* check if lost */ + if( hp < 0 ){ + rb->splash(HZ*2, "FAIL"); + run_menu = true; + } + + /* control fps */ + if ( *rb->current_tick - sTime < HZ/min_fps ){ + rb->sleep( (HZ/limit((min_fps+((float)score/10)),max_fps)) - (*rb->current_tick - sTime) ); + } + + /* update screen */ + rb->lcd_update(); + } + + /* Turn on backlight timeout (revert to settings) */ + backlight_use_settings(); /* backlight control in lib/helper.c */ + rb->lcd_setfont (FONT_UI); + /* unoost cpu */ + #ifdef HAVE_ADJUSTABLE_CPU_FREQ + rb->cpu_boost(false); + #endif + + return res; +} Property changes on: apps/plugins/fingersofrock.c ___________________________________________________________________ Added: svn:executable + *