X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fpacman.c;h=b079605f14c73bdc15ce9e5ffa755620e4dbab46;hp=356efeaaf1caa6b9b9d79baebf6ee9e0b4499607;hb=bc7b7a8eb122206d239ec0e693676bcce31be1aa;hpb=ffd8c0873576a9e3065696a624dce6b766b77062 diff --git a/hacks/pacman.c b/hacks/pacman.c index 356efeaa..b079605f 100644 --- a/hacks/pacman.c +++ b/hacks/pacman.c @@ -1,10 +1,7 @@ /* -*- 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 . @@ -22,6 +19,7 @@ static const char sccsid[] = "@(#)pacman.c 5.00 2000/11/01 xlockmore"; * 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 @@ -35,8 +33,7 @@ static const char sccsid[] = "@(#)pacman.c 5.00 2000/11/01 xlockmore"; /* 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" @@ -84,11 +81,17 @@ static const char sccsid[] = "@(#)pacman.c 5.00 2000/11/01 xlockmore"; # 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, @@ -457,13 +460,22 @@ drawlevel(ModeInfo * mi) /* 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; @@ -473,56 +485,44 @@ draw_pacman_sprite(ModeInfo * mi) 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); @@ -555,15 +555,15 @@ draw_ghost_sprite(ModeInfo * mi, const unsigned ghost){ 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){ @@ -572,7 +572,73 @@ draw_ghost_sprite(ModeInfo * mi, const unsigned ghost){ } } +#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 @@ -656,7 +722,7 @@ draw_ghost_sprite(ModeInfo * mi, const unsigned ghost) { 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 @@ -682,7 +748,7 @@ pacman_tick(ModeInfo * mi) * 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 @@ -731,9 +797,15 @@ scale_pixmap( Display **dpy, GC gc, Pixmap source, int dwidth, int dheight) 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; @@ -761,20 +833,13 @@ load_pixmaps(Display **dpy, Window window, pacmangamestruct **ps) 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++; } } @@ -786,25 +851,61 @@ load_pixmaps(Display **dpy, Window window, pacmangamestruct **ps) */ 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 @@ -815,9 +916,13 @@ init_pacman(ModeInfo * mi) 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 *) @@ -884,7 +989,8 @@ init_pacman(ModeInfo * mi) } #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) { @@ -930,7 +1036,6 @@ init_pacman(ModeInfo * mi) points, 9, Nonconvex, CoordModeOrigin); XFreeGC(display, bg_gc); XFreeGC(display, fg_gc); -#endif if (pp->pacmanPixmap[0][0] != None) @@ -985,6 +1090,7 @@ init_pacman(ModeInfo * mi) XFreeGC(display, fg_gc); XFreeGC(display, bg_gc); } +#endif /* USE_PIXMAP */ pp->pacman.lastbox = START; pp->pacman.mouthdirection = 1;