Breakout
Due to CMS by Saturday, May 5th
This assignment, including much of the wording of this document, is taken from an assignment from
Stanford University, by Professor Eric Roberts. Your task is to write the classic arcade game
Breakout. You can download our solution as a jar-file application and get a real taste for the
game.
Please keep track of the time you spent on this assignment. We will ask for it when it is time to
submit.
This assignment is easily within your grasp. You just have to start early, break the problem up
into manageable pieces, and program/test incrementally. Below, we discuss stages of implementation
and give suggestions for staying on top of the project. If you follow our advice and test each
piece thoroughly before proceeding to the next, you should be successful. Our solution is ~335
lines long and has 11-12 methods.
Table of Contents
Before You Get Started
Academic Integrity
This assignment is similar to one given in previous offerings of CS1110. It
is a violation of the Code of Academic Integrity for you to be in possession
of or to look at code (in any format) for this assignment of anyone in this
class or in previous classes of CS 1110. You should also not show another
student your program (this includes publicly posting your code on Piazza).
Please do not violate the Code; penalties for this will be severe. We will
try hard to give you all the help you need for this assignment.
As with the last assignment, it is highly unlikely that your code for
this assignment will look exactly like someone else's. Once gain, we
will actively be using Moss to check for instances of cheating and
plagiarism. Anyone caught using files that are obviously from a previous
semester will be prosecuted, with the end result perhaps being to fail
the course.
Collaboration Policy
You may do this assignment with one other person. If you are going to work
together, then form your group on CMS as soon as possible. If you do this
assignment with another person, you must work together. It is against the
rules for one person to do some programming on this assignment without the
other person sitting nearby and helping.
With the exception of your CMS-registered partner, you may not look at anyone
else's code or show your code to anyone else, in any form what-so-ever.
Necessary Files
The first thing to do in this assignment is to download the zip file
A7.zip from this link. You should unzip it and
put the contents in a new directory. This zip file contains
the following:
Breakout.java
This is the source code that you will modify, and the only file
that you submit for a grade.
Breakout.jar
This is a double-clickable Jar file with a solution. It gives you
something to compare against.
acm.jar
This is the jar file from Assignment A5.
docs
These are the specifications of all the classes in package acm
.
sound files
These are some sample sound files should you wish to add sound effects as
part of your extensions.
The only source code that you have access to in this assignment is the calass
Breakout
. A partial skeleton of this class appears to the right.
The class includes:
- Import statements for the various packages
-
Recall from class that a GUI application needs to access a lot of
packages to function properly; this class imports them all.
- Constants that control the game parameters
-
These are mnemonic constants for things like the height of the game paddle.
Your code should use these constants internally so that changing them in
your file changes the behavior of your program accordingly.
- A static
main
method
-
This is a method that starts the application pro- gram, fixes bricks, and sets
the window to the appropriate size. Run the program by clicking button Run
or by executing this in the interactions pane:
run Breakout
You will notice that by cramming everything into the Breakout
class, this application is in clear violation of the model-view-controller
pattern. We chose to do it this way for two reasons. First, our hands are
somewhat tied by the ACM Graphics package which is primarily designed for
beginners, and so trades poor design for simplified presentation. Second,
this assignment has always been distributed this way, so we did not want
to introduce a lot of bugs by rewriting the program.
You should use the instructions from Assignment A5
to add the JAR file to DrJava. As before, if you need more detailed specifications
than the ones we give, they are available from the
official site.
Class Breakout
is a subclass of class GraphicsProgram
,
which is associated with the window on which the graphics takes place. Method
main
creates an instance of the class and then calls method start
of the instance, which is inherited from GraphicsProgram
.
Assignment Scope
GraphicsProgram
also declares procedure run
, which is
overridden in class Breakout
. Execution of start(sizeArgs)
constructs the basic GUI window and then calls procedure run
. You have to write
the body of run
(and any other methods you need) to initialize the GUI
with bricks, paddle, and ball and play the game. You also have to write class Brick
.
An important part of your programming will be to develop new methods whenever you need
them, in order to keep each method small and manageable. Your grade will depend partly
on the design of your program. As one guideline, points will be deducted for methods
that are more than 50 lines long (including the specification).
You must provide a class invariant (for the fields). You must specify each method
precisely and thoroughly. You need not write loop invariants, although doing so
will help you. If you show your code to an instructor, TA, or consultant and they
see a method that is not specified, they will ask you to go away, fix it, and
come back at another time.
Pacing Yourself
You should start as soon as possible. If you wait until the day before this assignment
is due, you will have a hard time completing it. If you do one part of it every 2-3 days,
you will enjoy it and get it done on time. The hard part may be "finishing up":
designing the final reorganization in order to incorporate three balls in a game.
Implement the program in stages, as described in this handout. Do not try to get
everything working all at once. Make sure that each stage is working before moving
on to the next stage.
Set up a schedule. We have suggested some milestones, but make up your own schedule.
Leave time for learning things and asking questions. You may have to learn some points
about package acm.graphics
by yourself.
Finally, do not try to extend the program until you
get the basic functionality working. If you add extensions too
early, debugging may get very difficult.
Getting Help
We have tried to give you as much guidance in this document as we can. However, if your are
still lost, please see someone immediately. Like the last assignment, this is a fairly
involved project, and you should get started early. To get help, you may talk to the course
instructor, a TA, or a consultant. See the
staff page for more information.
In addition, you should always check Piazza
for student questions as the assignment progresses. We may also periodically post announcements
regard this assignment on the course website.
Breakout
The initial configuration of the game Breakout is shown in the left-most picture below.
The colored rectangles in the top part of the screen are bricks, and the slightly larger
rectangle at the bottom is the paddle. The paddle is in a fixed position in the vertical
dimension; it moves back and forth horizontally across the screen along with the mouse
— unless the mouse goes past the edge of the window.

Starting Position
|
|

Hitting a Brick
|
A complete game consists of three turns. On each turn, a ball is launched from the center
of the window toward the bottom of the screen at a random angle. The ball bounces off the
paddle and the walls of the world, in accordance with the physical principle generally
expressed as "the angle of incidence equals the angle of reflection" (it is easy to implement).
The start of a possible trajectory, bouncing off the paddle and then off the right wall,
is shown to the right. The dotted line is there only to show the ball's path and will
no actually appear on the screen.
In the second diagram above, the ball is about to collide with a brick on the bottom row.
When that happens, the ball bounces just as it does on any other collision, but the
brick disappears. The left-most diagram below shows the game after that collision and
after the player has moved the paddle to put it in line with the oncoming ball.

Intercepting the Ball
|
|

Breaking Out
|
The play on a turn continues in this way until one of two conditions occurs:
-
The ball hits the lower wall, which means that the player missed it with the paddle.
In this case, the turn ends. If the player has a turn left, the next ball is served;
otherwise, the game ends in a loss for the player.
-
The last brick is eliminated. In this case the player wins, and the game ends.
Clearing all the bricks in a particular column opens a path to the top wall. When
this delightful situation occurs, the ball may bounce back and forth several times
between the top wall and the upper line of bricks without the user having to worry
about hitting the ball with the paddle. This condition, a reward for "breaking out",
gives meaning to the name of the game. The last diagram above shows the situation
shortly after the first ball has broken through the wall. The ball goes on to clear
several more bricks before it comes back down the open channel.
Breaking out is an exciting part of the game, but you do not have to do anything in
your program to make it happen. The game is operating by the same rules it always
applies: bouncing off walls, clearing bricks, and obeying the "laws of physics".
The Basic Game
We have divided these instructions into two parts. The first part covers the
basic things that you must implement just to get the game running. Once you do that,
the assignment gets more interesting. You should try to finish everything in this
part of the assignment by Wednesday, May 2 (during the last week of class).
If you do that, you will be in good shape to finish the rest of the assignment.
Set up the Bricks
The first step is to write the code that puts the various pieces on the playing board.
Thus, it probably makes sense to implement procedure run
(which drives the
game) as two method calls: one that sets up the game and one that plays it. An important
part of the setup consists of creating rows of bricks at the top of the game, which are
shown to the right.
The number, dimensions, and spacing of the bricks, as well as the distance from the
top of the window to the first line of bricks, are specified using named constants
given in class Breakout
. The only value you need to compute is the
x coordinate of the first column, which should be chosen so that the bricks
are centered in the window, with the leftover space divided equally on the left and
right sides
(Hint: the leftmost brick should be placed at x-coordinate BRICK_SEP_H
/2).
The colors of the bricks remain constant for two rows and run in the following sequence:
RED
, ORANGE
, YELLOW
, GREEN
, CYAN
.
If there are more than 10 rows, your start over with RED, and do the sequence again.
All objects placed on the playing board are instances of subclasses of abstract class
GObject
. The bricks and paddle are objects of subclass GRect
.
You should complete subclass Brick
of GRect
(given at the
end of Breakout.java
) and use objects of class Brick
for the
bricks.
Class Brick
has no fields and needs only two methods:
-
a constructor for a new brick of a given width and height and
-
a constructor for a new brick at a point (x,y) and of a given width and height.
Class
GRect
has similar constructors, if you wish to compare.
Class
Brick
can stay inside
Breakout.java
, you do not need
to have it in a separate file (notice the lack of
public before
class).
To add a GRect
object r
to the playing board, call inherited
procedure add(r) inside the class Breakout
. To begin, you might
want to create a single Brick
object of some position and size and add it
to the playing board, just to see what happens. Then think about how you can place the
8 rows of bricks.
You need to fill a Brick
(which is a GRect
) with a particular color;
you should also to set its color so that its outline is the same color (instead of black).
Look for GRect
methods to do this. In order to allow the object to be filled
with a color, you need to use a procedure call like rect.setFilled(true);
.
Important Considerations
Do not use an array or Vector to keep track of the bricks. Just add the bricks to
the playing board as they are created. Do not be concerned about keeping track of them.
Later, you will see why you do not need to keep them in an array or Vector.
In addition, make sure your creation of the rows of bricks works with any number of rows
and any number bricks in each row (e.g. 1, 2, ..., 10, and perhaps more).
Try to finish this part by April 22. All you need to do is to produce the brick diagram
shown above. This will give you considerable confidence that you can get the rest done.
Write Method fixBricks
While you are working with the program, you should play with just 3-4 bricks er row and 1-2 r
ows of bricks. This will save time and let you more quickly see whether the program works
correctly when the ball breaks out (gets to the top of the canvas). It will also allow
you to test when someone wins or loses.
Unforunately, this would require changing the values of the static constants that give the
number of rows and number of bricks in a row. This is undesirable (you might forget to change
them back) Instead of that, we can use the fact that this is an application and give the
application some values when it starts out. Use the following command in the interactions
pane.
java Breakout 3 2
This is equivalent to writing
Breakout.main(new String[]{"3","2"};
That is, it
calls method
main
with the given String array as argument.
Look at method Breakout.main
. Its first statement calls fixBricks
.
Your task is to write the body of fixBricks, following its specification (and the hint
given as a comment) carefully. You will then be able to start the program as shown above
and have just 3 bricks per row and 2 rows.
Complete this part by April 24.
Create the Paddle
Next you need to create the black paddle. You will need to reference the paddle often, so
declare it as a private field of type GRect
. A public static variable of class
Breakout gives its vertical position relative to the bottom of the window.
Making the paddle move in response to mouse movements means that something has to be
registered as a "listener" to the mouse. We talked about how to do this in general
in lecture, but the ACM classes handle this a bit differently (sigh). Read the
ACM documentation
to find out how to make the "appropriate something" in the ACM-package framework listen
to the mouse. The whole window associated with the GraphicsProgram should listen to mouse
movement, not the paddle.
Once you have done that, here iss how to make the paddle track the mouse (horizontally only).
Declare a procedure like this:
/** Move the horizontal middle of the paddle to the
* x-coordinate of the mouse position, but keep the
* paddle completely on the board. */
public void mouseMoved(MouseEvent e) {
GPoint p= new GPoint(e.getPoint());
...
}
Thus you are overriding inherited procedure
mouseMoved
. This procedure is
called whenever the mouse is moved. Parameter
e
has a function
getPoint
,
and the assignment statement we give you in the body stores in
p
the coordinates
of the point where the mouse currently is. Replace the three dots above by code that changes
the
x-coordinate of the paddle as indicated in the specification, using the
x-coordinate of point
p
.
Be careful that the paddle stays completely on the board even if the mouse moves off the
board. Our code for this is 3 lines long; it uses function Math.min
and
Math.max
.
Complete this part by April 26.
Create a Ball and Make it Bounce
You are now past the "setup" phase and into the "play" phase of the game. In this phase,
a ball is created and moves and bounces appropriately. A ball is just a filled GOval
.
To start, create a ball and put it in the center of the window. Again, you probably want a private
field ball
of type GOval
to contain the ball, since you will have to
refer to it often. Keep in mind that the coordinates of the GOval
specify the upper
left corner and not the center of the ball.
The play phase of the game should contain a loop, each iteration of which does the following:
-
moves the ball a bit
-
changes direction if it hits a wall
-
pauses for 10 milliseconds, using
pause(10);
The program needs to keep track of the velocity of the ball, which consists of its horizontal
(
x) component and its vertical (
y) component. You should declare them as fields
like this:
private double vx, vy; // give their meanings in a comment!
These velocity components represent the change in position that occurs on each time step
(each loop iteration).
Initially, the ball should head downward, so you should use a starting velocity of +3.0 for
vy
. The game would be boring if every ball took the same course, so you should
choose component vx
randomly. You can read about random numbers in the text, but
for now simply do the following:
-
Declare a field
rgen
, which will serve as a random-number generator:
private RandomGenerator rgen= new RandomGenerator();
-
Initialize variable vx as follows:
vx = rgen.nextDouble(1.0, 3.0);
if (!rgen.nextBoolean(0.5)) { vx = -vx };
This code sets vx to be a random double in the range 1.0 to 3.0 and then makes it
negative half the time.
Your next challenge is to get the ball to bounce off the walls of the playing board, ignoring
entirely the paddle and the bricks. Once you have moved the ball one step —
by (vx
,vy
) — do the following:
Suppose the ball is going up. Then, if any part of the ball has a y-coordinate
less than or equal to 0, the ball has reached the top and its direction has to be changed so
that it goes down. So this by setting vy
to -vy
. Check the other
three sides in the same fashion. When you have finished this, the ball will bounce around
the playing board forever — until you stop it.
You have to figure out whether the ball has reached (or gone over) the top. Remember that
the location of a GOval
is the top-left corner of its bounding box.
Complete this part by April 30.
Check for Collisions
Now comes the interesting part. In order to make Breakout into a real game, you have to be
able to tell when the ball collides with another object in the window. As scientists often
do, we make a simplifying assumption and then relax the assumption later. Suppose the ball
were a single point (x,y) rather than a circle. The call
getElementAt(x,y)
of inherited function
getElementAt
does the follow:
-
return
null
if no graphical object covers point (x,y)
-
return (the name on the tab of) the
GObject
that covers point (x,y),
if some GObject
actually covers the point.
If several
GObjects
cover the point, the one that appears to be in front on
the display is returned.
Suppose getElementAt
returns (the name on the tab of) a GObject gob
.
If gob == paddle
, you know the paddle has collided with the single-point ball at
(x,y). If gob
is an instance of Brick
, then
gob
must be a brick. So, we have just explained how to test whether a
single-point ball has collided with the paddle or a brick.
However, the ball is not a single point. It occupies physical area, so it may collide with
something on the screen even though its center does not. The easiest thing to do —
which is typical of the simplifying assumptions made in real computer games is to check a
few carefully chosen points on the outside of the ball and see whether any of those points
has collided with anything. As soon as you find something at one of those points
(other than the ball of course) you can declare that the ball has collided with that object.
One of the easiest ways to come up with these "carefully chosen points" is to treat everything
in the game as rectangles. A GOval
is defined in terms of is bounding rectangle
(e.g. the rectangle in which it is inscribed). Therefore the upper left corner of the ball is
at the point (x,y) and the other corners are at the locations shown in the diagram
to the right (r is the radius of the ball). These points have the advantage of being outside
the ball, so that getElementAt
cannot return the ball itself. But they are close
enough to make it appear that a collision has occurred.
Write a function
GObject getCollidingObject()
that checks the four corners, one at a time. If one of them collides with the paddle or a
brick, stop the checking immediately and return the object involved in the collision. Return
null
if no collision occurred.
Next you need to modify the main game loop, discussed above.
After moving the ball, call getCollidingObject
to check for a collision. If
the ball going up collides with the paddle, do nt do anything. If the ball going down
collides with the paddle, negate the vertical direction of the ball. If the ball (going
in either vertical direction) collides with a brick, remove the brick from the board and
negate the vertical direction.
The inherited function remove(gob)
can be used to remove object gob
(such as a brick). You can check whether the object is a brick by asking whether it is an
instance of class Brick
.
Try to finish this part by May 2.
Expanding the Game
If you have followed our suggested timeline, you now have three days to take care of some minor
additional details. You are also welcome to extend the game and try to make it more fun. In
doing this, you might find yourself reorganizing run
. That is okay. However, we
highly suggest that you save a copy of the basic game in a separate folder before you start
to make major changes. That way you have something to revert to if you really screw up
the program.
Mandatory Details
While many of the extensions to the game are optional, the ones below are not. They must
be completed for you to get full credit on this assignment.
Player lives
You need to care of the case that the ball hits the bottom wall. Right now, the ball just
bounces off this wall like all the others, but hitting the bottom means that the ball is
gone. In a game, the player should get three balls before losing. If the player can have
another ball, put a message on the board somewhere (use a GLabel
object),
telling the player that another ball is coming in 3 seconds, pause for 3 seconds,
remove the message, and continue with a new ball.
Win condition
You need to check for hitting the last brick, in which case the player wins. An easy way
to do this is to keep track of how many bricks are left on the board. When there are none,
the game ends and the player has won.
Ending message
When a game ends, you should place a message somewhere on the window. Use a GLabel
object to do this.
Tune the game
Once you have finished everything else, experiment with the settings that control the speed of
your program. How long should you pause in the loop that updates the ball? Do you need to
change the velocity values to get better play action?
Possible Extensions
There are many ways — and fun ways — to extend this assignment. Add more and
we will be a bit more lenient with grading than if you implement the bare minimum. But
note that a submission that does not have a good class invariant and good specifications
for the methods will not be looked at kindly under any circumstances.
Here are some ways to extend the game.
Improve user control over bounces
The program gets rather boring if the only thing the player has to do is hit the ball.
Let the player control the ball by hitting it with different parts of the paddle. For
example, suppose the ball is coming down toward the right (or left). If it hits the left
(or right) 1/4 the paddle, the ball goes back the way it came (both vx and vy are negated).
Implement "Try Again"
Let the player play as many games as they want. The player could click the mouse button
to start a new game. A call on inherited procedure waitForClick()
will wait
(or pause) until the mouse is clicked.
Implement sound effects
It is an easy extension to add appropriate sounds for game events. We have provided several
audio files in
A7.zip. You are not restricted by those; you can
easily find lots more (
but it is a violation of the Academic Integrity Policy to use
copyrighted material in your assignment).
You can load an audio file (e.g. bounce.au) by writing the following command
AudioClip bounceClip= MediaTools.loadAudioClip("bounce.au");
Once it is loaded, you can play it whenever you want (such as when the ball hits something)
by calling
bounceClip.play();
. The sound might get monotonous after a while,
so make the sounds vary, and figure out a way to let the user turn sound off (and on).
Add the kicker
The arcade version of Breakout lures you in by starting off slowly. But as soon as you think
you are getting the hang of things, the ball speeds up, making life more exciting. Implement
this in some fashion, perhaps by doubling the horizontal velocity of the ball on the seventh
time it hits the paddle.
Keep score
Design some way to score the player performance. This could be as simple as the number
of bricks destroyed. However, you may want to make the bricks in the higher rows more
valuable.
It is best to display the score underneath the paddle. However, remember that
GLabel
is an object, and the ball hitting it should have
no effect.
Use your imagination
What else have you always wanted a game like this to do? At some point your game might
stop being like Breakout and be more like
Arkanoid.
Create a Jar File (Optional)
You might want people to be able to play your game without having to have DrJava installed.
To do this, create a jar file Breakout.jar
, checking that you can run it as a
stand-alone application (e.g. by double-clicking on its icon). You can use the procedure
outlined in the lecture notes during the last week of class (also covered in appendix I.4
in the text). Alternatively, you can use
DrJava's project facilities.
You do not have to turn anything in for this step. Just send your jar file to your friends
and let them amuse themselves for a couple of hours destroying innocent bricks that never
did them any harm, while you study for the final.
Completing the Assignment
Before submitting anything, test your program to see that it works. Play for a while and
make sure that as many parts of it as you can check are working. If you think everything
is working, try this: just before the ball is going to pass the paddle level, move the
paddle quickly so that the paddle collides with the ball rather than vice-versa.
Does everything still work, or does your ball seem to get "glued" to the paddle?
If you get this error, try to understand why it occurs and how you might fix it.
When you are done, you should put a non-JavaDoc comment (/* */, not /** */) in
Breakout.java
with the following information:
- Your name(s) and netid(s);
- The time you spent on this assignment.
- A brief description of your extensions.
- Your opinion of this assignment and how we could improve it.
As always, you should make sure that class Breakout
is indented properly. Do this
by hitting tab on every line in DrJava, so that it will auto-indent for you.
Turning it In
You should upload the file Breakout.java
onto CMS by the due date:
Saturday, May 5th at 11:59PM. If you have extra files to submit (e.g. custom
sound or art files), put all your files in a zip file called everything.zip
and submit this instead. Do not give us .class files and other stuff; just zip up
Breakout.java
and other files that your program needs.