summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrank Gevaerts <frank@gevaerts.be>2011-01-08 16:32:56 +0000
committerFrank Gevaerts <frank@gevaerts.be>2011-01-08 16:32:56 +0000
commit17585a991cdd045ea5a166dd78d609262ebf3efb (patch)
treef2eadff15e53114900b5d0456f2ac877040add88
parent1c06d83c1527bb39436c922815e9f9d55318d072 (diff)
downloadrockbox-17585a991cdd045ea5a166dd78d609262ebf3efb.tar.gz
rockbox-17585a991cdd045ea5a166dd78d609262ebf3efb.zip
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
-rw-r--r--apps/plugins/pong.c103
-rw-r--r--manual/plugins/pong.tex8
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 @@
28 28
29#define SPEEDX ( LCD_WIDTH * 3 ) / 2 /* Recorder: 168 iRiver: 240 */ 29#define SPEEDX ( LCD_WIDTH * 3 ) / 2 /* Recorder: 168 iRiver: 240 */
30#define SPEEDY LCD_HEIGHT * 2 /* Recorder: 128 iRiver: 256 */ 30#define SPEEDY LCD_HEIGHT * 2 /* Recorder: 128 iRiver: 256 */
31#define CPU_PLAYER_DIST ( (LCD_WIDTH/8 ) * 5 ) /* This is the width of the dead spot where the */
32#define DEM_PLAYER_DIST ( (LCD_WIDTH/8 ) * 3 ) /* cpu player doesnt care about the ball -- 3/8 of the screen */
31 33
32#define RES 100 34#define RES 100
33 35
@@ -263,8 +265,8 @@ struct pong {
263 int e_pad[2]; /* existing current Y positions of pads */ 265 int e_pad[2]; /* existing current Y positions of pads */
264 int ballspeedx; /* */ 266 int ballspeedx; /* */
265 int ballspeedy; /* */ 267 int ballspeedy; /* */
266
267 int score[2]; 268 int score[2];
269 bool cpu_player[2]; /* Status of AI players */
268}; 270};
269 271
270void singlepad(int x, int y, int set) 272void singlepad(int x, int y, int set)
@@ -298,11 +300,11 @@ bool wallcollide(struct pong *p, int pad)
298 the wall */ 300 the wall */
299 if(pad) { 301 if(pad) {
300 /* right-side */ 302 /* right-side */
301 if(p->ballx > LCD_WIDTH*RES) 303 if(p->ballx > ( LCD_WIDTH*RES ) - PAD_WIDTH )
302 return true; 304 return true;
303 } 305 }
304 else { 306 else {
305 if(p->ballx < 0) 307 if(p->ballx < PAD_WIDTH)
306 return true; 308 return true;
307 } 309 }
308 return false; 310 return false;
@@ -346,9 +348,15 @@ bool padcollide(struct pong *p, int pad, int *info)
346 348
347void bounce(struct pong *p, int pad, int info) 349void bounce(struct pong *p, int pad, int info)
348{ 350{
349 (void)pad; /* not used right now */
350 p->ballspeedx = -p->ballspeedx; 351 p->ballspeedx = -p->ballspeedx;
351 352
353 if(pad==0) { /* Give ball a little push to keep it from getting stuck between wall and pad */
354 p->ballx += PAD_WIDTH;
355 }
356 else {
357 p->ballx -= PAD_WIDTH;
358 }
359
352 /* info is the hit-angle into the pad */ 360 /* info is the hit-angle into the pad */
353 if(p->ballspeedy > 0) { 361 if(p->ballspeedy > 0) {
354 /* downwards */ 362 /* downwards */
@@ -522,17 +530,53 @@ int keys(struct pong *p)
522 530
523 key = rb->button_status(); /* ignore BUTTON_REPEAT */ 531 key = rb->button_status(); /* ignore BUTTON_REPEAT */
524 532
525 if(key & PONG_LEFT_DOWN) /* player left goes down */ 533 if(p->cpu_player[1] == true) {
526 padmove(&p->w_pad[0], MOVE_STEP); 534 if( (p->bally/RES > p->w_pad[0])
535 & (p->ballx/RES < DEM_PLAYER_DIST) ) /* player right goes down */
536 padmove(&p->w_pad[0], MOVE_STEP);
537
538 if( (p->bally/RES < p->w_pad[0])
539 & (p->ballx/RES < DEM_PLAYER_DIST) ) /* player right goes up */
540 padmove(&p->w_pad[0], -MOVE_STEP);
541
542 if( (key & PONG_LEFT_DOWN) || (key & PONG_LEFT_UP) ) {
543 /* if left player presses control keys stop cpu player */
544 p->cpu_player[1] = false;
545 p->score[0] = p->score[1] = 0; /* reset the score */
546 rb->lcd_clear_display(); /* get rid of the text */
547 }
548 }
549 else {
550 if(key & PONG_LEFT_DOWN) /* player left goes down */
551 padmove(&p->w_pad[0], MOVE_STEP);
527 552
528 if(key & PONG_LEFT_UP) /* player left goes up */ 553 if(key & PONG_LEFT_UP) /* player left goes up */
529 padmove(&p->w_pad[0], -MOVE_STEP); 554 padmove(&p->w_pad[0], -MOVE_STEP);
555 }
530 556
531 if(key & PONG_RIGHT_DOWN) /* player right goes down */ 557 if(p->cpu_player[2] == true) {
532 padmove(&p->w_pad[1], MOVE_STEP); 558 if( (p->bally/RES > p->w_pad[1])
559 & (p->ballx/RES > CPU_PLAYER_DIST) ) /* player right goes down */
560 padmove(&p->w_pad[1], MOVE_STEP);
561
562 if( (p->bally/RES < p->w_pad[1])
563 & (p->ballx/RES > CPU_PLAYER_DIST) ) /* player right goes up */
564 padmove(&p->w_pad[1], -MOVE_STEP);
565
566 if( (key & PONG_RIGHT_DOWN) || (key & PONG_RIGHT_UP) ) {
567 /* if right player presses control keys stop cpu player */
568 p->cpu_player[2] = false;
569 p->score[0] = p->score[1] = 0; /* reset the score */
570 rb->lcd_clear_display(); /* get rid of the text */
571 }
572 }
573 else {
574 if(key & PONG_RIGHT_DOWN) /* player right goes down */
575 padmove(&p->w_pad[1], MOVE_STEP);
533 576
534 if(key & PONG_RIGHT_UP) /* player right goes up */ 577 if(key & PONG_RIGHT_UP) /* player right goes up */
535 padmove(&p->w_pad[1], -MOVE_STEP); 578 padmove(&p->w_pad[1], -MOVE_STEP);
579 }
536 580
537 if(rb->default_event_handler(key) == SYS_USB_CONNECTED) 581 if(rb->default_event_handler(key) == SYS_USB_CONNECTED)
538 return -1; /* exit game because of USB */ 582 return -1; /* exit game because of USB */
@@ -550,12 +594,28 @@ void showscore(struct pong *p)
550 rb->lcd_putsxy( (LCD_WIDTH / 2) - (w / 2), 0, (unsigned char *)buffer); 594 rb->lcd_putsxy( (LCD_WIDTH / 2) - (w / 2), 0, (unsigned char *)buffer);
551} 595}
552 596
597void blink_demo(void)
598{
599 static char buffer[30];
600 int w;
601
602 rb->snprintf(buffer, sizeof(buffer), "Press Key To Play");
603 w = rb->lcd_getstringsize((unsigned char *)buffer, NULL, NULL);
604 if(LCD_WIDTH > ( (w/8)*7 ) ) /* make sure text isn't too long for screen */
605 rb->lcd_putsxy( (LCD_WIDTH / 2) - (w / 2), (LCD_HEIGHT / 2),
606 (unsigned char *)buffer);
607}
608
553/* this is the plugin entry point */ 609/* this is the plugin entry point */
554enum plugin_status plugin_start(const void* parameter) 610enum plugin_status plugin_start(const void* parameter)
555{ 611{
556 struct pong pong; 612 struct pong pong;
557 int game = 1; 613 int game = 1;
558 614
615 int blink_timer = 0;
616 int blink_rate = 20;
617 bool blink = true;
618
559 /* init the struct with some silly values to start with */ 619 /* init the struct with some silly values to start with */
560 620
561 pong.ballx = 20*RES; 621 pong.ballx = 20*RES;
@@ -565,6 +625,7 @@ enum plugin_status plugin_start(const void* parameter)
565 pong.w_pad[0] = 7; 625 pong.w_pad[0] = 7;
566 pong.e_pad[1] = 0; 626 pong.e_pad[1] = 0;
567 pong.w_pad[1] = 40; 627 pong.w_pad[1] = 40;
628 pong.cpu_player[1] = pong.cpu_player[2] = true; /* start every game in demo mode */
568 629
569 pong.ballspeedx = SPEEDX; 630 pong.ballspeedx = SPEEDX;
570 pong.ballspeedy = SPEEDY; 631 pong.ballspeedy = SPEEDY;
@@ -586,6 +647,24 @@ enum plugin_status plugin_start(const void* parameter)
586 game = keys(&pong); /* short circuit */ 647 game = keys(&pong); /* short circuit */
587 rb->lcd_clear_display(); 648 rb->lcd_clear_display();
588 } 649 }
650
651 if( (pong.cpu_player[1]==true) && (pong.cpu_player[2]==true) ) {
652 if(blink_timer<blink_rate) {
653 ++blink_timer;
654 }
655 else {
656 blink_timer=0;
657 blink = !blink;
658 }
659
660 if(blink==true) {
661 blink_demo();
662 }
663 else {
664 rb->lcd_clear_display();
665 }
666 }
667
589 showscore(&pong); 668 showscore(&pong);
590 pad(&pong, 0); /* draw left pad */ 669 pad(&pong, 0); /* draw left pad */
591 pad(&pong, 1); /* draw right pad */ 670 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 @@
1\subsection{Pong} 1\subsection{Pong}
2\screenshot{plugins/images/ss-pong}{Pong}{img:pong} 2\screenshot{plugins/images/ss-pong}{Pong}{img:pong}
3Pong is a simple two player ``tennis game''. Whenever a player misses the ball the other scores. 3Pong is a simple one or two player ``tennis game''. Whenever a player misses the ball the other scores.
4
5The game starts in demo mode, with the CPU controlling both sides.
6
7As soon as a button to control one of the paddles is pressed, control of that paddle passes to the player,
8so for a single player game, just press the appropriate buttons to control the side you want to play. For
9a two player game, both players should just press the appropriate buttons for their side.
4 10
5\begin{btnmap} 11\begin{btnmap}
6 \opt{RECORDER_PAD}{\ButtonFOne} 12 \opt{RECORDER_PAD}{\ButtonFOne}