This is Explosion.m in view mode; [Download] [Up]
#import "Explosion.h" #define DO_ROCKET 1 #define DO_EXPLOSION 2 /* arrays for precalculated rotation */ float points0[] = { 4.0, 0.0, -6, 3.5, 0.0, -7, 6.0, 3.5 }; float points20[] = { 3.8, 1.4, -6.9, 1.2, 2.4, -6.5, 4.5, 5.3 }; float points40[] = { 3.0, 2.6, -6.8, -1.2, 4.5, -5.4, 2.3, 6.6 }; float points60[] = { 2.0, 3.4, -6.0, -3.4, 6.0, -3.5, 0.0, 7.0 }; float points80[] = { 0.7, 3.9, -4.5, -5.3, 6.8, -1.2, -2.3, 6.5 }; float points100[] = { -0.7, 4.0, -2.4, -6.5, 7.0, 1.1, -3.1, 5.4 }; float qpoints0[] = { 6.0, 0.0, -6.0, 6.0, -6.0, -6.0, 6.0, -6.0, 6.0, 6.0 }; float qpoints30[] = { 5.2, 3.0, -8.2, 2.2, -2.2, -8.2, 8.2, -2.2, 2.2, 8.2 }; float qpoints60[] = { 3.0, 5.2, -8.2, -2.2, 2.2, -8.2, 8.2, 2.2, -2.2, 8.2 }; float colorTab[ 7 ][ 3 ] = { { 1.0, 1.0, 1.0 }, { 1.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 0.0, 1.0 }, { 1.0, 1.0, 0.0 }, { 0.0, 1.0, 1.0 }, { 1.0, 0.0, 1.0 } }; int sequences[ 6 ][ 6 ] = { { 0, 1, 2, 3, 4, 5 }, { 5, 4, 3, 2, 1, 0 }, { 0, 2, 4, 0, 2, 4 }, { 4, 2, 0, 4, 2, 0 }, { 0, 3, 0, 3, 0, 3 }, { 3, 0, 3, 0, 3, 0 } }; @implementation Explosion - init { int loop, to; [ super init ]; to = time( 0 ) % 16; for( loop = 0; loop < to; loop++ ) rand(); qani = qdelay = 0; colorMode = NO; return self; } - initStart:( NXRect *)aRect withPlots:( int )Plots mode:( BOOL )aMode { maxPlot = Plots; colorMode = aMode; cArray0 = ( float * )malloc( 10 * maxPlot * sizeof( float ) ); cArray20 = ( float * )malloc( 10 * maxPlot * sizeof( float ) ); cArray40 = ( float * )malloc( 10 * maxPlot * sizeof( float ) ); cArray60 = ( float * )malloc( 10 * maxPlot * sizeof( float ) ); cArray80 = ( float * )malloc( 10 * maxPlot * sizeof( float ) ); cArray100 = ( float * )malloc( 10 * maxPlot * sizeof( float ) ); oArray = ( char * )malloc( 2 + 5 * maxPlot * sizeof( char ) ); theRect.size.width = aRect -> size.width; theRect.size.height = aRect -> size.height; theRect.origin.x = aRect -> origin.x; theRect.origin.y = aRect -> origin.y; [ self initPlots ]; [ self initRocket ]; simMode = DO_ROCKET; return self; } - free { free( cArray0 ); free( cArray20 ); free( cArray40 ); free( cArray60 ); free( cArray80 ); free( cArray100 ); free( oArray ); return( [ super free ] ); } - doSim { if( simMode == DO_ROCKET ) [ self moveRocket ]; else if( simMode == DO_EXPLOSION ) [ self moveExplosion ]; return self; } - clearSim { PSsetgray( 0 ); if( simMode == DO_ROCKET ) [ self showRocket ]; else if( simMode == DO_EXPLOSION ) [ self showExplosion ]; return self; } - showSim { if( colorMode == NO ) PSsetgray( 1 ); else PSsetrgbcolor( colorTab[ color ][ 0 ], colorTab[ color ][ 1 ], colorTab[ color ][ 2 ] ); if( simMode == DO_ROCKET ) [ self showRocket ]; else if( simMode == DO_EXPLOSION ) [ self showExplosion ]; return self; } - initExplosion { int loop, first, toggle; float dx, dy, trand, check, destx, desty, randtab[] = { 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 }; deadCount = toggle = 0; for( loop = 0; loop < maxPlot; loop++ ) { plots[ loop ].currx = explosionx; plots[ loop ].curry = explosiony; /* set virtual destination point for 'explosionpart' */ destx = rand() % 300 - rand() % 300 + explosionx; desty = rand() % ( int )( theRect.size.height ) + explosiony -150; if( desty < 50 ) desty = 50; if( desty == explosiony ) desty += 50; if( destx == explosionx ) destx += 50; /* delay for first movement of 'explosionpart' */ plots[ loop ].delay = rand() % 5; /* calculate x/y speed */ dx = abs( plots[ loop ].currx - destx ); dy = abs( plots[ loop ].curry - desty ); if( dx > dy ) { plots[ loop ].mx = 1.0; plots[ loop ].my = dy / dx; check = plots[ loop ].mx / plots[ loop ].my; plots[ loop ].count = ( int )( dx / ( int )( plots[ loop ].mx ) + 1 ); } else { plots[ loop ].mx = dx / dy; plots[ loop ].my = 1.0; check = plots[ loop ].my / plots[ loop ].mx; plots[ loop ].count = ( int )( dy / ( int )( plots[ loop ].my ) + 1 ); } if( plots[ loop ].curry > desty ) plots[ loop ].my *= -1; if( plots[ loop ].currx > destx ) plots[ loop ].mx *= -1; /* speedup 'explosionparts' */ trand = randtab[ rand() % 10 ] * ( rand() % 7 ) +2; plots[ loop ].mx *= trand; plots[ loop ].my *= trand; /* slowdown parts with diagonal direction */ if( check < 1.5 ) { plots[ loop ].mx *= .8; plots[ loop ].my *= .8; } /* generate 'explosionpart' lifetime */ plots[ loop ].count = rand() % 30 + 30; /* set rotation direction */ if( rand() % 100 > 50 ) plots[ loop ].sequence = 0; else plots[ loop ].sequence = 1; plots[ loop ].sequencecount = 0 ; } [ self preparePlots ]; first = 0; scount = 0; return self; } - moveExplosion { if( deadCount < maxPlot ) { [ self toPos ]; [ self preparePlots ]; } else { [ self initRocket ]; simMode = DO_ROCKET; } return self; } - showExplosion { switch( scount ) { case 0: case 5: if( ci0 > 0 ) DPSDoUserPath( cArray0, ci0, dps_float, oArray, ( ci0 /2 +2 ), bbox, dps_ustroke ); if( ci100 > 0 ) DPSDoUserPath( cArray100, ci100, dps_float, oArray, ( ci100 /2 +2 ), bbox, dps_ustroke ); break; case 1: case 4: if( ci20 > 0 ) DPSDoUserPath( cArray20, ci20, dps_float, oArray, ( ci20 /2 +2 ), bbox, dps_ustroke ); if( ci80 > 0 ) DPSDoUserPath( cArray80, ci80, dps_float, oArray, ( ci80 /2 +2 ), bbox, dps_ustroke ); break; case 2: case 3: if( ci40 > 0 ) DPSDoUserPath( cArray40, ci40, dps_float, oArray, ( ci40 /2 +2 ), bbox, dps_ustroke ); if( ci60 > 0 ) DPSDoUserPath( cArray60, ci60, dps_float, oArray, ( ci60 /2 +2 ), bbox, dps_ustroke ); break; } return self; } /* explosion simulation */ - toPos { int loop; float tmpcurrx, tmpcurry, tmpmx, tmpmy; scount++; if( scount > 5 ) scount = 0; for( loop = 0; loop < maxPlot; loop++ ) { if( plots[ loop ].delay > 0 ) plots[ loop ].delay--; if( plots[ loop ].count != 0 && plots[ loop ].delay == 0 ) { tmpmx = plots[ loop ].mx; tmpmy = plots[ loop ].my; tmpcurrx = plots[ loop ].currx; tmpcurry = plots[ loop ].curry; tmpcurrx += tmpmx; tmpcurry += tmpmy; plots[ loop ].count--; if( abs( tmpmx ) > 1 ) tmpmx *= 0.97; if( tmpmy > -3 ) tmpmy -= 0.2; if( tmpcurrx >= theRect.size.width -6 || tmpcurrx <= 0 || tmpcurry >= theRect.size.height -6 || tmpcurry <= 0 ) { tmpcurrx = -5; tmpcurry = -5; plots[ loop ].count = 0; deadCount++; } else if( plots[ loop ].count <= 0 ) { deadCount++; tmpcurrx = -5; tmpcurry = -5; } plots[ loop ].mx = tmpmx; plots[ loop ].my = tmpmy; plots[ loop ].currx = tmpcurrx; plots[ loop ].curry = tmpcurry; } } return self; } - preparePlots { int loop; ci0 = ci20 = ci40 = ci60 = ci80 = ci100 = 0; for( loop = 0; loop < maxPlot; loop++ ) { switch( sequences[ plots[ loop ].sequence ][ scount ] ) { case 0: *( cArray0 + ci0++ ) = plots[ loop ].currx + *( points0 ); *( cArray0 + ci0++ ) = plots[ loop ].curry + *( points0 +1 ); ci0 += 6; break; case 1: *( cArray20 + ci20++ ) = plots[ loop ].currx + *( points20 ); *( cArray20 + ci20++ ) = plots[ loop ].curry + *( points20 +1 ); ci20 += 6; break; case 2: *( cArray40 + ci40++ ) = plots[ loop ].currx + *( points40 ); *( cArray40 + ci40++ ) = plots[ loop ].curry + *( points40 +1 ); ci40 += 6; break; case 3: *( cArray60 + ci60++ ) = plots[ loop ].currx + *( points60 ); *( cArray60 + ci60++ ) = plots[ loop ].curry + *( points60 +1 ); ci60 += 6; break; case 4: *( cArray80 + ci80++ ) = plots[ loop ].currx + *( points80 ); *( cArray80 + ci80++ ) = plots[ loop ].curry + *( points80 +1 ); ci80 += 6; break; case 5: *( cArray100 + ci100++ ) = plots[ loop ].currx + *( points100 ); *( cArray100 + ci100++ ) = plots[ loop ].curry + *( points100 +1 ); ci100 += 6; break; } } return self; } - initRocket { speedf = theRect.size.height / 70; gravsim = speedf / 90; gravdelay = rand() % 20; startx = ( rand() % ( int )( theRect.size.width -100 ) ) + 50; starty = -10; rdestx = ( rand() % ( int )( theRect.size.width -150 ) ) + 75; rdesty = rand() % ( int )( theRect.size.height / 3.0 ) + theRect.size.height / 3.0 * 2 -100; if( rdestx < 90 ) rdestx = 90; vx = abs( startx - rdestx ); vy = rdesty; if( vx / vy > 1 ) { vy = vy / vx * speedf - rand() % 2; steps = abs( startx - rdestx ) / vx + rand() % 100 + 10; } else { vy = speedf - rand() % 2;; steps = rdesty / vy + rand() % 100 + 10; } vx = rand() %4 +1; if( vy > speedf ) vy = speedf; if( rdestx < startx ) vx *= -1; if( colorMode == YES ) color = rand() %7; startx += qpoints0[ 0 ]; starty += qpoints0[ 1 ]; qcArray0[ 0 ] = qcArray30[ 0 ] = qcArray60[ 0 ] = startx; qcArray0[ 1 ] = qcArray30[ 1 ] = qcArray60[ 1 ] = starty; return self; } - showRocket { switch( qani ) { case 0: DPSDoUserPath( qcArray0, 10, dps_float, roArray, 7, bbox, dps_ustroke ); break; case 1: DPSDoUserPath( qcArray30, 10, dps_float, roArray, 7, bbox, dps_ustroke ); break; case 2: DPSDoUserPath( qcArray60, 10, dps_float, roArray, 7, bbox, dps_ustroke ); break; } return self; } - moveRocket { startx += vx; starty += vy; steps--; if( gravdelay > 0 ) gravdelay--; else vy -= gravsim; /* animation delay */ qdelay++; if( qdelay > 1 ) { qdelay = 0; qani++; if( qani > 2 ) qani = 0; } switch( qani ) { case 0: qcArray0[ 0 ] = startx + qpoints0[ 0 ]; qcArray0[ 1 ] = starty + qpoints0[ 1 ]; break; case 1: qcArray30[ 0 ] = startx + qpoints30[ 0 ]; qcArray30[ 1 ] = starty + qpoints30[ 1 ]; break; case 2: qcArray60[ 0 ] = startx + qpoints60[ 0 ]; qcArray60[ 1 ] = starty + qpoints60[ 1 ]; break; } if( startx > theRect.size.width -50 || startx < 50 || starty > theRect.size.height - 50 || ( starty < 50 && vy < 0 ) ) { qani = 4; steps = 0; } if( steps == 0 ) { explosionx = startx; explosiony = starty; [ self initExplosion ]; simMode = DO_EXPLOSION; } return self; } - initPlots { int loop, oi = 0, ci = 0; /* setup 'explosion array' for userpath */ oArray[oi++] = dps_ucache; oArray[oi++] = dps_setbbox; for( loop = 0; loop < maxPlot; loop++ ) { cArray0[ ci ] = plots[ loop ].currx; cArray0[ ci +1 ] = plots[ loop ].curry; cArray20[ ci ] = plots[ loop ].currx; cArray20[ ci +1 ] = plots[ loop ].curry; cArray40[ ci ] = plots[ loop ].currx; cArray40[ ci +1 ] = plots[ loop ].curry; cArray60[ ci ] = plots[ loop ].currx; cArray60[ ci +1 ] = plots[ loop ].curry; cArray80[ ci ] = plots[ loop ].currx; cArray80[ ci +1 ] = plots[ loop ].curry; cArray100[ ci++ ] = plots[ loop ].currx; cArray100[ ci++ ] = plots[ loop ].curry; oArray[ oi++ ] = dps_moveto; cArray0[ ci ] = points0[ 2 ]; cArray0[ ci +1 ] = points0[ 3 ]; cArray20[ ci ] = points20[ 2 ]; cArray20[ ci +1 ] = points20[ 3 ]; cArray40[ ci ] = points40[ 2 ]; cArray40[ ci +1 ] = points40[ 3 ]; cArray60[ ci ] = points60[ 2 ]; cArray60[ ci +1 ] = points60[ 3 ]; cArray80[ ci ] = points80[ 2 ]; cArray80[ ci +1 ] = points80[ 3 ]; cArray100[ ci++ ] = points100[ 2 ]; cArray100[ ci++ ] = points100[ 3 ]; oArray[ oi++ ] = dps_rlineto; cArray0[ ci ] = points0[ 4 ]; cArray0[ ci +1 ] = points0[ 5 ]; cArray20[ ci ] = points20[ 4 ]; cArray20[ ci +1 ] = points20[ 5 ]; cArray40[ ci ] = points40[ 4 ]; cArray40[ ci +1 ] = points40[ 5 ]; cArray60[ ci ] = points60[ 4 ]; cArray60[ ci +1 ] = points60[ 5 ]; cArray80[ ci ] = points80[ 4 ]; cArray80[ ci +1 ] = points80[ 5 ]; cArray100[ ci++ ] = points100[ 4 ]; cArray100[ ci++ ] = points100[ 5 ]; oArray[ oi++ ] = dps_rlineto; cArray0[ ci ] = points0[ 6 ]; cArray0[ ci +1 ] = points0[ 7 ]; cArray20[ ci ] = points20[ 6 ]; cArray20[ ci +1 ] = points20[ 7 ]; cArray40[ ci ] = points40[ 6 ]; cArray40[ ci +1 ] = points40[ 7 ]; cArray60[ ci ] = points60[ 6 ]; cArray60[ ci +1 ] = points60[ 7 ]; cArray80[ ci ] = points80[ 6 ]; cArray80[ ci +1 ] = points80[ 7 ]; cArray100[ ci++ ] = points100[ 6 ]; cArray100[ ci++ ] = points100[ 7 ]; oArray[ oi++ ] = dps_rlineto; } /* setup 'rocket array' for userpath */ roArray[ 0 ] = dps_ucache; roArray[ 1 ] = dps_setbbox; roArray[ 2 ] = dps_moveto; roArray[ 3 ] = dps_rlineto; roArray[ 4 ] = dps_rlineto; roArray[ 5 ] = dps_rlineto; roArray[ 6 ] = dps_rlineto; for( loop = 2; loop < 10; loop++ ) { qcArray0[ loop ] = qpoints0[ loop ]; qcArray30[ loop ] = qpoints30[ loop ]; qcArray60[ loop ] = qpoints60[ loop ]; } bbox[ 0 ] = -50.0; bbox[ 1 ] = -50.0; bbox[ 2 ] = theRect.size.width +100; bbox[ 3 ] = theRect.size.height +100; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.