123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /* $XConsortium: pyro.c /main/3 1995/11/02 16:07:59 rswiston $ */
- /*
- */
- /* *
- * (c) Copyright 1993, 1994 Hewlett-Packard Company *
- * (c) Copyright 1993, 1994 International Business Machines Corp. *
- * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
- * (c) Copyright 1993, 1994 Novell, Inc. *
- */
- /*-
- * pyro.c - Fireworks for dtscreen, the X Window System lockscreen.
- *
- * Copyright (c) 1991 by Patrick J. Naughton.
- *
- * See dtscreen.c for copying information.
- *
- * Revision History:
- * 16-Mar-91: Written. (received from David Brooks, brooks@osf.org).
- */
- /* The physics of the rockets is a little bogus, but it looks OK. Each is
- * given an initial velocity impetus. They decelerate slightly (gravity
- * overcomes the rocket's impulse) and explode as the rocket's main fuse
- * gives out (we could add a ballistic stage, maybe). The individual
- * stars fan out from the rocket, and they decelerate less quickly.
- * That's called bouyancy, but really it's again a visual preference.
- */
- #include "dtscreen.h"
- #include <math.h>
- #include <stdlib.h>
- #define TWOPI 6.2831853
- /* Define this >1 to get small rectangles instead of points */
- #ifndef STARSIZE
- #define STARSIZE 2
- #endif
- #define SILENT 0
- #define REDGLARE 1
- #define BURSTINGINAIR 2
- #define CLOUD 0
- #define DOUBLECLOUD 1
- /* Clearly other types and other fascinating visual effects could be added...*/
- /* P_xxx parameters represent the reciprocal of the probability... */
- #define P_IGNITE 5000 /* ...of ignition per cycle */
- #define P_DOUBLECLOUD 10 /* ...of an ignition being double */
- #define P_MULTI 75 /* ...of an ignition being several @ once */
- #define P_FUSILLADE 250 /* ...of an ignition starting a fusillade */
- #define ROCKETW 2 /* Dimensions of rocket */
- #define ROCKETH 4
- #define XVELFACTOR 0.0025 /* Max horizontal velocity / screen width */
- #define MINYVELFACTOR 0.016 /* Min vertical velocity / screen height */
- #define MAXYVELFACTOR 0.018
- #define GRAVFACTOR 0.0002 /* delta v / screen height */
- #define MINFUSE 50 /* range of fuse lengths for rocket */
- #define MAXFUSE 100
- #define FUSILFACTOR 10 /* Generate fusillade by reducing P_IGNITE */
- #define FUSILLEN 100 /* Length of fusillade, in ignitions */
- #define SVELFACTOR 0.1 /* Max star velocity / yvel */
- #define BOUYANCY 0.2 /* Reduction in grav deceleration for stars */
- #define MAXSTARS 75 /* Number of stars issued from a shell */
- #define MINSTARS 50
- #define MINSFUSE 50 /* Range of fuse lengths for stars */
- #define MAXSFUSE 100
- #define INTRAND(min,max) (random()%((max+1)-(min))+(min))
- #define FLOATRAND(min,max) ((min)+(random()/MAXRAND)*((max)-(min)))
- static void ignite();
- static void animate();
- static void shootup();
- static void burst();
- typedef struct {
- int state;
- int shelltype;
- int color1, color2;
- int fuse;
- float xvel, yvel;
- float x, y;
- int nstars;
- #if STARSIZE > 1
- XRectangle Xpoints[MAXSTARS];
- XRectangle Xpoints2[MAXSTARS];
- #else
- XPoint Xpoints[MAXSTARS];
- XPoint Xpoints2[MAXSTARS];
- #endif
- float sx[MAXSTARS], sy[MAXSTARS]; /* Distance from notional
- * center */
- float sxvel[MAXSTARS], syvel[MAXSTARS]; /* Relative to notional
- * center */
- } rocket;
- typedef struct {
- Screen *scr;
- Colormap cmap;
- int p_ignite;
- unsigned long bgpixel;
- unsigned long fgpixel;
- unsigned long rockpixel;
- GC bgGC;
- int nflying;
- int fusilcount;
- int width, lmargin, rmargin, height;
- float minvelx, maxvelx;
- float minvely, maxvely;
- float maxsvel;
- float rockdecel, stardecel;
- rocket *rockq;
- } pyrostruct;
- static int orig_p_ignite;
- static int just_started = True;/* Greet the user right away */
- void
- initpyro(perwindow *pwin)
- {
- pyrostruct *pp;
- rocket *rp;
- XWindowAttributes xwa;
- XGCValues xgcv;
- int rockn, starn, bsize;
- if (pwin->data) free(pwin->data);
- pwin->data = (pyrostruct *)malloc(sizeof(pyrostruct));
- memset(pwin->data, '\0', sizeof(pyrostruct));
- pp = (pyrostruct *)pwin->data;
- XGetWindowAttributes(dsp, pwin->w, &xwa);
- orig_p_ignite = P_IGNITE / batchcount;
- if (orig_p_ignite <= 0)
- orig_p_ignite = 1;
- pp->p_ignite = orig_p_ignite;
- pp->rockq = (rocket *) malloc(batchcount * sizeof(rocket));
- pp->nflying = pp->fusilcount = 0;
- bsize = (xwa.height <= 64) ? 1 : STARSIZE;
- for (rockn = 0, rp = pp->rockq; rockn < batchcount; rockn++, rp++) {
- rp->state = SILENT;
- #if STARSIZE > 1
- for (starn = 0; starn < MAXSTARS; starn++) {
- rp->Xpoints[starn].width = rp->Xpoints[starn].height =
- rp->Xpoints2[starn].width = rp->Xpoints2[starn].height = bsize;
- }
- #endif
- }
- pp->width = xwa.width;
- pp->lmargin = xwa.width / 16;
- pp->rmargin = xwa.width - pp->lmargin;
- pp->height = xwa.height;
- pp->scr = pwin->perscreen->screen;
- pp->cmap = DefaultColormapOfScreen(pp->scr);
- pp->fgpixel = WhitePixelOfScreen(pp->scr);
- pp->bgpixel = BlackPixelOfScreen(pp->scr);
- if (!mono && pwin->perscreen->npixels > 3)
- pp->rockpixel = pwin->perscreen->pixels[3];/* Just the right shade of
- * orange */
- else
- pp->rockpixel = pp->fgpixel;
- xgcv.foreground = pp->bgpixel;
- pp->bgGC = XCreateGC(dsp, pwin->w, GCForeground, &xgcv);
-
- /* Geometry-dependent physical data: */
- pp->maxvelx = (float) (xwa.width) * XVELFACTOR;
- pp->minvelx = -pp->maxvelx;
- pp->minvely = -(float) (xwa.height) * MINYVELFACTOR;
- pp->maxvely = -(float) (xwa.height) * MAXYVELFACTOR;
- pp->maxsvel = pp->minvely * SVELFACTOR;
- pp->rockdecel = (float) (pp->height) * GRAVFACTOR;
- pp->stardecel = pp->rockdecel * BOUYANCY;
- XFillRectangle(dsp, pwin->w, pp->bgGC, 0, 0, xwa.width, xwa.height);
- }
- /*ARGSUSED*/
- void
- drawpyro(perwindow *pwin)
- {
- pyrostruct *pp;
- rocket *rp;
- int rockn;
- pp = (pyrostruct *)pwin->data;
- if (just_started || (random() % pp->p_ignite == 0)) {
- just_started = False;
- if (random() % P_FUSILLADE == 0) {
- pp->p_ignite = orig_p_ignite / FUSILFACTOR;
- pp->fusilcount = INTRAND(FUSILLEN * 9 / 10, FUSILLEN * 11 / 10);
- }
- ignite(pwin, pp);
- if (pp->fusilcount > 0) {
- if (--pp->fusilcount == 0)
- pp->p_ignite = orig_p_ignite;
- }
- }
- for (rockn = pp->nflying, rp = pp->rockq; rockn > 0; rp++) {
- if (rp->state != SILENT) {
- animate(pwin, pp, rp);
- rockn--;
- }
- }
- }
- static void
- ignite(perwindow *pwin, pyrostruct *pp)
- {
- rocket *rp;
- int multi, shelltype, nstars, fuse, npix, pix, color1, color2;
- float xvel, yvel, x;
- x = random() % pp->width;
- xvel = FLOATRAND(-pp->maxvelx, pp->maxvelx);
- /* All this to stop too many rockets going offscreen: */
- if ((x < pp->lmargin && xvel < 0.0) || (x > pp->rmargin && xvel > 0.0))
- xvel = -xvel;
- yvel = FLOATRAND(pp->minvely, pp->maxvely);
- fuse = INTRAND(MINFUSE, MAXFUSE);
- nstars = INTRAND(MINSTARS, MAXSTARS);
- if (!mono && (npix = pwin->perscreen->npixels) > 2) {
- color1 = pwin->perscreen->pixels[pix = random() % npix];
- color2 = pwin->perscreen->pixels[(pix + (npix / 2)) % npix];
- } else {
- color1 = color2 = WhitePixelOfScreen(pwin->perscreen->screen);
- }
- multi = 1;
- if (random() % P_DOUBLECLOUD == 0)
- shelltype = DOUBLECLOUD;
- else {
- shelltype = CLOUD;
- if (random() % P_MULTI == 0)
- multi = INTRAND(5, 15);
- }
- rp = pp->rockq;
- while (multi--) {
- if (pp->nflying >= batchcount)
- return;
- while (rp->state != SILENT)
- rp++;
- pp->nflying++;
- rp->shelltype = shelltype;
- rp->state = REDGLARE;
- rp->color1 = color1;
- rp->color2 = color2;
- rp->xvel = xvel;
- rp->yvel = FLOATRAND(yvel * 0.97, yvel * 1.03);
- rp->fuse = INTRAND((fuse * 90) / 100, (fuse * 110) / 100);
- rp->x = x + FLOATRAND(multi * 7.6, multi * 8.4);
- rp->y = pp->height - 1;
- rp->nstars = nstars;
- }
- }
- static void
- animate(perwindow *pwin, pyrostruct *pp, rocket *rp)
- {
- int starn;
- float r, theta;
- if (rp->state == REDGLARE) {
- shootup(pwin, pp, rp);
- /* Handle setup for explosion */
- if (rp->state == BURSTINGINAIR) {
- for (starn = 0; starn < rp->nstars; starn++) {
- rp->sx[starn] = rp->sy[starn] = 0.0;
- rp->Xpoints[starn].x = (int) rp->x;
- rp->Xpoints[starn].y = (int) rp->y;
- if (rp->shelltype == DOUBLECLOUD) {
- rp->Xpoints2[starn].x = (int) rp->x;
- rp->Xpoints2[starn].y = (int) rp->y;
- }
- /* This isn't accurate solid geometry, but it looks OK. */
- r = FLOATRAND(0.0, pp->maxsvel);
- theta = FLOATRAND(0.0, TWOPI);
- rp->sxvel[starn] = r * cos(theta);
- rp->syvel[starn] = r * sin(theta);
- }
- rp->fuse = INTRAND(MINSFUSE, MAXSFUSE);
- }
- }
- if (rp->state == BURSTINGINAIR) {
- burst(pwin, pp, rp);
- }
- }
- static void
- shootup(perwindow *pwin, pyrostruct *pp, rocket *rp)
- {
- XFillRectangle(dsp, pwin->w, pp->bgGC, (int) (rp->x), (int) (rp->y),
- ROCKETW, ROCKETH + 3);
- if (rp->fuse-- <= 0) {
- rp->state = BURSTINGINAIR;
- return;
- }
- rp->x += rp->xvel;
- rp->y += rp->yvel;
- rp->yvel += pp->rockdecel;
- XSetForeground(dsp, pwin->gc, pp->rockpixel);
- XFillRectangle(dsp, pwin->w, pwin->gc, (int) (rp->x), (int) (rp->y),
- ROCKETW, ROCKETH + random() % 4);
- }
- static void
- burst(perwindow *pwin, pyrostruct *pp, rocket *rp)
- {
- int starn;
- int nstars, stype;
- float rx, ry, sd; /* Help compiler optimize :-) */
- float sx, sy;
- nstars = rp->nstars;
- stype = rp->shelltype;
- #if STARSIZE > 1
- XFillRectangles(dsp, pwin->w, pp->bgGC, rp->Xpoints, nstars);
- if (stype == DOUBLECLOUD)
- XFillRectangles(dsp, pwin->w, pp->bgGC, rp->Xpoints2, nstars);
- #else
- XDrawPoints(dsp, pwin->w, pp->bgGC, rp->Xpoints, nstars, CoordModeOrigin);
- if (stype == DOUBLECLOUD)
- XDrawPoints(dsp, pwin->w, pp->bgGC, rp->Xpoints2, nstars, CoordModeOrigin);
- #endif
- if (rp->fuse-- <= 0) {
- rp->state = SILENT;
- pp->nflying--;
- return;
- }
- /* Stagger the stars' decay */
- if (rp->fuse <= 7) {
- if ((rp->nstars = nstars = nstars * 90 / 100) == 0)
- return;
- }
- rx = rp->x;
- ry = rp->y;
- sd = pp->stardecel;
- for (starn = 0; starn < nstars; starn++) {
- sx = rp->sx[starn] += rp->sxvel[starn];
- sy = rp->sy[starn] += rp->syvel[starn];
- rp->syvel[starn] += sd;
- rp->Xpoints[starn].x = (int) (rx + sx);
- rp->Xpoints[starn].y = (int) (ry + sy);
- if (stype == DOUBLECLOUD) {
- rp->Xpoints2[starn].x = (int) (rx + 1.7 * sx);
- rp->Xpoints2[starn].y = (int) (ry + 1.7 * sy);
- }
- }
- rp->x = rx + rp->xvel;
- rp->y = ry + rp->yvel;
- rp->yvel += sd;
- XSetForeground(dsp, pwin->gc, rp->color1);
- #if STARSIZE > 1
- XFillRectangles(dsp, pwin->w, pwin->gc, rp->Xpoints, nstars);
- if (stype == DOUBLECLOUD) {
- XSetForeground(dsp, pwin->gc, rp->color2);
- XFillRectangles(dsp, pwin->w, pwin->gc, rp->Xpoints2, nstars);
- }
- #else
- XDrawPoints(dsp, pwin->w, pwin->gc, rp->Xpoints, nstars, CoordModeOrigin);
- if (stype == DOUBLECLOUD) {
- XSetForeground(dsp, pwin->gc, rp->color2);
- XDrawPoints(dsp, pwin->w, pwin->gc, rp->Xpoints2, nstars,
- CoordModeOrigin);
- }
- #endif
- }
|