import java.awt.Graphics; import java.awt.Image; import java.awt.Dimension; //import java.awt.Cursor; import java.awt.image.MemoryImageSource; import java.awt.event.MouseEvent; import java.awt.AWTEvent; import java.applet.Applet; public class Sand extends Applet implements Runnable { private Image image = null; private MemoryImageSource source = null; private volatile Thread thread = null; private int dropx = -1, dropy = -1; private int HEIGHT = 64; //private int r = 0xFF, g = 0xCC, b = 0x00; public void start() { (thread = new Thread( this )).start(); } protected void processMouseMotionEvent( MouseEvent me ) { if ( me.getID() == MouseEvent.MOUSE_MOVED ) { synchronized( this ) { dropx = me.getX(); dropy = me.getY(); } } } protected void processMotionEvent( MouseEvent me ) { if ( me.getID() == MouseEvent.MOUSE_EXITED ) { synchronized( this ) { dropx = -1; dropy = -1; } } } public void run() { //setCursor( Cursor.getPredefinedCursor( Cursor.CROSSHAIR_CURSOR ) ); enableEvents( AWTEvent.MOUSE_EVENT_MASK ); enableEvents( AWTEvent.MOUSE_MOTION_EVENT_MASK ); Dimension size = getSize(); int width = size.width; int height = size.height; int[] pixels = new int[ width*height ]; int[] stateNow = new int[ width*height ]; int[] stateNext = new int[ width*height ]; synchronized( this ) { source = new MemoryImageSource( width, height, pixels, 0, width ); source.setFullBufferUpdates( true ); source.setAnimated( true ); image = createImage( source ); } while( thread == Thread.currentThread() ) { synchronized( this ) { if ( dropx >= 0 && dropx < width && dropy >= 0 && dropy < height && Math.random() < 0.5 ) stateNow[ dropy*width + dropx ] += HEIGHT; for ( int i = 0; i < stateNext.length; i++ ) stateNext[ i ] = 0; for ( int j = 0; j < height; j++ ) { for ( int i = 0; i < width; i++ ) { int state = stateNow[ j*width + i ]; int numNeighbours = 8; if ( numNeighbours <= state ) { //state -= 8; for ( int x = i-1; x <= (i+1); x++ ) { int nx = (x+width)%width; for ( int y = j-1; y <= (j+1); y++ ) { if ( x == i && y == j ) continue; int ny = (y+height)%height; stateNext[ ny*width + nx ]++; state--; } } } stateNext[ j*width + i ] += state; } } int[] tmp = stateNow; stateNow = stateNext; stateNext = tmp; for ( int i = 0; i < stateNow.length; i++ ) { int state = stateNow[ i ]; //if ( state > 255 ) System.out.println( "Too beacoup " + state + " " + stateNow[ i ] ); //if ( state < 0 ) System.out.println( "Too small " + state + " " + stateNow[ i ] ); //sum += stateNow[ i ]; state = Math.min( Math.max( state, 0 ), 255 ); int r = (state+20)*(state), g = (state+5)*(state), b = 2*state; r = Math.min( 255, r ); b = Math.min( 255, b ); g = Math.min( 255, g ); pixels[ i ] = 0xFF000000 | (r << 16) | (g << 8) | (b); } //System.out.println( sum ); source.newPixels(); repaint(); } try { Thread.sleep( 20 ); } catch( Exception e ) { } } } public void stop() { thread = null; } public void update( Graphics g ) { paint( g ); } public synchronized void paint( Graphics g ) { if ( image != null ) { g.drawImage( image, 0, 0, this ); } } }