CMPU 101 - Assignment 7 Due: by 11:59 PM on Wednesday, April 26th

$Revision: 1.2 $

In this assignment you will update the bouncing ball program from Assignment 3 so that it becomes a one-player version of the game Pong.  By using objects and inheritance, this should be a very simple conversion.

Getting Started

Download cs101-assign7.zip into the Home directory.  Extract it by opening a terminal window and running the command

unzip cs101-assign7.zip

The Java source files will be in a directory called cs101-assign7 within the Home directory.

Make sure you save all of your Java files before logging out by copying them to a USB drive, recordable CD-ROM, VSpace, or emailing them to yourself as attachments.

Walls, Paddles, and Collisions

Here is a screen shot of the one-player Pong game:

The playing field consists of three walls---top, left, and right---and a paddle.  The bottom of the playing field is now open, allowing the ball to disappear and be lost.  The player can move the paddle left and right (using the left and right arrow keys) to block the ball and prevent it from being lost.

The three walls and the paddle are each represented by an object.  The walls are instances of a class called Wall (or a subclass of a class called Wall).  The paddle is an instance of a class called Paddle, which is a subclass of Wall.

A Wall object has two main capabilities.  It can draw itself in the window using a method called draw, and it can check to see if a Ball object has collided with the wall using a method called checkCollision.  When a collision occurs, the Ball should be deflected in the appropriate direction.

In addition to the capabilities of a Wall, a Paddle object also has the capability to move left and right when the move method is called.  A Paddle object has a limited range of motion: if an attempt is made to move a Paddle further left or further right than the limits of its range of motion, then it will stop exactly at the left or right limit.

Your Task

Your task is to implement the WallFactory class.  This class contains static methods which create and return new Wall and Paddle objects to represent the top, left, and right walls, and the paddle object.  In order to implement these methods, you will need to implement Wall and Paddle classes, and possibly other classes, depending on how you decide to design your solution.

The Wall class must have the following methods:

public void draw(Graphics graphics)
Draw the wall in a window using the given Graphics object.

public boolean checkCollision(Ball ball)
Check whether or not the given Ball object has collided with the Wall.  If so, change the Ball's motion to deflect it.  The top wall should deflect the ball down, the left wall should deflect the ball right, etc.  The method should return true if a collision was detected, and false if the ball did not collide with the wall.

In addition to the methods of Wall, the Paddle class must contain an additional method:

public void move(int dx)
Change the horizontal position of the Paddle by the given amount, making sure that the paddle does not move beyond the limits of its range of motion.

To get started, try defining just the Wall and Paddle classes.  Implement the draw method in the wall class using the fillRect method of the Graphics class.  Implement a dummy checkCollision method in Wall that just returns false.  Finally, leave the move method in the Paddle class empty.  Implement each method in the WallFactory class by creating a new Wall or Paddle object as appropriate.  When you run the program, you should see the walls and the paddle, but the ball will pass through them.  Once you have this much of the program working, you can work towards supporting collisions and moving the paddle.

Don't forget to import the java.awt.Graphics and java.awt.Color classes in your Java source files.

Once the program compiles, you can run it by executing the command

java Bounce

in the DrJava interactions window.

Suggested Approach

Here is a suggested design:

In this design, the base class Wall has attributes (instance variables) representing the x and y coordinate and the width and height.  This allows the draw method to be fully implemented.  In addition, the base class has getter methods, and a setter method for the x-coordinate.  The setter method (setX) is needed by Paddle, which will need to be capable of changing its horizontal position.  The checkCollision method can just be a dummy implementation that returns false; each subclass will override this method.

The LeftWall, RightWall, and TopWall classes each override the checkCollision method.  For example, the checkCollision method in the LeftWall class should check to see if the ball's leftmost point has passed to the left of the wall's right edge, and if so, deflect its motion to the right.

Don't forget to change WallFactory so that it returns instances of your Wall subclasses instead of plain Wall objects where appropriate.

The Paddle class needs additional attributes to define its range of horizontal motion.  Its checkCollision method also needs to check that the ball's bottom-most point falls within the paddle's horizontal extent for a collision to occur.  The move method must ensure that the paddle does not move too far to the left or right based on its leftEdge and rightEdge attributes.

Extra Credit

You may implement the following features for extra credit:

Directional paddle
Rather than simply having the paddle deflect the ball vertically, make the new direction of the ball depend on where it makes contact with the paddle.  If the ball hits the paddle in the center, it should travel straight up.  The further away the point of contact is from the center, the more the ball should angle away from vertical.  (E.g., if the ball hits the paddle far to the left, its motion should angle significantly to the left from vertical.)  Make sure that the velocity of the ball does not change.  You will need to use some trigonometry: e.g., the Math.sin, Math.cos, and Math.sqrt static methods.

Breakout (hard)
Turn the Pong game into a Breakout game.  You can add a Brick class as a subclass of Wall.  When the ball collides with a brick, it should disappear.  Unlike the walls and paddles, Brick objects should support collisions with all four surfaces: top, bottom, left, and right.  You should make sure that bricks are at least 15 pixels high and wide.  You will need to modify the PlayingField class so that bricks are added to the array of Wall objects.

When You Are Done

Create a zip file containing all of your Java source files.  If your Java source files are in a directory called cs101-assign7 within the Home directory, then you can create a zip file as follows from a terminal window:

cd
zip -9r cs101-assign7-solution.zip cs101-assign7

Submit your zip file to the CS 101 Submission Website.

Make sure your zip file contains all of your Java source files!