//
import java.awt.*; import java.util.*; public class butterflies extends BufferedApplet { int N = 8; // NUMBER OF BUTTERFLIES PER ROW Graphics g; int width = 0, height = 0; Color bgColor = new Color(0xff, 0x90, 0x00); Color shadowColor = bgColor.darker(); Color fgColor[] = new Color[N*N]; double oldTime, rate = .5, var = .5; double randomSeed[] = new double[N*N]; Random R = new Random(); double rnd() { return Math.abs(R.nextDouble()) % 1.0; } // RANDOM NUMBER BETWEEN ZERO AND ONE public void render(Graphics g) { this.g = g; if (width == 0) { width = bounds().width; height = bounds().height; oldTime = System.currentTimeMillis() / 1000.; // PICK A RANDOM COLOR FOR EACH BUTTERFLY for (int i = 0 ; i < N ; i++) for (int j = 0 ; j < N ; j++) { int n = N * i + j; fgColor[n] = new Color((float)(.3+.6*rnd()),(float)(.2+.6*rnd()),(float)(.1+.6*rnd())); randomSeed[n] = rnd() - .5; } } // HOW MUCH TIME HAS GONE BY SINCE LAST FRAME? double newTime = System.currentTimeMillis() / 1000.; double deltaTime = newTime - oldTime; oldTime = newTime; // BLANK OUT THE BACKGROUND g.setColor(bgColor); g.fillRect(0,0, width, height); // DRAW ALL THE BUTTERFLIES for (int i = 0 ; i < N ; i++) for (int j = 0 ; j < N ; j++) { int x = i * width / N + width /N/2; int y = j * height / N + height/N/2; drawButterfly(deltaTime, i + N * j, x, y, width/(2*N-N/2), width/(2*N-N/2)); } animating = true; // FORCE APPLET TO REDISPLAY EVERY FRAME } // DATA CONTAINING SHAPE OF ONE BUTTERFLY WING double X[] = {.0, .3, .7 , 1., .9, .85, .6, .7, .4, .2, .0}; double Y[] = {.8, .95, .98, .9, .8, .65, .4, .3, .0, .05, .2}; int iX[] = new int[X.length]; int iY[] = new int[Y.length]; double theta[] = new double[N*N]; // TIME-VARYING FLAP POSITION FOR EACH BUTTERFLY public void drawButterfly(double deltaTime, int n, int x, int y, int w, int h) { // COMPUTE HOW MUCH TO PROGRESS THE FLAPPING MOTION FOR THIS BUTTERFLY theta[n] += rate * deltaTime * (20 + 30 * var * randomSeed[n]); // COMPUTE HORIZONTAL SCALE FACTOR DUE TO FLAPPING double s = .4 + .15 * Math.sin(theta[n]); // COMPUTE THE VERTICAL DISPLAY POSITIONS OF WING VERTICES for (int i = 0 ; i < X.length ; i++) iY[i] = y + (int)(h * (.5 - Y[i])); // DRAW SHADOWS OF WINGS g.setColor(shadowColor); for (int i = 0 ; i < X.length ; i++) iY[i] += w/5; for (int i = 0 ; i < X.length ; i++) iX[i] = x + (int)(w * (.03 + s * X[i]) + (.1 + 2*X[i]*(1-s))*w/5); g.fillPolygon(iX, iY, X.length); for (int i = 0 ; i < X.length ; i++) iX[i] = x + (int)(w * (-.03 - s * X[i]) + (.1 + 2*X[i]*(1-s))*w/5); g.fillPolygon(iX, iY, X.length); for (int i = 0 ; i < X.length ; i++) iY[i] -= w/5; // DRAW BUTTERFLY'S BODY g.setColor(Color.black); g.fillOval(x-w/20, y-h/2+h/8, w/10, h); // DRAW ANTENNAE int a = (int)(.05 * w * Math.sin(.4 * theta[n])); g.drawLine(x, y-h/3, x-w/4 + a, y-h/2-h/4); g.drawLine(x, y-h/3, x+w/4 - a, y-h/2-h/4); // DRAW BUTTERFLY'S RIGHT WING for (int i = 0 ; i < X.length ; i++) iX[i] = x + (int)(w * (.03 + s * X[i])); g.setColor(fgColor[n]); g.fillPolygon(iX, iY, X.length); g.setColor(Color.black); g.drawPolygon(iX, iY, X.length); // DRAW BUTTERFLY'S LEFT WING for (int i = 0 ; i < X.length ; i++) iX[i] = x + (int)(w * (-.03 - s * X[i])); g.setColor(fgColor[n]); g.fillPolygon(iX, iY, X.length); g.setColor(Color.black); g.drawPolygon(iX, iY, X.length); // DRAW SPOTS ON WINGS g.setColor(bgColor); int sw = (int)(s * w); g.fillOval(x+w/33 + sw/4 , y - h/3, sw/2,h/4); g.fillOval(x-w/33 - 3*sw/4+1, y - h/3, sw/2,h/4); g.fillOval(x+w/33 + sw/5 , y , sw/3,h/3); g.fillOval(x-w/33 - 3*sw/5+1, y , sw/3,h/3); } // USER CALLBACK TO MONITOR MOUSE POSITION public boolean mouseMove(Event e, int x, int y) { rate = .1 + Math.max(0, Math.min(.9, .9 * x / width)); // MOUSE X CONTROLS FLAP RATE var = Math.max(0, Math.min(1, 1. * y / height)); // MOUSE Y CONTROLS RANDOMNESS return true; } }