summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2004-06-16 21:54:53 +0000
committerDaniel Stenberg <daniel@haxx.se>2004-06-16 21:54:53 +0000
commit3430c5d6e6afa9df107c655bc7d4094e9cc6ff75 (patch)
tree4487869b6df59b2e59e05992f300a0485c970863 /apps/plugins
parentc5800382c34f04eadaf19611a6f6693f6411061a (diff)
downloadrockbox-3430c5d6e6afa9df107c655bc7d4094e9cc6ff75.tar.gz
rockbox-3430c5d6e6afa9df107c655bc7d4094e9cc6ff75.zip
Initial version of pong, not tested on target by me yet.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4762 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/pong.c313
1 files changed, 313 insertions, 0 deletions
diff --git a/apps/plugins/pong.c b/apps/plugins/pong.c
new file mode 100644
index 0000000000..2345605995
--- /dev/null
+++ b/apps/plugins/pong.c
@@ -0,0 +1,313 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2004 Daniel Stenberg
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "plugin.h"
20
21#define PAD_HEIGHT 10
22#define PAD_WIDTH 2
23
24#define BALL_HEIGTH 2
25#define BALL_WIDTH 2
26
27#define SPEEDX 150
28#define SPEEDY 120
29
30#define RES 100
31
32static struct plugin_api* rb;
33
34struct pong {
35 int ballx; /* current X*RES position of the ball */
36 int bally; /* current Y*RES position of the ball */
37 int w_pad[2]; /* wanted current Y positions of pads */
38 int e_pad[2]; /* existing current Y positions of pads */
39 int ballspeedx; /* */
40 int ballspeedy; /* */
41
42 int score[2];
43};
44
45void singlepad(int x, int y, int set)
46{
47 if(set)
48 rb->lcd_fillrect(x, y, PAD_WIDTH, PAD_HEIGHT);
49 else
50 rb->lcd_clearrect(x, y, PAD_WIDTH, PAD_HEIGHT);
51}
52
53void pad(struct pong *p, int pad)
54{
55 static int xpos[2]={0, 112-PAD_WIDTH};
56
57 /* clear existing pad */
58 singlepad(xpos[pad], p->e_pad[pad], 0);
59
60 /* draw wanted pad */
61 singlepad(xpos[pad], p->w_pad[pad], 1);
62
63 /* existing is now the wanted */
64 p->e_pad[pad] = p->w_pad[pad];
65}
66
67bool wallcollide(struct pong *p, int pad)
68{
69 /* we have already checked for pad-collision, just check if this hits
70 the wall */
71 if(pad) {
72 /* right-side */
73 if(p->ballx > 112*RES)
74 return true;
75 }
76 else {
77 if(p->ballx < 0)
78 return true;
79 }
80 return false;
81}
82
83/* returns true if the ball has hit a pad, and then the info variable
84 will have extra angle info */
85
86bool padcollide(struct pong *p, int pad, int *info)
87{
88 int x = p->ballx/RES;
89 int y = p->bally/RES;
90
91 if((y < (p->e_pad[pad]+PAD_HEIGHT)) &&
92 (y + BALL_HEIGTH > p->e_pad[pad])) {
93 /* Y seems likely right */
94
95 /* store the delta between ball-middle MINUS pad-middle, so
96 it returns:
97 0 when the ball hits exactly the middle of the pad
98 positive numbers when the ball is below the middle of the pad
99 negative numbers when the ball is above the middle of the pad
100
101 max number is +- PAD_HEIGHT/2
102 */
103
104 *info = (y+BALL_HEIGTH/2) - (p->e_pad[pad] + PAD_HEIGHT/2);
105
106 if(pad) {
107 /* right-side */
108 if((x + BALL_WIDTH) > (112 - PAD_WIDTH))
109 return true; /* phump */
110 }
111 else {
112 if(x <= 0)
113 return true;
114 }
115 }
116 return false; /* nah */
117}
118
119void bounce(struct pong *p, int pad, int info)
120{
121 (void)pad; /* not used right now */
122 p->ballspeedx = -p->ballspeedx;
123
124 /* info is the hit-angle into the pad */
125 if(p->ballspeedy > 0) {
126 /* downwards */
127 if(info > 0) {
128 /* below the middle of the pad */
129 p->ballspeedy += info * RES/3;
130 }
131 else if(info < 0) {
132 /* above the middle */
133 p->ballspeedy = info * RES/2;
134 }
135 }
136 else {
137 /* upwards */
138 if(info > 0) {
139 /* below the middle of the pad */
140 p->ballspeedy = info * RES/2;
141 }
142 else if(info < 0) {
143 /* above the middle */
144 p->ballspeedy -= info * RES/3;
145 }
146 }
147
148 p->ballspeedy += rb->rand()%21-10;
149
150#if 0
151 fprintf(stderr, "INFO: %d YSPEED: %d\n", info, p->ballspeedy);
152#endif
153}
154
155void score(struct pong *p, int pad)
156{
157 rb->splash(HZ/4, true, "%s scores!", pad?"right":"left");
158 rb->lcd_clear_display();
159 p->score[pad]++;
160
161 /* then move the X-speed of the ball and give it a random Y position */
162 p->ballspeedx = -p->ballspeedx;
163 p->bally = rb->rand()%(64-BALL_HEIGTH);
164
165 /* restore Y-speed to default */
166 p->ballspeedy = (p->ballspeedy > 0) ? SPEEDY : -SPEEDY;
167
168 /* set the existing pad positions to something weird to force pad
169 updates */
170 p->e_pad[0] = -1;
171 p->e_pad[1] = -1;
172}
173
174void ball(struct pong *p)
175{
176 int x = p->ballx/RES;
177 int y = p->bally/RES;
178
179 int newx;
180 int newy;
181
182 int info;
183
184 /* movement */
185 p->ballx += p->ballspeedx;
186 p->bally += p->ballspeedy;
187
188 newx = p->ballx/RES;
189 newy = p->bally/RES;
190
191 /* detect if ball hits a wall */
192 if(newy + BALL_HEIGTH > 64) {
193 /* hit floor, bounce */
194 p->ballspeedy = -p->ballspeedy;
195 newy = 64 - BALL_HEIGTH;
196 p->bally = newy * RES;
197 }
198 else if(newy < 0) {
199 /* hit ceiling, bounce */
200 p->ballspeedy = -p->ballspeedy;
201 p->bally = 0;
202 newy = 0;
203 }
204
205 /* detect if ball hit pads */
206 if(padcollide(p, 0, &info))
207 bounce(p, 0, info);
208 else if(padcollide(p, 1, &info))
209 bounce(p, 1, info);
210 else if(wallcollide(p, 0))
211 score(p, 1);
212 else if(wallcollide(p, 1))
213 score(p, 0);
214
215 /* clear old position */
216 rb->lcd_clearrect(x, y, BALL_WIDTH, BALL_HEIGTH);
217
218 /* draw the new ball position */
219 rb->lcd_fillrect(newx, newy, BALL_WIDTH, BALL_HEIGTH);
220}
221
222void padmove(int *pos, int dir)
223{
224 *pos += dir;
225 if(*pos > (64-PAD_HEIGHT))
226 *pos = (64-PAD_HEIGHT);
227 else if(*pos < 0)
228 *pos = 0;
229}
230
231bool keys(struct pong *p)
232{
233 int key;
234
235 int time = 4; /* number of ticks this function will loop reading keys */
236 int start = *rb->current_tick;
237 int end = start + time;
238
239 while(end > *rb->current_tick) {
240 key = rb->button_get_w_tmo(end - *rb->current_tick);
241
242 if(key & BUTTON_OFF)
243 return false; /* exit game NOW */
244
245 if(key & BUTTON_LEFT) /* player left goes down */
246 padmove(&p->w_pad[0], 1);
247
248 if(key & BUTTON_F1) /* player left goes up */
249 padmove(&p->w_pad[0], -1);
250
251 if(key & BUTTON_RIGHT) /* player right goes down */
252 padmove(&p->w_pad[1], 1);
253
254 if(key & BUTTON_F3) /* player right goes up */
255 padmove(&p->w_pad[1], -1);
256 }
257 return true; /* return false to exit game */
258}
259
260void showscore(struct pong *p)
261{
262 static char buffer[20];
263
264 snprintf(buffer, 20, "%d - %d", p->score[0], p->score[1]);
265 rb->lcd_puts(4, 0, buffer);
266}
267
268/* this is the plugin entry point */
269enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
270{
271 TEST_PLUGIN_API(api);
272
273 struct pong pong;
274 bool game = true;
275
276 /* init the struct with some silly values to start with */
277
278 pong.ballx = 20*RES;
279 pong.bally = 20*RES;
280
281 pong.e_pad[0] = 0;
282 pong.w_pad[0] = 7;
283 pong.e_pad[1] = 0;
284 pong.w_pad[1] = 40;
285
286 pong.ballspeedx = SPEEDX;
287 pong.ballspeedy = SPEEDY;
288
289 pong.score[0] = pong.score[1] = 0; /* lets start at 0 - 0 ;-) */
290
291 /* if you don't use the parameter, you can do like
292 this to avoid the compiler warning about it */
293 (void)parameter;
294
295 rb = api; /* use the "standard" rb pointer */
296
297 /* Clear screen */
298 rb->lcd_clear_display();
299
300 /* go go go */
301 while(game) {
302 showscore(&pong);
303 pad(&pong, 0); /* draw left pad */
304 pad(&pong, 1); /* draw right pad */
305 ball(&pong); /* move and draw ball */
306
307 rb->lcd_update();
308
309 game = keys(&pong); /* deal with keys */
310 }
311
312 return PLUGIN_OK;
313}