/* * Name: Water * Date: December 2004 * Author: Neil Wallis * Purpose: Simulate ripples on water. */ import java.awt.*; import java.awt.event.*; import java.awt.image.*; import java.applet.Applet; import java.net.URL; public class water extends Applet implements Runnable, MouseListener, MouseMotionListener { String str; int width,height,hwidth,hheight; MemoryImageSource source; Image image, offImage; Graphics offGraphics; int i,a,b; int MouseX,MouseY; int fps,delay,size; short ripplemap[]; int texture[]; int ripple[]; int oldind,newind,mapind; int riprad; Image im; Thread animatorThread; boolean frozen = false; public void init() { addMouseListener(this); addMouseMotionListener(this); //Retrieve the base image str = getParameter("image"); if (str != null) { try { MediaTracker mt = new MediaTracker(this); im = getImage(getDocumentBase(),str); mt.addImage(im,0); try { mt.waitForID(0); } catch (InterruptedException e) { return; } } catch(Exception e) {} } //How many milliseconds between frames? str = getParameter("fps"); try { if (str != null) { fps = (int)Integer.parseInt(str); } } catch (Exception e) {} delay = (fps > 0) ? (1000 / fps) : 100; width = im.getWidth(this); height = im.getHeight(this); hwidth = width>>1; hheight = height>>1; riprad=3; size = width * (height+2) * 2; ripplemap = new short[size]; ripple = new int[width*height]; texture = new int[width*height]; oldind = width; newind = width * (height+3); PixelGrabber pg = new PixelGrabber(im,0,0,width,height,texture,0,width); try { pg.grabPixels(); } catch (InterruptedException e) {} source = new MemoryImageSource(width, height, ripple, 0, width); source.setAnimated(true); source.setFullBufferUpdates(true); image = createImage(source); offImage = createImage(width, height); offGraphics = offImage.getGraphics(); } public void start() { if (frozen) { //Do nothing. } else { //Start animation thread if (animatorThread == null) { animatorThread = new Thread(this); } animatorThread.start(); } } public void stop() { animatorThread = null; } public void destroy() { removeMouseListener(this); removeMouseMotionListener(this); } public void mouseEntered(MouseEvent e) {} public void mouseDragged(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mouseClicked(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mousePressed(MouseEvent e) { if (frozen) { frozen = false; start(); } else { frozen = true; animatorThread = null; } } public void mouseMoved(MouseEvent e) { disturb(e.getX(),e.getY()); } public void run() { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); long startTime = System.currentTimeMillis(); while (Thread.currentThread() == animatorThread) { newframe(); source.newPixels(); offGraphics.drawImage(image,0,0,width,height,null); repaint(); try { startTime += delay; Thread.sleep(Math.max(0,startTime-System.currentTimeMillis())); } catch (InterruptedException e) { break; } } } public void paint(Graphics g) { update(g); } public void update(Graphics g) { g.drawImage(offImage,0,0,this); } public void disturb(int dx, int dy) { for (int j=dy-riprad;j=0 && j=0 && k>1); data -= ripplemap[newind+i]; data -= data >> 5; ripplemap[newind+i]=data; //where data=0 then still, where data>0 then wave data = (short)(1024-data); //offsets a=((x-hwidth)*data/1024)+hwidth; b=((y-hheight)*data/1024)+hheight; //bounds check if (a>=width) a=width-1; if (a<0) a=0; if (b>=height) b=height-1; if (b<0) b=0; ripple[i]=texture[a+(b*width)]; mapind++; i++; } } } }