2 * Fireworkx 1.5 - pyrotechnics simulation program
3 * Copyright (c) 1999-2005 Rony B Chandran <ronybc@asia.com>
7 * url: http://www.ronybc.8k.com
9 * Permission to use, copy, modify, distribute, and sell this software and its
10 * documentation for any purpose is hereby granted without fee, provided that
11 * the above copyright notice appear in all copies and that both that
12 * copyright notice and this permission notice appear in supporting
13 * documentation. No representations are made about the suitability of this
14 * software for any purpose. It is provided "as is" without express or
17 * Additional programming:
18 * ------------------------
19 * Support for different display color modes:
20 * Jean-Pierre Demailly <Jean-Pierre.Demailly@ujf-grenoble.fr>
22 * Fixed array access problems by beating on it with a large hammer.
23 * Nicholas Miell <nmiell@gmail.com>
25 * Freed 'free'ing up of memory by adding the forgotten 'XSync's
26 * Renuka S <renuka@local.net>
31 #include "screenhack.h"
32 #include <X11/Xutil.h>
34 #define FWXVERSION "1.5"
36 #define SHELLCOUNT 3 /* 3 or 5 */
37 #define PIXCOUNT 500 /* 500 */
38 #define POWER 5 /* 5 */
39 #define FTWEAK 12 /* 12 */
42 void mmx_blur(char *a, int b, int c, int d);
43 void mmx_glow(char *a, int b, int c, int d, char *e);
46 #define rnd(x) ((int)(random() % (x)))
50 static Bool flash_on = True;
51 static Bool glow_on = True;
52 static Bool verbose = False;
53 static Bool shoot = False;
59 static float flash_fade = 0.99;
60 static unsigned char *palaka1=NULL;
61 static unsigned char *palaka2=NULL;
62 static XImage *xim=NULL;
63 static XColor *colors;
64 static int ncolors = 255;
81 firepix *fpix; }fireshell;
83 int explode(fireshell *fs)
85 float air,adg = 0.001; /* gravity */
87 unsigned int h = height;
88 unsigned int w = width;
90 unsigned char *palaka = palaka1;
91 firepix *fp = fs->fpix;
93 if(--fs->cy == fs->shy){
95 fs->flash = rnd(30000)+15000;}
97 fs->flash = 50+(fs->cy - fs->shy)*2;
98 prgb=(unsigned int *)(palaka + (fs->cy * w + fs->cx + rnd(5)-2)*4);
99 *prgb=(rnd(8)+8)*0x000f0f10;
101 if(fs->cshift) --fs->cshift;
102 if((fs->cshift+1)%50==0) fs->color = ~fs->color;
105 fs->flash *= flash_fade;
106 for(n=PIXCOUNT;n;n--){
107 if(fp->burn){ --fp->burn;
109 fp->x += fp->xv = fp->xv * air + (float)(rnd(200)-100)/2000;
110 fp->y += fp->yv = fp->yv * air + (float)(rnd(200)-100)/2000 + adg; }
112 fp->x += fp->xv = fp->xv * air + (float)(rnd(200)-100)/20000;
113 fp->y += fp->yv = fp->yv * air + adg; }
115 if(rnd(5)==3) {fp->yv *= -0.24; fp->y = h;}
116 else fp->burn=0;} /* touch muddy ground :) */
117 if(fp->x < w && fp->x > 0 && fp->y < h && fp->y > 0){
118 prgb = (unsigned int *)(palaka + ((int)fp->y * w + (int)fp->x)*4);
121 } return(--fs->life); }
123 void recycle(fireshell *fs,int x,int y)
125 unsigned int n,pixlife;
126 firepix *fp = fs->fpix;
130 fs->cy = shoot ? height : y ;
131 fs->color = (rnd(155)+100) <<16 |
134 fs->life = rnd(rndlife)+minlife;
135 fs->air = 1-(float)(rnd(200))/10000;
136 fs->flash = rnd(30000)+15000; /* million jouls */
137 fs->cshift = !rnd(5) ? 120:0;
138 fs->special = !rnd(10) ? 1:0;
140 printf("recycle(): color = %x air = %f life = %d \n",fs->color,fs->air,fs->life);
141 pixlife = rnd(fs->life)+fs->life/10+1; /* ! */
142 for(n=0;n<PIXCOUNT;n++){
143 fp->burn = rnd(pixlife)+32;
144 fp->xv = POWER*(float)(rnd(20000)-10000)/10000;
145 fp->yv = sqrt(POWER*POWER - fp->xv * fp->xv) *
146 (float)(rnd(20000)-10000)/10000;
154 unsigned int w = width;
155 unsigned int h = height;
156 unsigned char *pa, *pb, *pm, *po;
160 {pm[n]=0; po[n]=0;} /* clean first line */
164 for(n=4;n<w*h*4-4;n++){
165 q = pm[n-4] + (pm[n]*8) + pm[n+4] +
166 pa[n-4] + pa[n] + pa[n+4] +
167 pb[n-4] + pb[n] + pb[n+4];
175 {pm[n]=0; po[n]=0;}} /* clean last line */
180 unsigned int w = width;
181 unsigned int h = height;
182 unsigned char *pa, *pb, *pm;
184 pm += w*4; h-=2; /* line 0&h */
187 for(n=4;n<w*h*4-4;n++){
188 q = pm[n-4] + (pm[n]*8) + pm[n+4] +
189 pa[n-4] + pa[n] + pa[n+4] +
190 pb[n-4] + pb[n] + pb[n+4];
193 pm += n-4; /* last line */
194 for(n=0;n<w*4+4;n++) pm[n]=0;
195 pm = palaka1; /* first line */
196 for(n=0;n<w*4+4;n++) pm[n]=pm[n+w*4]; }
198 void light_2x2(fireshell *fss)
200 unsigned int l,t,n,x,y;
204 unsigned char *dim = palaka2;
205 unsigned char *sim = palaka1;
212 for(n=SHELLCOUNT;n;n--,f++){
213 s += f->flash/(sqrt(1+(f->cx - x)*(f->cx - x)+
214 (f->cy - y)*(f->cy - y)));}
218 dim[0] = (t > 255 ? 255 : t);
220 dim[1] = (t > 255 ? 255 : t);
222 dim[2] = (t > 255 ? 255 : t);
225 dim[4] = (t > 255 ? 255 : t);
227 dim[5] = (t > 255 ? 255 : t);
229 dim[6] = (t > 255 ? 255 : t);
232 dim[nl+0] = (t > 255 ? 255 : t);
234 dim[nl+1] = (t > 255 ? 255 : t);
236 dim[nl+2] = (t > 255 ? 255 : t);
239 dim[nl+4] = (t > 255 ? 255 : t);
241 dim[nl+5] = (t > 255 ? 255 : t);
243 dim[nl+6] = (t > 255 ? 255 : t);
245 sim += 8; dim += 8; } sim += nl; dim += nl;}}
247 void resize(Display *display, Window win)
249 XWindowAttributes xwa;
250 XGetWindowAttributes (display, win, &xwa);
251 xwa.width -= xwa.width % 2;
252 xwa.height -= xwa.height % 2;
253 if(xwa.height != height || xwa.width != width) {
257 printf("sky size: %dx%d ------------------------------\n",width,height);
260 if (xim->data==(char *)palaka2) xim->data=NULL;
263 if (palaka2!=palaka1) free(palaka2 - 8);
268 xim = XCreateImage(display, xwa.visual, xwa.depth, ZPixmap, 0, 0,
269 width, height, 8, 0);
270 palaka1 = (unsigned char *) calloc(xim->height+1,xim->width*4) + 8;
272 palaka2 = (unsigned char *) calloc(xim->height+1,xim->width*4) + 8;
276 xim->data = (char *)palaka2;
278 xim->data = calloc(xim->height,xim->bytes_per_line); }}
280 void put_image(Display *display, Window win, GC gc, XImage *xim)
283 unsigned char r, g, b;
288 for (y=0;y<xim->height; y++)
289 for (x=0;x<xim->width; x++) {
294 xim->data[i++] = (g&224)>>5 | (r&248);
295 xim->data[i++] = (b&248)>>3 | (g&28)<<3;
298 for (y=0;y<xim->height; y++)
299 for (x=0;x<xim->width; x++) {
304 xim->data[i++] = (b&248)>>3 | (g&28)<<3;
305 xim->data[i++] = (g&224)>>5 | (r&248);
310 for (y=0;y<xim->height; y++)
311 for (x=0;x<xim->width; x++) {
316 xim->data[i++] = (g&192)>>6 | (r&248)>>1;
317 xim->data[i++] = (b&248)>>3 | (g&56)<<2;
320 for (y=0;y<xim->height; y++)
321 for (x=0;x<xim->width; x++) {
326 xim->data[i++] = (b&248)>>3 | (g&56)<<2;
327 xim->data[i++] = (g&192)>>6 | (r&248)>>1;
331 for (y=0;y<xim->height; y++)
332 for (x=0;x<xim->width; x++) {
337 xim->data[i++] = (((7*g)/256)*36)+(((6*r)/256)*6)+((6*b)/256);
340 XPutImage(display,win,gc,xim,0,0,0,0,xim->width,xim->height); }
342 void sniff_events(Display *dis, Window win, fireshell *fss)
345 while (XPending(dis)){
346 XNextEvent (dis, &e);
347 if (e.type == ConfigureNotify) resize(dis,win);
348 if (e.type == ButtonPress) recycle(fss,e.xbutton.x, e.xbutton.y);
349 screenhack_handle_event(dis,&e); }}
352 char *progclass = "Fireworkx";
354 char *defaults [] = {
355 ".background: black",
356 ".foreground: white",
357 "*delay: 10000", /* never default to zero! */
366 XrmOptionDescRec options [] = {
367 { "-delay", ".delay", XrmoptionSepArg, 0 },
368 { "-maxlife", ".maxlife", XrmoptionSepArg, 0 },
369 { "-noflash", ".flash", XrmoptionNoArg, "False" },
370 { "-noglow", ".glow", XrmoptionNoArg, "False" },
371 { "-shoot", ".shoot", XrmoptionNoArg, "True" },
372 { "-verbose", ".verbose", XrmoptionNoArg, "True" },
377 screenhack (Display *display, Window win)
383 XWindowAttributes xwa;
386 firepix *fpix, *ffpix;
387 fireshell *fshell, *ffshell;
388 glow_on = get_boolean_resource("glow" , "Boolean");
389 flash_on = get_boolean_resource("flash" , "Boolean");
390 shoot = get_boolean_resource("shoot" , "Boolean");
391 verbose = get_boolean_resource("verbose" , "Boolean");
392 rndlife = get_integer_resource("maxlife" , "Integer");
393 delay = get_integer_resource("delay" , "Integer");
395 if(rndlife<1000) flash_fade=0.98;
396 if(rndlife<500) flash_fade=0.97;
398 printf("Fireworkx %s - pyrotechnics simulation program \n", FWXVERSION);
399 printf("Copyright (c) 1999-2005 Rony B Chandran <ronybc@asia.com> \n\n");
400 printf("url: http://www.ronybc.8k.com \n\n");}
402 XGetWindowAttributes(display,win,&xwa);
406 bigendian = (ImageByteOrder(display) == MSBFirst);
410 printf("Pseudocolor color: use '-noflash' for better results.\n");}
411 colors = (XColor *) calloc(sizeof(XColor),ncolors+1);
413 make_smooth_colormap(display, vi, cmap, colors, &ncolors,
414 False, &writable, True);
416 gc = XCreateGC(display, win, 0, &gcv);
418 resize(display,win); /* initialize palakas */
420 ffpix = malloc(sizeof(firepix) * PIXCOUNT * SHELLCOUNT);
421 ffshell = malloc(sizeof(fireshell) * SHELLCOUNT);
424 for (n=0;n<SHELLCOUNT;n++){
426 recycle (fshell,rnd(width),rnd(height));
433 for(n=SHELLCOUNT;n;n--){
434 if (!explode(fshell)){
435 recycle(fshell,rnd(width),rnd(height)); }
438 if(glow_on) mmx_glow(palaka1,width,height,8,palaka2);
442 if(flash_on) light_2x2(ffshell);
443 put_image(display,win,gc,xim);
446 sniff_events(display, win, ffshell);
448 if(!glow_on) mmx_blur(palaka1,width,height,8);