From ee6ea59c764e023c4cf63e1ca9eac8a62cf4a2b4 Mon Sep 17 00:00:00 2001 From: Teruaki Kawashima Date: Thu, 20 Jan 2011 13:37:20 +0000 Subject: pong: make related variables a structure. Correct collision detecting. Disable turn off backlight. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29095 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/pong.c | 262 +++++++++++++++++++++++++++++----------------------- 1 file changed, 144 insertions(+), 118 deletions(-) (limited to 'apps/plugins') diff --git a/apps/plugins/pong.c b/apps/plugins/pong.c index 49fc8e1468..9394b7a857 100644 --- a/apps/plugins/pong.c +++ b/apps/plugins/pong.c @@ -19,6 +19,7 @@ * ****************************************************************************/ #include "plugin.h" +#include "lib/helper.h" #define PAD_HEIGHT LCD_HEIGHT / 6 /* Recorder: 10 iRiver: 21 */ #define PAD_WIDTH LCD_WIDTH / 50 /* Recorder: 2 iRiver: 2 */ @@ -28,8 +29,10 @@ #define SPEEDX ( LCD_WIDTH * 3 ) / 2 /* Recorder: 168 iRiver: 240 */ #define SPEEDY LCD_HEIGHT * 2 /* Recorder: 128 iRiver: 256 */ -#define CPU_PLAYER_DIST ( (LCD_WIDTH/8 ) * 5 ) /* This is the width of the dead spot where the */ -#define DEM_PLAYER_DIST ( (LCD_WIDTH/8 ) * 3 ) /* cpu player doesnt care about the ball -- 3/8 of the screen */ +/* This is the width of the dead spot where the + * cpu player doesnt care about the ball -- 3/8 of the screen */ +#define CPU_PLAYER_RIGHT_DIST ( (LCD_WIDTH/8 ) * 5 ) +#define CPU_PLAYER_LEFT_DIST ( (LCD_WIDTH/8 ) * 3 ) #define RES 100 @@ -258,15 +261,24 @@ CONFIG_KEYPAD == MROBE500_PAD #endif #endif +struct player { + int xpos; /* X position of pad */ + int w_pad; /* wanted current Y position of pad */ + int e_pad; /* existing current Y position of pad */ + int score; + bool iscpu; /* Status of AI player */ +}; + +struct ball { + int x; /* current X*RES position of the ball */ + int y; /* current Y*RES position of the ball */ + int speedx; /* */ + int speedy; /* */ +}; + struct pong { - int ballx; /* current X*RES position of the ball */ - int bally; /* current Y*RES position of the ball */ - int w_pad[2]; /* wanted current Y positions of pads */ - int e_pad[2]; /* existing current Y positions of pads */ - int ballspeedx; /* */ - int ballspeedy; /* */ - int score[2]; - bool cpu_player[2]; /* Status of AI players */ + struct ball ball; + struct player player[2]; }; void singlepad(int x, int y, int set) @@ -281,17 +293,17 @@ void singlepad(int x, int y, int set) } } -static int xpos[2]={0, LCD_WIDTH-PAD_WIDTH}; void pad(struct pong *p, int pad) { + struct player *player = &p->player[pad]; /* clear existing pad */ - singlepad(xpos[pad], p->e_pad[pad], 0); + singlepad(player->xpos, player->e_pad, 0); /* draw wanted pad */ - singlepad(xpos[pad], p->w_pad[pad], 1); + singlepad(player->xpos, player->w_pad, 1); /* existing is now the wanted */ - p->e_pad[pad] = p->w_pad[pad]; + player->e_pad = player->w_pad; } bool wallcollide(struct pong *p, int pad) @@ -300,11 +312,11 @@ bool wallcollide(struct pong *p, int pad) the wall */ if(pad) { /* right-side */ - if(p->ballx > ( LCD_WIDTH*RES ) - PAD_WIDTH ) + if(p->ball.x > ( LCD_WIDTH*RES ) - PAD_WIDTH ) return true; } else { - if(p->ballx < PAD_WIDTH) + if(p->ball.x + ( BALL_WIDTH*RES ) < PAD_WIDTH ) return true; } return false; @@ -315,11 +327,12 @@ bool wallcollide(struct pong *p, int pad) bool padcollide(struct pong *p, int pad, int *info) { - int x = p->ballx/RES; - int y = p->bally/RES; + struct player *player = &p->player[pad]; + int x = p->ball.x/RES; + int y = p->ball.y/RES; - if((y < (p->e_pad[pad]+PAD_HEIGHT)) && - (y + BALL_HEIGHT > p->e_pad[pad])) { + if((y < (player->e_pad+PAD_HEIGHT)) && + (y + BALL_HEIGHT > player->e_pad)) { /* Y seems likely right */ /* store the delta between ball-middle MINUS pad-middle, so @@ -331,7 +344,7 @@ bool padcollide(struct pong *p, int pad, int *info) max number is +- PAD_HEIGHT/2 */ - *info = (y+BALL_HEIGHT/2) - (p->e_pad[pad] + PAD_HEIGHT/2); + *info = (y+BALL_HEIGHT/2) - (player->e_pad + PAD_HEIGHT/2); if(pad) { /* right-side */ @@ -348,43 +361,45 @@ bool padcollide(struct pong *p, int pad, int *info) void bounce(struct pong *p, int pad, int info) { - p->ballspeedx = -p->ballspeedx; + p->ball.speedx = -p->ball.speedx; - if(pad==0) { /* Give ball a little push to keep it from getting stuck between wall and pad */ - p->ballx += PAD_WIDTH; + /* Give ball a little push to keep it from getting stuck between wall and pad */ + if(pad) { + /* right side */ + p->ball.x -= PAD_WIDTH*RES/4; } else { - p->ballx -= PAD_WIDTH; + p->ball.x += PAD_WIDTH*RES/4; } /* info is the hit-angle into the pad */ - if(p->ballspeedy > 0) { + if(p->ball.speedy > 0) { /* downwards */ if(info > 0) { /* below the middle of the pad */ - p->ballspeedy += info * RES/3; + p->ball.speedy += info * RES/3; } else if(info < 0) { /* above the middle */ - p->ballspeedy = info * RES/2; + p->ball.speedy = info * RES/2; } } else { /* upwards */ if(info > 0) { /* below the middle of the pad */ - p->ballspeedy = info * RES/2; + p->ball.speedy = info * RES/2; } else if(info < 0) { /* above the middle */ - p->ballspeedy -= info * RES/3; + p->ball.speedy += info * RES/3; } } - p->ballspeedy += rb->rand()%21-10; + p->ball.speedy += rb->rand()%21-10; #if 0 - fprintf(stderr, "INFO: %d YSPEED: %d\n", info, p->ballspeedy); + fprintf(stderr, "INFO: %d YSPEED: %d\n", info, p->ball.speedy); #endif } @@ -395,29 +410,29 @@ void score(struct pong *p, int pad) else rb->splash(HZ/4, "left scores!"); rb->lcd_clear_display(); - p->score[pad]++; + p->player[pad].score++; /* then move the X-speed of the ball and give it a random Y position */ - p->ballspeedx = -p->ballspeedx; - p->bally = rb->rand()%(LCD_HEIGHT*RES - BALL_HEIGHT); + p->ball.speedx = -p->ball.speedx; + p->ball.y = rb->rand()%((LCD_HEIGHT-BALL_HEIGHT)*RES); /* avoid hitting the pad with the new ball */ - p->ballx = (p->ballx < 0) ? + p->ball.x = (p->ball.x < 0) ? (RES * PAD_WIDTH) : (RES * (LCD_WIDTH - PAD_WIDTH - BALL_WIDTH)); /* restore Y-speed to default */ - p->ballspeedy = (p->ballspeedy > 0) ? SPEEDY : -SPEEDY; + p->ball.speedy = (p->ball.speedy > 0) ? SPEEDY : -SPEEDY; /* set the existing pad positions to something weird to force pad updates */ - p->e_pad[0] = -1; - p->e_pad[1] = -1; + p->player[0].e_pad = -1; + p->player[1].e_pad = -1; } void ball(struct pong *p) { - int x = p->ballx/RES; - int y = p->bally/RES; + int oldx = p->ball.x/RES; + int oldy = p->ball.y/RES; int newx; int newy; @@ -425,24 +440,22 @@ void ball(struct pong *p) int info; /* movement */ - p->ballx += p->ballspeedx; - p->bally += p->ballspeedy; + p->ball.x += p->ball.speedx; + p->ball.y += p->ball.speedy; - newx = p->ballx/RES; - newy = p->bally/RES; + newx = p->ball.x/RES; + newy = p->ball.y/RES; /* detect if ball hits a wall */ if(newy + BALL_HEIGHT > LCD_HEIGHT) { /* hit floor, bounce */ - p->ballspeedy = -p->ballspeedy; - newy = LCD_HEIGHT - BALL_HEIGHT; - p->bally = newy * RES; + p->ball.speedy = -p->ball.speedy; + p->ball.y = (LCD_HEIGHT - BALL_HEIGHT) * RES; } else if(newy < 0) { /* hit ceiling, bounce */ - p->ballspeedy = -p->ballspeedy; - p->bally = 0; - newy = 0; + p->ball.speedy = -p->ball.speedy; + p->ball.y = 0; } /* detect if ball hit pads */ @@ -455,12 +468,12 @@ void ball(struct pong *p) else if(wallcollide(p, 1)) score(p, 0); - newx = p->ballx/RES; - newy = p->bally/RES; + newx = p->ball.x/RES; + newy = p->ball.y/RES; /* clear old position */ rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); - rb->lcd_fillrect(x, y, BALL_WIDTH, BALL_HEIGHT); + rb->lcd_fillrect(oldx, oldy, BALL_WIDTH, BALL_HEIGHT); rb->lcd_set_drawmode(DRMODE_SOLID); /* draw the new ball position */ @@ -476,6 +489,36 @@ void padmove(int *pos, int dir) *pos = 0; } +void key_pad(struct pong *p, int pad, int up, int down) +{ + struct player *player = &p->player[pad]; + if(player->iscpu) { + if((pad && (p->ball.x/RES > CPU_PLAYER_RIGHT_DIST)) /* cpu right */ + || (!pad && (p->ball.x/RES < CPU_PLAYER_LEFT_DIST)) /* cpu left */) + { + if(p->ball.y/RES > player->w_pad) /* player goes down */ + padmove(&player->w_pad, MOVE_STEP); + + if(p->ball.y/RES < player->w_pad) /* player goes up */ + padmove(&player->w_pad, -MOVE_STEP); + } + + if(down || up) { + /* if player presses control keys stop cpu player */ + player->iscpu = false; + p->player[0].score = p->player[1].score = 0; /* reset the score */ + rb->lcd_clear_display(); /* get rid of the text */ + } + } + else { + if(down) /* player goes down */ + padmove(&player->w_pad, MOVE_STEP); + + if(up) /* player goes up */ + padmove(&player->w_pad, -MOVE_STEP); + } +} + int keys(struct pong *p) { int key; @@ -499,19 +542,39 @@ int keys(struct pong *p) short touch_x, touch_y; if(key & BUTTON_TOUCHSCREEN) { + struct player *player; touch_x = rb->button_get_data() >> 16; touch_y = rb->button_get_data() & 0xFFFF; - if(touch_x >= xpos[0] && touch_x <= xpos[0]+(PAD_WIDTH*4)) - padmove(&p->w_pad[0], touch_y-(p->e_pad[0]*2+PAD_HEIGHT)/2); - if(touch_x >= xpos[1]-(PAD_WIDTH*4) && touch_x <= xpos[1]) - padmove(&p->w_pad[1], touch_y-(p->e_pad[1]*2+PAD_HEIGHT)/2); + player = &p->player[0]; + if(touch_x >= player->xpos && touch_x <= player->xpos+(PAD_WIDTH*4)) + { + padmove(&player->w_pad, touch_y-(player->e_pad*2+PAD_HEIGHT)/2); + if (player->iscpu) { + /* if left player presses control keys stop cpu player */ + player->iscpu = false; + p->player[0].score = p->player[1].score = 0; /* reset the score */ + rb->lcd_clear_display(); /* get rid of the text */ + } + } + + player = &p->player[1]; + if(touch_x >= player->xpos-(PAD_WIDTH*4) && touch_x <= player->xpos) + { + padmove(&player->w_pad, touch_y-(player->e_pad*2+PAD_HEIGHT)/2); + if (player->iscpu) { + /* if right player presses control keys stop cpu player */ + player->iscpu = false; + p->player[0].score = p->player[1].score = 0; /* reset the score */ + rb->lcd_clear_display(); /* get rid of the text */ + } + } } #endif #ifdef HAS_BUTTON_HOLD if (rb->button_hold()) - return 2; /* Pause game */ + return 2; /* Pause game */ #endif if(key & PONG_QUIT @@ -530,53 +593,8 @@ int keys(struct pong *p) key = rb->button_status(); /* ignore BUTTON_REPEAT */ - if(p->cpu_player[1] == true) { - if( (p->bally/RES > p->w_pad[0]) - & (p->ballx/RES < DEM_PLAYER_DIST) ) /* player right goes down */ - padmove(&p->w_pad[0], MOVE_STEP); - - if( (p->bally/RES < p->w_pad[0]) - & (p->ballx/RES < DEM_PLAYER_DIST) ) /* player right goes up */ - padmove(&p->w_pad[0], -MOVE_STEP); - - if( (key & PONG_LEFT_DOWN) || (key & PONG_LEFT_UP) ) { - /* if left player presses control keys stop cpu player */ - p->cpu_player[1] = false; - p->score[0] = p->score[1] = 0; /* reset the score */ - rb->lcd_clear_display(); /* get rid of the text */ - } - } - else { - if(key & PONG_LEFT_DOWN) /* player left goes down */ - padmove(&p->w_pad[0], MOVE_STEP); - - if(key & PONG_LEFT_UP) /* player left goes up */ - padmove(&p->w_pad[0], -MOVE_STEP); - } - - if(p->cpu_player[2] == true) { - if( (p->bally/RES > p->w_pad[1]) - & (p->ballx/RES > CPU_PLAYER_DIST) ) /* player right goes down */ - padmove(&p->w_pad[1], MOVE_STEP); - - if( (p->bally/RES < p->w_pad[1]) - & (p->ballx/RES > CPU_PLAYER_DIST) ) /* player right goes up */ - padmove(&p->w_pad[1], -MOVE_STEP); - - if( (key & PONG_RIGHT_DOWN) || (key & PONG_RIGHT_UP) ) { - /* if right player presses control keys stop cpu player */ - p->cpu_player[2] = false; - p->score[0] = p->score[1] = 0; /* reset the score */ - rb->lcd_clear_display(); /* get rid of the text */ - } - } - else { - if(key & PONG_RIGHT_DOWN) /* player right goes down */ - padmove(&p->w_pad[1], MOVE_STEP); - - if(key & PONG_RIGHT_UP) /* player right goes up */ - padmove(&p->w_pad[1], -MOVE_STEP); - } + key_pad(p, 0, (key & PONG_LEFT_UP), (key & PONG_LEFT_DOWN)); + key_pad(p, 1, (key & PONG_RIGHT_UP), (key & PONG_RIGHT_DOWN)); if(rb->default_event_handler(key) == SYS_USB_CONNECTED) return -1; /* exit game because of USB */ @@ -589,7 +607,8 @@ void showscore(struct pong *p) static char buffer[20]; int w; - rb->snprintf(buffer, sizeof(buffer), "%d - %d", p->score[0], p->score[1]); + rb->snprintf(buffer, sizeof(buffer), "%d - %d", + p->player[0].score, p->player[1].score); w = rb->lcd_getstringsize((unsigned char *)buffer, NULL, NULL); rb->lcd_putsxy( (LCD_WIDTH / 2) - (w / 2), 0, (unsigned char *)buffer); } @@ -618,24 +637,29 @@ enum plugin_status plugin_start(const void* parameter) /* init the struct with some silly values to start with */ - pong.ballx = 20*RES; - pong.bally = 20*RES; + pong.ball.x = 20*RES; + pong.ball.y = 20*RES; + pong.ball.speedx = SPEEDX; + pong.ball.speedy = SPEEDY; - pong.e_pad[0] = 0; - pong.w_pad[0] = 7; - pong.e_pad[1] = 0; - pong.w_pad[1] = 40; - pong.cpu_player[1] = pong.cpu_player[2] = true; /* start every game in demo mode */ + pong.player[0].xpos = 0; + pong.player[0].e_pad = 0; + pong.player[0].w_pad = 7; + pong.player[1].xpos = LCD_WIDTH-PAD_WIDTH; + pong.player[1].e_pad = 0; + pong.player[1].w_pad = 40; - pong.ballspeedx = SPEEDX; - pong.ballspeedy = SPEEDY; + /* start every game in demo mode */ + pong.player[0].iscpu = pong.player[1].iscpu = true; - pong.score[0] = pong.score[1] = 0; /* lets start at 0 - 0 ;-) */ + pong.player[0].score = pong.player[1].score = 0; /* lets start at 0 - 0 ;-) */ /* if you don't use the parameter, you can do like this to avoid the compiler warning about it */ (void)parameter; + /* Turn off backlight timeout */ + backlight_force_on(); /* Clear screen */ rb->lcd_clear_display(); @@ -648,7 +672,7 @@ enum plugin_status plugin_start(const void* parameter) rb->lcd_clear_display(); } - if( (pong.cpu_player[1]==true) && (pong.cpu_player[2]==true) ) { + if( pong.player[0].iscpu && pong.player[1].iscpu ) { if(blink_timer