Assignment 11: Snipe
Fall 2007, David Matuszek

Purposes of this assignment:

General idea of the assignment:

Implement a simple game based on the Bouncing Ball animation. You can use this code as a starting point for your game.

You are in control of a single ball on the screen. Your job is to manuver your ball to hit every other ball on the screen in as short a time as possible.

To simplify the description, several numbers are specified below--the size of the window, the number, sizes and speeds of the balls, etc. In all cases, those numbers should be defined constants (final variables), so that they can be changed simply by changing the value of the constant in one place and recompiling. Start with these numbers, but you can adjust them to improve game play if you like.

The playing field (a JPanel) should be about 500 by 500 pixels. Balls should be about 20 pixels in diameter.

At the start of the game, your ball (which is black) is stationary in the center of the playing field. Seven other balls, of varying colors (but not black or white), are moving randomly about the playing field. You manuver your ball so as to collide with each of the other balls. When you collide with a ball, it stops moving and remains in place. When all the balls (except yours) are stationary, the game is over.

While you play, the elapsed time is displayed in the top right corner of the playing field. When the game ends, the elapsed time stops advancing, so that you can read how well you did. Shorter times are better.

Details:

The animation will proceed at a rate of 20 frames/second.

Each ball (except yours) starts in a random location on the screen, and moves with a random velocity. The velocity is determined by two quantities: deltaX, which is the amount to add to the x position for each new frame, and deltaY, which is the amount to add to the y position for each new frame. The values deltaX and deltaY are randomly chosen integers between -5 and +5, inclusive, except that at least one of them must be nonzero.

Your black ball starts in the center of the screen, with deltaX = deltaY = 0. You control the ball by hitting keys which increment or decrement deltaX and deltaY, as follows:

w or i   Subtract 1 from deltaY
a or j   Subtract 1 from deltaX
s or k   Add 1 to deltaY
d or l   Add 1 to deltaX

By hitting the same key repeatedly, you can increase the speed of your ball up to a maximum speed of 20 pixels/frame (or -20).

All balls (yours included) bounce when they hit the "walls" (the borders of the window). When a vertical wall is hit, the  sign of deltaX changes; when a horizontal wall is hit, the sign of deltaY changes.

Your ball and another ball "collide" when the distance between their (x, y) positions is less than or equal to the ball diameter. When this happens, your ball is unaffected, but the other ball stops moving (its deltaX and deltaY values are set to zero), and it is considered to be "dead."

Other balls do not collide with one another. They can pass through one another without any effect. Only test for collisions with your black ball.

Display the elapsed time in the top right corner of the playing field, and update it every time you display a new frame (20 times a second). Balls can pass through the time display with no effect--but you should display the time after displaying all the balls, so that if a ball is stopped in that location, the time is drawn over the ball, rather than being obscured by the ball.

Put four buttons at the bottom of the screen:

Use the MVC design pattern. Name your main class Snipe, and have (at least) three other classes, called Model, View, and Controller. (You should have at least a Ball class as well.)

Starting the game should start a Timer to perform a TimerTask every 1/20 of a second. The TimerTask should call the Model to update the positions of all the balls and the elapsed time. When the model is finished and all changes have been made, it should notify its observers. (Don't notify observers after every little change!) The View is an Observer which calls repaint() to display the balls and the elapsed time on the screen.

Do something to indicate the end of a game, rather than just have the program stop. This doesn't have to be anything fancy, but it's discouraging when the computer doesn't appear to even notice when the player has finished. (If you want to show off your finished game to others, a display of the best scores so far, and who made them, adds a lot of appeal to your game--but that's not a requirement.)

You may write this game as either an application or as an applet. Your choice. Remember that applets cannot do file I/O, so applets can't save scores when you are done playing.

There will be methods in your Model class that deserve JUnit testing. All methods should be properly commented.

Due date:

Friday, December 7,  before midnight. Turn in your program electronically, using Blackboard. (See my Instructions for Using Zip Files and Blackboard). Only assignments submitted via Blackboard will be accepted--do not send your program by email. My TAs and myself will get together for grading a few days after the assignment is due; after that that grading session, no more late programs will be accepted.