Asteroids!

Introduction

The goal for this project is to develop a version of the classic video game Asteroids. If you've never played Asteroids, we encourage you to find an on-line version to try.

Provided Code

StdDraw, GameDriver and GameConstants

All of the graphics for this application will be handled by the StdDraw library developed by Robert Sedgewick and Kevin Wayne at Princeton University. This library is not particularly powerful or full-featured but it makes it easy to develop simple graphical applications in Java.

The following driver initializes the drawing window and handles the main game loop:

GameDriver.java (DO NOT MODIFY)

It is your responsibility to develop an AsteroidsGame class that provides an "update" method that updates the state of all game elements at each time step, and a "draw" method that re-draws game elements after they have been updated. Your code will be tested using the driver above.

The file GameConstants.java contains a set of constant values such as the window size, the update rate etc. You are free to add additional constants to this file.

GameUtils, Point, Pose, Vector2D

It will be necessary to store and update the poses and velocities of game elements. The following classes will be helpful for maintaining and updating these quantities.

It should not be necessary to modify any of these classes, but you are free to do so if you wish.

Game Elements

You must provide implementations for the following game elements.

Asteroid

The Asteroids must fulfill the following requirements:

  1. Asteroids must be displayed as open circles with a radius of 30 pixels.
  2. Asteroids (and all other non-filled game elements) should be drawn using the default StdDraw pen radius of .002.
  3. The initial location of each asteroid must be generated randomly. Positions should be selected uniformly from the entire game screen.
  4. The direction of motion for each asteroid must be drawn uniformly from the interval [0, 2π).
  5. Asteroids must maintain a constant speed of one pixel per time step.
  6. The location of asteroids must "wrap" at the edges of the game screen. For example, when an asteroid departs from the left side of the screen, it must reappear in the corresponding location on the right side of the screen.
  7. Asteroids are worth 20 points when destroyed.

Saucer

Enemy saucers must fulfill the following requirements:

  1. Saucers must be displayed as open rectangles with a width of 20 pixels and a height of 10 pixels.
  2. The initial location of each saucer must be generated randomly. Positions should be selected uniformly from the entire game screen.
  3. The initial direction of motion for each saucer must be drawn uniformly from the interval [0, 2π).
  4. Saucers must maintain a constant speed of 2 pixels per time step.
  5. On each time step a saucer must select a new direction of motion with probability .05. The direction of motion must be drawn uniformly from the interval [0, 2π).
  6. The location of the saucer must not "wrap" at the edges of the game screen. Saucers must disappear permanently when they exit the screen.
  7. Saucers are worth 200 points when destroyed.

Ship

The player's ship must fulfill the following requirements.
  1. The initial pose of the ship must be at the center of the game screen pointing upward.
  2. The ship must be represented as an open isosceles triangle with a base of 10 pixels and a height of 20 pixels. You may use the GameUtils.drawPoseAsTriangle method do draw the ship to the screen.
  3. The movements of the ship should be controlled through keyboard interaction. You must use the method StdDraw.isKeyPressed to detect keyboard events.
  4. TURNING: On each time step, if the user is pressing the left arrow key (java.awt.event.KeyEvent.VK_LEFT) the ship should be turned .1 radians to the left. If the user is pressing the right arrow key java.awt.event.KeyEvent.VK_RIGHT the ship should be turned .1 radians to the right. Note that you don't need to worry about keeping heading values within the range 0 to 2π. All of the provided heading-related methods will perform correctly for values outside of this range.
  5. THRUST: On each time step, if the user is pressing the down arrow key java.awt.event.KeyEvent.VK_DOWN, a thrust of .1 pixels/time step squared must be applied. The thrust should push the ship in the direction represented by its current heading. The applyThrust method defined in the GameUtils class may be used to update the ship's velocity vector.
  6. FRICTION: The ship must slow down in the absence of thrust. On each time step the speed of the ship should be reduced to 99% of it's speed on the previous time step.
  7. The location of the ship must "wrap" at the edges of the game screen.

Bullet

  1. Bullets must be displayed as filled circles with a radius of 1.5 pixels.
  2. Bullets should be created at the current position of the ship each time the user presses the space bar. You must use the StdDraw.hasNextKeyTyped and StdDraw.nextKeyTyped methods to detect space bar presses.
  3. Bullets must move at a constant speed of 20 pixels per time step.
  4. The direction of the bullet's motion must match the heading of the ship at the time the bullet is fired.
  5. Bullets should exist for a maximum of 20 time steps.
  6. The location of bullets must "wrap" at the edges of the game screen.

Stars

  1. Stars must be displayed as closed circles with a radius of 1 pixel.
  2. The initial location of each star must be generated randomly. Positions should be selected uniformly from the entire game screen.
  3. Stars must remain stationary.

Scoreboard

The player's score must appear 60 pixels from the left edge of the game screen and 20 pixels from the top. The numeric score must be prefixed by the string "Score: ". The score must be initialized to 0.

Lives Remaining

The number of lives remaining must appear 60 pixels from the left edge of the game screen and 60 pixels from the top. The number of lives must be prefixed by the string "Lives: ". The number of lives remaining must be initialized to 3.

Game Logic

Initialization

When the game starts, the ship must be present on the game screen along with 10 asteroids, 100 stars and the two numeric displays. It is not necessary to guarantee that the the ship is safe from asteroids when the game starts. If the ship appears inside an asteroid, that's just bad luck for the player.

There must be no saucers on the initial game screen. A new saucer must be added to the game screen on each time step with a probability of .002. Note that this means there may occasionally be more than one saucer present on the game screen. Again, it is possible for saucers to appear in a location that will cause an immediate collision with the ship.

Collisions and Scoring

For the purposes of collision checking, the game elements can be divided into three categories.

It is not necessary to perform pixel-level collision detection. Instead, you should perform approximate collision detection by associating each game element with an appropriate collision radius. For the case of the circular elements (Asteroids and bullets) this should match the radius of the element. For the case of non-circular objects (Ship and Saucers) this radius should be chosen to be half the length of the longest axis of the element. For example, the ship's longest axis is 20 pixels, so the collision radius should be 10 pixels. A collision should occur whenever two objects are near enough that the circles defined by their collision radii overlap.

Whenever a collision occurs, both elements involved in the collision must be destroyed and removed from the screen. The player's score must be increased by the point value associated with the Asteroid or Saucer that was involved in the collision.

If the player's ship is destroyed, and the player has remaining lives, then a new ship should be created at the starting location.

If the player loses all three lives, then no future game updates must occur: the game screen must freeze. The Lives Remaining indicator must read 0 and the score should reflect the final collision that caused the game to end.

Any time the player manages to destroy all of the Asteroids and Saucers on the game screen, a new "level" should begin: 10 new asteroids must appear at randomly selected locations. The position of the ship and the position of the stars should not be modified.

The following video illustrates how the completed game should look:

Part A: Readiness Quiz (10%)

The readiness quiz for this assignment will focus on UML syntax. YOU MUST ANSWER ALL QUESTIONS CORRECTLY TO GET ANY CREDIT FOR THIS PART. You may take the quiz as many times as necessary.

Part B: UML (40%)

By the first deadline you must submit a UML diagram illustrating your design. For full credit, your design must make appropriate use of the object oriented features that we have been covering in class: specialization, abstract classes, interfaces, etc. Your UML should be as complete as possible. It should show the attributes of each class as well as the signatures of all public and protected methods. It should also show the relationships between your classes.

Part of your grade for this portion of the assignment will be based on using correct UML "syntax". Your UML diagram may be prepared electronically or very neatly hand-drawn and scanned. This page lists some tools for preparing UML diagrams. (I usually use UMLet to prepare UML diagrams for this course.)

You are free to brain-storm design ideas with other students in the class. The final UML diagram must be prepared and submitted individually, but you are encouraged to discuss the design with others. If you do work with another student in developing your design, you must acknowledge that assistance in your submission.

Your UML design document must include a few paragraphs describing and defending your design decisions. For full credit this document must include definitions of inheritance and polymorphism. It must explicitly point out where inheritance and polymorphism are used to prevent code duplication. It may also be appropriate to use the concepts of coupling and cohesion to justify aspects of your design.

Your UML diagram must be submitted through Canvas as a .pdf file.

No late submissions will be accepted for Part B.

Design Rubric

Design supports the required functionality 15%
Correct UML "syntax" 15%
UML is visually well organized and neatly drawn or electronically prepared. 10%
Appropriate names (Names are meaningful. Method names are verbs and instance variables and classes are nouns. Plural nouns are only used for collections.) 10%
Appropriate use of inheritance (Superclasses are used to prevent code duplication. Subclasses meaningfully extend the functionality of superclasses. Instance variables are not shadowed in subclasses.) 10%
Classes and methods are abstract where appropriate. 10%
Appropriate use of polymorphism (Using interfaces, superclasses or both.) 10%
Documentation provides a coherent defense of key design decisions. 10%
Documentation uses correct spelling, grammar etc. 10%

Part C: Code (50%)

You must submit your finished project through Web-CAT by the second deadline. Note that the Web-CAT submission tests will not be able to verify that your game elements are updated or drawn correctly or that your game logic is correct. Passing the Web-CAT tests will only mean that your code is formatted correctly and doesn't crash when it is executed. This makes it particularly important that you carefully test your code before submitting. Any submission that does not pass all of the automated tests will receive a score of 0.

Design and Implementation Suggestions

Working with Random Numbers

Miscellaneous Advice

Going Further

There are a huge number of improvements that could be introduced beyond the basic version of the game described above. Asteroids could break up on impact instead of being destroyed. Asteroids could be displayed as rock-like polygons instead of circles. Saucers could fire on the player's ship, etc.

We encourage you to experiment with as many of these improvements as you want, but the version you submit should strictly match the specification above.

Acknowledgments

This project was loosely inspired by the Asteroids project presented by Dan Leyzberg and Art Simon at the 2008 SIGCSE Nifty Assignments Session.