ウォーター
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) {
}
}
}
}