summaryrefslogtreecommitdiffstats
path: root/meta/recipes-graphics/pong-clock/pong-clock/pong-clock-no-flicker.c
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-graphics/pong-clock/pong-clock/pong-clock-no-flicker.c')
-rw-r--r--meta/recipes-graphics/pong-clock/pong-clock/pong-clock-no-flicker.c410
1 files changed, 410 insertions, 0 deletions
diff --git a/meta/recipes-graphics/pong-clock/pong-clock/pong-clock-no-flicker.c b/meta/recipes-graphics/pong-clock/pong-clock/pong-clock-no-flicker.c
new file mode 100644
index 0000000000..41cebc58a7
--- /dev/null
+++ b/meta/recipes-graphics/pong-clock/pong-clock/pong-clock-no-flicker.c
@@ -0,0 +1,410 @@
1/*
2 * Pong Clock - A clock that plays pong.
3 * See http://mocoloco.com/archives/001766.php for the inspiration.
4 *
5 * Copyright (C) 2005 Matthew Allum
6 *
7 * Author: Matthew Allum mallum@openedhand.com
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 *
23 */
24
25#include <stdlib.h>
26#include <time.h>
27#include <sys/time.h>
28#include <sys/types.h>
29#include <string.h>
30#include <stdio.h>
31#include <unistd.h>
32#include <signal.h>
33
34#include <X11/Xlib.h>
35#include <X11/Xutil.h>
36#include <X11/Xatom.h>
37
38/* Tweak values for different hw setups */
39
40#define FPS 50
41#define RESX 40
42#define RESY 40
43#define TO_MISS_SECS 55
44#define BALLDX 16
45#define BALLDY 4
46
47
48typedef struct PongClock
49{
50 Display *xdpy;
51 int xscreen;
52 Window xwin, xwin_root;
53 Pixmap backbuffer;
54 GC xgc;
55 int xwin_width, xwin_height;
56 int pixelw, pixelh;
57
58 int ball_x, ball_y, ball_dx, ball_dy;
59 int bata_y, batb_y;
60 Bool bata_to_miss, batb_to_miss;
61
62}
63PongClock;
64
65void
66get_time(int *hour, int *min, int *sec)
67{
68 struct timeval tv;
69 struct tm *localTime = NULL;
70 time_t actualTime;
71
72 gettimeofday(&tv, 0);
73 actualTime = tv.tv_sec;
74 localTime = localtime(&actualTime);
75
76 if (hour)
77 *hour = localTime->tm_hour;
78
79 if (min)
80 *min = localTime->tm_min;
81
82 if (sec)
83 *sec = localTime->tm_sec;
84}
85
86void
87draw_rect (PongClock *pong_clock,
88 int x,
89 int y,
90 int width,
91 int height)
92{
93 XFillRectangle (pong_clock->xdpy,
94 pong_clock->backbuffer,
95 pong_clock->xgc,
96 x * pong_clock->pixelw,
97 y * pong_clock->pixelh,
98 width * pong_clock->pixelw,
99 height * pong_clock->pixelh);
100}
101
102void
103draw_field (PongClock *pong_clock)
104{
105 int i;
106
107 draw_rect (pong_clock, 0, 0, RESX+1, 1);
108 draw_rect (pong_clock, 0, RESY-1, RESX+1, 1);
109
110 for (i=0; i < RESY/2; i++)
111 draw_rect (pong_clock, (RESX/2)-1, i*2, 2, 1);
112}
113
114void
115draw_digit (PongClock *pong_clock,
116 int x,
117 int y,
118 int digit)
119{
120 int digits[] = { 0x1f8c63f, 0x1f21086, 0x1f0fe1f, 0x1f87e1f, 0x1087e31,
121 0x1f87c3f, 0x1f8fc3f, 0x84421f, 0x1f8fe3f, 0x1087e3f };
122
123 XRectangle rects[5*5];
124 int i,j,k;
125
126 i = 0;
127
128 for (k=0; k<5; k++)
129 for (j=0; j<5; j++)
130 if (digits[digit] & (1 << ((k*5)+j)))
131 {
132 rects[i].x = (x + j) * pong_clock->pixelw;
133 rects[i].y = (y + k) * pong_clock->pixelh;
134 rects[i].width = pong_clock->pixelw;
135 rects[i].height = pong_clock->pixelh;
136 i++;
137 }
138
139 XFillRectangles (pong_clock->xdpy,
140 pong_clock->backbuffer,
141 pong_clock->xgc,
142 rects, i);
143}
144
145void
146draw_time (PongClock *pong_clock)
147{
148 int hour, min;
149
150 get_time(&hour, &min, NULL);
151
152 draw_digit (pong_clock,
153 (RESX/2) - 14,
154 5,
155 hour / 10 );
156
157 draw_digit (pong_clock,
158 (RESX/2) - 8,
159 5,
160 hour % 10 );
161
162 draw_digit (pong_clock,
163 (RESX/2) + 3,
164 5,
165 min / 10 );
166
167 draw_digit (pong_clock,
168 (RESX/2) + 9,
169 5,
170 min % 10 );
171}
172
173void
174draw_bat_and_ball (PongClock *pong_clock)
175{
176 /* ball */
177
178 XFillRectangle (pong_clock->xdpy,
179 pong_clock->backbuffer,
180 pong_clock->xgc,
181 pong_clock->ball_x,
182 pong_clock->ball_y,
183 pong_clock->pixelw,
184 pong_clock->pixelh);
185
186 /* bat a */
187
188 XFillRectangle (pong_clock->xdpy,
189 pong_clock->backbuffer,
190 pong_clock->xgc,
191 0,
192 pong_clock->bata_y - (2 * pong_clock->pixelh),
193 pong_clock->pixelw,
194 pong_clock->pixelh * 5);
195
196 /* bat b */
197
198 XFillRectangle (pong_clock->xdpy,
199 pong_clock->backbuffer,
200 pong_clock->xgc,
201 (pong_clock->xwin_width - pong_clock->pixelw),
202 pong_clock->batb_y - (2 * pong_clock->pixelh),
203 pong_clock->pixelw,
204 pong_clock->pixelh * 5);
205
206}
207
208void
209update_state (PongClock *pong_clock)
210{
211 int sec, min, hour;
212
213 get_time(&hour, &min, &sec);
214
215 /* Check ball is on field and no ones dues to miss a shot.
216 */
217 if ( (pong_clock->ball_x < 0 && !pong_clock->bata_to_miss)
218 || (pong_clock->ball_x > (pong_clock->xwin_width - pong_clock->pixelw)
219 && !pong_clock->batb_to_miss) )
220 pong_clock->ball_dx *= -1;
221
222 if ((pong_clock->ball_y < pong_clock->pixelh)
223 || pong_clock->ball_y > (pong_clock->xwin_height - (2*pong_clock->pixelh)))
224 pong_clock->ball_dy *= -1;
225
226 pong_clock->ball_x += pong_clock->ball_dx;
227 pong_clock->ball_y += pong_clock->ball_dy;
228
229 /* Set up someone to miss if we getting close to an hour or min.
230 */
231 if (sec > TO_MISS_SECS)
232 {
233 if (min == 59)
234 pong_clock->batb_to_miss = True;
235 else
236 pong_clock->bata_to_miss = True;
237 }
238 else
239 {
240 /* Reset the game */
241 if (pong_clock->bata_to_miss)
242 {
243 pong_clock->bata_to_miss = False;
244 pong_clock->ball_y = pong_clock->bata_y;
245 pong_clock->ball_x = pong_clock->pixelw;
246 pong_clock->ball_dx *= -1;
247 }
248
249 if (pong_clock->batb_to_miss)
250 {
251 pong_clock->batb_to_miss = False;
252 pong_clock->ball_y = pong_clock->batb_y;
253 pong_clock->ball_x = pong_clock->xwin_width - pong_clock->pixelw;
254 pong_clock->ball_dx *= -1;
255 }
256 }
257
258 /* Keep bats on field and only move in not setup to miss */
259 if (pong_clock->ball_y >= (3*pong_clock->pixelh)
260 && pong_clock->ball_y <= (pong_clock->xwin_height - (5*pong_clock->pixelh)))
261 {
262 if (!pong_clock->batb_to_miss)
263 pong_clock->batb_y = pong_clock->ball_y;
264
265 if (!pong_clock->bata_to_miss)
266 pong_clock->bata_y = pong_clock->ball_y;
267 }
268}
269
270void
271draw_frame (PongClock *pong_clock)
272{
273 update_state (pong_clock);
274
275 /* Clear playfield */
276 XSetForeground (pong_clock->xdpy,
277 pong_clock->xgc,
278 BlackPixel(pong_clock->xdpy,
279 pong_clock->xscreen));
280
281 XFillRectangle (pong_clock->xdpy,
282 pong_clock->backbuffer,
283 pong_clock->xgc,
284 0, 0,
285 pong_clock->xwin_width,
286 pong_clock->xwin_height);
287
288 XSetForeground (pong_clock->xdpy,
289 pong_clock->xgc,
290 WhitePixel(pong_clock->xdpy,
291 pong_clock->xscreen));
292
293 draw_field (pong_clock);
294
295 draw_time (pong_clock);
296
297 draw_bat_and_ball (pong_clock);
298
299 /* flip 'backbuffer' */
300 XSetWindowBackgroundPixmap (pong_clock->xdpy,
301 pong_clock->xwin,
302 pong_clock->backbuffer);
303 XClearWindow(pong_clock->xdpy, pong_clock->xwin);
304
305 XSync(pong_clock->xdpy, False);
306}
307
308int
309main (int argc, char **argv)
310{
311 XGCValues gcv;
312 Atom atoms_WINDOW_STATE, atoms_WINDOW_STATE_FULLSCREEN;
313 PongClock *pong_clock;
314
315 pong_clock = malloc(sizeof(PongClock));
316 memset(pong_clock, 0, sizeof(PongClock));
317
318 if ((pong_clock->xdpy = XOpenDisplay(getenv("DISPLAY"))) == NULL) {
319 fprintf(stderr, "Cannot connect to X server on display %s.",
320 getenv("DISPLAY"));
321 exit(-1);
322 }
323
324 pong_clock->xscreen = DefaultScreen(pong_clock->xdpy);
325 pong_clock->xwin_root = DefaultRootWindow(pong_clock->xdpy);
326 pong_clock->xwin_width = DisplayWidth(pong_clock->xdpy,
327 pong_clock->xscreen);
328 pong_clock->xwin_height = DisplayHeight(pong_clock->xdpy,
329 pong_clock->xscreen);
330
331 pong_clock->pixelw = pong_clock->xwin_width / RESX;
332 pong_clock->pixelh = pong_clock->xwin_height / RESY;
333
334 pong_clock->ball_x = 0;
335 pong_clock->ball_y = pong_clock->xwin_height / 2;
336
337 pong_clock->ball_dx = BALLDX;
338 pong_clock->ball_dy = BALLDY;
339
340 pong_clock->batb_y = pong_clock->bata_y = pong_clock->ball_y;
341
342 gcv.background = BlackPixel(pong_clock->xdpy,
343 pong_clock->xscreen);
344 gcv.foreground = WhitePixel(pong_clock->xdpy,
345 pong_clock->xscreen);
346 gcv.graphics_exposures = False;
347
348 pong_clock->xgc = XCreateGC (pong_clock->xdpy, pong_clock->xwin_root,
349 GCForeground|GCBackground|GCGraphicsExposures,
350 &gcv);
351
352 atoms_WINDOW_STATE
353 = XInternAtom(pong_clock->xdpy, "_NET_WM_STATE",False);
354 atoms_WINDOW_STATE_FULLSCREEN
355 = XInternAtom(pong_clock->xdpy, "_NET_WM_STATE_FULLSCREEN",False);
356
357 pong_clock->xwin = XCreateSimpleWindow(pong_clock->xdpy,
358 pong_clock->xwin_root,
359 0, 0,
360 pong_clock->xwin_width,
361 pong_clock->xwin_height,
362 0,
363 WhitePixel(pong_clock->xdpy,
364 pong_clock->xscreen),
365 BlackPixel(pong_clock->xdpy,
366 pong_clock->xscreen));
367
368 pong_clock->backbuffer = XCreatePixmap(pong_clock->xdpy,
369 pong_clock->xwin_root,
370 pong_clock->xwin_width,
371 pong_clock->xwin_height,
372 DefaultDepth(pong_clock->xdpy,
373 pong_clock->xscreen));
374
375 XSelectInput(pong_clock->xdpy, pong_clock->xwin, KeyPressMask);
376
377
378 /* Set the hints for fullscreen */
379 XChangeProperty(pong_clock->xdpy,
380 pong_clock->xwin,
381 atoms_WINDOW_STATE,
382 XA_ATOM,
383 32,
384 PropModeReplace,
385 (unsigned char *) &atoms_WINDOW_STATE_FULLSCREEN, 1);
386
387 XMapWindow(pong_clock->xdpy, pong_clock->xwin);
388
389 while (True)
390 {
391 struct timeval timeout;
392 XEvent xev;
393
394 timeout.tv_sec = 0;
395 timeout.tv_usec = 1000000 / FPS;
396 select (0, NULL, NULL, NULL, &timeout);
397
398 draw_frame (pong_clock);
399
400 XFlush(pong_clock->xdpy);
401
402 if (XPending(pong_clock->xdpy))
403 {
404 if (XCheckMaskEvent(pong_clock->xdpy,
405 KeyPressMask,
406 &xev))
407 exit(-1);
408 }
409 }
410}