/* -*- Mode: C; tab-width: 4 -*- */
/* pacman --- Mr. Pacman and his ghost friends */
-#if !defined( lint ) && !defined( SABER )
-static const char sccsid[] = "@(#)pacman.c 5.00 2000/11/01 xlockmore";
-
-#endif
+/*static const char sccsid[] = "@(#)pacman.c 5.00 2000/11/01 xlockmore";*/
/*-
* Copyright (c) 2002 by Edwin de Jong <mauddib@gmx.net>.
* other special, indirect and consequential damages.
*
* Revision History:
+ * 15-Aug-2004: Added support for pixmap pacman. Jeremy English jenglish@myself.com
* 11-Aug-2004: Added support for pixmap ghost. jenglish@myself.com
* 13-May-2002: Added -trackmouse feature thanks to code from 'maze.c'.
* splitted up code into several files. Retouched AI code, cleaned
/* TODO:
1. add "bonus" dots
- 2. make a bit better pacman sprite (mouth should be larger)
- 3. think of a better level generation algorithm
+ 2. think of a better level generation algorithm
*/
#define DEF_TRACKMOUSE "False"
# include "images/pacman/ghost-d1.xpm"
# include "images/pacman/ghost-d2.xpm"
# include "images/pacman/ghost-mask.xpm" /* Used to clean up the dust left by wag. */
+# include "images/pacman/pacman-u1.xpm"
+# include "images/pacman/pacman-u2.xpm"
+# include "images/pacman/pacman-r1.xpm"
+# include "images/pacman/pacman-r2.xpm"
+# include "images/pacman/pacman-l1.xpm"
+# include "images/pacman/pacman-l2.xpm"
+# include "images/pacman/pacman-d1.xpm"
+# include "images/pacman/pacman-d2.xpm"
+# include "images/pacman/pacman-0.xpm"
#endif
-static const struct { int dx, dy; } dirvecs[DIRVECS] =
- { {-1, 0}, {0, 1}, {1, 0}, {0, -1}};
-
#ifdef DISABLE_INTERACTIVE
ModeSpecOpt pacman_opts = {
0,
/* Draws the pacman sprite, removing the previous location. */
+#if defined(USE_PIXMAP)
+
static void
draw_pacman_sprite(ModeInfo * mi)
{
- Display *display = MI_DISPLAY(mi);
- Window window = MI_WINDOW(mi);
+ Display *display = MI_DISPLAY(mi);
+ Window window = MI_WINDOW(mi);
pacmangamestruct *pp = &pacmangames[MI_SCREEN(mi)];
- unsigned int dir;
+ unsigned int dir = 0;
+ int old_mask_dir = 0;
+ int old_mask_mouth = 0;
+ static int mouth = 0;
+ static int mouth_delay = 0;
+ static int open_mouth = 0;
+
+#define MAX_MOUTH_DELAY 10
pp->pacman.cf = pp->pacman.col * pp->xs + pp->pacman.delta.x *
pp->pacman.cfactor + pp->xb + pp->spritedx;
dir = (ABS(pp->pacman.cfactor) * (2 - pp->pacman.cfactor) +
ABS(pp->pacman.rfactor) * (1 + pp->pacman.rfactor)) % 4;
- XSetForeground(display, pp->stippledGC,
- MI_BLACK_PIXEL(mi));
- if (pp->pacman.oldcf != NOWHERE && pp->pacman.oldrf != NOWHERE) {
-#ifdef FLASH
- XFillRectangle(display, window, pp->stippledGC,
- pp->pacman.oldcf, pp->pacman.oldrf,
- pp->spritexs, pp->spriteys);
-#else
- ERASE_IMAGE(display, window, pp->stippledGC,
- pp->pacman.cf, pp->pacman.rf,
- pp->pacman.oldcf, pp->pacman.oldrf,
- pp->spritexs, pp->spriteys);
-#endif
+ if (mouth_delay == MAX_MOUTH_DELAY){
+ if (mouth == (MAXMOUTH - 1)|| mouth == 0){
+ open_mouth = !open_mouth;
+ }
+ open_mouth ? mouth++ : mouth--;
+ mouth_delay = 0;
+ }else {
+ mouth_delay++;
}
- XSetTSOrigin(display, pp->stippledGC,
- pp->pacman.cf, pp->pacman.rf);
- if (MI_NPIXELS(mi) > 2)
- XSetForeground(display, pp->stippledGC,
- MI_PIXEL(mi, YELLOW));
- else
- XSetForeground(display, pp->stippledGC,
- MI_WHITE_PIXEL(mi));
+ XSetForeground(display,
+ pp->stippledGC,
+ MI_BLACK_PIXEL(mi));
- XSetStipple(display, pp->stippledGC,
- pp->pacmanPixmap[dir][pp->pacman.mouthstage]);
-#ifdef FLASH
- XSetFillStyle(display, pp->stippledGC, FillStippled);
-#else
- XSetFillStyle(display, pp->stippledGC,
- FillOpaqueStippled);
-#endif
- if (pp->xs < 2 || pp->ys < 2)
- XDrawPoint(display, window, pp->stippledGC,
- pp->pacman.cf, pp->pacman.rf);
- else
- XFillRectangle(display, window, pp->stippledGC,
- pp->pacman.cf, pp->pacman.rf,
- pp->spritexs, pp->spriteys);
- pp->pacman.mouthstage += pp->pacman.mouthdirection;
- if ((pp->pacman.mouthstage >= MAXMOUTH) ||
- (pp->pacman.mouthstage < 0)) {
- pp->pacman.mouthdirection *= -1;
- pp->pacman.mouthstage += pp->pacman.mouthdirection * 2;
- }
+ XSetClipMask(display, pp->stippledGC, pp->pacmanMask[old_mask_dir][old_mask_mouth]);
+ XSetClipOrigin(display, pp->stippledGC,
+ pp->pacman.oldcf, pp->pacman.oldrf);
+ XFillRectangle(display,
+ window,
+ pp->stippledGC,
+ pp->pacman.oldcf,
+ pp->pacman.oldrf,
+ pp->spritexs, pp->spriteys);
+ XSetClipMask(display, pp->stippledGC, pp->pacmanMask[dir][mouth]);
+ XSetClipOrigin(display, pp->stippledGC,
+ pp->pacman.cf, pp->pacman.rf);
+ XCopyArea(display, pp->pacmanPixmap[dir][mouth], window,
+ pp->stippledGC,0,0,pp->spritexs,pp->spriteys,
+ pp->pacman.cf, pp->pacman.rf);
+ XSetClipMask(display, pp->stippledGC, None);
pp->pacman.oldcf = pp->pacman.cf;
pp->pacman.oldrf = pp->pacman.rf;
+ old_mask_dir = dir;
+ old_mask_mouth = mouth;
}
-#if defined(USE_PIXMAP)
+
+
static void
draw_ghost_sprite(ModeInfo * mi, const unsigned ghost){
Display *display = MI_DISPLAY(mi);
pp->ghosts[ghost].oldcf,
pp->ghosts[ghost].oldrf,
pp->spritexs, pp->spriteys);
+ drawlevelblock(mi, pp,
+ (unsigned int)pp->ghosts[ghost].col,
+ (unsigned int)pp->ghosts[ghost].row);
XSetClipOrigin(display, pp->stippledGC,
pp->ghosts[ghost].cf, pp->ghosts[ghost].rf);
XCopyArea(display, pp->ghostPixmap[ghost][dir][wag], window,
pp->stippledGC,0,0,pp->spritexs,pp->spriteys,
pp->ghosts[ghost].cf, pp->ghosts[ghost].rf);
XSetClipMask(display, pp->stippledGC, None);
- drawlevelblock(mi, pp,
- (unsigned int)pp->ghosts[ghost].col,
- (unsigned int)pp->ghosts[ghost].row);
pp->ghosts[ghost].oldcf = pp->ghosts[ghost].cf;
pp->ghosts[ghost].oldrf = pp->ghosts[ghost].rf;
if (wag_count++ == MAX_WAG_COUNT){
}
}
+#else /* USE_PIXMAP */
+
+/* Draws the pacman sprite, removing the previous location. */
+static void
+draw_pacman_sprite(ModeInfo * mi)
+{
+ Display *display = MI_DISPLAY(mi);
+ Window window = MI_WINDOW(mi);
+ pacmangamestruct *pp = &pacmangames[MI_SCREEN(mi)];
+ unsigned int dir;
+
+ pp->pacman.cf = pp->pacman.col * pp->xs + pp->pacman.delta.x *
+ pp->pacman.cfactor + pp->xb + pp->spritedx;
+ pp->pacman.rf = pp->pacman.row * pp->ys + pp->pacman.delta.y *
+ pp->pacman.rfactor + pp->yb + pp->spritedy;
+
+ dir = (ABS(pp->pacman.cfactor) * (2 - pp->pacman.cfactor) +
+ ABS(pp->pacman.rfactor) * (1 + pp->pacman.rfactor)) % 4;
+
+ XSetForeground(display, pp->stippledGC,
+ MI_BLACK_PIXEL(mi));
+ if (pp->pacman.oldcf != NOWHERE && pp->pacman.oldrf != NOWHERE) {
+#ifdef FLASH
+ XFillRectangle(display, window, pp->stippledGC,
+ pp->pacman.oldcf, pp->pacman.oldrf,
+ pp->spritexs, pp->spriteys);
#else
+ ERASE_IMAGE(display, window, pp->stippledGC,
+ pp->pacman.cf, pp->pacman.rf,
+ pp->pacman.oldcf, pp->pacman.oldrf,
+ pp->spritexs, pp->spriteys);
+#endif
+ }
+
+ XSetTSOrigin(display, pp->stippledGC,
+ pp->pacman.cf, pp->pacman.rf);
+ if (MI_NPIXELS(mi) > 2)
+ XSetForeground(display, pp->stippledGC,
+ MI_PIXEL(mi, YELLOW));
+ else
+ XSetForeground(display, pp->stippledGC,
+ MI_WHITE_PIXEL(mi));
+
+ XSetStipple(display, pp->stippledGC,
+ pp->pacmanPixmap[dir][pp->pacman.mouthstage]);
+#ifdef FLASH
+ XSetFillStyle(display, pp->stippledGC, FillStippled);
+#else
+ XSetFillStyle(display, pp->stippledGC,
+ FillOpaqueStippled);
+#endif
+ if (pp->xs < 2 || pp->ys < 2)
+ XDrawPoint(display, window, pp->stippledGC,
+ pp->pacman.cf, pp->pacman.rf);
+ else
+ XFillRectangle(display, window, pp->stippledGC,
+ pp->pacman.cf, pp->pacman.rf,
+ pp->spritexs, pp->spriteys);
+ pp->pacman.mouthstage += pp->pacman.mouthdirection;
+ if ((pp->pacman.mouthstage >= MAXMOUTH) ||
+ (pp->pacman.mouthstage < 0)) {
+ pp->pacman.mouthdirection *= -1;
+ pp->pacman.mouthstage += pp->pacman.mouthdirection * 2;
+ }
+ pp->pacman.oldcf = pp->pacman.cf;
+ pp->pacman.oldrf = pp->pacman.rf;
+}
/* Draws a ghost sprite, removing the previous sprite and restores the level. */
static void
pp->ghosts[ghost].oldcf = pp->ghosts[ghost].cf;
pp->ghosts[ghost].oldrf = pp->ghosts[ghost].rf;
}
-#endif
+#endif /* USE_PIXMAP */
/* Does all drawing of moving sprites in the level. */
static void
* Changed it so that the information specific
* to the source pixmap does not have to be a parameter.
*
- * There is probable a better way to scale pixmaps.
+ * There is probably a better way to scale pixmaps.
* From: Chris Fiddyment (cxf@itd.dsto.gov.au)
* Subject: Scaling Pixmap Algorithm.
* Newsgroups: comp.graphics.algorithms
return (Pixmap) dest;
}
-/* Load any needed pixmaps and their mask. */
static void
-load_pixmaps(Display **dpy, Window window, pacmangamestruct **ps)
+pacman_fail(char *s){
+ fprintf (stderr, "%s: %s\n", progname, s);
+ exit(1);
+}
+
+/* Load the ghost pixmaps and their mask. */
+static void
+load_ghost_pixmaps(Display **dpy, Window window, pacmangamestruct **ps)
{
pacmangamestruct *pp = *ps;
Display *display = *dpy;
bits[m][2] = colors[i];
pp->ghostPixmap[i][j][k] = xpm_data_to_pixmap (display, window, bits[m],
&w, &h, &pp->ghostMask);
- if (!pp->ghostPixmap[i][j][k])
- {
- fprintf (stderr, "%s: Can't load ghost images\n", progname);
- exit(1);
- }
+
+ if (!pp->ghostPixmap[i][j][k]) pacman_fail("Cannot load ghost images");
pp->ghostPixmap[i][j][k] = scale_pixmap(&display, pp->stippledGC,
pp->ghostPixmap[i][j][k], pp->spritexs, pp->spriteys);
- if (!pp->ghostPixmap[i][j][k])
- {
- fprintf (stderr, "%s: Can't load ghost images\n", progname);
- exit(1);
- }
-
+
+ if (!pp->ghostPixmap[i][j][k]) pacman_fail("Cannot scale ghost images");
m++;
}
}
*/
temp = xpm_data_to_pixmap (display, window, ghost_mask_xpm,
&w, &h, &pp->ghostMask);
- if (!temp)
- {
- fprintf (stderr, "%s: Can't load ghost images\n", progname);
- exit(1);
- }
+
+ if (!temp) pacman_fail("Cannot load temporary ghost image");
temp = scale_pixmap(&display, pp->stippledGC,
temp, pp->spritexs, pp->spriteys);
- if (!temp)
- {
- fprintf (stderr, "%s: Can't load ghost images\n", progname);
- exit(1);
- }
+
+ if (!temp) pacman_fail("Cannot scale temporary ghost image");
+
gc = XCreateGC(display, pp->ghostMask, 0, 0);
+
pp->ghostMask = scale_pixmap(&display, gc, pp->ghostMask,
pp->spritexs, pp->spriteys);
XFreePixmap(display, temp);
}
-#endif
+
+/* Load the pacman pixmaps and their mask. */
+static void
+load_pacman_pixmaps(Display **dpy, Window window, pacmangamestruct **ps)
+{
+ pacmangamestruct *pp = *ps;
+ Display *display = *dpy;
+
+ static char **bits[] = {
+ pacman_0_xpm, pacman_u1_xpm, pacman_u2_xpm,
+ pacman_0_xpm, pacman_r1_xpm, pacman_r2_xpm,
+ pacman_0_xpm, pacman_d1_xpm, pacman_d2_xpm,
+ pacman_0_xpm, pacman_l1_xpm, pacman_l2_xpm
+ };
+ int i, j, m;
+ int w = pp->spritexs;
+ int h = pp->spriteys;
+ GC gc = 0;
+
+ m = 0;
+ for (i = 0; i < 4; i++){
+ for ( j = 0; j < MAXMOUTH; j++){
+ pp->pacmanPixmap[i][j] = xpm_data_to_pixmap (display, window, bits[m++],
+ &w, &h, &pp->pacmanMask[i][j]);
+
+ if (!pp->pacmanPixmap[i][j]) pacman_fail("Cannot load pacman pixmap.");
+
+ pp->pacmanPixmap[i][j] = scale_pixmap(&display, pp->stippledGC,
+ pp->pacmanPixmap[i][j], pp->spritexs, pp->spriteys);
+
+ if (!pp->pacmanPixmap[i][j]) pacman_fail("Cannot scale pacman pixmap.");
+
+ if (!gc)
+ gc = XCreateGC(display, pp->pacmanMask[i][j], 0, 0);
+
+ pp->pacmanMask[i][j] = scale_pixmap(&display, gc, pp->pacmanMask[i][j],
+ pp->spritexs, pp->spriteys);
+ }
+ }
+}
+#endif /* USE_PIXMAP */
/* Hook function, sets state to initial position. */
void
int size = MI_SIZE(mi);
pacmangamestruct *pp;
XGCValues gcv;
- int dir, mouth, i, j, k;
+ int i, j, k;
+
+#if (! defined( USE_PIXMAP ))
GC fg_gc, bg_gc;
-/* XPoint points[9]; */
+ XPoint points[9];
+ int dir, mouth;
+#endif
if (pacmangames == NULL) {
if ((pacmangames = (pacmangamestruct *)
}
#if defined(USE_PIXMAP)
- load_pixmaps(&display,window,&pp);
+ load_ghost_pixmaps(&display,window,&pp);
+ load_pacman_pixmaps(&display,window,&pp);
#else
if ((pp->ghostPixmap[0][0][0] = XCreatePixmap(display, window,
pp->spritexs, pp->spriteys, 1)) == None) {
points, 9, Nonconvex, CoordModeOrigin);
XFreeGC(display, bg_gc);
XFreeGC(display, fg_gc);
-#endif
if (pp->pacmanPixmap[0][0] != None)
XFreeGC(display, fg_gc);
XFreeGC(display, bg_gc);
}
+#endif /* USE_PIXMAP */
pp->pacman.lastbox = START;
pp->pacman.mouthdirection = 1;