# Java: Example - Bouncing Ball

| This program does a simple animation. Animation is done by creating a timer which calls an ActionListener at fixed intervals (eg, every 35 milliseconds). The listener tells the ball to move it's coordinates a little, then it repaints the panel. repaint() indirectly calls our paintComponent() method, which then draws the ball with the updated coordinates.

## BBDemo.java - The main program and window creation

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
    // File: animation/bb/BBDemo.java
    // Description: Illustrates animation with a ball bouncing in a box
    //              Possible extensions: faster/slower button,
    // Author: Fred Swartz
    // Date:   February 2005 ...

    import javax.swing.*;

    /////////////////////////////////////////////////////////////// BBDemo
    public class BBDemo extends JApplet {

        //============================================== applet constructor
        public BBDemo() {
            add(new BBPanel());
        }

        //============================================================ main
        public static void main(String[] args) {
            JFrame win = new JFrame("Bouncing Ball Demo");
            win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            win.setContentPane(new BBPanel());

            win.pack();
            win.setVisible(true);
        }
    }//endclass BBDemo

## BBPanel.java - The JPanel which organizes the GUI

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
    // File:  animation/bb/BBPanel.java
    // Description: Panel to layout buttons and graphics area.
    // Author: Fred Swartz
    // Date:   February 2005

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

    /////////////////////////////////////////////////////////////////// BBPanel
    class BBPanel extends JPanel {
        BallInBox m_bb;   // The bouncing ball panel

        //========================================================== constructor
        /** Creates a panel with the controls and bouncing ball display. */
        BBPanel() {
            //... Create components
            m_bb = new BallInBox();
            JButton startButton = new JButton("Start");
            JButton stopButton  = new JButton("Stop");

            //... Add Listeners
            startButton.addActionListener(new StartAction());
            stopButton.addActionListener(new StopAction());

            //... Layout inner panel with two buttons horizontally
            JPanel buttonPanel = new JPanel();
            buttonPanel.setLayout(new FlowLayout());
            buttonPanel.add(startButton);
            buttonPanel.add(stopButton);

            //... Layout outer panel with button panel above bouncing ball
            this.setLayout(new BorderLayout());
            this.add(buttonPanel, BorderLayout.NORTH);
            this.add(m_bb       , BorderLayout.CENTER);
        }//end constructor

        ////////////////////////////////////// inner listener class StartAction
        class StartAction implements ActionListener {
            public void actionPerformed(ActionEvent e) {
                m_bb.setAnimation(true);
            }
        }

        //////////////////////////////////////// inner listener class StopAction
        class StopAction implements ActionListener {
            public void actionPerformed(ActionEvent e) {
                m_bb.setAnimation(false);
            }
        }
    }//endclass BBPanel

## BallInBox.java - The graphics panel that does the animation.

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
    // File:   animation/bb/BouncingBall.java
    // Description: This Graphics panel simulates a ball bouncing in a box.
    //         Animation is done by changing instance variables
    //         in the timer's actionListener, then calling repaint().
    //         * Flicker can be reduced by drawing into a BufferedImage,
    //           and/or using a clip region.
    //         * The edge of the oval could be antialiased (using Graphics2).
    // Author: Fred Swartz
    // Date:   February 2005

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

    /////////////////////////////////////////////////////////////// BouncingBall
    public class BallInBox extends JPanel {
        //============================================== fields
        //... Instance variables representing the ball.
        private Ball m_ball         = new Ball(0, 0, 2, 3);

        //... Instance variables for the animiation
        private int   m_interval  = 35;  // Milliseconds between updates.
        private Timer m_timer;           // Timer fires to anmimate one step.

        //========================================================== constructor
        /** Set panel size and creates timer. */
        public BallInBox() {
            setPreferredSize(new Dimension(200, 80));
            setBorder(BorderFactory.createLineBorder(Color.BLACK));
            m_timer = new Timer(m_interval, new TimerAction());
        }

        //========================================================= setAnimation
        /** Turn animation on or off.
         *@param turnOnOff Specifies state of animation.
         */
        public void setAnimation(boolean turnOnOff) {
            if (turnOnOff) {
                m_timer.start();  // start animation by starting the timer.
            } else {
                m_timer.stop();   // stop timer
            }
        }

        //======================================================= paintComponent
        public void paintComponent(Graphics g) {
            super.paintComponent(g);  // Paint background, border
            m_ball.draw(g);           // Draw the ball.
        }

        //////////////////////////////////// inner listener class ActionListener
        class TimerAction implements ActionListener {
            //================================================== actionPerformed
            /** ActionListener of the timer.  Each time this is called,
             *  the ball's position is updated, creating the appearance of
             *  movement.
             *@param e This ActionEvent parameter is unused.
             */
            public void actionPerformed(ActionEvent e) {
                m_ball.setBounds(getWidth(), getHeight());
                m_ball.move();  // Move the ball.
                repaint();      // Repaint indirectly calls paintComponent.
            }
        }
    }//endclass

## Ball.java - The logic/model of the ball.

This class holds the information about the ball, its diameter, position, and velocity. Other attributes are possible (eg, color). This ball knows nothing about animation, only about its current state, how to update its coordinates, and how to draw itself.

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
    // File: animation/bb/BallModel.java
    // Description: The logic / model of a ball.
    // Author: Fred Swartz
    // Date:   February 2005

    import java.awt.*;

    ///////////////////////////////////////////////////////////////// BallModel
    public class Ball {
        //... Constants
        final static int DIAMETER = 21;

        //... Instance variables
        private int m_x;           // x and y coordinates upper left
        private int m_y;

        private int m_velocityX;   // Pixels to move each time move() is called.
        private int m_velocityY;

        private int m_rightBound;  // Maximum permissible x, y values.
        private int m_bottomBound;

        //======================================================== constructor
        public Ball(int x, int y, int velocityX, int velocityY) {
            m_x = x;
            m_y = y;
            m_velocityX = velocityX;
            m_velocityY = velocityY;
        }

        //======================================================== setBounds
        public void setBounds(int width, int height) {
            m_rightBound  = width  - DIAMETER;
            m_bottomBound = height - DIAMETER;
        }

        //============================================================== move
        public void move() {
            //... Move the ball at the give velocity.
            m_x += m_velocityX;
            m_y += m_velocityY;

            //... Bounce the ball off the walls if necessary.
            if (m_x < 0) {                  // If at or beyond left side
                m_x         = 0;            // Place against edge and
                m_velocityX = -m_velocityX; // reverse direction.

            } else if (m_x > m_rightBound) { // If at or beyond right side
                m_x         = m_rightBound;    // Place against right edge.
                m_velocityX = -m_velocityX;  // Reverse direction.
            }

            if (m_y < 0) {                 // if we're at top
                m_y       = 0;
                m_velocityY = -m_velocityY;

            } else if (m_y > m_bottomBound) { // if we're at bottom
                m_y       =  m_bottomBound;
                m_velocityY = -m_velocityY;
            }
        }

        //============================================================== draw
        public void draw(Graphics g) {
            g.fillOval(m_x, m_y, DIAMETER, DIAMETER);
        }

        //============================================= getDiameter, getX, getY
        public int  getDiameter() { return DIAMETER;}
        public int  getX()        { return m_x;}
        public int  getY()        { return m_y;}

        //======================================================== setPosition
        public void setPosition(int x, int y) {
            m_x = x;
            m_y = y;
        }
    }