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
This commit is contained in:
Frank Gevaerts 2011-01-08 16:32:56 +00:00
parent 1c06d83c15
commit 17585a991c
2 changed files with 98 additions and 13 deletions

View file

@ -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(key & PONG_LEFT_UP) /* player left goes up */
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_RIGHT_DOWN) /* player right goes down */
padmove(&p->w_pad[1], 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_RIGHT_UP) /* player right goes up */
padmove(&p->w_pad[1], -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);
}
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_timer<blink_rate) {
++blink_timer;
}
else {
blink_timer=0;
blink = !blink;
}
if(blink==true) {
blink_demo();
}
else {
rb->lcd_clear_display();
}
}
showscore(&pong);
pad(&pong, 0); /* draw left pad */
pad(&pong, 1); /* draw right pad */

View file

@ -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}