Index: rockbox/apps/plugins/fingersofrock.c =================================================================== --- rockbox/apps/plugins/fingersofrock.c (revision 0) +++ rockbox/apps/plugins/fingersofrock.c (revision 0) @@ -0,0 +1,785 @@ +/*************************************************************************** + * __________ __ ___. + * 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 "fixedpoint.h" +#include "helper.c" + +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 == 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) + + +#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 LCD_WIDTH > LCD_HEIGHT + # define ARROW_DIRECTION HORIZONTAL + # define ARROW_SIZE ((LCD_HEIGHT-(4*ARROW_SPACING))/4) + # define MAX_ARROWS (LCD_WIDTH/ARROW_SIZE*2) + # 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 (LCD_HEIGHT-(4*ARROW_SPACING)/ARROW_SIZE*2) + # 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 + +# define ARROW_SPEED 2.5 //pixels per frame +# define MAX_HP 100 +# define FPS 35 //base fps. automaticaly increases with score + + +static struct plugin_api* rb; + + +//from robotfindskitten.c +#if LCD_DEPTH >= 16 +#define USE_COLOUR +const unsigned int red = 0; +const unsigned int green = 1; +const unsigned int blue = 2; +const unsigned int yellow = 3; +const unsigned int black = 4; +const unsigned int white = 5; +const unsigned int grey = 6; +const unsigned int orange = 7; +const unsigned int colours[8] = { + LCD_RGBPACK(255, 0, 0), //red + LCD_RGBPACK(0, 255, 0), //green + LCD_RGBPACK(0, 0, 255), //blue + LCD_RGBPACK(255, 255, 0), //yellow + LCD_RGBPACK(0, 0, 0), //black + LCD_RGBPACK(255, 255, 255), //white + LCD_RGBPACK(192, 192, 192), //grey + LCD_RGBPACK(255, 128, 0) //orange + +}; +#endif +void setColour(unsigned int colour){ + #ifdef USE_COLOUR + rb->lcd_set_foreground(colours[colour]); + #endif +} + + +enum Directions{ LEFT, RIGHT, UP, DOWN, NONE }; +enum ArrowState{ ACTIVE, MISSED, OFF }; //for drawing +enum Accuracy{ PERFECT, GOOD, MISS, IGNORE }; //for awarding points + +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; +}; + +void deployArrow( struct Arrow *arrow ){ + arrow->state = 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; + return PERFECT; + } + arrow->state = OFF; + return GOOD; + } + arrow->state = MISSED; + 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; + return PERFECT; + } + arrow->state = OFF; + return GOOD; + } + arrow->state = MISSED; + 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; + return PERFECT; + } + arrow->state = OFF; + return GOOD; + } + arrow->state = MISSED; + 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; + return PERFECT; + } + arrow->state = OFF; + return GOOD; + } + arrow->state = MISSED; + 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 showscore(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 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 drawBasicArrow( 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 drawArrow1( unsigned int direction, + signed int x, signed int y, + unsigned int w, unsigned int h){ + switch( direction ){ + case LEFT: + drawBasicArrow( LEFT, x, y, w, h); + drawBasicArrow( LEFT, x+1, y+1, w-2, h-2); + drawBasicArrow( LEFT, x+2, y+2, w-4, h-4); + break; + + case UP: + drawBasicArrow( UP, x, y, w, h); + drawBasicArrow( UP, x+1, y+1, w-2, h-2); + drawBasicArrow( UP, x+2, y+2, w-4, h-4); + break; + + case DOWN: + drawBasicArrow( DOWN, x, y, w, h); + drawBasicArrow( DOWN, x+1, y+1, w-2, h-2); + drawBasicArrow( DOWN, x+2, y+2, w-4, h-4); + break; + + case RIGHT: + drawBasicArrow( RIGHT, x, y, w, h); + drawBasicArrow( RIGHT, x+1, y+1, w-2, h-2); + drawBasicArrow( RIGHT, x+2, y+2, w-4, h-4); + return; + default: + rb->splash(HZ*2, "Bad Arrow"); + } +} + + +enum plugin_status plugin_start(const struct plugin_api* api, + const void* parameter) +{ + (void)parameter; + rb = api; + #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(rb); /* backlight control in lib/helper.c */ + rb->srand (*rb->current_tick); + + + // iuno, intro thingy + disclaimer + rb->splash(HZ*4, "Rockbox will not be responsible for button \ + damage resulting from the use of this plugin"); + rb->lcd_clear_display(); + rb->splash(HZ*3, "Fingers Of Rock. BYO music edition"); + rb->lcd_clear_display(); + #if ARROW_DIRECTION == HORIZONTAL + rb->splash(HZ*3, "Please physically rotate player 90* clockwise"); + rb->lcd_clear_display(); + #endif + rb->splash(HZ*1, "Ready"); + rb->lcd_clear_display(); + rb->splash(HZ*1, "Set"); + rb->lcd_clear_display(); + rb->splash(HZ*1, "GO!"); + + + int i = 0; + //Ticks, at the start of a cycle + int sTime; + int hitAccuracy; + //previous hit hit acc. + int prevAccuracy; + //am = accuracy message + int amMaxTime = HZ; + int amTimeLeft = 0; + + + 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; + } + int hp = MAX_HP; + unsigned int score = 0; + bool done = false; + long button; + + + while ( !done ){ + 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 ){ + if( 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 ){ + if( 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 ){ + if( 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 ){ + if( 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 ) + done = true; + + if ( rb->default_event_handler(button) == SYS_USB_CONNECTED ) + done = true; + + + //spawn arrow + if( rb->rand()/10 > rb->rand() ){ + for ( i = 0; i < MAX_ARROWS; ++i){ + if ( arrows[i].state == OFF ){ + deployArrow(&arrows[i]); + 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; + } + #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; + } + #endif + } + } + + + + //clear display and redraw frame + #ifdef USE_COLOUR + rb->lcd_set_background(colours[black]); + #endif + rb->lcd_clear_display(); + + setColour(white); + showscore(score); + + //draw accuracy messeges + setColour(yellow); + if( amTimeLeft > 0 ){ + showAccuracy( prevAccuracy ); + } + + //draw hp bar + if( hp > MAX_HP/4 ){ + setColour(blue); + } else { + setColour(red); + } + #if ARROW_DIRECTION == VERTICAL + rb->lcd_fillrect(0,0,((float)hp/MAX_HP)*HP_BAR_WIDTH,HP_BAR_HEIGHT); + #else + rb->lcd_fillrect(0,0,HP_BAR_WIDTH,((float)hp/MAX_HP)*HP_BAR_HEIGHT); + #endif + + //draw arrow frames + setColour(grey); + #if ARROW_DIRECTION == VERTICAL + drawArrow1( LEFT, LEFT_ARROW_X, FRAME_ARROW_Y, + ARROW_SIZE, ARROW_SIZE); + drawArrow1( UP, UP_ARROW_X, FRAME_ARROW_Y, + ARROW_SIZE, ARROW_SIZE); + drawArrow1( DOWN, DOWN_ARROW_X, FRAME_ARROW_Y, + ARROW_SIZE, ARROW_SIZE); + drawArrow1( RIGHT, RIGHT_ARROW_X, FRAME_ARROW_Y, + ARROW_SIZE, ARROW_SIZE); + #else + drawArrow1( LEFT, FRAME_ARROW_X, LEFT_ARROW_Y, + ARROW_SIZE, ARROW_SIZE); + drawArrow1( UP, FRAME_ARROW_X, UP_ARROW_Y, + ARROW_SIZE, ARROW_SIZE); + drawArrow1( DOWN, FRAME_ARROW_X, DOWN_ARROW_Y, + ARROW_SIZE, ARROW_SIZE); + drawArrow1( 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: + drawArrow1( LEFT, arrows[i].x, arrows[i].y, + ARROW_SIZE, ARROW_SIZE); + break; + case UP: + drawArrow1( UP, arrows[i].x, arrows[i].y, + ARROW_SIZE, ARROW_SIZE); + break; + case DOWN: + drawArrow1( DOWN, arrows[i].x, arrows[i].y, + ARROW_SIZE, ARROW_SIZE); + break; + case RIGHT: + drawArrow1( 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*3, "FAIL."); + done = true; + } + + //control fps + if ( *rb->current_tick - sTime < HZ/FPS ){ + rb->sleep( (HZ/(FPS+((float)score/4))) - (*rb->current_tick - sTime) ); + } + + //update screen + rb->lcd_update(); + } + + /* Turn on backlight timeout (revert to settings) */ + backlight_use_settings(rb); /* backlight control in lib/helper.c */ + rb->lcd_setfont (FONT_UI); + + return PLUGIN_OK; +} +