Prepare new maemo release
[maemo-rb.git] / apps / plugins / pong.c
blob372b84c9acadd2d4f76b511d68caaee0b396518c
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2004 Daniel Stenberg
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "plugin.h"
22 #include "lib/helper.h"
24 #define PAD_HEIGHT LCD_HEIGHT / 6 /* Recorder: 10 iRiver: 21 */
25 #define PAD_WIDTH LCD_WIDTH / 50 /* Recorder: 2 iRiver: 2 */
27 #define BALL_HEIGHT LCD_HEIGHT / 32 /* Recorder: 2 iRiver: 4 */
28 #define BALL_WIDTH LCD_HEIGHT / 32 /* We want a square ball */
30 #define SPEEDX ( LCD_WIDTH * 3 ) / 2 /* Recorder: 168 iRiver: 240 */
31 #define SPEEDY LCD_HEIGHT * 2 /* Recorder: 128 iRiver: 256 */
32 /* This is the width of the dead spot where the
33 * cpu player doesnt care about the ball -- 3/8 of the screen */
34 #define CPU_PLAYER_RIGHT_DIST ( (LCD_WIDTH/8 ) * 5 )
35 #define CPU_PLAYER_LEFT_DIST ( (LCD_WIDTH/8 ) * 3 )
37 #define RES 100
39 #define MOVE_STEP LCD_HEIGHT / 32 /* move pad this many steps up/down each move */
41 /* variable button definitions */
42 #if CONFIG_KEYPAD == RECORDER_PAD
43 #define PONG_QUIT BUTTON_OFF
44 #define PONG_PAUSE BUTTON_ON
45 #define PONG_LEFT_UP BUTTON_F1
46 #define PONG_LEFT_DOWN BUTTON_LEFT
47 #define PONG_RIGHT_UP BUTTON_F3
48 #define PONG_RIGHT_DOWN BUTTON_RIGHT
50 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
51 #define PONG_QUIT BUTTON_OFF
52 #define PONG_PAUSE BUTTON_ON
53 #define PONG_LEFT_UP BUTTON_F1
54 #define PONG_LEFT_DOWN BUTTON_LEFT
55 #define PONG_RIGHT_UP BUTTON_F3
56 #define PONG_RIGHT_DOWN BUTTON_RIGHT
58 #elif CONFIG_KEYPAD == ONDIO_PAD
59 #define PONG_QUIT BUTTON_OFF
60 #define PONG_PAUSE BUTTON_RIGHT
61 #define PONG_LEFT_UP BUTTON_LEFT
62 #define PONG_LEFT_DOWN BUTTON_MENU
63 #define PONG_RIGHT_UP BUTTON_UP
64 #define PONG_RIGHT_DOWN BUTTON_DOWN
66 #elif CONFIG_KEYPAD == IRIVER_H100_PAD
67 #define PONG_QUIT BUTTON_OFF
68 #define PONG_LEFT_UP BUTTON_UP
69 #define PONG_LEFT_DOWN BUTTON_DOWN
70 #define PONG_RIGHT_UP BUTTON_ON
71 #define PONG_RIGHT_DOWN BUTTON_MODE
72 #define PONG_RC_QUIT BUTTON_RC_STOP
74 #elif CONFIG_KEYPAD == IRIVER_H300_PAD
75 #define PONG_QUIT BUTTON_OFF
76 #define PONG_LEFT_UP BUTTON_UP
77 #define PONG_LEFT_DOWN BUTTON_DOWN
78 #define PONG_RIGHT_UP BUTTON_REC
79 #define PONG_RIGHT_DOWN BUTTON_MODE
80 #define PONG_RC_QUIT BUTTON_RC_STOP
82 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
83 (CONFIG_KEYPAD == IPOD_3G_PAD) || \
84 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
85 #define PONG_QUIT BUTTON_SELECT
86 #define PONG_LEFT_UP BUTTON_MENU
87 #define PONG_LEFT_DOWN BUTTON_LEFT
88 #define PONG_RIGHT_UP BUTTON_RIGHT
89 #define PONG_RIGHT_DOWN BUTTON_PLAY
91 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
92 #define PONG_QUIT BUTTON_POWER
93 #define PONG_LEFT_UP BUTTON_UP
94 #define PONG_LEFT_DOWN BUTTON_DOWN
95 #define PONG_RIGHT_UP BUTTON_REC
96 #define PONG_RIGHT_DOWN BUTTON_PLAY
98 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
99 #define PONG_QUIT BUTTON_POWER
100 #define PONG_PAUSE BUTTON_SELECT
101 #define PONG_LEFT_UP BUTTON_UP
102 #define PONG_LEFT_DOWN BUTTON_DOWN
103 #define PONG_RIGHT_UP BUTTON_VOL_UP
104 #define PONG_RIGHT_DOWN BUTTON_VOL_DOWN
106 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || \
107 (CONFIG_KEYPAD == SANSA_CLIP_PAD) || \
108 (CONFIG_KEYPAD == SANSA_M200_PAD) || \
109 (CONFIG_KEYPAD == SANSA_CONNECT_PAD)
110 #define PONG_QUIT BUTTON_POWER
111 #define PONG_PAUSE BUTTON_SELECT
112 #define PONG_LEFT_UP BUTTON_LEFT
113 #define PONG_LEFT_DOWN BUTTON_DOWN
114 #define PONG_RIGHT_UP BUTTON_UP
115 #define PONG_RIGHT_DOWN BUTTON_RIGHT
117 #elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
118 #define PONG_QUIT BUTTON_HOME
119 #define PONG_PAUSE BUTTON_SELECT
120 #define PONG_LEFT_UP BUTTON_LEFT
121 #define PONG_LEFT_DOWN BUTTON_DOWN
122 #define PONG_RIGHT_UP BUTTON_UP
123 #define PONG_RIGHT_DOWN BUTTON_RIGHT
125 #elif (CONFIG_KEYPAD == SANSA_C200_PAD)
126 #define PONG_QUIT BUTTON_POWER
127 #define PONG_PAUSE BUTTON_SELECT
128 #define PONG_LEFT_UP BUTTON_VOL_UP
129 #define PONG_LEFT_DOWN BUTTON_VOL_DOWN
130 #define PONG_RIGHT_UP BUTTON_UP
131 #define PONG_RIGHT_DOWN BUTTON_DOWN
133 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
134 #define PONG_QUIT BUTTON_POWER
135 #define PONG_LEFT_UP BUTTON_SCROLL_UP
136 #define PONG_LEFT_DOWN BUTTON_SCROLL_DOWN
137 #define PONG_RIGHT_UP BUTTON_REW
138 #define PONG_RIGHT_DOWN BUTTON_FF
140 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
141 #define PONG_QUIT BUTTON_BACK
142 #define PONG_LEFT_UP BUTTON_UP
143 #define PONG_LEFT_DOWN BUTTON_DOWN
144 #define PONG_RIGHT_UP BUTTON_VOL_UP
145 #define PONG_RIGHT_DOWN BUTTON_VOL_DOWN
147 #elif (CONFIG_KEYPAD == MROBE100_PAD)
148 #define PONG_QUIT BUTTON_POWER
149 #define PONG_PAUSE BUTTON_SELECT
150 #define PONG_LEFT_UP BUTTON_MENU
151 #define PONG_LEFT_DOWN BUTTON_LEFT
152 #define PONG_RIGHT_UP BUTTON_PLAY
153 #define PONG_RIGHT_DOWN BUTTON_RIGHT
155 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
156 #define PONG_QUIT BUTTON_RC_REC
157 #define PONG_PAUSE BUTTON_RC_PLAY
158 #define PONG_LEFT_UP BUTTON_RC_VOL_UP
159 #define PONG_LEFT_DOWN BUTTON_RC_VOL_DOWN
160 #define PONG_RIGHT_UP BUTTON_VOL_UP
161 #define PONG_RIGHT_DOWN BUTTON_VOL_DOWN
163 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
164 #define PONG_QUIT BUTTON_POWER
166 #elif CONFIG_KEYPAD == IAUDIO67_PAD
167 #define PONG_QUIT BUTTON_POWER
168 #define PONG_PAUSE BUTTON_MENU
169 #define PONG_LEFT_UP BUTTON_VOLUP
170 #define PONG_LEFT_DOWN BUTTON_VOLDOWN
171 #define PONG_RIGHT_UP BUTTON_RIGHT
172 #define PONG_RIGHT_DOWN BUTTON_LEFT
174 #elif CONFIG_KEYPAD == CREATIVEZVM_PAD
175 #define PONG_QUIT BUTTON_BACK
176 #define PONG_LEFT_UP BUTTON_UP
177 #define PONG_LEFT_DOWN BUTTON_DOWN
178 #define PONG_RIGHT_UP BUTTON_PLAY
179 #define PONG_RIGHT_DOWN BUTTON_MENU
181 #elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
182 #define PONG_QUIT BUTTON_POWER
183 #define PONG_PAUSE BUTTON_MENU
184 #define PONG_LEFT_UP BUTTON_UP
185 #define PONG_LEFT_DOWN BUTTON_DOWN
186 #define PONG_RIGHT_UP BUTTON_VOL_UP
187 #define PONG_RIGHT_DOWN BUTTON_VOL_DOWN
189 #elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
190 #define PONG_QUIT BUTTON_POWER
191 #define PONG_PAUSE BUTTON_MENU
192 #define PONG_LEFT_UP BUTTON_UP
193 #define PONG_LEFT_DOWN BUTTON_DOWN
194 #define PONG_RIGHT_UP BUTTON_VOL_UP
195 #define PONG_RIGHT_DOWN BUTTON_VOL_DOWN
197 #elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
198 #define PONG_QUIT BUTTON_POWER
199 #define PONG_PAUSE BUTTON_MENU
200 #define PONG_LEFT_UP BUTTON_UP
201 #define PONG_LEFT_DOWN BUTTON_DOWN
202 #define PONG_RIGHT_UP BUTTON_VOL_UP
203 #define PONG_RIGHT_DOWN BUTTON_VOL_DOWN
205 #elif CONFIG_KEYPAD == ONDAVX747_PAD || \
206 CONFIG_KEYPAD == ONDAVX777_PAD || \
207 CONFIG_KEYPAD == MROBE500_PAD
208 #define PONG_QUIT BUTTON_POWER
210 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
211 #define PONG_QUIT BUTTON_REC
212 #define PONG_PAUSE BUTTON_PLAY
213 #define PONG_LEFT_UP BUTTON_UP
214 #define PONG_LEFT_DOWN BUTTON_DOWN
215 #define PONG_RIGHT_UP BUTTON_FFWD
216 #define PONG_RIGHT_DOWN BUTTON_REW
218 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
219 #define PONG_QUIT BUTTON_REC
220 #define PONG_PAUSE BUTTON_OK
221 #define PONG_LEFT_UP BUTTON_MENU
222 #define PONG_LEFT_DOWN BUTTON_PREV
223 #define PONG_RIGHT_UP BUTTON_PLAY
224 #define PONG_RIGHT_DOWN BUTTON_NEXT
226 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
227 #define PONG_QUIT (BUTTON_REC|BUTTON_PLAY)
228 #define PONG_LEFT_UP BUTTON_REW
229 #define PONG_LEFT_DOWN BUTTON_FF
230 #define PONG_RIGHT_UP BUTTON_VOL_UP
231 #define PONG_RIGHT_DOWN BUTTON_VOL_DOWN
233 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
234 #define PONG_QUIT (BUTTON_MENU|BUTTON_REPEAT)
235 #define PONG_LEFT_UP BUTTON_REW
236 #define PONG_LEFT_DOWN BUTTON_REC
237 #define PONG_RIGHT_UP BUTTON_FF
238 #define PONG_RIGHT_DOWN BUTTON_PLAY
240 #elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD
241 #define PONG_QUIT BUTTON_POWER
242 #define PONG_LEFT_UP BUTTON_BACK
243 #define PONG_LEFT_DOWN BUTTON_BOTTOMLEFT
244 #define PONG_RIGHT_UP BUTTON_PLAYPAUSE
245 #define PONG_RIGHT_DOWN BUTTON_BOTTOMRIGHT
246 #define PONG_PAUSE BUTTON_SELECT
248 #elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD)
249 #define PONG_QUIT BUTTON_BACK
250 #define PONG_PAUSE BUTTON_SELECT
251 #define PONG_LEFT_UP BUTTON_UP
252 #define PONG_LEFT_DOWN BUTTON_DOWN
253 #define PONG_RIGHT_UP BUTTON_MENU
254 #define PONG_RIGHT_DOWN BUTTON_POWER
256 #elif (CONFIG_KEYPAD == HM60X_PAD) || \
257 (CONFIG_KEYPAD == HM801_PAD)
258 #define PONG_QUIT BUTTON_POWER
259 #define PONG_PAUSE BUTTON_SELECT
260 #define PONG_LEFT_UP BUTTON_UP
261 #define PONG_LEFT_DOWN BUTTON_DOWN
262 #define PONG_RIGHT_UP BUTTON_RIGHT
263 #define PONG_RIGHT_DOWN BUTTON_LEFT
265 #else
266 #error No keymap defined!
267 #endif
269 #ifdef HAVE_TOUCHSCREEN
270 #ifndef PONG_QUIT
271 #define PONG_QUIT BUTTON_TOPMIDDLE
272 #endif
273 #ifndef PONG_LEFT_UP
274 #define PONG_LEFT_UP BUTTON_TOPLEFT
275 #endif
276 #ifndef PONG_LEFT_DOWN
277 #define PONG_LEFT_DOWN BUTTON_BOTTOMLEFT
278 #endif
279 #ifndef PONG_RIGHT_UP
280 #define PONG_RIGHT_UP BUTTON_TOPRIGHT
281 #endif
282 #ifndef PONG_RIGHT_DOWN
283 #define PONG_RIGHT_DOWN BUTTON_BOTTOMRIGHT
284 #endif
285 #ifndef PONG_PAUSE
286 #define PONG_PAUSE BUTTON_CENTER
287 #endif
288 #endif
290 struct player {
291 int xpos; /* X position of pad */
292 int w_pad; /* wanted current Y position of pad */
293 int e_pad; /* existing current Y position of pad */
294 int score;
295 bool iscpu; /* Status of AI player */
298 struct ball {
299 int x; /* current X*RES position of the ball */
300 int y; /* current Y*RES position of the ball */
301 int speedx; /* */
302 int speedy; /* */
305 struct pong {
306 struct ball ball;
307 struct player player[2];
310 static void singlepad(int x, int y, int set)
312 if(set) {
313 rb->lcd_fillrect(x, y, PAD_WIDTH, PAD_HEIGHT);
315 else {
316 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
317 rb->lcd_fillrect(x, y, PAD_WIDTH, PAD_HEIGHT);
318 rb->lcd_set_drawmode(DRMODE_SOLID);
322 static void pad(struct pong *p, int pad)
324 struct player *player = &p->player[pad];
325 /* clear existing pad */
326 singlepad(player->xpos, player->e_pad, 0);
328 /* draw wanted pad */
329 singlepad(player->xpos, player->w_pad, 1);
331 /* existing is now the wanted */
332 player->e_pad = player->w_pad;
335 static bool wallcollide(struct pong *p, int pad)
337 /* we have already checked for pad-collision, just check if this hits
338 the wall */
339 if(pad) {
340 /* right-side */
341 if(p->ball.x > ( LCD_WIDTH*RES ) - PAD_WIDTH )
342 return true;
344 else {
345 if(p->ball.x + ( BALL_WIDTH*RES ) < PAD_WIDTH )
346 return true;
348 return false;
351 /* returns true if the ball has hit a pad, and then the info variable
352 will have extra angle info */
354 static bool padcollide(struct pong *p, int pad, int *info)
356 struct player *player = &p->player[pad];
357 int x = p->ball.x/RES;
358 int y = p->ball.y/RES;
360 if((y < (player->e_pad+PAD_HEIGHT)) &&
361 (y + BALL_HEIGHT > player->e_pad)) {
362 /* Y seems likely right */
364 /* store the delta between ball-middle MINUS pad-middle, so
365 it returns:
366 0 when the ball hits exactly the middle of the pad
367 positive numbers when the ball is below the middle of the pad
368 negative numbers when the ball is above the middle of the pad
370 max number is +- PAD_HEIGHT/2
373 *info = (y+BALL_HEIGHT/2) - (player->e_pad + PAD_HEIGHT/2);
375 if(pad) {
376 /* right-side */
377 if((x + BALL_WIDTH) >= (LCD_WIDTH - PAD_WIDTH))
378 return true; /* phump */
380 else {
381 if(x <= PAD_WIDTH)
382 return true;
385 return false; /* nah */
388 static void bounce(struct pong *p, int pad, int info)
390 p->ball.speedx = -p->ball.speedx;
392 /* Give ball a little push to keep it from getting stuck between wall and pad */
393 if(pad) {
394 /* right side */
395 p->ball.x -= PAD_WIDTH*RES/4;
397 else {
398 p->ball.x += PAD_WIDTH*RES/4;
401 /* info is the hit-angle into the pad */
402 if(p->ball.speedy > 0) {
403 /* downwards */
404 if(info > 0) {
405 /* below the middle of the pad */
406 p->ball.speedy += info * RES/3;
408 else if(info < 0) {
409 /* above the middle */
410 p->ball.speedy = info * RES/2;
413 else {
414 /* upwards */
415 if(info > 0) {
416 /* below the middle of the pad */
417 p->ball.speedy = info * RES/2;
419 else if(info < 0) {
420 /* above the middle */
421 p->ball.speedy += info * RES/3;
425 p->ball.speedy += rb->rand()%21-10;
427 #if 0
428 fprintf(stderr, "INFO: %d YSPEED: %d\n", info, p->ball.speedy);
429 #endif
432 static void score(struct pong *p, int pad)
434 if(pad)
435 rb->splash(HZ/4, "right scores!");
436 else
437 rb->splash(HZ/4, "left scores!");
438 rb->lcd_clear_display();
439 p->player[pad].score++;
441 /* then move the X-speed of the ball and give it a random Y position */
442 p->ball.speedx = -p->ball.speedx;
443 p->ball.y = rb->rand()%((LCD_HEIGHT-BALL_HEIGHT)*RES);
445 /* avoid hitting the pad with the new ball */
446 p->ball.x = (p->ball.x < 0) ?
447 (RES * PAD_WIDTH) : (RES * (LCD_WIDTH - PAD_WIDTH - BALL_WIDTH));
449 /* restore Y-speed to default */
450 p->ball.speedy = (p->ball.speedy > 0) ? SPEEDY : -SPEEDY;
452 /* set the existing pad positions to something weird to force pad
453 updates */
454 p->player[0].e_pad = -1;
455 p->player[1].e_pad = -1;
458 static void ball(struct pong *p)
460 int oldx = p->ball.x/RES;
461 int oldy = p->ball.y/RES;
463 int newx;
464 int newy;
466 int info;
468 /* movement */
469 p->ball.x += p->ball.speedx;
470 p->ball.y += p->ball.speedy;
472 newx = p->ball.x/RES;
473 newy = p->ball.y/RES;
475 /* detect if ball hits a wall */
476 if(newy + BALL_HEIGHT > LCD_HEIGHT) {
477 /* hit floor, bounce */
478 p->ball.speedy = -p->ball.speedy;
479 p->ball.y = (LCD_HEIGHT - BALL_HEIGHT) * RES;
481 else if(newy < 0) {
482 /* hit ceiling, bounce */
483 p->ball.speedy = -p->ball.speedy;
484 p->ball.y = 0;
487 /* detect if ball hit pads */
488 if(padcollide(p, 0, &info))
489 bounce(p, 0, info);
490 else if(padcollide(p, 1, &info))
491 bounce(p, 1, info);
492 else if(wallcollide(p, 0))
493 score(p, 1);
494 else if(wallcollide(p, 1))
495 score(p, 0);
497 newx = p->ball.x/RES;
498 newy = p->ball.y/RES;
500 /* clear old position */
501 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
502 rb->lcd_fillrect(oldx, oldy, BALL_WIDTH, BALL_HEIGHT);
503 rb->lcd_set_drawmode(DRMODE_SOLID);
505 /* draw the new ball position */
506 rb->lcd_fillrect(newx, newy, BALL_WIDTH, BALL_HEIGHT);
509 static void padmove(int *pos, int dir)
511 *pos += dir;
512 if(*pos > (LCD_HEIGHT-PAD_HEIGHT))
513 *pos = (LCD_HEIGHT-PAD_HEIGHT);
514 else if(*pos < 0)
515 *pos = 0;
518 static void key_pad(struct pong *p, int pad, int up, int down)
520 struct player *player = &p->player[pad];
521 if(player->iscpu) {
522 if((pad && (p->ball.x/RES > CPU_PLAYER_RIGHT_DIST)) /* cpu right */
523 || (!pad && (p->ball.x/RES < CPU_PLAYER_LEFT_DIST)) /* cpu left */)
525 if(p->ball.y/RES > player->w_pad) /* player goes down */
526 padmove(&player->w_pad, MOVE_STEP);
528 if(p->ball.y/RES < player->w_pad) /* player goes up */
529 padmove(&player->w_pad, -MOVE_STEP);
532 if(down || up) {
533 /* if player presses control keys stop cpu player */
534 player->iscpu = false;
535 p->player[0].score = p->player[1].score = 0; /* reset the score */
536 rb->lcd_clear_display(); /* get rid of the text */
539 else {
540 if(down) /* player goes down */
541 padmove(&player->w_pad, MOVE_STEP);
543 if(up) /* player goes up */
544 padmove(&player->w_pad, -MOVE_STEP);
548 static int keys(struct pong *p)
550 int key;
551 #ifdef PONG_PAUSE
552 static bool pause = false;
553 #endif
555 /* number of ticks this function will loop reading keys */
556 #ifndef HAVE_TOUCHSCREEN
557 int time = 4;
558 #else
559 int time = 1;
560 #endif
561 int start = *rb->current_tick;
562 int end = start + time;
564 while(TIME_BEFORE(*rb->current_tick, end)) {
565 key = rb->button_get_w_tmo(end - *rb->current_tick);
567 #ifdef HAVE_TOUCHSCREEN
568 short touch_x, touch_y;
569 if(key & BUTTON_TOUCHSCREEN)
571 struct player *player;
572 touch_x = rb->button_get_data() >> 16;
573 touch_y = rb->button_get_data() & 0xFFFF;
575 player = &p->player[0];
576 if(touch_x >= player->xpos && touch_x <= player->xpos+(PAD_WIDTH*4))
578 padmove(&player->w_pad, touch_y-(player->e_pad*2+PAD_HEIGHT)/2);
579 if (player->iscpu) {
580 /* if left player presses control keys stop cpu player */
581 player->iscpu = false;
582 p->player[0].score = p->player[1].score = 0; /* reset the score */
583 rb->lcd_clear_display(); /* get rid of the text */
587 player = &p->player[1];
588 if(touch_x >= player->xpos-(PAD_WIDTH*4) && touch_x <= player->xpos)
590 padmove(&player->w_pad, touch_y-(player->e_pad*2+PAD_HEIGHT)/2);
591 if (player->iscpu) {
592 /* if right player presses control keys stop cpu player */
593 player->iscpu = false;
594 p->player[0].score = p->player[1].score = 0; /* reset the score */
595 rb->lcd_clear_display(); /* get rid of the text */
599 #endif
601 #ifdef HAS_BUTTON_HOLD
602 if (rb->button_hold())
603 return 2; /* Pause game */
604 #endif
606 if(key & PONG_QUIT
607 #ifdef PONG_RC_QUIT
608 || key & PONG_RC_QUIT
609 #endif
611 return 0; /* exit game NOW */
613 #ifdef PONG_PAUSE
614 if(key == PONG_PAUSE)
615 pause = !pause;
616 if(pause)
617 return 2; /* Pause game */
618 #endif
620 key = rb->button_status(); /* ignore BUTTON_REPEAT */
622 key_pad(p, 0, (key & PONG_LEFT_UP), (key & PONG_LEFT_DOWN));
623 key_pad(p, 1, (key & PONG_RIGHT_UP), (key & PONG_RIGHT_DOWN));
625 if(rb->default_event_handler(key) == SYS_USB_CONNECTED)
626 return -1; /* exit game because of USB */
628 return 1; /* return 0 to exit game */
631 static void showscore(struct pong *p)
633 static char buffer[20];
634 int w;
636 rb->snprintf(buffer, sizeof(buffer), "%d - %d",
637 p->player[0].score, p->player[1].score);
638 w = rb->lcd_getstringsize((unsigned char *)buffer, NULL, NULL);
639 rb->lcd_putsxy( (LCD_WIDTH / 2) - (w / 2), 0, (unsigned char *)buffer);
642 static void blink_demo(void)
644 static char buffer[30];
645 int w;
647 rb->snprintf(buffer, sizeof(buffer), "Press Key To Play");
648 w = rb->lcd_getstringsize((unsigned char *)buffer, NULL, NULL);
649 if(LCD_WIDTH > ( (w/8)*7 ) ) /* make sure text isn't too long for screen */
650 rb->lcd_putsxy( (LCD_WIDTH / 2) - (w / 2), (LCD_HEIGHT / 2),
651 (unsigned char *)buffer);
654 /* this is the plugin entry point */
655 enum plugin_status plugin_start(const void* parameter)
657 struct pong pong;
658 int game = 1;
660 int blink_timer = 0;
661 int blink_rate = 20;
662 bool blink = true;
664 /* init the struct with some silly values to start with */
666 pong.ball.x = 20*RES;
667 pong.ball.y = 20*RES;
668 pong.ball.speedx = SPEEDX;
669 pong.ball.speedy = SPEEDY;
671 pong.player[0].xpos = 0;
672 pong.player[0].e_pad = 0;
673 pong.player[0].w_pad = 7;
674 pong.player[1].xpos = LCD_WIDTH-PAD_WIDTH;
675 pong.player[1].e_pad = 0;
676 pong.player[1].w_pad = 40;
678 /* start every game in demo mode */
679 pong.player[0].iscpu = pong.player[1].iscpu = true;
681 pong.player[0].score = pong.player[1].score = 0; /* lets start at 0 - 0 ;-) */
683 /* if you don't use the parameter, you can do like
684 this to avoid the compiler warning about it */
685 (void)parameter;
687 /* Turn off backlight timeout */
688 backlight_ignore_timeout();
689 /* Clear screen */
690 rb->lcd_clear_display();
692 /* go go go */
693 while(game > 0) {
694 if (game == 2) { /* Game Paused */
695 rb->splash(0, "PAUSED");
696 while(game == 2)
697 game = keys(&pong); /* short circuit */
698 rb->lcd_clear_display();
701 if( pong.player[0].iscpu && pong.player[1].iscpu ) {
702 if(blink_timer<blink_rate) {
703 ++blink_timer;
705 else {
706 blink_timer=0;
707 blink = !blink;
710 if(blink==true) {
711 blink_demo();
713 else {
714 rb->lcd_clear_display();
718 showscore(&pong);
719 pad(&pong, 0); /* draw left pad */
720 pad(&pong, 1); /* draw right pad */
721 ball(&pong); /* move and draw ball */
723 rb->lcd_update();
725 game = keys(&pong); /* deal with keys */
728 /* Turn on backlight timeout (revert to settings) */
729 backlight_use_settings();
730 return (game == 0) ? PLUGIN_OK : PLUGIN_USB_CONNECTED;