Workshop: Follow the Bouncing Ball

This hour's workshop is an animation that definitely couldn't be replicated with an animated GIF file or any other non-programming alternative. You'll write a program that bounces a tennis ball around the screen in lazy arcs, bouncing off the sides of the panel that contains the animation. Though a few laws of physics will be broken along the way, you'll learn one way to move an image file around the screen. Create a new file in your word processor called, and enter the text of Listing 24.3 into it. Save and compile the file when you're done.

Listing 24.3. The Full Text of
 1: import java.awt.*;
 2: import javax.swing.*;
 3: import java.util.*;
 5: public class BouncePanel extends JPanel implements Runnable {
 6: Image ball, court;
 7: float current = 0F;
 8: Thread runner;
 9: int xPosition = 10;
10: int xMove = 1;
11: int yPosition = -1;
12: int ballHeight = 185;
13: int ballWidth = 190;
14: int height;
16: public BouncePanel() {
17: super();
18: Toolkit kit = Toolkit.getDefaultToolkit();
19: ball = kit.getImage("tennis.gif");
20: court = kit.getImage("court.jpg");
21: runner = new Thread(this);
22: runner.start();
23: }
25: public void paintComponent(Graphics comp) {
26: Graphics2D comp2D = (Graphics2D) comp;
27: height = getSize().height - ballHeight;
28: if (yPosition == -1) {
29: yPosition = height - 20;
30: }
31: if ((court != null) && (ball != null)) {
32: comp2D.drawImage(court, 0, 0, this);
33: comp2D.drawImage(ball,
34: (int) xPosition,
35: (int) yPosition,
36: this);
37: }
38: }
40: public void run() {
41: Thread thisThread = Thread.currentThread();
42: while (runner == thisThread) {
43: current += (float) 0.1;
44: if (current > 3) {
45: current = (float) 0;
46: }
47: xPosition += xMove;
48: if (xPosition > (getSize().width - ballWidth)) {
49: xMove *= -1;
50: }
51: if (xPosition < 1) {
52: xMove *= -1;
53: }
54: double bounce = Math.sin(current) * height;
55: yPosition = (int) (height - bounce);
56: repaint();
57: try {
58: Thread.sleep(100);
59: } catch (InterruptedException e) {
60: // do nothing
61: }
62: }
63: }
64: }

Before you dive into the discussion of what's taking place in this class, you should see what it does. You need to create a program and add the BouncePanel component to the program's graphical user interface. Create a new file in your word processor called and enter Listing 24.4 into it.

Listing 24.4. The Full Text of
 1: import java.awt.*;
 2: import javax.swing.*;
 4: public class Bounce extends JFrame {
 5: public Bounce() {
 6: super("Tennis");
 7: setSize(550, 450);
 8: setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 9: BouncePanel boing = new BouncePanel();
10: add(boing);
11: setVisible(true);
12: }
14: public static void main(String[] arguments) {
15: Bounce frame = new Bounce();
16: }
17: }

After saving this file, you need to get a copy of the tennis.gif and court.gif files and put them in the same folder as Bounce.class and BouncePanel.class. This file is available from the same place as the lighthouse image files: the tutorial's website at Once you have copied the graphics files into the right place, run the Bounce app by typing this command:

java Bounce

Screenshot shows the app running after both graphics have fully loaded.

Screenshot Moving graphics files in an animation.

Java ScreenShot

This app displays the animation on the BouncePanel component: a GIF file of a tennis ball bounces back and forth in front of a GIF file depicting a net. When the ball hits a point at the bottom edge of the frame, it rebounds upward close to the top edge. When the ball hits the right or left edge, it bounces in the opposite direction. The animated sequence in the BouncePanel class illustrates how to animate an image file using Java. It consists of the following steps:

Draw the ball at its current location.

Move the ball according to the rules that have been established for how the ball should move.

Check whether the rules need to be changed based on the ball's new location.


Drawing the Image

The BouncePanel class is threaded, so all its image-manipulation code is placed in a run() method that will be called when the thread is started. The paintComponent() method is where the court is drawn, followed by the ball at its current location.

By the Way

If you display the tennis.gif file in a graphics viewer or editing program, you will see that it has a dark gray background around the ball. This background does not show up in the animated sequence because the tennis.gif file has been saved with that dark gray color designated as a transparent color. Java 2 supports transparency in graphics files, making it much easier to animate one image atop another.

The Image object called ball is loaded with the tennis.gif image in the init() method. Several variables are used in the class to keep track of the ball's location and its current rate of movement:

  • xPosition This variable is the x coordinate where the ball should be drawn. This coordinate begins as 10.
  • xMove This variable is the amount the ball should move along the x axis after every screen update. This amount starts out as 1, but it will change to -1 when the ball hits the right edge of the applet window. It changes back and forth from -1 to 1 every time it hits an edge, and this change is handled by Lines 48–53.
  • yPosition This variable is the y coordinate where the ball should be drawn. This coordinate is initially set to -1, which is a signal to the paint() method that the yPosition needs to be set up before the ball can be drawn for the first time. The yPosition value varies from a point near the bottom of the applet window to the top edge.
  • current This floating point number starts at 0 and increases by 0.1 each time the ball is redrawn. When it reaches 3, it is set back to 0 again. The current variable is used with a mathematical sine function to determine how high the ball bounces. Sine waves are a good way to approximate the movements of a bouncing ball, and the Math.sin() method enables a sine value to be used in conjunction with animation. The tennis ball is traveling half a sine wave each time it goes from the ground to the top of the window and back.

The movement rules that you establish for an animated program will vary depending on what you're trying to show. The Bounce app uses the Math.sin() method to create the slow arcs traveled by the ball.