1 /* xscreensaver, Copyright (c) 1992, 1994 Jamie Zawinski <jwz@netscape.com>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
12 /* Draw some fireworks. Inspired from TI Explorer Lisp code by
13 John S. Pezaris <pz@hx.lcs.mit.edu>
16 #include "screenhack.h"
19 int x, y; /* position */
20 int dx, dy; /* velocity */
27 struct projectile *next_free;
30 static struct projectile *projectiles, *free_projectiles;
32 static struct projectile *
39 free_projectiles = p->next_free;
52 p->next_free = free_projectiles;
58 launch (xlim, ylim, g, dpy, cmap)
63 struct projectile *p = get_projectile ();
68 x = (random () % xlim);
69 dx = 30000 - (random () % 60000);
71 } while (xxx <= 0 || xxx >= xlim);
78 p->dy = (random () % 4000) - 13000;
79 p->fuse = ((((random () % 500) + 500) * abs (p->dy / g)) / 1000);
84 hsv_to_rgb (random () % 360, 1.0, 1.0,
85 &p->color.red, &p->color.green, &p->color.blue);
86 p->color.flags = DoRed | DoGreen | DoBlue;
87 if (!XAllocColor (dpy, cmap, &p->color))
89 p->color.pixel = WhitePixel (dpy, DefaultScreen (dpy));
90 p->color.red = p->color.green = p->color.blue = 0;
95 static struct projectile *
96 shrapnel (parent, dpy, cmap)
97 struct projectile *parent;
101 struct projectile *p = get_projectile ();
105 p->dx = (random () % 5000) - 2500 + parent->dx;
106 p->dy = (random () % 5000) - 2500 + parent->dy;
107 p->decay = (random () % 50) - 60;
108 p->size = (parent->size * 2) / 3;
112 p->color = parent->color;
114 XAllocColor (dpy, cmap, &p->color); /* dup the lock */
119 static GC draw_gc, erase_gc;
120 static unsigned int default_fg_pixel;
122 static int how_many, frequency, scatter;
125 init_pyro (dpy, window)
132 XWindowAttributes xgwa;
133 XGetWindowAttributes (dpy, window, &xgwa);
134 cmap = xgwa.colormap;
135 how_many = get_integer_resource ("count", "Integer");
136 frequency = get_integer_resource ("frequency", "Integer");
137 scatter = get_integer_resource ("scatter", "Integer");
138 if (how_many <= 0) how_many = 100;
139 if (frequency <= 0) frequency = 30;
140 if (scatter <= 0) scatter = 20;
142 free_projectiles = 0;
143 projectiles = (struct projectile *)
144 calloc (how_many, sizeof (struct projectile));
145 for (i = 0; i < how_many; i++)
146 free_projectile (&projectiles [i]);
147 gcv.foreground = default_fg_pixel =
148 get_pixel_resource ("foreground", "Foreground", dpy, cmap);
149 draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
150 gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
151 erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
152 XClearWindow (dpy, window);
157 pyro (dpy, window, cmap)
162 XWindowAttributes xgwa;
163 static int xlim, ylim, real_xlim, real_ylim;
167 if ((random () % frequency) == 0)
169 XGetWindowAttributes (dpy, window, &xgwa);
170 real_xlim = xgwa.width;
171 real_ylim = xgwa.height;
172 xlim = real_xlim * 1000;
173 ylim = real_ylim * 1000;
174 launch (xlim, ylim, g, dpy, cmap);
180 for (i = 0; i < how_many; i++)
182 struct projectile *p = &projectiles [i];
183 int old_x, old_y, old_size;
185 if (p->dead) continue;
188 old_size = p->size >> 10;
189 size = (p->size += p->decay) >> 10;
190 x = (p->x += p->dx) >> 10;
191 y = (p->y += p->dy) >> 10;
192 p->dy += (p->size >> 6);
193 if (p->primary) p->fuse--;
196 XFillRectangle (dpy, window, erase_gc, old_x, old_y,
199 if ((p->primary ? (p->fuse > 0) : (p->size > 0)) &&
205 if (mono_p || p->primary)
206 XSetForeground (dpy, draw_gc, default_fg_pixel);
208 XSetForeground (dpy, draw_gc, p->color.pixel);
210 if /*(p->primary)*/ (size > 2)
211 XFillArc (dpy, window, draw_gc, x, y, size, size, 0, 360*64);
213 XFillRectangle (dpy, window, draw_gc, x, y, size, size);
218 if (! mono_p) XFreeColors (dpy, cmap, &p->color.pixel, 1, 0);
221 if (p->primary && p->fuse <= 0)
223 int i = (random () % scatter) + (scatter/2);
225 shrapnel (p, dpy, cmap);
231 char *progclass = "Pyro";
233 char *defaults [] = {
234 "Pyro.background: black", /* to placate SGI */
235 "Pyro.foreground: white",
239 "*geometry: 800x500",
243 XrmOptionDescRec options [] = {
244 { "-count", ".count", XrmoptionSepArg, 0 },
245 { "-frequency", ".frequency", XrmoptionSepArg, 0 },
246 { "-scatter", ".scatter", XrmoptionSepArg, 0 }
248 int options_size = (sizeof (options) / sizeof (options[0]));
251 screenhack (dpy, window)
255 Colormap cmap = init_pyro (dpy, window);
257 pyro (dpy, window, cmap);