pong-clock: Add
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@2119 311d38ba-8fff-0310-9ca6-ca027cbcb966
This commit is contained in:
parent
1d28e031a4
commit
e5379100d5
|
@ -0,0 +1,410 @@
|
|||
/*
|
||||
* Pong Clock - A clock that plays pong.
|
||||
* See http://mocoloco.com/archives/001766.php for the inspiration.
|
||||
*
|
||||
* Copyright (C) 2005 Matthew Allum
|
||||
*
|
||||
* Author: Matthew Allum mallum@openedhand.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
/* Tweak values for different hw setups */
|
||||
|
||||
#define FPS 50
|
||||
#define RESX 40
|
||||
#define RESY 40
|
||||
#define TO_MISS_SECS 55
|
||||
#define BALLDX 16
|
||||
#define BALLDY 4
|
||||
|
||||
|
||||
typedef struct PongClock
|
||||
{
|
||||
Display *xdpy;
|
||||
int xscreen;
|
||||
Window xwin, xwin_root;
|
||||
Pixmap backbuffer;
|
||||
GC xgc;
|
||||
int xwin_width, xwin_height;
|
||||
int pixelw, pixelh;
|
||||
|
||||
int ball_x, ball_y, ball_dx, ball_dy;
|
||||
int bata_y, batb_y;
|
||||
Bool bata_to_miss, batb_to_miss;
|
||||
|
||||
}
|
||||
PongClock;
|
||||
|
||||
void
|
||||
get_time(int *hour, int *min, int *sec)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct tm *localTime = NULL;
|
||||
time_t actualTime;
|
||||
|
||||
gettimeofday(&tv, 0);
|
||||
actualTime = tv.tv_sec;
|
||||
localTime = localtime(&actualTime);
|
||||
|
||||
if (hour)
|
||||
*hour = localTime->tm_hour;
|
||||
|
||||
if (min)
|
||||
*min = localTime->tm_min;
|
||||
|
||||
if (sec)
|
||||
*sec = localTime->tm_sec;
|
||||
}
|
||||
|
||||
void
|
||||
draw_rect (PongClock *pong_clock,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
XFillRectangle (pong_clock->xdpy,
|
||||
pong_clock->backbuffer,
|
||||
pong_clock->xgc,
|
||||
x * pong_clock->pixelw,
|
||||
y * pong_clock->pixelh,
|
||||
width * pong_clock->pixelw,
|
||||
height * pong_clock->pixelh);
|
||||
}
|
||||
|
||||
void
|
||||
draw_field (PongClock *pong_clock)
|
||||
{
|
||||
int i;
|
||||
|
||||
draw_rect (pong_clock, 0, 0, RESX+1, 1);
|
||||
draw_rect (pong_clock, 0, RESY-1, RESX+1, 1);
|
||||
|
||||
for (i=0; i < RESY/2; i++)
|
||||
draw_rect (pong_clock, (RESX/2)-1, i*2, 2, 1);
|
||||
}
|
||||
|
||||
void
|
||||
draw_digit (PongClock *pong_clock,
|
||||
int x,
|
||||
int y,
|
||||
int digit)
|
||||
{
|
||||
int digits[] = { 0x1f8c63f, 0x1f21086, 0x1f0fe1f, 0x1f87e1f, 0x1087e31,
|
||||
0x1f87c3f, 0x1f8fc3f, 0x84421f, 0x1f8fe3f, 0x1087e3f };
|
||||
|
||||
XRectangle rects[5*5];
|
||||
int i,j,k;
|
||||
|
||||
i = 0;
|
||||
|
||||
for (k=0; k<5; k++)
|
||||
for (j=0; j<5; j++)
|
||||
if (digits[digit] & (1 << ((k*5)+j)))
|
||||
{
|
||||
rects[i].x = (x + j) * pong_clock->pixelw;
|
||||
rects[i].y = (y + k) * pong_clock->pixelh;
|
||||
rects[i].width = pong_clock->pixelw;
|
||||
rects[i].height = pong_clock->pixelh;
|
||||
i++;
|
||||
}
|
||||
|
||||
XFillRectangles (pong_clock->xdpy,
|
||||
pong_clock->backbuffer,
|
||||
pong_clock->xgc,
|
||||
rects, i);
|
||||
}
|
||||
|
||||
void
|
||||
draw_time (PongClock *pong_clock)
|
||||
{
|
||||
int hour, min;
|
||||
|
||||
get_time(&hour, &min, NULL);
|
||||
|
||||
draw_digit (pong_clock,
|
||||
(RESX/2) - 14,
|
||||
5,
|
||||
hour / 10 );
|
||||
|
||||
draw_digit (pong_clock,
|
||||
(RESX/2) - 8,
|
||||
5,
|
||||
hour % 10 );
|
||||
|
||||
draw_digit (pong_clock,
|
||||
(RESX/2) + 3,
|
||||
5,
|
||||
min / 10 );
|
||||
|
||||
draw_digit (pong_clock,
|
||||
(RESX/2) + 9,
|
||||
5,
|
||||
min % 10 );
|
||||
}
|
||||
|
||||
void
|
||||
draw_bat_and_ball (PongClock *pong_clock)
|
||||
{
|
||||
/* ball */
|
||||
|
||||
XFillRectangle (pong_clock->xdpy,
|
||||
pong_clock->backbuffer,
|
||||
pong_clock->xgc,
|
||||
pong_clock->ball_x,
|
||||
pong_clock->ball_y,
|
||||
pong_clock->pixelw,
|
||||
pong_clock->pixelh);
|
||||
|
||||
/* bat a */
|
||||
|
||||
XFillRectangle (pong_clock->xdpy,
|
||||
pong_clock->backbuffer,
|
||||
pong_clock->xgc,
|
||||
0,
|
||||
pong_clock->bata_y - (2 * pong_clock->pixelh),
|
||||
pong_clock->pixelw,
|
||||
pong_clock->pixelh * 5);
|
||||
|
||||
/* bat b */
|
||||
|
||||
XFillRectangle (pong_clock->xdpy,
|
||||
pong_clock->backbuffer,
|
||||
pong_clock->xgc,
|
||||
(pong_clock->xwin_width - pong_clock->pixelw),
|
||||
pong_clock->batb_y - (2 * pong_clock->pixelh),
|
||||
pong_clock->pixelw,
|
||||
pong_clock->pixelh * 5);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
update_state (PongClock *pong_clock)
|
||||
{
|
||||
int sec, min, hour;
|
||||
|
||||
get_time(&hour, &min, &sec);
|
||||
|
||||
/* Check ball is on field and no ones dues to miss a shot.
|
||||
*/
|
||||
if ( (pong_clock->ball_x < 0 && !pong_clock->bata_to_miss)
|
||||
|| (pong_clock->ball_x > (pong_clock->xwin_width - pong_clock->pixelw)
|
||||
&& !pong_clock->batb_to_miss) )
|
||||
pong_clock->ball_dx *= -1;
|
||||
|
||||
if ((pong_clock->ball_y < pong_clock->pixelh)
|
||||
|| pong_clock->ball_y > (pong_clock->xwin_height - (2*pong_clock->pixelh)))
|
||||
pong_clock->ball_dy *= -1;
|
||||
|
||||
pong_clock->ball_x += pong_clock->ball_dx;
|
||||
pong_clock->ball_y += pong_clock->ball_dy;
|
||||
|
||||
/* Set up someone to miss if we getting close to an hour or min.
|
||||
*/
|
||||
if (sec > TO_MISS_SECS)
|
||||
{
|
||||
if (min == 59)
|
||||
pong_clock->batb_to_miss = True;
|
||||
else
|
||||
pong_clock->bata_to_miss = True;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset the game */
|
||||
if (pong_clock->bata_to_miss)
|
||||
{
|
||||
pong_clock->bata_to_miss = False;
|
||||
pong_clock->ball_y = pong_clock->bata_y;
|
||||
pong_clock->ball_x = pong_clock->pixelw;
|
||||
pong_clock->ball_dx *= -1;
|
||||
}
|
||||
|
||||
if (pong_clock->batb_to_miss)
|
||||
{
|
||||
pong_clock->batb_to_miss = False;
|
||||
pong_clock->ball_y = pong_clock->batb_y;
|
||||
pong_clock->ball_x = pong_clock->xwin_width - pong_clock->pixelw;
|
||||
pong_clock->ball_dx *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Keep bats on field and only move in not setup to miss */
|
||||
if (pong_clock->ball_y >= (3*pong_clock->pixelh)
|
||||
&& pong_clock->ball_y <= (pong_clock->xwin_height - (5*pong_clock->pixelh)))
|
||||
{
|
||||
if (!pong_clock->batb_to_miss)
|
||||
pong_clock->batb_y = pong_clock->ball_y;
|
||||
|
||||
if (!pong_clock->bata_to_miss)
|
||||
pong_clock->bata_y = pong_clock->ball_y;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
draw_frame (PongClock *pong_clock)
|
||||
{
|
||||
update_state (pong_clock);
|
||||
|
||||
/* Clear playfield */
|
||||
XSetForeground (pong_clock->xdpy,
|
||||
pong_clock->xgc,
|
||||
BlackPixel(pong_clock->xdpy,
|
||||
pong_clock->xscreen));
|
||||
|
||||
XFillRectangle (pong_clock->xdpy,
|
||||
pong_clock->backbuffer,
|
||||
pong_clock->xgc,
|
||||
0, 0,
|
||||
pong_clock->xwin_width,
|
||||
pong_clock->xwin_height);
|
||||
|
||||
XSetForeground (pong_clock->xdpy,
|
||||
pong_clock->xgc,
|
||||
WhitePixel(pong_clock->xdpy,
|
||||
pong_clock->xscreen));
|
||||
|
||||
draw_field (pong_clock);
|
||||
|
||||
draw_time (pong_clock);
|
||||
|
||||
draw_bat_and_ball (pong_clock);
|
||||
|
||||
/* flip 'backbuffer' */
|
||||
XSetWindowBackgroundPixmap (pong_clock->xdpy,
|
||||
pong_clock->xwin,
|
||||
pong_clock->backbuffer);
|
||||
XClearWindow(pong_clock->xdpy, pong_clock->xwin);
|
||||
|
||||
XSync(pong_clock->xdpy, False);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
XGCValues gcv;
|
||||
Atom atoms_WINDOW_STATE, atoms_WINDOW_STATE_FULLSCREEN;
|
||||
PongClock *pong_clock;
|
||||
|
||||
pong_clock = malloc(sizeof(PongClock));
|
||||
memset(pong_clock, 0, sizeof(PongClock));
|
||||
|
||||
if ((pong_clock->xdpy = XOpenDisplay(getenv("DISPLAY"))) == NULL) {
|
||||
fprintf(stderr, "Cannot connect to X server on display %s.",
|
||||
getenv("DISPLAY"));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
pong_clock->xscreen = DefaultScreen(pong_clock->xdpy);
|
||||
pong_clock->xwin_root = DefaultRootWindow(pong_clock->xdpy);
|
||||
pong_clock->xwin_width = DisplayWidth(pong_clock->xdpy,
|
||||
pong_clock->xscreen);
|
||||
pong_clock->xwin_height = DisplayHeight(pong_clock->xdpy,
|
||||
pong_clock->xscreen);
|
||||
|
||||
pong_clock->pixelw = pong_clock->xwin_width / RESX;
|
||||
pong_clock->pixelh = pong_clock->xwin_height / RESY;
|
||||
|
||||
pong_clock->ball_x = 0;
|
||||
pong_clock->ball_y = pong_clock->xwin_height / 2;
|
||||
|
||||
pong_clock->ball_dx = BALLDX;
|
||||
pong_clock->ball_dy = BALLDY;
|
||||
|
||||
pong_clock->batb_y = pong_clock->bata_y = pong_clock->ball_y;
|
||||
|
||||
gcv.background = BlackPixel(pong_clock->xdpy,
|
||||
pong_clock->xscreen);
|
||||
gcv.foreground = WhitePixel(pong_clock->xdpy,
|
||||
pong_clock->xscreen);
|
||||
gcv.graphics_exposures = False;
|
||||
|
||||
pong_clock->xgc = XCreateGC (pong_clock->xdpy, pong_clock->xwin_root,
|
||||
GCForeground|GCBackground|GCGraphicsExposures,
|
||||
&gcv);
|
||||
|
||||
atoms_WINDOW_STATE
|
||||
= XInternAtom(pong_clock->xdpy, "_NET_WM_STATE",False);
|
||||
atoms_WINDOW_STATE_FULLSCREEN
|
||||
= XInternAtom(pong_clock->xdpy, "_NET_WM_STATE_FULLSCREEN",False);
|
||||
|
||||
pong_clock->xwin = XCreateSimpleWindow(pong_clock->xdpy,
|
||||
pong_clock->xwin_root,
|
||||
0, 0,
|
||||
pong_clock->xwin_width,
|
||||
pong_clock->xwin_height,
|
||||
0,
|
||||
WhitePixel(pong_clock->xdpy,
|
||||
pong_clock->xscreen),
|
||||
BlackPixel(pong_clock->xdpy,
|
||||
pong_clock->xscreen));
|
||||
|
||||
pong_clock->backbuffer = XCreatePixmap(pong_clock->xdpy,
|
||||
pong_clock->xwin_root,
|
||||
pong_clock->xwin_width,
|
||||
pong_clock->xwin_height,
|
||||
DefaultDepth(pong_clock->xdpy,
|
||||
pong_clock->xscreen));
|
||||
|
||||
XSelectInput(pong_clock->xdpy, pong_clock->xwin, KeyPressMask);
|
||||
|
||||
|
||||
/* Set the hints for fullscreen */
|
||||
XChangeProperty(pong_clock->xdpy,
|
||||
pong_clock->xwin,
|
||||
atoms_WINDOW_STATE,
|
||||
XA_ATOM,
|
||||
32,
|
||||
PropModeReplace,
|
||||
(unsigned char *) &atoms_WINDOW_STATE_FULLSCREEN, 1);
|
||||
|
||||
XMapWindow(pong_clock->xdpy, pong_clock->xwin);
|
||||
|
||||
while (True)
|
||||
{
|
||||
struct timeval timeout;
|
||||
XEvent xev;
|
||||
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 1000000 / FPS;
|
||||
select (0, NULL, NULL, NULL, &timeout);
|
||||
|
||||
draw_frame (pong_clock);
|
||||
|
||||
XFlush(pong_clock->xdpy);
|
||||
|
||||
if (XPending(pong_clock->xdpy))
|
||||
{
|
||||
if (XCheckMaskEvent(pong_clock->xdpy,
|
||||
KeyPressMask,
|
||||
&xev))
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
DESCRIPTION = "A clock combined with a game of pong"
|
||||
LICENCE = "GPLv2"
|
||||
|
||||
SRC_URI = "file://pong-clock-no-flicker.c"
|
||||
|
||||
S = "${WORKDIR}"
|
||||
|
||||
do_compile () {
|
||||
${CC} -o pong-clock pong-clock-no-flicker.c `pkg-config --cflags --libs x11 xau xdmcp`
|
||||
}
|
||||
|
||||
do_install () {
|
||||
install -d ${D}${bindir}
|
||||
install -m 0755 pong-clock ${D}${bindir}
|
||||
}
|
Loading…
Reference in New Issue