//
import java.awt.*; public class AutoshutterApplet extends GenericApplet { int inch = 20; // scale an inch to be 20 applet pixels int width, height; int gapSize = 4 * inch; int screenWidth = 10 * inch; int shutterWidth = 27 * inch / 2; int phase = 0; int leftX, rightX, leftY, rightY; int headX, headY, noseX, noseY, leftEyeX, leftEyeY, rightEyeX, rightEyeY; int screenY, shutterY, screenLeft, screenRight, shutterLeft, shutterRight; double theta = 0; boolean isDamage = true, isPaused = true, isVisible = false; public void init() { super.init(); width = bounds().width; height = bounds().height; screenLeft = width/2 - screenWidth/2; screenRight = width/2 + screenWidth/2; shutterLeft = width/2 - shutterWidth/2; shutterRight = width/2 + shutterWidth/2; screenY = 50; shutterY = screenY + gapSize; setPosition(width/2, 20 * inch, 0); } void setPosition(int x, int y, double angle) { double P = 0.75 * inch; double r = 1.25 * inch; double E = 2 * inch; double N = 2.75 * inch; double s = Math.sin(theta); double c = Math.cos(theta); y = (int)Math.max(y, shutterY+E+2*P+1); theta = angle; headX = x; headY = y; noseX = (int)(x + s * N); noseY = (int)(y - c * N); int eyeX = (int)(x + s * E); int eyeY = (int)(y - c * E); leftEyeX = (int)(eyeX - c * r); rightEyeX = (int)(eyeX + c * r); leftEyeY = (int)(eyeY - s * r); rightEyeY = (int)(eyeY + s * r); double phi = Math.atan((double)(noseX - width/2) / (noseY - screenY)); c = Math.cos(phi/2); s = Math.sin(phi/2); leftX = (int)(leftEyeX - s * P); rightX = (int)(rightEyeX - s * P); leftY = (int)(leftEyeY - c * P); rightY = (int)(rightEyeY - c * P); isDamage = true; } public boolean mouseDrag(Event e, int x, int y) { if (y < shutterY) return true; setPosition(x, y, theta); return true; } public boolean mouseUp(Event e, int x, int y) { if (y < 20 && x < 50) { phase = (phase + 1) % 3; isDamage = true; } else if (y < 20 && x > width - 50) { isPaused = ! isPaused; isDamage = true; } else if (y < shutterY) { setPosition(headX, headY, theta + (x < width/2 ? -.1 : .1)); isDamage = true; } return true; } int intercept(int ax, int ay, int bx, int by, int cy) { return ax + (bx - ax) * (cy - ay) / (by - ay); } public void render(Graphics g) { // determine which phase we're in now if (!isPaused) { isDamage = true; phase = (phase + 1) % 3; } if (! isDamage) return; isDamage = false; // draw distance ruling every inch g.setColor(Color.white); g.fillRect(0, 0, width, height); g.setColor(Color.black); for (int y = screenY ; y < height ; y += inch) g.drawLine(0, y, width, y); // draw head and eyes g.setColor(Color.gray); g.fillOval(headX - 3*inch, headY - 3*inch, 6*inch, 6*inch); g.fillOval(noseX - inch*3/4, noseY - inch*3/4, inch*3/2, inch*3/2); g.setColor(Color.white); g.fillOval(leftEyeX - inch*3/4, leftEyeY - inch, inch*3/2, inch*3/2); g.fillOval(rightEyeX - inch*3/4, rightEyeY - inch, inch*3/2, inch*3/2); g.setColor(Color.black); g.drawOval(leftEyeX - inch*3/4, leftEyeY - inch, inch*3/2, inch*3/2); g.drawOval(rightEyeX - inch*3/4, rightEyeY - inch, inch*3/2, inch*3/2); int pupilSize = inch * 2 / 3; g.fillOval(leftX - pupilSize/2, leftY - pupilSize/2, pupilSize, pupilSize); g.fillOval(rightX - pupilSize/2, rightY - pupilSize/2, pupilSize, pupilSize); // print text labels g.setColor(Color.magenta.darker()); g.drawString("Instructions: drag mouse to move head", width/2-105, 14); g.drawString(isPaused ? "STEP" : "", 2, 14); g.drawString(isPaused ? "CYCLE" : "PAUSE", width - 45, 14); int clickY = (screenY + shutterY) / 2 + 3; g.drawString("[Click here to turn left]", width/12, clickY); g.drawString("[Click here to turn right]", width*2/3, clickY); g.setColor(Color.yellow.darker().darker().darker()); g.drawString(" (display screen)", screenRight, screenY + 3); g.setColor(Color.black); g.drawString(" (active shutter)", shutterRight, shutterY + 3); g.drawString("Viewer distance: " + (((leftY + rightY)/2 - screenY)/inch) + " inches", 2, shutterY + 45); // display the interleaved screen and the autoshutter g.fillRect(shutterLeft, shutterY-1, shutterRight-shutterLeft, 2); int x, x1, x2; cx = screenRight; isVisible = true; for (ax = bx = screenLeft ; isVisible && cx > bx ; ax = cx) { computeIntercepts(); if (ax == screenLeft && phase > 0) { ax += (phase - 3) * (cx - ax) / 3; computeIntercepts(); } isVisible = false; g.setColor(Color.green); x1 = Math.max(screenLeft , ax); x2 = Math.min(screenRight, bx); g.fillRect(x1, screenY-2, x2-x1, 4); x = (ax + bx) / 2; if (x >= screenLeft && x < screenRight) { g.drawLine(x, screenY, leftX, leftY); isVisible = true; g.setColor(Color.yellow); g.fillRect(aX + (bX-aX)/6, shutterY-1, (bX-aX)*2/3, 2); } g.setColor(Color.red); x1 = Math.max(screenLeft , bx); x2 = Math.min(screenRight, cx); g.fillRect(x1, screenY-2, x2-x1, 4); x = (bx + cx) / 2; if (x >= screenLeft && x < screenRight) { g.drawLine(x, screenY, rightX, rightY); isVisible = true; g.setColor(Color.yellow); g.fillRect(cX + (dX-cX)/6, shutterY-1, (dX-cX)*2/3, 2); } } } int ax, bx, cx, aX, bX, cX, dX; void computeIntercepts() { aX = intercept(ax, screenY, leftX, leftY, shutterY); bX = intercept(ax, screenY, rightX, rightY, shutterY); bx = intercept(bX, shutterY, leftX, leftY, screenY); cX = intercept(bx, screenY, rightX, rightY, shutterY); cx = intercept(cX, shutterY, leftX, leftY, screenY); dX = intercept(cx, screenY, rightX, rightY, shutterY); } }