/** WaterFall Applet  Copyright(c) 2002 WakuWaku.All rights reserved.*/
import java.applet.Applet;
import java.awt.*;
import java.awt.image.*;
import java.util.Random;
import java.awt.event.*;
public class WaterFall extends Applet implements Runnable,MouseListener
{
	private Thread th=null;
	private Image img;
	private int w,h;	//アプレットの幅と高さ
	private Color color;
	private static final int FADE_MAX=128,COL_MAX=256;
	public int[] pal=new int[COL_MAX],
				fred=new int[FADE_MAX],fgreen=new int[FADE_MAX],fblue=new int[FADE_MAX];

	private int MAX=300;
	
	public void init()
	{
		setBackground(Color.black);
		addMouseListener(this);
		color=Color.black;
	}
	public void start()
	{
		String param=getParameter("MAX");
		if(param!=null)
		{
			try
			{
				MAX=Integer.parseInt(param);
			}catch(NumberFormatException e){}
		}
		Dimension d=getSize();
		w=d.width;
		h=d.height;

		if(th==null)
			th=new Thread(this);
		th.start();	//スレッド開始
	}
	public void stop()
	{	//スレッドを停止
		if(th!=null)
		{
			th.stop();
			th=null;
		}
	}
	public void makeFadePalette(int rs,int gs,int bs,int re,int ge,int be)
	{	//フェード処理用パレット生成
		double d;
		int red,green,blue;
		for(int i=0;i<FADE_MAX;i++)
		{
			d=i/(double)(FADE_MAX-1);
			fred[i]=(int)((re-rs)*d+rs);
			fgreen[i]=(int)((ge-gs)*d+gs);
			fblue[i]=(int)((be-bs)*d+bs);
		}
	}
	public void makePalette(int re,int ge,int be,int max)
	{	//パレット生成(背景黒固定)
		double d;
		int red,green,blue;
		for(int i=0;i<max;i++)
		{
			d=i/(double)(max-1);
			red=(int)(re*d);
			green=(int)(ge*d);
			blue=(int)(be*d);
			pal[i]=(red<<16)+(green<<8)+blue;
		}
		int c=(re<<16)+(ge<<8)+be;
		for(int i=max;i<COL_MAX;i++)
			pal[i]=c;
	}
	public void run()
	{
		try
		{
			int[] px,pix;	//内部用、表示用のイメージ配列
			px=new int[w*h];
			pix=new int[w*h];
			Random rand=new Random();
			MemoryImageSource source=new MemoryImageSource(w,h,
				new DirectColorModel(0xffffff,0xff0000,0x00ff00,0x0000ff),pix,0,w);
			int wait=0,whalf=w/2;
			double[] fmy=new double[MAX]
				,fmx=new double[MAX]
				,fx=new double[MAX]
				,fy=new double[MAX];
			int[] fwait=new int[MAX];
			int windx=0,colindex=0;
			int rback=0,gback=0,bback=0;
			double maxX=0,maxY=0;
			int z=0;
			for(int i=0;i<MAX;i++)
				fy[i]=Integer.MAX_VALUE;
			for(int i=0;i<pix.length;i++)
				pix[i]=0x000000;

			while(true)
			{
				if(--wait<0)
				{
					wait=(int)(rand.nextFloat()*400)+150;
					maxX=rand.nextDouble()*3;
					maxY=rand.nextDouble()*4;
					z=rand.nextInt()%(w/8)+(w/8);
					do
						windx+=rand.nextInt()%2;
					while(windx>2 || windx<-2);
					int rm,gm,bm;
					do
					{
						rm=(int)(rand.nextFloat()*256);
						gm=(int)(rand.nextFloat()*256);
						bm=(int)(rand.nextFloat()*256);
					}while(rm+gm+bm<400);
					makeFadePalette(rback,gback,bback,rm,gm,bm);
					rback=rm;
					gback=gm;
					bback=bm;
					colindex=0;
				}
				if(colindex<fred.length-1)
				{
					colindex++;
					makePalette(fred[colindex],
								fgreen[colindex],
								fblue[colindex],180);
				}
				//水たまりの生成
				int hh=w*(h-2);
				for(int i=0;i<h;i++)
					px[hh+i]=0;
				for(int i=0;i<200;i++)
					px[hh+(int)(Math.random()*(w-20)+10)]=255;
				
				for(int i=0;i<MAX;i++)
				{
					if(fy[i]>h+5)
					{
						fmx[i]=rand.nextDouble()*maxX-((int)maxX+1)/2;
						fmy[i]=-rand.nextDouble()*maxY-((int)maxY)/2;
						fx[i]=whalf+rand.nextInt()%z-windx*16;
						fy[i]=h/8+rand.nextDouble()*4;
						fwait[i]=(int)(rand.nextDouble()*MAX)/4;
					}else if(fwait[i]<0)
					{
						fx[i]+=fmx[i]+windx;
						fy[i]+=fmy[i];
						fmy[i]+=0.3;
						int d=w*(int)fy[i]+(int)fx[i];
						if(fx[i]>1 && fx[i]<w-2 && fy[i]>1 && fy[i]<h-1)
							px[d]=px[d+1]=px[d+1+w]=px[d+w]=rand.nextInt()%22+200;
					}else
						fwait[i]--;
				}
				
				//種をぼかす
				int pt,py,x,y;
				for(y=1;y<h-2;y++)
				{
					py=w*y;
					for(x=1;x<w-1;x++)
					{
						pt=py+x;
						px[pt]=(
								   px[pt-w]		//上
								  +px[pt+w]	//下
								  +px[pt+1]	//右
								  +px[pt-1]	//左
								  )>>2;
						pix[pt]=pal[px[pt-w]];	//パレットと関連付ける
					}
				}
				pt=w*(h-2);
				for(int i=0;i<w;i++)
					px[pt+i]=0x00;
				source.newPixels();
				img=createImage(source);	//イメージに変換
				th.sleep(12);	//12ms待つ
				repaint();		//描画
			}
		}catch(InterruptedException e){}
	}

	public void update(Graphics g)
	{	//ちらつき防止用
		paint(g);
	}
	public void paint(Graphics g)
	{	//イメージバッファを描画（ダブルバッファリング）
		g.drawImage(img,0,0,this);
	}
	
	public void setMax(int value)
	{
		if(th!=null)
		{
			th.stop();
			th=new Thread(this);
			MAX=value;
			th.start();
		}
	}
	public void mousePressed(MouseEvent e)
	{
		th.suspend();
	}
	public void mouseReleased(MouseEvent e)
	{
		th.resume();
	}
	public void mouseClicked(MouseEvent e){}
	public void mouseExited(MouseEvent e){}
	public void mouseEntered(MouseEvent e){}
}

