/*

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 Ball

{

	int locx,locy;//Coordinates of topleft corner

	int vx,vy;//Velocity of ball

	int wid,ht;//Width and height of ball

	int buf[];

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

	int randInt(int min,int max)

	{return (int)Math.floor(min+Math.random()*(max-min-0.000001));}

	

	public Ball(int screenW,int screenH)

	{

	//Init variables

		wid=randInt(screenW/16,screenW/4);

		ht=randInt(screenH/16,screenH/4);

		locx=randInt(0,screenW-wid);

		locy=randInt(0,screenH-ht);

		vx=randInt(-screenW/64,screenW/64+1);

		vy=randInt(-screenH/64,screenH/64+1);

	//Create image buffer of new ball.

		buf=new int[wid*ht];

		int x,y;

		int style=randInt(0,2);

		for (y=0;y<ht;y++)

		{

			int l=y*wid;

			for (x=0;x<wid;x++)

			{

				double cx=wid/2.0,cy=ht/2.0;

				double dx=(x-cx)/cx;

				double dy=(y-cy)/cy;

				double r=Math.sqrt(dx*dx+dy*dy);

				if (r>=1.0)

					buf[l+x]=512;

				else if (style==0)

					buf[l+x]=(int)(512+128*((1+Math.cos(r*16))/2));

				else if (style==1)

					buf[l+x]=(int)(512+128*((1+Math.cos(r*10))/2));

			}

		}

	}

	

	public void advance(int screenW,int screenH)

	{

		locx+=vx;locy+=vy;//Balls move with given velocity

		//Check for border bounce

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

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

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

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

		vy++;//Gravity accellerates balls downward.

	}

	public void draw(int screenW,int screenH,byte dest[],ByteTable table)

	{

		int x,y;

		for (y=0;y<ht;y++)

		{

			int in=y*wid;

			int out=(y+locy)*screenW+locx;

			for (x=0;x<wid;x++)

			//The table-based add is just a pinned-to-bytes addition.

				dest[out+x]=table.add[buf[in+x]+(0xff&(int)dest[out+x])];

		}

	}

}



class Demo 

{

	int cenOffset=512;

	int stdDev=41;

	int len;

	int w,h;

	ByteTable table=new ByteTable();

	byte store_pix[];

	Ball balls[];

	int nBalls=100;

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

	{

		//Broilerplate

		int x,y;

		w=Nw;h=Nh;

		store_pix=pix;

		int dex[]  ={0,140,255},

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

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

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

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

		len=8*w;

		table.init(cenOffset,len,stdDev);

		//Allocate and initialize our array of Balls.

		int ball;

		balls=new Ball[nBalls];

		for (ball=0;ball<nBalls;ball++)

			balls[ball]=new Ball(w,h);

		

	}

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

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

	{

		int x,y,l;

		//Erase old buffer

		for (y=0;y<h;y++)

		{

			l=y*w;

			for (x=0;x<w;x++)

				pix[l+x]=0;

		}

		//Advance and draw each ball

		int ball;

		for (ball=0;ball<nBalls;ball++)

		{

			balls[ball].advance(w,h);

			balls[ball].draw(w,h,pix,table);

		}

	}

}

