FileDocCategorySizeDatePackage
Bouncer.javaAPI DocExample6240Mon Apr 05 12:09:20 BST 1999None

Bouncer.java

import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.util.Random;

public class Bouncer
    extends AnimationComponent {
  public static void main(String[] args) {
    final Bouncer bouncer = new Bouncer();
    Frame f = new AnimationFrame(bouncer);
    f.setFont(new Font("Serif", Font.PLAIN, 12));
    
    Panel controls = new Panel();
    controls.add(bouncer.createCheckbox("Anti.", Bouncer.ANTIALIASING));
    controls.add(bouncer.createCheckbox("Trans.", Bouncer.TRANSFORM));
    controls.add(bouncer.createCheckbox("Gradient", Bouncer.GRADIENT));
    controls.add(bouncer.createCheckbox("Outline", Bouncer.OUTLINE));
    controls.add(bouncer.createCheckbox("Dotted", Bouncer.DOTTED));
    controls.add(bouncer.createCheckbox("Axes", Bouncer.AXES));
    controls.add(bouncer.createCheckbox("Clip", Bouncer.CLIP));
    f.add(controls, BorderLayout.NORTH);
    
    f.setVisible(true);
  }
    
  // Tweakable variables
  private boolean mAntialiasing, mGradient, mOutline;
  private boolean mTransform, mDotted, mAxes, mClip;
  // ...and the constants that represent them. See setSwitch().
  public static final int ANTIALIASING = 0;
  public static final int GRADIENT = 1;
  public static final int OUTLINE = 2;
  public static final int TRANSFORM = 3;
  public static final int DOTTED = 4;
  public static final int AXES = 5;
  public static final int CLIP = 6;
  
  private float[] mPoints;
  private float[] mDeltas;
  private float mTheta;
  private int mN;
  private Shape mClipShape;
  
  public Bouncer() {
    mN = 38;
    mPoints = new float[mN];
    mDeltas = new float[mN];
    Random random = new Random();
    for (int i = 0; i < mN; i++) {
      mPoints[i] = random.nextFloat() * 500;
      mDeltas[i] = random.nextFloat() * 3;
    }
    // Make sure points are within range.
    addComponentListener(new ComponentAdapter() {
      public void componentResized(ComponentEvent ce) {
        Dimension d = getSize();
        for (int i = 0; i < mN; i++) {
          int limit = ((i % 2) == 0) ? d.width : d.height;
          if (mPoints[i] < 0) mPoints[i] = 0;
          else if (mPoints[i] >= limit) mPoints[i] = limit - 1;
        }
      }
    });
  }
  
  public void setSwitch(int item, boolean value) {
    switch(item) {
      case ANTIALIASING: mAntialiasing = value; break;
      case GRADIENT: mGradient = value; break;
      case OUTLINE: mOutline = value; break;
      case TRANSFORM: mTransform = value; break;
      case DOTTED: mDotted = value; break;
      case AXES: mAxes = value; break;
      case CLIP: mClip = value; break;
      default: break;
    }
  }

  protected Checkbox createCheckbox(String label, final int item) {
    Checkbox check = new Checkbox(label);
    check.addItemListener(new ItemListener() {
      public void itemStateChanged(ItemEvent ie) {
        setSwitch(item, (ie.getStateChange() == ie.SELECTED));
      }
    });
    return check;
  }
  
  public void timeStep() {
    Dimension d = getSize();
    for (int i = 0; i < mN; i++) {
      float value = mPoints[i] + mDeltas[i];
      int limit = ((i % 2) == 0) ? d.width : d.height;
      if (value < 0 || value > limit) {
        mDeltas[i] = -mDeltas[i];
        mPoints[i] += mDeltas[i];
      }
      else mPoints[i] = value;
    }
    mTheta += Math.PI / 192;
    if (mTheta > (2 * Math.PI)) mTheta -= (2 * Math.PI);
  }
  
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D)g;
    setAntialiasing(g2);
    setClip(g2);
    setTransform(g2);
    Shape shape = createShape();
    setPaint(g2);
    // Fill the shape.
    g2.fill(shape);
    // Maybe draw the outline.
    if (mOutline) {
      setStroke(g2);
      g2.setPaint(Color.blue);
      g2.draw(shape);
    }
    drawAxes(g2);
  }

  protected void setAntialiasing(Graphics2D g2) {
    if (mAntialiasing == false) return;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
  }
  
  protected void setClip(Graphics2D g2) {
    if (mClip == false) return;
    if (mClipShape == null) {
      Dimension d = getSize();
      FontRenderContext frc = g2.getFontRenderContext();
      Font font = new Font("Serif", Font.PLAIN, 144);
      String s = "Spoon!";
      GlyphVector gv = font.createGlyphVector(frc, s);
      Rectangle2D bounds = font.getStringBounds(s, frc);
      mClipShape = gv.getOutline((d.width - (float)bounds.getWidth()) / 2,
          (d.height + (float)bounds.getHeight()) / 2);
    }
    g2.clip(mClipShape);
  }

  protected void setTransform(Graphics2D g2) {
    if (mTransform == false) return;
    Dimension d = getSize();
    g2.rotate(mTheta, d.width / 2, d.height / 2);
  }
  
  protected Shape createShape() {
    GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD,
        mPoints.length);
    path.moveTo(mPoints[0], mPoints[1]);
    for (int i = 2; i < mN; i += 6)
      path.curveTo(mPoints[i], mPoints[i + 1],
          mPoints[i + 2], mPoints[i + 3],
          mPoints[i + 4], mPoints[i + 5]);
    path.closePath();
    return path;
  }
  
  protected void setPaint(Graphics2D g2) {
    if (mGradient) {
      GradientPaint gp = new GradientPaint(0, 0, Color.yellow,
          50, 25, Color.red, true);
      g2.setPaint(gp);
    }
    else g2.setPaint(Color.orange);
  }
  
  protected void setStroke(Graphics2D g2) {
    if (mDotted == false) return;
    // Create a dotted stroke.
    Stroke stroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
        BasicStroke.JOIN_ROUND, 10,
        new float[] { 4, 4 }, 0);
    g2.setStroke(stroke);
  }

  protected void drawAxes(Graphics2D g2) {
    if (mAxes == false) return;
    g2.setPaint(getForeground());
    g2.setStroke(new BasicStroke());
    Dimension d = getSize();
    int side = 20;
    int arrow = 4;
    int w = d.width / 2, h = d.height / 2;
    g2.drawLine(w - side, h, w + side, h);
    g2.drawLine(w + side - arrow, h - arrow, w + side, h);
    g2.drawLine(w, h - side, w, h + side);
    g2.drawLine(w + arrow, h + side - arrow, w, h + side);
  }
}