import java.applet.Applet; import java.awt.Image; import java.awt.Graphics; import java.awt.image.MemoryImageSource; import java.awt.Dimension; import java.awt.AWTEvent; public class Fairy extends Applet implements Runnable { int width, height; int[] pixels; private Image image = null; private MemoryImageSource imageSource = null; public void init(){ Dimension size = getSize(); width = size.width; height = size.height; pixels = new int[ width*height ]; imageSource = new MemoryImageSource( width, height, pixels, 0, width ); imageSource.setAnimated( true ); imageSource.setFullBufferUpdates( true ); image = createImage( imageSource ); } public void drawDust( float x, float y, float radius, float a, int r, int g, int b ){ int min_x = (int)Math.max( 0, x - radius), min_y = (int)Math.max( 0, y - radius), max_x = (int)Math.min( width-1, x + radius +1.0f), max_y = (int)Math.min( height-1, y + radius +1.0f); float radiusSq = radius*radius; float halfARadiusSqInv = (0.75f*a)/radiusSq; for ( int i = min_x; i <= max_x; i++ ){ float dx = i - x; float dxSq = dx*dx; for ( int j = min_y; j <= max_y; j++ ){ float dy = j - y; float distSq = dxSq + dy*dy; if ( radiusSq >= distSq ){ float alpha = (radiusSq - distSq)*halfARadiusSqInv; float oneMinusAlpha = 1.0f - alpha; int index = j*width + i; int pixel = pixels[ index ]; int red = (pixel & 0x00FF0000) >> 16; int green = (pixel & 0x0000FF00) >> 8; int blue = (pixel & 0x000000FF); red = (int)(red*oneMinusAlpha + r*alpha); green = (int)(green*oneMinusAlpha + g*alpha); blue = (int)(blue*oneMinusAlpha + b*alpha); pixels[ index ] = 0xFF000000 | (red << 16 ) | (green << 8) | blue; } } } } private int mouse_x, mouse_y; public void processMouseMotionEvent( java.awt.event.MouseEvent me ) { if ( me.getID() == me.MOUSE_MOVED || me.getID() == me.MOUSE_DRAGGED ) { mouse_x = me.getX(); mouse_y = me.getY(); mouse_in = true; } } private boolean mouse_in = false; public void processMouseEvent( java.awt.event.MouseEvent me ) { if ( me.getID() == me.MOUSE_ENTERED ) { mouse_in = true; } else if ( me.getID() == me.MOUSE_EXITED ) { mouse_in = false; mouse_x = (int)((width/2)/* + 0.5*width*(0.5-Math.random())*/); mouse_y = (int)((height/2)/* + 0.5*height*(0.5-Math.random())*/); } } private volatile boolean running = true; public void start(){ running = true; (new Thread( this )).start(); } private long num = (long)(Integer.MAX_VALUE*Math.random()); private int randomInt(){ num = (num * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1); return (int)(num >>> (48 - 32)); } private int n = 0; private float random(){ return ((n = randomInt()) < 0?-n:n)/(float)(Integer.MAX_VALUE); } public void run(){ int num_particles = 70; enableEvents( AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK ); mouse_x = width/2; mouse_y = height/2; Thread.currentThread().setPriority( Thread.MIN_PRIORITY ); float[] x = new float[ num_particles ]; float[] y = new float[ num_particles ]; float[] time = new float[ num_particles ]; int[] red = new int[ num_particles ]; int[] green = new int[ num_particles ]; int[] blue = new int[ num_particles ]; for ( int i = 0; i < num_particles; i++ ) { x[ i ] = (float)(width/2 + 40*(0.5-random())); y[ i ] = (float)(height/2 + 40*(0.5-random())); time[ i ] = (float)random(); int r1 = 127 + (int)(128*random()); red[ i ] = r1; green[ i ] = r1; blue[ i ] = 127; } float xf = width/2; float yf = height/2; while ( running ) { long start = System.currentTimeMillis(); for ( int i = pixels.length-1; i >= 0; --i ) { int pixel = pixels[ i ]; int r = (0x00FF0000 & pixel) >> 16; r = 5*r/8; r = r < 0? 0 : r; int g = (0x0000FF00 & pixel) >> 8; g = 5*g/8; g = g < 0? 0 : g; int b = (0x000000FF & pixel); b = 5*b/8; b = b < 0? 0 : b; pixels[ i ] = 0xFF000000 | (r << 16) | (g << 8) | b; } for ( int i = 0; i < num_particles; i++ ) { float t = time[ i ]; if ( t > 0.9f ) { t = 9.0f*(1.0f - t); } drawDust( x[ i ], y[ i ], 5.0f*t + 2.0f, t, red[ i ], green[ i ], blue[ i ] ); x[ i ] += 3*(0.5 - random()); y[ i ] += 1 + 2*(random() -0.1); time[ i ] -= 0.01; if ( time[ i ] < 0.0f ) { x[ i ] = (float)(xf + 40*(0.5-random())); y[ i ] = (float)(yf + 40*(0.5-random())); time[ i ] = 1.0f; int r1 = 127 + (int)(128*random()); red[ i ] = r1; green[ i ] = mouse_in? r1/2 : r1; blue[ i ] = 127; } } float speed = mouse_in? 1.0f : 0.2f; xf += speed*10.0f*(float)(0.5-random()); yf += speed*10.0f*(float)(0.5-random()); if ( !mouse_in ) { mouse_x += (int)(7*random()) -3; mouse_y += (int)(7*random()) -3; } float dx = 0.1f*speed; xf = (1.0f-dx)*xf + mouse_x*dx; yf = (1.0f-dx)*yf + mouse_y*dx; drawDust( xf, yf, (float)(10 + speed*10*(0.5-random())), 0.8f, 255, 255, 255 ); if ( mouse_in ) { drawDust( xf, yf, (float)(30 + 4*(0.5-random())), 0.7f, 250, 150, 128 ); } else { drawDust( xf, yf, (float)(30 + 2*(0.5-random())), 0.7f, 250, 250, 128 ); } long stop = System.currentTimeMillis(); /*drawDust( xf -6, yf -5, 10, 1.0f, 255, 255, 255 ); drawDust( xf +6, yf -5, 10, 1.0f, 255, 255, 255 ); drawDust( xf -5, yf +6, 8, 1.0f, 255, 255, 255 ); drawDust( xf +5, yf +6, 8, 1.0f, 255, 255, 255 );*/ imageSource.newPixels(); image.flush(); repaint(); long spare = start + 40 - stop; //System.out.print( spare ); //System.out.println(); spare = spare < 5? 5 : spare; try { Thread.sleep( spare ); } catch( Exception e ) {} } } public void stop(){ running = false; } public void update( Graphics g ){ g.drawImage( image, 0, 0, this ); } }