ftp.nice.ch/pub/next/tools/screen/backspace/Explode.NIHS.bs.tar.gz#/ExplodeView.BackModule/Explosion.m

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.