X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Feruption.c;h=14809b9f7d80095788707c93001ed5b08b8da5eb;hp=26ed801c823b269b2de27eebf2d224a44d4c7db5;hb=07faf451b99879183ed7e909e43a0e065be1ee7f;hpb=6a1da724858673ac40aa13a9612340d8bed8c7b9 diff --git a/hacks/eruption.c b/hacks/eruption.c index 26ed801c..14809b9f 100644 --- a/hacks/eruption.c +++ b/hacks/eruption.c @@ -17,44 +17,14 @@ #include #include "screenhack.h" -#include /*#define VERBOSE*/ -char *progclass = "Eruption"; - -char *defaults [] = { - ".background: black", - ".foreground: white", - "*cycles: 80", - "*ncolors: 256", - "*delay: 5000", - "*particles: 300", - "*cooloff: 2", - "*gravity: 1", - "*heat: 256", - 0 -}; - -XrmOptionDescRec options [] = { - { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, - { "-delay", ".delay", XrmoptionSepArg, 0 }, - { "-cycles", ".cycles", XrmoptionSepArg, 0 }, - { "-particles", ".particles", XrmoptionSepArg, 0 }, - { "-cooloff", ".cooloff", XrmoptionSepArg, 0 }, - { "-gravity", ".gravity", XrmoptionSepArg, 0 }, - { "-heat", ".heat", XrmoptionSepArg, 0 }, - { 0, 0, 0, 0 } -}; - /* Slightly whacked, for better explosions */ #define PI_2000 6284 #define SPREAD 15 -static int sin_cache[PI_2000]; -static int cos_cache[PI_2000]; - /*particle structure*/ typedef struct { @@ -63,16 +33,32 @@ typedef struct unsigned char dead; } PARTICLE; -static PARTICLE *particles; -static unsigned short iWinWidth, iWinHeight; -static unsigned char **fire; -static unsigned short nParticleCount; -static unsigned char xdelta, ydelta, decay; -static signed char gravity; -static signed short heat; +struct state { + Display *dpy; + Window window; + + int sin_cache[PI_2000]; + int cos_cache[PI_2000]; + + PARTICLE *particles; + unsigned short iWinWidth, iWinHeight; + unsigned char **fire; + unsigned short nParticleCount; + unsigned char xdelta, ydelta, decay; + signed char gravity; + signed short heat; + + int cycles, delay; + GC gc; + signed short iColorCount; + unsigned long *aiColorVals; + XImage *pImage; + + int draw_i; +}; static void -cache(void) /* jwz */ +cache(struct state *st) /* jwz */ { /*needs to be run once. Could easily be */ int i; /*reimplemented to run and cache at compile-time,*/ double dA; @@ -83,196 +69,195 @@ cache(void) /* jwz */ dA+=asin(frand(1.0))/M_PI_2*0.1; /*Approximating the integration of the binominal, for well-distributed randomness*/ - cos_cache[i]=-abs((int) (cos(((double)i)/1000.0)*dA*ydelta)); - sin_cache[i]=(int) (sin(((double)i)/1000.0)*dA*xdelta); + st->cos_cache[i]=-abs((int) (cos(((double)i)/1000.0)*dA*st->ydelta)); + st->sin_cache[i]=(int) (sin(((double)i)/1000.0)*dA*st->xdelta); } } -void init_particle(PARTICLE* particle, signed short iColorCount, unsigned short xcenter, unsigned short ycenter) +static void init_particle(struct state *st, PARTICLE* particle, unsigned short xcenter, unsigned short ycenter) { int v = random() % PI_2000; particle->xpos = xcenter - SPREAD + (random() % (SPREAD * 2)); particle->ypos = ycenter - SPREAD + (random() % (SPREAD * 2));; - particle->xdir = sin_cache[v]; - particle->ydir = cos_cache[v]; - particle->colorindex = iColorCount; + particle->xdir = st->sin_cache[v]; + particle->ydir = st->cos_cache[v]; + particle->colorindex = st->iColorCount-1; particle->dead = 0; } -static void Execute( Display *pDisplay, - Window MainWindow, - GC *pGC, XImage *pImage, - signed short iColorCount, unsigned long *aiColorVals ) +static void Execute( struct state *st ) { int i, j; unsigned int temp; - /* move and draw particles into fire array */ + /* move and draw particles into st->fire array */ - for (i = 0; i < nParticleCount; i++) + for (i = 0; i < st->nParticleCount; i++) { - if (!particles[i].dead) + if (!st->particles[i].dead) { - particles[i].xpos += particles[i].xdir; - particles[i].ypos += particles[i].ydir; + st->particles[i].xpos += st->particles[i].xdir; + st->particles[i].ypos += st->particles[i].ydir; /* is particle dead? */ - if (particles[i].colorindex == 0) + if (st->particles[i].colorindex == 0) { - particles[i].dead = 1; + st->particles[i].dead = 1; continue; } - if (particles[i].xpos < 1) + if (st->particles[i].xpos < 1) { - particles[i].xpos = 1; - particles[i].xdir = -particles[i].xdir - 4; - particles[i].colorindex = iColorCount; + st->particles[i].xpos = 1; + st->particles[i].xdir = -st->particles[i].xdir - 4; + st->particles[i].colorindex = st->iColorCount; } - else if (particles[i].xpos >= iWinWidth - 2) + else if (st->particles[i].xpos >= st->iWinWidth - 2) { - particles[i].xpos = iWinWidth - 2; - particles[i].xdir = -particles[i].xdir + 4; - particles[i].colorindex = iColorCount; + st->particles[i].xpos = st->iWinWidth - 2; + if (st->particles[i].xpos < 1) st->particles[i].xpos = 1; + st->particles[i].xdir = -st->particles[i].xdir + 4; + st->particles[i].colorindex = st->iColorCount; } - if (particles[i].ypos < 1) + if (st->particles[i].ypos < 1) { - particles[i].ypos = 1; - particles[i].ydir = -particles[i].ydir; - particles[i].colorindex = iColorCount; + st->particles[i].ypos = 1; + st->particles[i].ydir = -st->particles[i].ydir; + st->particles[i].colorindex = st->iColorCount; } - else if (particles[i].ypos >= iWinHeight - 3) + else if (st->particles[i].ypos >= st->iWinHeight - 3) { - particles[i].ypos = iWinHeight- 3; - particles[i].ydir = (-particles[i].ydir >> 2) - (random() % 2); - particles[i].colorindex = iColorCount; + st->particles[i].ypos = st->iWinHeight- 3; + if (st->particles[i].ypos < 1) st->particles[i].ypos = 1; + st->particles[i].ydir = (-st->particles[i].ydir >> 2) - (random() % 2); + st->particles[i].colorindex = st->iColorCount; } + - /* gravity kicks in */ - particles[i].ydir += gravity; + /* st->gravity kicks in */ + st->particles[i].ydir += st->gravity; /* particle cools off */ - particles[i].colorindex--; + st->particles[i].colorindex--; /* draw particle */ - fire[particles[i].ypos][particles[i].xpos] = particles[i].colorindex; - fire[particles[i].ypos][particles[i].xpos - 1] = particles[i].colorindex; - fire[particles[i].ypos + 1][particles[i].xpos] = particles[i].colorindex; - fire[particles[i].ypos - 1][particles[i].xpos] = particles[i].colorindex; - fire[particles[i].ypos][particles[i].xpos + 1] = particles[i].colorindex; + if (st->iWinHeight <= 2 || st->iWinWidth <= 2) continue; + st->fire[st->particles[i].ypos][st->particles[i].xpos] = st->particles[i].colorindex; + st->fire[st->particles[i].ypos][st->particles[i].xpos - 1] = st->particles[i].colorindex; + st->fire[st->particles[i].ypos + 1][st->particles[i].xpos] = st->particles[i].colorindex; + st->fire[st->particles[i].ypos - 1][st->particles[i].xpos] = st->particles[i].colorindex; + st->fire[st->particles[i].ypos][st->particles[i].xpos + 1] = st->particles[i].colorindex; } } - /* create fire effect */ - for (i = 0; i < iWinHeight; i++) + /* create st->fire effect */ + for (i = 0; i < st->iWinHeight; i++) { - for (j = 0; j < iWinWidth; j++) + for (j = 0; j < st->iWinWidth; j++) { - if (j + 1 >= iWinWidth) + if (j + 1 >= st->iWinWidth) temp = 0; else - temp = fire[i][j + 1]; + temp = st->fire[i][j + 1]; if (j - 1 >= 0) - temp += fire[i][j - 1]; + temp += st->fire[i][j - 1]; if (i - 1 >= 0) { - temp += fire[i - 1][j]; + temp += st->fire[i - 1][j]; if (j - 1 >= 0) - temp += fire[i - 1][j - 1]; - if (j + 1 < iWinWidth) - temp += fire[i - 1][j + 1]; + temp += st->fire[i - 1][j - 1]; + if (j + 1 < st->iWinWidth) + temp += st->fire[i - 1][j + 1]; } - if (i + 1 < iWinHeight) + if (i + 1 < st->iWinHeight) { - temp += fire[i + 1][j]; - if (j + 1 < iWinWidth) - temp += fire[i + 1][j + 1]; + temp += st->fire[i + 1][j]; + if (j + 1 < st->iWinWidth) + temp += st->fire[i + 1][j + 1]; if (j - 1 >= 0) - temp += fire[i + 1][j - 1]; + temp += st->fire[i + 1][j - 1]; } temp >>= 3; - if (temp > decay) + if (temp > st->decay) { - temp -= decay; + temp -= st->decay; } else temp = 0; - fire[i][j] = temp; + st->fire[i][j] = temp; } } - memset( pImage->data, 0, pImage->bytes_per_line * pImage->height ); + memset( st->pImage->data, 0, st->pImage->bytes_per_line * st->pImage->height ); - /* draw fire array to screen */ - for (i = 0; i < iWinHeight; ++i) + /* draw st->fire array to screen */ + for (i = 0; i < st->iWinHeight; ++i) { - for (j = 0; j < iWinWidth; ++j) + for (j = 0; j < st->iWinWidth; ++j) { - if (fire[i][j] > 0) - XPutPixel( pImage, j, i, aiColorVals[ fire[i][j] ] ); + if (st->fire[i][j] > 0) + XPutPixel( st->pImage, j, i, st->aiColorVals[ st->fire[i][j] ] ); } } - XPutImage( pDisplay, MainWindow, *pGC, pImage, - 0,0,0,0, iWinWidth, iWinHeight ); - XSync( pDisplay, False ); + XPutImage( st->dpy, st->window, st->gc, st->pImage, + 0,0,0,0, st->iWinWidth, st->iWinHeight ); } -static unsigned long * SetPalette(Display *pDisplay, Window Win, signed short *piColorCount ) +static unsigned long * SetPalette(struct state *st) { XWindowAttributes XWinAttribs; XColor Color, *aColors; - unsigned long *aiColorVals; signed short iColor; - XGetWindowAttributes( pDisplay, Win, &XWinAttribs ); + XGetWindowAttributes( st->dpy, st->window, &XWinAttribs ); - *piColorCount = get_integer_resource( "ncolors", "Integer" ); - if( *piColorCount < 16 ) *piColorCount = 16; - if( *piColorCount > 255 ) *piColorCount = 256; + st->iColorCount = get_integer_resource(st->dpy, "ncolors", "Integer" ); + if( st->iColorCount < 16 ) st->iColorCount = 16; + if( st->iColorCount > 255 ) st->iColorCount = 256; - aColors = calloc( *piColorCount, sizeof(XColor) ); - aiColorVals = calloc( *piColorCount, sizeof(unsigned long) ); + aColors = calloc( st->iColorCount, sizeof(XColor) ); + st->aiColorVals = calloc( st->iColorCount, sizeof(unsigned long) ); - Color.red = Color.green = Color.blue = 65535 / *piColorCount; + Color.red = Color.green = Color.blue = 65535 / st->iColorCount; - /* create fire palette */ - for( iColor=0; iColor < *piColorCount; iColor++ ) + /* create st->fire palette */ + for( iColor=0; iColor < st->iColorCount; iColor++ ) { - if (iColor < *piColorCount >> 3) + if (iColor < st->iColorCount >> 3) { /* black to blue */ aColors[iColor].red = 0; aColors[iColor].green = 0; aColors[iColor].blue = Color.blue * (iColor << 1); } - else if (iColor < *piColorCount >> 2) + else if (iColor < st->iColorCount >> 2) { /* blue to red */ - signed short temp = (iColor - (*piColorCount >> 3)); + signed short temp = (iColor - (st->iColorCount >> 3)); aColors[iColor].red = Color.red * (temp << 3); aColors[iColor].green = 0; aColors[iColor].blue = 16383 - Color.blue * (temp << 1); } - else if (iColor < (*piColorCount >> 2) + (*piColorCount >> 3)) + else if (iColor < (st->iColorCount >> 2) + (st->iColorCount >> 3)) { /* red to yellow */ - signed short temp = (iColor - (*piColorCount >> 2)) << 3; + signed short temp = (iColor - (st->iColorCount >> 2)) << 3; aColors[iColor].red = 65535; aColors[iColor].green = Color.green * temp; aColors[iColor].blue = 0; } - else if (iColor < *piColorCount >> 1) + else if (iColor < st->iColorCount >> 1) { /* yellow to white */ - signed int temp = (iColor - ((*piColorCount >> 2) + (*piColorCount >> 3))) << 3; + signed int temp = (iColor - ((st->iColorCount >> 2) + (st->iColorCount >> 3))) << 3; aColors[iColor].red = 65535; aColors[iColor].green = 65535; aColors[iColor].blue = Color.blue * temp; @@ -283,45 +268,45 @@ static unsigned long * SetPalette(Display *pDisplay, Window Win, signed short *p aColors[iColor].red = aColors[iColor].green = aColors[iColor].blue = 65535; } - if( !XAllocColor( pDisplay, XWinAttribs.colormap, &aColors[ iColor ] ) ) + if( !XAllocColor( st->dpy, XWinAttribs.colormap, &aColors[ iColor ] ) ) { /* start all over with less colors */ - XFreeColors( pDisplay, XWinAttribs.colormap, aiColorVals, iColor, 0 ); + XFreeColors( st->dpy, XWinAttribs.colormap, st->aiColorVals, iColor, 0 ); free( aColors ); - free( aiColorVals ); - (*piColorCount)--; - aColors = calloc( *piColorCount, sizeof(XColor) ); - aiColorVals = calloc( *piColorCount, sizeof(unsigned long) ); + free( st->aiColorVals ); + (st->iColorCount)--; + aColors = calloc( st->iColorCount, sizeof(XColor) ); + st->aiColorVals = calloc( st->iColorCount, sizeof(unsigned long) ); iColor = -1; } else - aiColorVals[ iColor ] = aColors[ iColor ].pixel; + st->aiColorVals[ iColor ] = aColors[ iColor ].pixel; } - if (heat < *piColorCount) - *piColorCount = heat; + if (st->heat < st->iColorCount) + st->iColorCount = st->heat; free( aColors ); - XSetWindowBackground( pDisplay, Win, aiColorVals[ 0 ] ); + XSetWindowBackground( st->dpy, st->window, st->aiColorVals[ 0 ] ); - return aiColorVals; + return st->aiColorVals; } -static void Initialize( Display *pDisplay, Window Win, GC *pGC, XImage **ppImage ) +static void Initialize( struct state *st ) { XGCValues gcValues; XWindowAttributes XWinAttribs; int iBitsPerPixel, i; /* Create the Image for drawing */ - XGetWindowAttributes( pDisplay, Win, &XWinAttribs ); + XGetWindowAttributes( st->dpy, st->window, &XWinAttribs ); /* Find the preferred bits-per-pixel. (jwz) */ { int pfvc = 0; - XPixmapFormatValues *pfv = XListPixmapFormats( pDisplay, &pfvc ); + XPixmapFormatValues *pfv = XListPixmapFormats( st->dpy, &pfvc ); for( i=0; igc = XCreateGC( st->dpy, st->window, 0, &gcValues ); - *ppImage = XCreateImage( pDisplay, XWinAttribs.visual, XWinAttribs.depth, ZPixmap, 0, NULL, - XWinAttribs.width, XWinAttribs.height, BitmapPad( pDisplay ), 0 ); - (*ppImage)->data = calloc((*ppImage)->bytes_per_line, (*ppImage)->height); + st->pImage = XCreateImage( st->dpy, XWinAttribs.visual, XWinAttribs.depth, ZPixmap, 0, NULL, + XWinAttribs.width, XWinAttribs.height, BitmapPad( st->dpy ), 0 ); + (st->pImage)->data = calloc((st->pImage)->bytes_per_line, (st->pImage)->height); - iWinWidth = XWinAttribs.width; - iWinHeight = XWinAttribs.height; + st->iWinWidth = XWinAttribs.width; + st->iWinHeight = XWinAttribs.height; - /* create fire array */ - fire = calloc( iWinHeight, sizeof(unsigned char*)); - for (i = 0; i < iWinHeight; ++i) - fire[i] = calloc( iWinWidth, sizeof(unsigned char)); + /* create st->fire array */ + st->fire = calloc( st->iWinHeight, sizeof(unsigned char*)); + for (i = 0; i < st->iWinHeight; ++i) + st->fire[i] = calloc( st->iWinWidth, sizeof(unsigned char)); - /*create particles */ - particles = malloc (nParticleCount * sizeof(PARTICLE)); + /*create st->particles */ + st->particles = malloc (st->nParticleCount * sizeof(PARTICLE)); } -void screenhack(Display *pDisplay, Window Win ) +static void * +eruption_init (Display *dpy, Window window) { + struct state *st = (struct state *) calloc (1, sizeof(*st)); XWindowAttributes XWinAttribs; - GC gc; - signed short iColorCount = 0; - unsigned long *aiColorVals = NULL; unsigned short sum = 0; - XImage *pImage = NULL; #ifdef VERBOSE time_t nTime = time( NULL ); unsigned short iFrame = 0; #endif /* VERBOSE */ - int delay, cycles, i; - - nParticleCount = get_integer_resource( "particles", "Integer" ); - if (nParticleCount < 100) - nParticleCount = 100; - if (nParticleCount > 2000) - nParticleCount = 2000; - - decay = get_integer_resource( "cooloff", "Integer" ); - if (decay <= 0) - decay = 0; - if (decay > 10) - decay = 10; - - gravity = get_integer_resource( "gravity", "Integer" ); - if (gravity < -5) - gravity = -5; - if (gravity > 5) - gravity = 5; - - heat = get_integer_resource( "heat", "Integer" ); - if (heat < 64) - heat = 64; - if (heat > 256) - heat = 256; + int i; + + st->dpy = dpy; + st->window = window; + + st->nParticleCount = get_integer_resource(st->dpy, "particles", "Integer" ); + if (st->nParticleCount < 100) + st->nParticleCount = 100; + if (st->nParticleCount > 2000) + st->nParticleCount = 2000; + + st->decay = get_integer_resource(st->dpy, "cooloff", "Integer" ); + if (st->decay <= 0) + st->decay = 0; + if (st->decay > 10) + st->decay = 10; + + st->gravity = get_integer_resource(st->dpy, "gravity", "Integer" ); + if (st->gravity < -5) + st->gravity = -5; + if (st->gravity > 5) + st->gravity = 5; + + st->heat = get_integer_resource(st->dpy, "heat", "Integer" ); + if (st->heat < 64) + st->heat = 64; + if (st->heat > 256) + st->heat = 256; #ifdef VERBOSE - printf( "%s: Allocated %d particles\n", progclass, nParticleCount ); + printf( "%s: Allocated %d st->particles\n", progclass, st->nParticleCount ); #endif /* VERBOSE */ - Initialize( pDisplay, Win, &gc, &pImage ); + Initialize( st ); - ydelta = 0; - while (sum < (iWinHeight >> 1) - SPREAD) + st->ydelta = 0; + while (sum < (st->iWinHeight >> 1) - SPREAD) { - ydelta++; - sum += ydelta; + st->ydelta++; + sum += st->ydelta; } sum = 0; - while (sum < (iWinWidth >> 3)) + while (sum < (st->iWinWidth >> 3)) { - xdelta++; - sum += xdelta; + st->xdelta++; + sum += st->xdelta; } - delay = get_integer_resource( "delay", "Integer" ); - cycles = get_integer_resource( "cycles", "Integer" ); - i = cycles; + st->delay = get_integer_resource(st->dpy, "delay", "Integer" ); + st->cycles = get_integer_resource(st->dpy, "cycles", "Integer" ); + i = st->cycles; - cache(); + cache(st); - XGetWindowAttributes( pDisplay, Win, &XWinAttribs ); - XFreeColors( pDisplay, XWinAttribs.colormap, aiColorVals, iColorCount, 0 ); - free( aiColorVals ); - aiColorVals = SetPalette( pDisplay, Win, &iColorCount ); - XClearWindow( pDisplay, Win ); - memset( pImage->data, 0, pImage->bytes_per_line * pImage->height ); - - while( 1 ) - { - screenhack_handle_events( pDisplay ); + XGetWindowAttributes( st->dpy, st->window, &XWinAttribs ); + XFreeColors( st->dpy, XWinAttribs.colormap, st->aiColorVals, st->iColorCount, 0 ); + free( st->aiColorVals ); + st->aiColorVals = SetPalette( st ); + XClearWindow( st->dpy, st->window ); + memset( st->pImage->data, 0, st->pImage->bytes_per_line * st->pImage->height ); + + st->draw_i = -1; + + return st; +} + + +static unsigned long +eruption_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; - if( i++ >= cycles ) - { - /* compute random center */ - unsigned short xcenter, ycenter; - xcenter = random() % iWinWidth; - ycenter = random() % iWinHeight; + if( st->draw_i < 0 || st->draw_i++ >= st->cycles ) + { + /* compute random center */ + unsigned short xcenter, ycenter; + xcenter = random() % st->iWinWidth; + ycenter = random() % st->iWinHeight; - for (i = 0; i < nParticleCount; i++) - init_particle(particles + i, iColorCount - 1, xcenter, ycenter); - i = 0; - } - - Execute( pDisplay, Win, &gc, pImage, iColorCount - 1, aiColorVals ); + for (st->draw_i = 0; st->draw_i < st->nParticleCount; st->draw_i++) + init_particle(st, st->particles + st->draw_i, xcenter, ycenter); + st->draw_i = 0; + } - if( delay && !(i % 4) ) - usleep(delay); + Execute( st ); #ifdef VERBOSE - iFrame++; - if( nTime - time( NULL ) ) - { - printf( "%s: %d FPS\n", progclass, iFrame ); - nTime = time( NULL ); - iFrame = 0; - } + iFrame++; + if( nTime - time( NULL ) ) + { + printf( "%s: %d FPS\n", progclass, iFrame ); + nTime = time( NULL ); + iFrame = 0; + } #endif /* VERBOSE */ - } + + return st->delay; +} - free( pImage->data ); - XDestroyImage( pImage ); - free( aiColorVals ); - for (i = 0; i < iWinHeight; ++i) - free( fire[i] ); - free( fire ); - free( particles ); + +static void +eruption_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} + +static Bool +eruption_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} + +static void +eruption_free (Display *dpy, Window window, void *closure) +{ +#if 0 + struct state *st = (struct state *) closure; + free( st->pImage->data ); + XDestroyImage( st->pImage ); + free( st->aiColorVals ); + for (i = 0; i < st->iWinHeight; ++i) + free( st->fire[i] ); + free( st->fire ); + free( st->particles ); +#endif } + +static const char *eruption_defaults [] = { + ".background: black", + ".foreground: white", + "*cycles: 80", + "*ncolors: 256", + "*delay: 10000", + "*particles: 300", + "*cooloff: 2", + "*gravity: 1", + "*heat: 256", + 0 +}; + +static XrmOptionDescRec eruption_options [] = { + { "-ncolors", ".ncolors", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-cycles", ".cycles", XrmoptionSepArg, 0 }, + { "-particles", ".particles", XrmoptionSepArg, 0 }, + { "-cooloff", ".cooloff", XrmoptionSepArg, 0 }, + { "-gravity", ".gravity", XrmoptionSepArg, 0 }, + { "-heat", ".heat", XrmoptionSepArg, 0 }, + { 0, 0, 0, 0 } +}; + + +XSCREENSAVER_MODULE ("Eruption", eruption) + /* End of Module - "eruption.c" */