Home : Course Map : Chapter 8 : Java : Supplements :
Animation with Java 2D
JavaTech
Course Map
Chapter 8

Introduction
Threads Overview
  Demo 1   Demo 2
Stopping Threads
Multi-Processing
Thread Tasks
Animations
 
 Demo 3   Demo 4  
  Demo 5

Non-interacting
  Demo 6

Task Splitting
  Demo 7

Exclusivity
  Demo 8

Communicating
  Demo 9

Priority/Scheduling
More Thread

Exercises

    Supplements
Java2D Animation
  Demo 1 
Processor View
More Concurrency
Cloning
  Demo 2  Demo 3 

     About JavaTech
     Codes List
     Exercises
     Feedback
     References
     Resources
     Tips
     Topic Index
     Course Guide
     What's New

In the Chapter 8: Java: Animations we presented examples of animations with Swing components but using the standard drawing tools in the Graphics class. Here we remake the DropApplet animation example with the more capable Java 2D drawing classes.

As before, the Drop2DApplet program below illustrates a simple simulation of a bouncing ball. The applet creates a thread to direct the drawing of the frames of the animation as the ball falls and bounces on the floor and gradually comes to a rest. The interface consists of a subclass of JPanel called Drop2DApplet and a button to initiate a new drop of the ball. Drop2DApplet displays the ball and calculates its position.

The applet implements Runnable and in the start() method it creates a thread to which it passes a reference to itself. The applet's run() method first does some initialization and then enters a loop that draws each frame of the animation. The loop begins with a 25 millisecond pause using the static sleep() method in the Thread class. Then the Drop2DApplet is told to paint the next frame.

If the drop is done, the process jumps from the loop and exits the run() method, thus killing this thread.

Note how the antialiasing makes the ball much more smoothly round than with the AWT version.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/**
  * This applet implements Runnable and uses a thread
  * to create a simple dropped ball demonstration.
 **/
public class Drop2DApplet extends JApplet
                        implements Runnable, ActionListener{
  // Will use thread reference as a flag
  Thread fThread;
  Drop2DPanel fDropPanel;
  JButton fDropButton;

  /** Build the interface. **/
  public void init () {
    Container content_pane = getContentPane ();
    content_pane.setLayout (new BorderLayout ());

    // Create an instance of DropPanel
    fDropPanel = new Drop2DPanel ();
    // Add the DropPanel to the content pane.
    content_pane.add ("Center",fDropPanel);

    // Create a button and add it
    fDropButton = new JButton ("Drop");
    fDropButton.addActionListener (this);
    content_pane.add ("South",fDropButton);

  } // init

  /** Start when browser is loaded or button pushed. **/
  public void start () {
    // If the thread reference not null then a
    // thread is already running. Otherwise, create
    // a thread and start it.
    if (fThread == null){
        fThread = new Thread (this);
        fThread.start ();
    }
  } // start

  /** Applet's stop method used to stop thread.**/
  public void stop () {
     // Setting thread to null will cause loop in
     // run () to finish and kill the thread.
     fThread = null;
  }

  /** Button command. **/
  public void actionPerformed (ActionEvent ae){
    if (fDropPanel.isDone ()) start ();
  }

  /** The thread loops to draw each frame of drop.**/
  public void run () {
    // Disable button during drop
    fDropButton.setEnabled (false);

    // Initialize the ball for the drop.
    fDropPanel.reset ();

    // Loop through animation frames
    while ( fThread != null){
       // Sleep 25msecs between frames
      try{ Thread.sleep (25);
      } catch  (InterruptedException e) { }
      // Repaint drop panel for each new frame
      fDropPanel.repaint ();
      if (fDropPanel.isDone ()) fThread = null;
    }
    // Enable button for another drop
    fDropButton.setEnabled (true);
  } // run
} // class DropApplet

import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;

/** This JPanel subclass animates the dropping of a ball.**/
public class Drop2DPanel extends JPanel{

  // Parameters for the drop
  double fY = 0.0, fVy = 0.0;
  // Conversion factor from cm to pixels.
  double fYConvert = 0.0;
  double fXPixel = 0.0, fYPixel = 0.0;
  double fRadius = 0.0, fDiam = 0.0;
  // starting point for ball in cm
  double fY0 = 1000.0;
  // Frame dimensions.
  double fFrameHt, fFrameWd;
    // Flag for drop status
  boolean fDropDone = false;

  Ellipse2D fBall;

  /** Reset parameters for a new drop. **/
  void reset(){
    fFrameHt = getHeight();
    fFrameWd = getWidth();

    fXPixel = getWidth()/2;
    fY = fY0; fVy = 0;

    // Conversion factor from cm to pixels
    // Start the ball about 20% from the top
    // of the frame
    fYConvert = fFrameHt / (1.2 * fY0);

    // Choose a size for the ball relative to the
    // height in pixel units.
    fRadius = (int)((0.1 * fY0) * fYConvert);
    fDiam = 2 * fRadius;

    fBall = new Ellipse2D.Double(fXPixel-fRadius,
                                 fYPixel-fRadius,
                                 fDiam,fDiam);
    setBackground(Color.WHITE);
    fDropDone=false;
  } // reset

  /** Draw the ball at its current position. **/
  public void paintComponent (Graphics g){
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D)g;
    // Antialiasing for smooth surfaces.
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
          RenderingHints.VALUE_ANTIALIAS_ON);

    // Determine position after this time increement
    calcPosition ();
    // Move the ball.
    fBall.setFrame(fXPixel-fRadius,
                   fYPixel-fRadius,
                   fDiam,fDiam);
    // Want a solid red ball
    g2.setColor (Color.RED);
    g2.fill(fBall);

    // Now draw the ball.
    g2.draw (fBall);
  } // paintComponent

  /** Calculate the ball position in the next frame. **/
  void calcPosition () {
    // Increment by 10 millseconds per frame
    double dt = 0.025;

    // Calculate position and velocity at each step
    fY = fY + fVy * dt - 490.* dt * dt;
    fVy = fVy  -  980.0 * dt;

    // Convert to the pixel coordinates
    fYPixel = fFrameHt - (int)(fY * fYConvert);

    // Reverse direction when ball hits bottom.
    if ((fYPixel + fRadius) >= (fFrameHt-1)) {
         fVy = Math.abs (fVy);
         // Subtract friction loss
         fVy -= 0.1*fVy;
         // Stop when speed at bottom drops below arbitrary limit
         if (fVy < 15.0) {
             fDropDone=true;
         }
    }
  } // clacPosition

  /** Provide a flag on drop status. **/
  public boolean isDone () {
    return fDropDone;
  }

} // class DropPanel

 

 

Latest update: Nov. 5, 2004

              Tech
Timers
  Demo 1
Hist. Adapt Range
  Demo 2
Sorting in Java
  Demo 3
Histogram Median
  Demo 4
Refactoring
  Demo 5
Error Bars
  Demo 6
Exercises

           Physics
Least Squares Fit
  Demo 1
Fit to Polynomial
  Demo 2
Fit Hist Errors
  Demo 3
Discretization
  Demo 4
Timing
  Demo 5
Exercises

  Part I Part II Part III
Java Core 1  2  3  4  5  6  7  8  9  10  11  12 13 14 15 16 17
18 19 20
21
22 23 24
Supplements

1  2  3  4  5  6  7  8  9  10  11  12

Tech 1  2  3  4  5  6  7  8  9  10  11  12
Physics 1  2  3  4  5  6  7  8  9  10  11  12

Java is a trademark of Sun Microsystems, Inc.