Computer Science 252
Problem Solving with Java

Spring 2015, The College of Saint Rose

PongBricks Demo

A working demo of PongBricks will appear below. Click inside the applet to interact with it.



PongBricks BlueJ Project

Click here to download a BlueJ project for PongBricks.


PongBricks Source Code

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


PongBricks.java

import objectdraw.*;
import java.awt.*;

/*
 * Example PongBricks
 *
 * Jim Teresco, Siena College, CSIS 120, Spring 2012
 * Updated for The College of Saint Rose, CSC 252, Fall 2013
 * Updated again Fall 2014
 *
 * $Id: PongBricks.java 2489 2014-11-18 14:04:50Z terescoj $
 */

public class PongBricks extends WindowController {

    // position and dimensions of the court
    private static final int COURT_LEFT = 50;
    private static final int COURT_TOP = 50;
    private static final int COURT_HEIGHT = 300;
    private static final int COURT_WIDTH = 300;
    private static final int COURT_RIGHT = COURT_LEFT + COURT_WIDTH;

    // dimensions of the paddle
    private static final int PADDLE_WIDTH = 50;
    private static final int PADDLE_HEIGHT = 20;

    private static final int PADDLE_Y = COURT_TOP + COURT_HEIGHT - PADDLE_HEIGHT - 1;

    // how many bricks in the playing area
    private static final int NUM_BRICKS = 50;
    
    private FilledRect paddle;
    private FramedRect boundary; // the boundary of the playing area.

    private BrickCollection bricks;
    
    public void begin() {
        // make the playing area
        boundary = new FramedRect(COURT_LEFT, COURT_TOP,
            COURT_WIDTH, COURT_HEIGHT,
            canvas);

        // make the paddle
        paddle = new FilledRect(COURT_LEFT + (COURT_WIDTH-PADDLE_WIDTH)/2,
            COURT_TOP + COURT_HEIGHT - PADDLE_HEIGHT -1,
            PADDLE_WIDTH, PADDLE_HEIGHT,
            canvas);
            
        // the collection of bricks
        bricks = new BrickCollection(COURT_LEFT, COURT_LEFT+COURT_WIDTH,
                                     COURT_TOP, COURT_TOP+COURT_HEIGHT/2,
                                     NUM_BRICKS, canvas);
    }

    // create a new pong ball if the press is in the playing area
    public void onMousePress(Location point) {

        if (boundary.contains(point)) {
            new PongBall(paddle, boundary, bricks, canvas);
        }
    }

    // move the paddle to follow the mouse's x coordinate
    public void onMouseMove(Location point) {

        if (point.getX() < COURT_LEFT) {
            // place paddle at left edge of the court
            paddle.moveTo(COURT_LEFT, PADDLE_Y);
        } else if (point.getX() + PADDLE_WIDTH > COURT_RIGHT) {
            // place paddle at right edge of the court
            paddle.moveTo(COURT_RIGHT - PADDLE_WIDTH, PADDLE_Y);
        } else {
            // keep the edge of the paddle lined up with the mouse
            paddle.moveTo(point.getX(), PADDLE_Y);
        }

    }
}

PongBall.java

import objectdraw.*;
import java.awt.*;
import java.util.Random;

/*
 * 
 * A simple active object that controls a ball that bounces around the
 * canvas and interacts with a boundary and a pong paddle
 *
 * Jim Teresco, Siena College, CSIS 120, Spring 2011
 * Updated for CSC 252, The College of Saint Rose, Fall 2013
 * Updated again Fall 2014 to start at the paddle, not on top
 *
 * $Id: PongBall.java 2482 2014-11-13 01:16:32Z terescoj $
 */

public class PongBall extends ActiveObject {

    // size and speed of falling balls
    private static final int BALLSIZE = 30;
    private static final double MIN_SPEED = 3;
    private static final double MAX_SPEED = 10;
    private static final int DELAY_TIME = 33;

    // the ball controlled by this instance
    private FilledOval ball;

    // the paddle with which we will interact
    private FilledRect paddle;

    // the bricks we are trying to hit
    private BrickCollection bricks;
    
    // how far to fall before stopping and disappearing?
    private double yMax;
    // how far up to go before bouncing off the ceiling?
    private double yMin;
    // and what about the walls?
    private double xMin, xMax;

    // Draw a ball and start it falling.
    public PongBall(FilledRect paddle, FramedRect boundary,
                    BrickCollection bricks,
                    DrawingCanvas aCanvas) {

        // compute/remember our boundaries (of the upper left corner of a ball)
        yMax = boundary.getY()+boundary.getHeight();
        yMin = boundary.getY();
        xMin = boundary.getX();
        xMax = boundary.getX() + boundary.getWidth() - BALLSIZE;

        // draw the ball at its initial position, which is atop the paddle
        ball = new FilledOval(paddle.getX(), paddle.getY() - BALLSIZE - 1,
            BALLSIZE, BALLSIZE, aCanvas);

        // remember the paddle
        this.paddle = paddle;
        
        // remember the bricks
        this.bricks = bricks;

        // activate!
        start();
    }

    // move the ball repeatedly until it falls off screen, bouncing
    // off the paddle and walls along the way
    public void run() {
        double xSpeed, ySpeed;

        // start by moving downward and some amount to the right
        Random r = new Random();

        xSpeed = r.nextDouble() * (MAX_SPEED - MIN_SPEED) + MIN_SPEED;
        double initYSpeed = r.nextDouble() * (MAX_SPEED - MIN_SPEED) + MIN_SPEED;
        ySpeed = -initYSpeed;

        // keep moving as long as we haven't fallen off the bottom of
        // the screen
        while (ball.getY() <= yMax) {
            // if we are above the top line, start moving down
            if (ball.getY() < yMin) {
                ySpeed = initYSpeed;
            }

            // if we are in contact with the paddle, start moving up
            if (ball.overlaps(paddle)) {
                ySpeed = -initYSpeed;
            }

            // bounce off side walls
            if (ball.getX() < xMin || ball.getX() > xMax) {
                xSpeed = -xSpeed;
            }

            // bounce off any bricks
            if (bricks.hit(ball)) {
                ySpeed = -ySpeed;
            }
            
            // move a little in the appropriate direction
            ball.move(xSpeed, ySpeed);
            pause(DELAY_TIME);
        }

        ball.removeFromCanvas();
    }
}

BrickCollection.java

import objectdraw.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Random;

/**
 * A collection of bricks that can be "hit" by a ball
 * in a pong/breakout game
 * 
 * Jim Teresco, Siena College, CSIS 120, Spring 2012
 * Updated for Fall 2013, The College of Saint Rose
 * Further update, Fall 2014
 *
 * $Id: BrickCollection.java 2489 2014-11-18 14:04:50Z terescoj $
 */
public class BrickCollection {

    private static final double BRICK_SIZE = 10;
    
    // we'll store our bricks in this ArrayList
    private ArrayList<FilledRect> bricks;
    
    /**
     * Constructor for objects of class BrickCollection
     */
    public BrickCollection(double xMin, double xMax, 
                           double yMin, double yMax,
                           int numBricks, DrawingCanvas canvas) {
    
        // place to store our bricks                      
        bricks = new ArrayList<FilledRect>();
        
        Random r = new Random();

        // randomly place numBricks bricks within the boundaries, making sure
        // none overlap
        for (int bricksSoFar = 0; bricksSoFar < numBricks; bricksSoFar++) {
            FilledRect newest = 
                new FilledRect(r.nextDouble() * (xMax-xMin-BRICK_SIZE) + xMin, 
                               r.nextDouble() * (yMax-yMin) + yMin,
                               BRICK_SIZE, BRICK_SIZE, canvas);
            bricks.add(newest);
        }
    }
    
    // check if the given ball overlaps any of our bricks -- if it does,
    // remove it from the canvas and the ArrayList of bricks and return true.
    // if not, return false.
    public boolean hit(FilledOval ball) {
        
        for (int brickNum = 0; brickNum < bricks.size(); brickNum++) {
            FilledRect thisBrick = bricks.get(brickNum);
            if (thisBrick.overlaps(ball)) {
                thisBrick.removeFromCanvas();
                bricks.remove(brickNum);
                return true;
            }
        }
        return false;
    }

}