From 17585a991cdd045ea5a166dd78d609262ebf3efb Mon Sep 17 00:00:00 2001 From: Frank Gevaerts Date: Sat, 8 Jan 2011 16:32:56 +0000 Subject: Add AI to the pong plugin, to allow single-player operation. Part of FS#5855 by Travis Hyyppa (the colour changes were removed from the patch) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29007 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/pong.c | 103 ++++++++++++++++++++++++++++++++++++++++++------ manual/plugins/pong.tex | 8 +++- 2 files changed, 98 insertions(+), 13 deletions(-) diff --git a/apps/plugins/pong.c b/apps/plugins/pong.c index eece69db12..49fc8e1468 100644 --- a/apps/plugins/pong.c +++ b/apps/plugins/pong.c @@ -28,6 +28,8 @@ #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 */ #define RES 100 @@ -263,8 +265,8 @@ struct pong { 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 */ }; void singlepad(int x, int y, int set) @@ -298,11 +300,11 @@ bool wallcollide(struct pong *p, int pad) the wall */ if(pad) { /* right-side */ - if(p->ballx > LCD_WIDTH*RES) + if(p->ballx > ( LCD_WIDTH*RES ) - PAD_WIDTH ) return true; } else { - if(p->ballx < 0) + if(p->ballx < PAD_WIDTH) return true; } return false; @@ -346,9 +348,15 @@ bool padcollide(struct pong *p, int pad, int *info) void bounce(struct pong *p, int pad, int info) { - (void)pad; /* not used right now */ p->ballspeedx = -p->ballspeedx; + if(pad==0) { /* Give ball a little push to keep it from getting stuck between wall and pad */ + p->ballx += PAD_WIDTH; + } + else { + p->ballx -= PAD_WIDTH; + } + /* info is the hit-angle into the pad */ if(p->ballspeedy > 0) { /* downwards */ @@ -522,17 +530,53 @@ int keys(struct pong *p) key = rb->button_status(); /* ignore BUTTON_REPEAT */ - if(key & PONG_LEFT_DOWN) /* player left goes down */ - padmove(&p->w_pad[0], MOVE_STEP); + 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(key & PONG_LEFT_UP) /* player left goes up */ + padmove(&p->w_pad[0], -MOVE_STEP); + } - if(key & PONG_RIGHT_DOWN) /* player right goes down */ - padmove(&p->w_pad[1], 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); + if(key & PONG_RIGHT_UP) /* player right goes up */ + padmove(&p->w_pad[1], -MOVE_STEP); + } if(rb->default_event_handler(key) == SYS_USB_CONNECTED) return -1; /* exit game because of USB */ @@ -550,12 +594,28 @@ void showscore(struct pong *p) rb->lcd_putsxy( (LCD_WIDTH / 2) - (w / 2), 0, (unsigned char *)buffer); } +void blink_demo(void) +{ + static char buffer[30]; + int w; + + rb->snprintf(buffer, sizeof(buffer), "Press Key To Play"); + w = rb->lcd_getstringsize((unsigned char *)buffer, NULL, NULL); + if(LCD_WIDTH > ( (w/8)*7 ) ) /* make sure text isn't too long for screen */ + rb->lcd_putsxy( (LCD_WIDTH / 2) - (w / 2), (LCD_HEIGHT / 2), + (unsigned char *)buffer); +} + /* this is the plugin entry point */ enum plugin_status plugin_start(const void* parameter) { struct pong pong; int game = 1; + int blink_timer = 0; + int blink_rate = 20; + bool blink = true; + /* init the struct with some silly values to start with */ pong.ballx = 20*RES; @@ -565,6 +625,7 @@ enum plugin_status plugin_start(const void* parameter) 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.ballspeedx = SPEEDX; pong.ballspeedy = SPEEDY; @@ -586,6 +647,24 @@ enum plugin_status plugin_start(const void* parameter) game = keys(&pong); /* short circuit */ rb->lcd_clear_display(); } + + if( (pong.cpu_player[1]==true) && (pong.cpu_player[2]==true) ) { + if(blink_timerlcd_clear_display(); + } + } + showscore(&pong); pad(&pong, 0); /* draw left pad */ pad(&pong, 1); /* draw right pad */ diff --git a/manual/plugins/pong.tex b/manual/plugins/pong.tex index 1e4d9b840b..adc9dd4a39 100644 --- a/manual/plugins/pong.tex +++ b/manual/plugins/pong.tex @@ -1,6 +1,12 @@ \subsection{Pong} \screenshot{plugins/images/ss-pong}{Pong}{img:pong} -Pong is a simple two player ``tennis game''. Whenever a player misses the ball the other scores. +Pong is a simple one or two player ``tennis game''. Whenever a player misses the ball the other scores. + +The game starts in demo mode, with the CPU controlling both sides. + +As soon as a button to control one of the paddles is pressed, control of that paddle passes to the player, +so for a single player game, just press the appropriate buttons to control the side you want to play. For +a two player game, both players should just press the appropriate buttons for their side. \begin{btnmap} \opt{RECORDER_PAD}{\ButtonFOne} -- cgit v1.2.3