/*

Java Graphics Demos: 

by Orion Lawlor, 12/1998

olawlor@acm.org



This code is totally free, and

should be considered in the public domain.

Use and modify it at will.

*/

import java.awt.*;

import java.awt.image.*;

//import ColorMap;

//import ByteTable;



class Spark

{

	public int x,y;//Integer coordinates of spark

	public byte color;//Index of spark color

	

	double locx,locy;//Coordinates of Spark

	double vx,vy;//Velocity of ball

	

	//Return a random number on [min,max)*/

	double rand(double min,double max)

		{return min+Math.random()*(max-min-0.0000001);}

	

	public Spark() {}

	public Spark(double Nx,double Ny,double Nvx,double Nvy,byte Ncolor)

	{

	//Init variables

		locx=Nx;

		locy=Ny;

		vx=Nvx;

		vy=Nvy;

		color=Ncolor;

	}

	

	public void advance(int screenW,int screenH)

	{

		locx+=vx;locy+=vy;//Move with given velocity

		//Check for border bounce

		if (locx<0) {locx-=vx;vx*=-1;}

		if (locx>=screenW) {locx-=vx;vx*=-1;}

		if (locy<0) {locy-=vy;vy*=-1;}

		if (locy>=screenH) {locy-=vy;vy*=-1;}

		vy+=0.02;//Accellerate downward (slightly).

		x=(int)locx;y=(int)locy;

	}

}



class Sparker extends Spark

{

	int time=0;

	Spark sparks[];

	int newSpark=0;

	int nSparks=0;

	int maxSparks=90;

	public Sparker(int screenW,int screenH)

	{

		locx=rand(0,screenW);

		locy=rand(0,screenH);

		vy=rand(-screenW/64,screenW/64);

		vx=rand(-screenH/64,screenH/64);

		color=(byte)(int)rand(1,255);

		sparks=new Spark[maxSparks];

		time=(int)rand(0,5000);

	}

	

	public void eraseOld(int screenW,int screenH,byte pix[])

	{

		int i;

		for (i=0;i<nSparks;i++)

			pix[screenW*sparks[i].y+sparks[i].x]=0;

	}

	

	void newSpark(double dir,double vel)

	{

		double nvx=vx+vel*Math.cos(dir);

		double nvy=vy+vel*Math.sin(dir);

		sparks[newSpark]=new Spark(locx,locy,nvx,nvy,color);

		

		double recoilFraction=0.01;

		vx-=(nvx-vx)*recoilFraction;

		vy-=(nvy-vy)*recoilFraction;//Recoil from spark.

		

		if (nSparks<maxSparks) 

			nSparks++;//Make room for new spark.

		newSpark++;//Prepare spot for next spark.

		if (newSpark>=maxSparks)

			newSpark=0;//Wrap new spark around.

		

	}

	

	public void drawNew(int screenW,int screenH,byte pix[])

	{

		//Advance ourselves

		super.advance(screenW,screenH);

		

		//Create three spark streams

		double dir=4*Math.cos(time/20.0);

		double vel=1.0;

		newSpark(dir,vel+0.2);

		newSpark(dir+0.5,vel-0.1);

		newSpark(dir+1.0,vel+0.3);

		

		//Advance and draw new sparks

		int i;

		for (i=0;i<nSparks;i++)

		{

			sparks[i].advance(screenW,screenH);

			pix[screenW*sparks[i].y+sparks[i].x]=sparks[i].color;

		}

		

		time++;

	}

}



class Demo 

{

	int w,h;

	Sparker sparkers[];

	int num=10;

	public void init(ColorMap cm,byte pix[],int Nw,int Nh)

	{

		//Broilerplate

		int x,y;

		w=Nw;h=Nh;

		int dex[]  ={   0,  1, 80,170,255},

			red[]  ={   0,  0,  0,255,  0},

			green[]={   0,  0,255,  0,  0},

			blue[] ={0x3f,255,  0,  0,255};

		cm.addBreaks(dex,red,green,blue);

		

		//Allocate and initialize our array of Sparkers.

		int i;

		sparkers=new Sparker[num];

		for (i=0;i<num;i++)

			sparkers[i]=new Sparker(w,h);

	}

	public boolean handleAction(Event ev,Object obj) {return false;}

	public void fillBuffer(ColorMap cm,byte pix[])

	{

		int i;

		//Erase old sparks

		for (i=0;i<num;i++)

			sparkers[i].eraseOld(w,h,pix);

			

		//Advance and draw new sparks

		for (i=0;i<num;i++)

			sparkers[i].drawNew(w,h,pix);

	}

}

