Csci 210 Lab4: Breakout

(Laura Toma adapted from Eric Chown)

Overview

For this lab you are going to implement the game of Breakout. In many ways this lab is a very simple extension of the last lab. Hopefully along the way you will learn about Vectors and gain a further appreciation of the value of writing general code.

Breakout is a simple game not unlike Pong except that there are a bunch of bricks on the screen that you need to get rid of (don't forget to leave blank space above the bricks). When a brick gets hit by the ball it disappears. To play a cheesy (and poor) version of the game look here.

Program structure

Your code will have the same basic structure as your Pong program. It will have a main class, a Paddle class, a Ball class, and two new classes - the Brick class, and a data structure to hold Bricks.

Hopefully you wrote nice general Ball and Paddle classes for the last lab. If so then they should work again with very little modification.

In many ways a Brick is like a Paddle that can't move. It is a rectangle and the ball bounces off it. Of course one difference is that the Brick disappears once the ball has hit it. Another difference is that there are lots of Bricks. That part has nothing to do with the Brick class itself. Finally it matters which edge of the Brick that you hit in terms of where the ball goes - hitting on the top or bottom should reverse the Y velocity while hitting on the sides should reverse the X velocity.

At a minimum a Brick should contain information about where it is on the screen. It also might have color information (or even use an image for displaying a brick-like looking brick). Advanced versions of the program might have specialized bricks with different properties (e.g. making the ball go faster or slower).

Once you have figured out the mechanics of an individual brick it is time to think about how to collect them up. For this lab we will make a data structure that uses a Vector to do so. The obvious data structure is a simple Vector. Each Brick gets one slot in the data structure. That isn't what we're going to do. For one thing, such a simple structure does not really capture how the game works. The Bricks come in rows. Each row consists of some number of Bricks. For another thing, we'll be searching the data structure a lot, and a simple Vector is not efficient in terms of search. Some sort of Row data structure will help us search more efficiently.

This suggests that the data structure for holding all the bricks actually consists of two pieces:

Rows of Bricks

The Row data structure will need to hold a row of bricks. This suggests that it will require a Vector to do the job. In addition, the Row itself has some properties: its height and width, the height of the Bricks, and the number of Bricks when it is full. All of this information will be passed to the Row constructor by the main class. Once a Row has that information then it can use it to create the appropriate number of Bricks at the appropriate locations and put them into its own Vector.

In terms of methods, the main processing you'll need to do is to figure out if the Ball has hit any of the Bricks within the Row. Essentially you'll call this method, and it in turn will figure out if any of its Bricks will be hit (by calling their own methods). If a Brick is hit, then it should be removed from the Row. Once again there is an obvious implementation: simply run through all of the Bricks in the Vector and see if any of them intersect the ball's location. This is not, however, the best implementation. First off, depending on the ball's location it may not even be possible for it to hit any bricks in a Row (it may be too low, for example). Second you can use information about the order of the Bricks to help your search (e.g. if you start finding Bricks that are to the right of the ball then it isn't necessary to keep scanning through the Bricks). So one of the goals of your Row data structure should be to make this search very efficient.

Collision detection

Before you start coding, think of the structure of your program. The key of the game is to have the ball move while determining collisions. There are collisions with the court walls, with the bricks, and with the rows of bricks. If the ball is to check for collisions itself, then it needs information about all these. But the main class knows about all these anyways---so in this case, it may be more appropriate to have the main class determine collisions than the ball class (it would be the other way around if we extended the game to add more balls, while keeping the world simple).

What I envision for this is that the Ball class calls a method in the main class that determines if there are any collisions, and if so of what type. The main class will have a method that determines whether there are any collisions given the current position of the balll --- to do so it will use all the information it has about bricks, and paddle, and the court; in turn, it may call specific methods in each of these classes. When determining a collision it would also determine where the collision was (e.g. left, right, top, bottom) and could be used to redirect the ball. The ball is "independent" in the sense that it listens to the timer, and decides how to move itself based on whether there are collisions or not. But the engine for collisions is in teh main class.

Rendering and Iterators

Another thing your Row class will have to do is to be able to provide appropriate information to the main class for drawing. In a sense it needs to be able to provide information on all of the Bricks. And, you need to do this for every Row.

You could get the information about all the bricks in a row, one by one, using accessors on the vector. Another way to do this is to take advantage of some functionality built-in to Java. It is so common to need to get all of the elements of a data structure that Java builds that right into the language in the form of an Iterator. An Iterator does what the name suggests, it allows you to iterate through the elements of a data structure. As part of this lab you'll learn about iterators.

Vectors, like other data structures, have an iterator() method that returns an object of type Iterator. Here is some sample code to show how it might be used. The code assumes a Vector called x.

Iterator i = x.iterator();
while (i.hasNext()) {
	element = i.next();
	// whatever you do with elements
}

As you can see from the code the two main things you do with an Iterator are to check if there are any more elements, and to get the next element. You do this with hasNext() and next() respectively. Your Row class should have an iterator method too, and it should simply return the Iterator from its own Vector. Then when it comes time to draw, your program can loop through the Rows grabbing each of the Iterators and using them to grab all of the Bricks.

Main Class

Now, in your main class you will have a Vector of Rows (Vector). Once you decide on how many Rows to make, it is a simple matter of having a loop where you create one Row for each iteration of the loop. For starters just consider the case where the size of the game is fixed as are the sizes of the Bricks. If you have time then think about having the size of the field vary and the number of Bricks either vary with the size of the field (with fixed Bricks), or the size of the Bricks vary by the size of the field (e.g. a really wide field means really wide Bricks). It is possible to get this information from the JFrame class as well as to control things like whether resizing should even be possible.

Remember to include a method to do ball collisions. This will be called by the Ball class (and presumably will take parameters describing where the ball is).

Summary

In this assignment, like all of them, you should think about how to do the project in chunks. It is almost never a good idea to do the whole project in one breath. For example, in this assignment I probably would work on a version with a single Brick first (make it nice and big!). Once I was happy with that then I'd try a Vector of bricks essentially constituting one Row (but without using a Row class). Only at that point would I take on the Row data structure.

The assignment is to be able to play a basic game of breakout. Your interface need not be fancy, but it should be very playable (same idea as the last lab).

The example link is not to a great application. However, it does contain some useful ideas for an interface. You aren't required to use them all, but some (buttons for starting and stopping) are clearly helpful. It should be obvious by this point that there are almost an infinite number of extensions possible for this program.

Have fun with it!

Handing in: As always this is due at the start of the next lab and you should hand in hard copy in addition to emailing me the classes. Please name your classes Paddle_yourname, etc. Email me the classes as attachments. If you prefer to zip or tar your code, then make sure that when it un-zips (un-tars) the file gives the classes, not a folder containing your classes; also, no .class files, and no BlueJ-related files. On the hard-copy sign that you followed the honor code for the class.


Last modified: Thu Sep 27 11:17:13 EDT 2007