The goal for this project is to develop a version of the classic video game Asteroids. If you've never played Asteroids, I encourage you to find an on-line version to try.
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
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.
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.
Vector2D
class represents a two-dimensional
vector. Vectors of this sort may be visualized as arrows with both a
direction and a length (or magnitude). Vectors may be used in this
application to represent the velocities of game elements. It should not be necessary to modify any of these classes, but you are free to do so if you wish.
You must provide implementations for the following game elements.
The Asteroids must fulfill the following requirements:
StdDraw
pen radius of .002.
Enemy saucers must fulfill the following requirements:
GameUtils.drawPoseAsTriangle
method do draw the ship to
the screen.
StdDraw.isKeyPressed
to detect keyboard events.
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.
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.
StdDraw.hasNextKeyTyped
and
StdDraw.nextKeyTyped
methods to detect space bar
presses.
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.
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:
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 diagram must be submitted through Canvas as a .pdf file.
No late submissions will be accepted for Part A.
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.
The
class java.util.Random
should be used to generate pseudo-random numbers for this application.
The nextDouble
method returns a double selected uniformly
from the interval [0, 1).
This method can be used to generate initial poses by multiplying the
generated values by the desired upper bound for each component of the
pose.
In order to create a block that occurs with a particular probability,
you can compare the output of nextDouble
to the desired
probability. For example:
if (generator.nextDouble() < .75) { // This block will execute with probability .75. }
StdDraw
library documentation as well as the
other provided classes.
When game elements are destroyed, you will probably want to remove
them from the collection(s) where they are stored. Unfortunately,
modifying Java collections during iteration can lead to problems. For
example, the following code will will result in a ConcurrentModificationException
:
ArrayList<String> words = new ArrayList<>(); words.add("tree"); words.add("car"); words.add("house"); // Attempt to remove "tree" from the list. for (String word : words) { if (word.equals("tree")) { words.remove(word); // Throws exception! } }
Iterators may be used to safely remove objects. The following code works correctly.
ArrayList<String> words = new ArrayList<>(); words.add("tree"); words.add("car"); words.add("house"); Iterator<String> it = words.iterator(); // Remove "tree" from the list. while (it.hasNext()) { String current = it.next(); if (current.equals("tree")) { it.remove(); // Safely removes the most recent item. } }
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.
I encourage you to experiment with as many of these improvements as you want, but the version you submit should strictly match the specification above.