// =================================================================== // 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) { } } } }