Mega Code Archive

 
Categories / Java / 2D Graphics GUI
 

Animation

import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Checkbox; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Frame; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Label; import java.awt.Panel; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.Stroke; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.geom.GeneralPath; import java.awt.geom.Rectangle2D; import java.text.NumberFormat; import java.util.Random; import javax.swing.JFrame; import javax.swing.JPanel; public class Bouncer extends JPanel implements Runnable {   private boolean trucking = true;   private long[] previousTimes; // milliseconds   private int previousIndex;   private boolean previousFilled;   private double frameRate; // frames per second   private Image image;   public static void main(String[] args) {     final Bouncer bouncer = new Bouncer();     Frame f = new AnimationFrame(bouncer);     f.setFont(new Font("Serif", Font.PLAIN, 12));     f.setSize(200, 200);     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() {     previousTimes = new long[128];     previousTimes[0] = System.currentTimeMillis();     previousIndex = 1;     previousFilled = false;     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;     }     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);     g2.fill(shape);     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 = "Java Source and Support!";       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;     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);   }   public void run() {     while (trucking) {       render();       timeStep();       calculateFrameRate();     }   }   protected void render() {     Graphics g = getGraphics();     if (g != null) {       Dimension d = getSize();       if (checkImage(d)) {         Graphics imageGraphics = image.getGraphics();         imageGraphics.setColor(getBackground());         imageGraphics.fillRect(0, 0, d.width, d.height);         imageGraphics.setColor(getForeground());         paint(imageGraphics);         g.drawImage(image, 0, 0, null);         imageGraphics.dispose();       }       g.dispose();     }   }   // Offscreen image.   protected boolean checkImage(Dimension d) {     if (d.width == 0 || d.height == 0)       return false;     if (image == null || image.getWidth(null) != d.width         || image.getHeight(null) != d.height) {       image = createImage(d.width, d.height);     }     return true;   }   protected void calculateFrameRate() {     // Measure the frame rate     long now = System.currentTimeMillis();     int numberOfFrames = previousTimes.length;     double newRate;     // Use the more stable method if a history is available.     if (previousFilled)       newRate = (double) numberOfFrames           / (double) (now - previousTimes[previousIndex]) * 1000.0;     else       newRate = 1000.0 / (double) (now - previousTimes[numberOfFrames - 1]);     firePropertyChange("frameRate", frameRate, newRate);     frameRate = newRate;     // Update the history.     previousTimes[previousIndex] = now;     previousIndex++;     if (previousIndex >= numberOfFrames) {       previousIndex = 0;       previousFilled = true;     }   }   public double getFrameRate() {     return frameRate;   }   // Property change support.   private transient AnimationFrame mRateListener;   public void setRateListener(AnimationFrame af) {     mRateListener = af;   }   public void firePropertyChange(String name, double oldValue, double newValue) {     mRateListener.rateChanged(newValue);   } } class AnimationFrame extends JFrame {   private Label mStatusLabel;   private NumberFormat mFormat;   public AnimationFrame(Bouncer ac) {     super();     setLayout(new BorderLayout());     add(ac, BorderLayout.CENTER);     add(mStatusLabel = new Label(), BorderLayout.SOUTH);     // Create a number formatter.     mFormat = NumberFormat.getInstance();     mFormat.setMaximumFractionDigits(1);     // Listen for the frame rate changes.     ac.setRateListener(this);     // Kick off the animation.     Thread t = new Thread(ac);     t.start();   }   public void rateChanged(double frameRate) {     mStatusLabel.setText(mFormat.format(frameRate) + " fps");   } }