1 /* xscreensaver, Copyright (c) 1992, 1994, 1996, 1998
2 * Jamie Zawinski <jwz@jwz.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
13 /* Draw some fireworks. Inspired from TI Explorer Lisp code by
14 John S. Pezaris <pz@hx.lcs.mit.edu>
17 #include "screenhack.h"
20 int x, y; /* position */
21 int dx, dy; /* velocity */
28 struct projectile *next_free;
31 static struct projectile *projectiles, *free_projectiles;
33 static struct projectile *
40 free_projectiles = p->next_free;
50 free_projectile (struct projectile *p)
52 p->next_free = free_projectiles;
58 launch (int xlim, int ylim, int g,
59 Display *dpy, Colormap cmap)
61 struct projectile *p = get_projectile ();
66 x = (random () % xlim);
67 dx = 30000 - (random () % 60000);
69 } while (xxx <= 0 || xxx >= xlim);
76 p->dy = (random () % 4000) - 13000;
77 p->fuse = ((((random () % 500) + 500) * abs (p->dy / g)) / 1000);
82 hsv_to_rgb (random () % 360, 1.0, 1.0,
83 &p->color.red, &p->color.green, &p->color.blue);
84 p->color.flags = DoRed | DoGreen | DoBlue;
85 if (!XAllocColor (dpy, cmap, &p->color))
87 p->color.pixel = WhitePixel (dpy, DefaultScreen (dpy));
88 p->color.red = p->color.green = p->color.blue = 0xFFFF;
93 static struct projectile *
94 shrapnel (struct projectile *parent, Display *dpy, Colormap cmap)
96 struct projectile *p = get_projectile ();
100 p->dx = (random () % 5000) - 2500 + parent->dx;
101 p->dy = (random () % 5000) - 2500 + parent->dy;
102 p->decay = (random () % 50) - 60;
103 p->size = (parent->size * 2) / 3;
107 p->color = parent->color;
109 XAllocColor (dpy, cmap, &p->color); /* dup the lock */
114 static GC draw_gc, erase_gc;
115 static unsigned int default_fg_pixel;
117 static int how_many, frequency, scatter;
120 init_pyro (Display *dpy, Window window)
125 XWindowAttributes xgwa;
126 XGetWindowAttributes (dpy, window, &xgwa);
127 cmap = xgwa.colormap;
128 how_many = get_integer_resource ("count", "Integer");
129 frequency = get_integer_resource ("frequency", "Integer");
130 scatter = get_integer_resource ("scatter", "Integer");
131 if (how_many <= 0) how_many = 100;
132 if (frequency <= 0) frequency = 30;
133 if (scatter <= 0) scatter = 20;
135 free_projectiles = 0;
136 projectiles = (struct projectile *)
137 calloc (how_many, sizeof (struct projectile));
138 for (i = 0; i < how_many; i++)
139 free_projectile (&projectiles [i]);
140 gcv.foreground = default_fg_pixel =
141 get_pixel_resource ("foreground", "Foreground", dpy, cmap);
142 draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
143 gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
144 erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
145 XClearWindow (dpy, window);
150 pyro (Display *dpy, Window window, Colormap cmap)
152 XWindowAttributes xgwa;
153 static int xlim, ylim, real_xlim, real_ylim;
157 if ((random () % frequency) == 0)
159 XGetWindowAttributes (dpy, window, &xgwa);
160 real_xlim = xgwa.width;
161 real_ylim = xgwa.height;
162 xlim = real_xlim * 1000;
163 ylim = real_ylim * 1000;
164 launch (xlim, ylim, g, dpy, cmap);
168 screenhack_handle_events (dpy);
171 for (i = 0; i < how_many; i++)
173 struct projectile *p = &projectiles [i];
174 int old_x, old_y, old_size;
176 if (p->dead) continue;
179 old_size = p->size >> 10;
180 size = (p->size += p->decay) >> 10;
181 x = (p->x += p->dx) >> 10;
182 y = (p->y += p->dy) >> 10;
183 p->dy += (p->size >> 6);
184 if (p->primary) p->fuse--;
187 XFillRectangle (dpy, window, erase_gc, old_x, old_y,
190 if ((p->primary ? (p->fuse > 0) : (p->size > 0)) &&
196 if (mono_p || p->primary)
197 XSetForeground (dpy, draw_gc, default_fg_pixel);
199 XSetForeground (dpy, draw_gc, p->color.pixel);
201 if /*(p->primary)*/ (size > 2)
202 XFillArc (dpy, window, draw_gc, x, y, size, size, 0, 360*64);
204 XFillRectangle (dpy, window, draw_gc, x, y, size, size);
210 if (p->color.pixel != WhitePixel (dpy, DefaultScreen (dpy)))
211 XFreeColors (dpy, cmap, &p->color.pixel, 1, 0);
214 if (p->primary && p->fuse <= 0)
216 int j = (random () % scatter) + (scatter/2);
218 shrapnel (p, dpy, cmap);
224 char *progclass = "Pyro";
226 char *defaults [] = {
227 ".background: black",
228 ".foreground: white",
232 "*geometry: 800x500",
236 XrmOptionDescRec options [] = {
237 { "-count", ".count", XrmoptionSepArg, 0 },
238 { "-frequency", ".frequency", XrmoptionSepArg, 0 },
239 { "-scatter", ".scatter", XrmoptionSepArg, 0 },
244 screenhack (Display *dpy, Window window)
246 Colormap cmap = init_pyro (dpy, window);
248 pyro (dpy, window, cmap);