ウォーター

download


// ===================================================================
//	import
// ===================================================================
import java.applet.*;
import java.awt.*;
import java.util.*;
import java.awt.image.*;
import java.awt.event.*;

// ===================================================================
//	draw
// ===================================================================


class KcWater {

	Image 				w_img;
	MemoryImageSource	w_mi;
	
	int					w_width;
	int					w_hight;
	int					w_pixels[];
	
	int					w_org_pixels[];
	int					w_high_tbl[][];
	int					w_page;
	


	// --------------------------------- コンストラクタ
	public KcWater(Applet oya, String s) {
		
					
		
		// --------- get pixels
		Image image = oya.getImage(oya.getDocumentBase() , s);
		PixelGrabber pg = new PixelGrabber(image , 0 , 0 , -1 , -1 , true);

		try { 
			pg.grabPixels(); 
		}
		catch (InterruptedException e) {
		}
		
		w_org_pixels = (int[])pg.getPixels();


		// --------- buffer 
		w_pixels = new int[w_org_pixels.length];
		w_high_tbl = new int[2][w_org_pixels.length];
		
		for( int i = 0; i < w_org_pixels.length; i ++ ) {
			w_pixels[i] = w_org_pixels[i];
			w_high_tbl[0][i] = w_high_tbl[1][i] = 0;
		}

		w_page = 0;

		// --------- offscreen  
		w_width = pg.getWidth();
		w_hight = pg.getHeight();

		
		w_mi = new MemoryImageSource(w_width , w_hight , w_pixels , 0 , w_width);
		w_mi.setAnimated( true );
		w_img = oya.createImage(w_mi);
		

	}
		
	// --------------------------------- 水面の揺らす点を設定
	public void setWaterPos( int x, int y, int height ) {
		
		int pos = x + (y * w_width);
		
		if( x <= 1 || x >= w_width-2 ||
			y <= 1 || y >= w_hight-2 ) return;
	
		w_high_tbl[w_page][pos] = height;
		
		w_high_tbl[w_page][pos-1] = height >>1;
		w_high_tbl[w_page][pos+1] = height >>1;
		w_high_tbl[w_page][pos-w_width] = height >>1;
		w_high_tbl[w_page][pos+w_width] = height >>1;

	}

	
	// --------------------------------- 水面の高さ計算
	void calcWater() {
	
		int new_page = w_page ^1;
	
		int pos = w_width + 1;
		for( int y = 1; y < w_hight-1; y++ ) {
			for( int x = 1; x < w_width-1; x ++ ) {
				
				
				w_high_tbl[new_page][pos] 	= ((w_high_tbl[w_page][pos-1] +
											w_high_tbl[w_page][pos+1] +
											w_high_tbl[w_page][pos-w_width] + 
											w_high_tbl[w_page][pos+w_width] ) >>1) -
											w_high_tbl[new_page][pos];
				
				w_high_tbl[new_page][pos] -= (w_high_tbl[new_page][pos] >> 4);
				
				
				pos ++;
			}
			pos += 2;
		}
		
		
		w_page ^=1;

	}
	
	
	// --------------------------------- バッファ描画
	void drawWater() {
		

		int pos, get_pos, du, dv, u, v;
		int length = w_width * w_hight;
		
		for( int y = 0; y < w_hight-1; y++ ) {
			for( int x = 0; x < w_width; x ++ ) {
				pos = x + (y * w_width);
				
				du = w_high_tbl[w_page][pos] - w_high_tbl[w_page][pos+1] ;
				dv = w_high_tbl[w_page][pos] - w_high_tbl[w_page][pos+w_width] ;
			
				u = x + (du>>3);		
				v = y + (dv>>3);
				
				get_pos = u + v*w_width;
				if( get_pos < 0 ) {
					get_pos = 0;
				}else if( get_pos >= length ) {
					get_pos = length -1;
				}
				
				w_pixels[pos] = w_org_pixels[get_pos];
			}
		}


	}
			
		
	// --------------------------------- ペイント
	public void paint() {
		
		drawWater();

		// --------- ピクセルが変更されたでよ
		w_mi.newPixels();
		
		calcWater();
					
  	}
	
	// --------------------------------- イメージ取得
	public Image getImage() {
		return	w_img;
	}
	
}

// ===================================================================
//	mouse
// ===================================================================
class KcMouse implements MouseMotionListener {

	int 	w_x, w_y;
	boolean w_move_flg;
	
	public KcMouse() {
		w_x = 0;
		w_y = 0;
		w_move_flg = false;
	}
	// ---------------------------------  info
	public void clearMoveFlg() {
		w_move_flg = false;
	}
	public boolean isMove() {
		return w_move_flg;
	}
	
	public int getX() {
		return w_x;
	}
	public int getY() {
		return w_y;
	}
	
	// ---------------------------------  event
	public void mouseDragged(MouseEvent e) {
	}
	
	public void mouseMoved(MouseEvent e) {
		w_x = e.getX();
		w_y = e.getY();
		
		w_move_flg = true;
	}
}

// ===================================================================
//	main
// ===================================================================
public class KcApp extends Applet implements Runnable {

	Thread 			w_thread = null;
	
	KcWater			w_draw;
	KcMouse			w_mouse;
	int				w_width;
	int				w_hight;
	
	int				w_wave_height;
			

	// --------------------------------- アプレット起動時に実行
	public void init() {
	}

	// --------------------------------- アプレットがあるHTMLページに入ったときに実行
	public void start() {
		if (w_thread == null)
		{
			// スレッドの起動
			w_thread = new Thread(this);
			w_thread.start();
			
			String s = getParameter("file");
			w_draw = new KcWater( this, s );
			
			s = getParameter("wave height");
			if( s != null ) {
				w_wave_height = Integer.parseInt(s);
			}else {
				w_wave_height = 200;	// default wave height 
			}
			
			//System.out.println("波の高さ:"+w_wave_height);

			w_mouse = new KcMouse();
			addMouseMotionListener(w_mouse);
										
		}
	}

	// --------------------------------- アプレットがあるHTMLページから出たときに実行
	public void stop() {
		if (w_thread != null)
		{
			// スレッドの停止
			w_thread = null;
		}
	}
	
	// --------------------------------- アプレット終了時に実行
	public void destroy() {
	}

	// --------------------------------- 描画
	public void paint(Graphics g) {
      	
      	if( w_draw == null ) return;
              		
	    g.drawImage(w_draw.getImage() ,0,0,this);
		
	}

	// --------------------------------- 再描画
	public void update(Graphics g) {
		paint(g);
	}

	// --------------------------------- スレッドの実行
	public void run() {

        Thread thisThread = Thread.currentThread();

		while (w_thread == thisThread) {
			
			
			// 再描画
			repaint();
			
			// 水面処理
			if( w_draw != null && w_mouse != null ) {
				if( w_mouse.isMove() == true ) {
					w_draw.setWaterPos( w_mouse.getX(), w_mouse.getY(), w_wave_height );
					w_mouse.clearMoveFlg();
				}
				w_draw.paint();
			}
			
			try
			{
				// 0.01秒間の停止
				thisThread.sleep(10);
			}
			catch(Exception e) {
			}
			
			
		}
	}
}