2 * Fireworkx 1.3 - pyrotechnics simulation program
3 * Copyright (c) 1999-2004 Rony B Chandran <ronybc@asia.com>
5 * url: http://www.ronybc.8k.com
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation. No representations are made about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
15 * Additional programming:
16 * ------------------------
17 * Support for different display color modes:
18 * Jean-Pierre Demailly <Jean-Pierre.Demailly@ujf-grenoble.fr>
20 * Fixed array access problems by beating on it with a large hammer.
21 * Nicholas Miell <nmiell@gmail.com>
26 #include "screenhack.h"
27 #include <X11/Xutil.h>
29 #define FWXVERSION "1.3"
34 #define PIXCOUNT 500 /* 500 */
35 #define RNDLIFE0 250 /* violent */
36 #define RNDLIFE1 1200 /* 1200 */
37 #define MINLIFE0 50 /* violent */
38 #define MINLIFE1 500 /* 500 */
39 #define POWER 5 /* 5 */
40 #define FTWEAK 12 /* 12 */
44 static Bool light_on = True;
45 static Bool fade_on = False;
46 static Bool shoot = False;
47 static Bool verbose = False;
49 static int fsc_width = 0;
50 static int fsc_height= 0;
51 static int rndlife = RNDLIFE1;
52 static int minlife = MINLIFE1;
53 static float light_fade = 0.99;
54 static unsigned char *real_palaka1 = NULL;
55 static unsigned char *real_palaka2 = NULL;
56 static unsigned char *palaka1=NULL;
57 static unsigned char *palaka2=NULL;
58 static XImage *xim=NULL;
59 static XColor *colors;
60 static int ncolors = 255;
77 firepix *fpix; }fireshell;
82 if ((seed = seed % 44488 * 48271 - seed / 44488 * 3399) < 0)
87 int explode(fireshell *fs)
89 float air,adg = 0.001; /* gravity */
91 unsigned int h = fsc_height;
92 unsigned int w = fsc_width;
94 unsigned char *palaka = palaka1;
95 firepix *fp = fs->fpix;
97 if(--fs->cy == fs->shy){
99 fs->lum = 20000;} /* millions of jouls..! */
101 fs->lum = 50+(fs->cy - fs->shy)*2;
103 if(fs->cshift) --fs->cshift;
104 if((fs->cshift+1)%50==0) fs->color = ~fs->color;
107 fs->lum *= light_fade;
108 for(n=PIXCOUNT;n;n--){
109 if(fp->burn){ --fp->burn;
111 fp->x += fp->xv = fp->xv * air + (float)(rnd(200)-100)/2000;
112 fp->y += fp->yv = fp->yv * air + (float)(rnd(200)-100)/2000 +adg; }
114 fp->x += fp->xv = fp->xv * air + (float)(rnd(200)-100)/20000;
115 fp->y += fp->yv = fp->yv * air + adg; }
117 if(rnd(5)==3) {fp->yv *= -0.24; fp->y = h;}
118 else fp->burn=0;} /* touch muddy ground :) */
119 if(fp->x < w && fp->x > 0 && fp->y < h && fp->y > 0){
120 prgb = (unsigned int *)(palaka + ((int)fp->y * w + (int)fp->x)*4);
123 } return(--(fs->life));
126 void recycle(fireshell *fs,int x,int y)
128 unsigned int n,pixlife;
129 firepix *fp = fs->fpix;
133 fs->cy = shoot ? fsc_height : y ;
134 fs->color = (rnd(155)+100) <<16 |
137 fs->life = rnd(rndlife)+minlife;
138 fs->air = 1-(float)(rnd(200))/10000;
140 fs->cshift = !rnd(5) ? 120:0;
141 fs->special = !rnd(10) ? 1:0;
142 pixlife = rnd(fs->life)+fs->life/10+1; /* ! */
143 for(n=0;n<PIXCOUNT;n++){
144 fp->burn = rnd(pixlife)+32;
145 fp->xv = POWER*(float)(rnd(20000)-10000)/10000;
146 fp->yv = sqrt(POWER*POWER - fp->xv * fp->xv) *
147 (float)(rnd(20000)-10000)/10000;
156 unsigned int w = fsc_width;
157 unsigned int h = fsc_height;
158 unsigned char *pa, *pb, *pm;
160 for(n=0;n<w*4;n++) pm[n]=0; /* clean first line */
166 for(n=0;n<w*h*4;n++){
167 pm[n]=(pm[n-4] + pm[n] + pm[n+4] +
168 pa[n-4] + pa[n] + pa[n+4] +
169 pb[n-4] + pb[n] + pb[n+4] +
170 pm[n] + pm[n] + (pm[n]<<2))/ 16;}}
172 for(n=0;n<w*h*4;n++){
173 pm[n]=(pm[n-4] + pm[n] + pm[n+4] +
174 pa[n-4] + pa[n] + pa[n+4] +
175 pb[n-4] + pb[n] + pb[n+4])/ 9;}}
177 for(n=0;n<w*4;n++) pm[n]=0; /* clean last line */
180 void light_2x2(fireshell *fss)
182 unsigned int l,t,n,x,y;
186 unsigned char *dim = palaka2;
187 unsigned char *sim = palaka1;
193 for(n=SHELLCOUNT;n;n--,f++){
194 s += f->lum / ( 1 + sqrt((f->cx - x)*(f->cx - x)+(f->cy - y)*(f->cy - y))); }
198 dim[0] = (t > 255 ? 255 : t); /* cmov's */
200 dim[1] = (t > 255 ? 255 : t);
202 dim[2] = (t > 255 ? 255 : t);
205 dim[4] = (t > 255 ? 255 : t);
207 dim[5] = (t > 255 ? 255 : t);
209 dim[6] = (t > 255 ? 255 : t);
212 dim[nl+0] = (t > 255 ? 255 : t);
214 dim[nl+1] = (t > 255 ? 255 : t);
216 dim[nl+2] = (t > 255 ? 255 : t);
219 dim[nl+4] = (t > 255 ? 255 : t);
221 dim[nl+5] = (t > 255 ? 255 : t);
223 dim[nl+6] = (t > 255 ? 255 : t);
225 sim += 8; dim += 8; } sim += nl; dim += nl;}
228 void resize(Display *display, Window win)
230 XWindowAttributes xwa;
231 XGetWindowAttributes (display, win, &xwa);
232 xwa.width -= xwa.width % 4;
233 xwa.height -= xwa.height % 4;
234 if(xwa.height != fsc_height || xwa.width != fsc_width) {
235 fsc_width = xwa.width;
236 fsc_height = xwa.height;
238 if (xim->data==(char *)palaka2) xim->data=NULL;
240 if (palaka2!=palaka1) free(real_palaka2);
245 xim = XCreateImage(display, xwa.visual, xwa.depth, ZPixmap, 0, 0,
246 fsc_width, fsc_height, 32, 0);
247 real_palaka1 = calloc(xim->height + 4,xim->width*4);
248 palaka1 = real_palaka1 + xim->width * 4 * 2;
250 real_palaka2 = calloc(xim->height + 4,xim->width*4);
251 palaka2 = real_palaka2 + xim->width * 4 * 2;
256 xim->data = (char *)palaka2;
258 xim->data = calloc(xim->height,xim->bytes_per_line);
262 void put_image(Display *display, Window win, GC gc, XImage *xim)
265 unsigned char r, g, b;
270 for (y=0;y<xim->height; y++)
271 for (x=0;x<xim->width; x++) {
276 xim->data[i++] = (g&224)>>5 | (r&248);
277 xim->data[i++] = (b&248)>>3 | (g&28)<<3;
280 for (y=0;y<xim->height; y++)
281 for (x=0;x<xim->width; x++) {
286 xim->data[i++] = (b&248)>>3 | (g&28)<<3;
287 xim->data[i++] = (g&224)>>5 | (r&248);
292 for (y=0;y<xim->height; y++)
293 for (x=0;x<xim->width; x++) {
298 xim->data[i++] = (g&192)>>6 | (r&248)>>1;
299 xim->data[i++] = (b&248)>>3 | (g&56)<<2;
302 for (y=0;y<xim->height; y++)
303 for (x=0;x<xim->width; x++) {
308 xim->data[i++] = (b&248)>>3 | (g&56)<<2;
309 xim->data[i++] = (g&192)>>6 | (r&248)>>1;
313 for (y=0;y<xim->height; y++)
314 for (x=0;x<xim->width; x++) {
319 xim->data[i++] = (((7*g)/256)*36)+(((6*r)/256)*6)+((6*b)/256);
322 XPutImage(display,win,gc,xim,0,0,0,0,xim->width,xim->height);
325 void sniff_events(Display *dis, Window win, fireshell *fss)
328 while (XPending(dis)){
329 XNextEvent (dis, &e);
330 if (e.type == ConfigureNotify) resize(dis,win);
331 if (e.type == ButtonPress) recycle(fss,e.xbutton.x, e.xbutton.y);
332 screenhack_handle_event(dis,&e);}
336 char *progclass = "Fireworkx";
338 char *defaults [] = {
339 ".background: black",
340 ".foreground: white",
350 XrmOptionDescRec options [] = {
351 { "-delay", ".delay", XrmoptionSepArg, 0 },
352 { "-maxlife", ".maxlife", XrmoptionSepArg, 0 },
353 { "-nolight", ".light", XrmoptionNoArg, "False" },
354 { "-fade", ".fade", XrmoptionNoArg, "True" },
355 { "-shoot", ".shoot", XrmoptionNoArg, "True" },
356 { "-verbose", ".verbose", XrmoptionNoArg, "True" },
361 screenhack (Display *display, Window win)
367 XWindowAttributes xwa;
370 firepix *fpixs, *fpix;
371 fireshell *fshells, *fshell;
372 fade_on = get_boolean_resource("fade" , "Boolean");
373 light_on = get_boolean_resource("light" , "Boolean");
374 shoot = get_boolean_resource("shoot" , "Boolean");
375 verbose = get_boolean_resource("verbose" , "Boolean");
376 rndlife = get_integer_resource("maxlife" , "Integer");
377 delay = get_integer_resource("delay" , "Integer");
379 if(rndlife<1000) light_fade=0.98;
380 if(rndlife<500) light_fade=0.97;
381 if(fade_on) light_fade=0.97;
383 printf("Fireworkx %s - pyrotechnics simulation program \n", FWXVERSION);
384 printf("Copyright (c) 1999-2004 Rony B Chandran <ronybc@asia.com> \n\n");
385 printf("url: http://www.ronybc.8k.com \n\n");}
387 XGetWindowAttributes(display,win,&xwa);
391 bigendian = (ImageByteOrder(display) == MSBFirst);
395 printf("Pseudocolor color: use '-fade' & '-nolight' for better results.\n");}
396 colors = (XColor *) calloc(sizeof(XColor),ncolors+1);
398 make_smooth_colormap(display, vi, cmap, colors, &ncolors,
399 False, &writable, True);
401 gc = XCreateGC(display, win, 0, &gcv);
403 resize(display,win); /* initialize palakas */
406 fpixs = malloc(sizeof(firepix) * PIXCOUNT * SHELLCOUNT);
407 fshells = malloc(sizeof(fireshell) * SHELLCOUNT);
410 for (n=0;n<SHELLCOUNT;n++){
412 recycle (fshell,rnd(fsc_width),rnd(fsc_height));
419 for(n=SHELLCOUNT;n;n--){
420 if (!explode(fshell)){
421 recycle(fshell,rnd(fsc_width),rnd(fsc_height)); }
423 if(light_on) light_2x2(fshells);
424 put_image(display,win,gc,xim);
427 sniff_events(display, win, fshells);