Computer Science 225
Advanced Programming

Spring 2017, Siena College

BallDropper BlueJ Project

Click here to download a BlueJ project for BallDropper.


BallDropper Source Code

The Java source code for BallDropper is below. Click on a file name to download it.


BallDropper.java

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.Timer;

/**
 * Example BetterBallDropper: a program that drops multiple ball
 * objects
 *
 * Jim Teresco, Siena College, Computer Science 225, Spring 2017
 *
 * $Id: templateapp.java 2975 2016-08-30 02:35:29Z terescoj $
 */

public class BallDropper extends JFrame implements MouseListener {
    
    private static final int WINDOW_SIZE = 400;
    private static final int TIMER_DELAY = 30;
    
    /** list of falling balls */
    private ArrayList<FallingBall> balls = new ArrayList<>();

    /**
     * construct a BallDropper frame
     */
    public BallDropper() {
        
        // set window properties
        setSize(WINDOW_SIZE, WINDOW_SIZE);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true); 
        
        addMouseListener(this);
        // create and start the timer that will repaint periodically
        Timer t = new Timer(TIMER_DELAY, 
            new ActionListener() {

                // the timer will wake up and call this method every
                // TIMER_DELAY milliseconds.
                @Override
                public void actionPerformed(ActionEvent e) {
                   
                    repaint();
                }
        });
        t.start();
        
    }
    
    /**
     * paint contents of our frame
     * 
     * @param g Graphics object on which to draw
     */
    @Override
    public void paint(Graphics g) {
        
        g.setColor(Color.white);
        g.fillRect(0, 0, WINDOW_SIZE, WINDOW_SIZE);
        g.setColor(Color.black);
        for (FallingBall fb : balls) {
            fb.paint(g);
        }
       
    }
    
    /**
     * mouse listener to create a new ball on each mouse press
     * 
     * @param e mouse event information
     */
    @Override
    public void mousePressed(MouseEvent e) {
     
        balls.add(new FallingBall(e.getX(), e.getY(), WINDOW_SIZE));
        
    }
    
    // remaining methods for MouseListener
    public void mouseReleased(MouseEvent e) {}
    public void mouseClicked(MouseEvent e) {}    
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
        
    /**
     * simple main method to allow this class to be run as an application
     * 
     * @param args not used
     */
    public static void main(String[] args) {
	
        new BallDropper();
    }
}

FallingBall.java

import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;

/**
 * A Falling Ball that manages its own animation
 * 
 * @author Jim Teresco
 */
public class FallingBall extends Thread {

    private static final int BALL_SIZE = 50;
    //private static final int VELOCITY = 2;
    private static final long PAUSE_TIME = 15;
    
    private static Random r = new Random();
    
    /** current ball position (upper left corner of bounding box) */
    private double x, y;
    /** how far the ball can fall */
    private int yMax;
    
    /** color of this ball */
    private Color c;
    
    /** x "side to side" velocity */
    private double xSpeed;
    
    /** y velocity */
    private double ySpeed = 1.0;
    
    /**
     * construct a FallingBall and start its animation
     * 
     * @param x x-coordinate of the center of the ball
     * @param y y-coordinate of the top of the ball
     * @param yMax the y-coordinate of the bottom of the window
     */
    public FallingBall(int x, int y, int yMax) {
        
        // set initial position of this ball
        this.x = x - BALL_SIZE/2;
        this.y = y;
        this.yMax = yMax;
        
        c = new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256));
        
        xSpeed = 0;
        start();
    }
    
    /**
     * thread run method: move the ball periodically
     */
    public void run() {

        while (true) {
            
            try {
                sleep(PAUSE_TIME);
            }
            catch (InterruptedException e) {}
            
            // move the ball according to current velocity components
            y += ySpeed;
            x += xSpeed;
            
            // bounce off the floor!  include some damping so
            // we stop bouncing eventually
            if (y + BALL_SIZE > yMax) {
                y = yMax - BALL_SIZE;
                ySpeed = -ySpeed * 0.75;
            }
            
            // accelerate a bit left and right and some down to 
            // simulate gravity
            xSpeed += r.nextDouble()*0.25 - 0.125;
            ySpeed += .01;
        }
    }

    /**
     * paint this item on the given Graphics area
     * 
     * @param g Graphics area on which to draw
     */
    public void paint(Graphics g) {
    
        g.setColor(c);
        g.fillOval((int)x, (int)y, BALL_SIZE, BALL_SIZE);
    }
}