In this program assignment, you will implement classes for a very minimalist version of the classic video game called Asteroids. While the requirements for this assignment are very basic, you also have the freedom to adapt or expand on the basic ideas presented here in many ways if you would like to customize the game.

Example Asteroids screen

Note: For simplicity, we will not be implementing the full physics of the original Asteroids game. Instead, we will use a simplified physics approach that is much simpler to program. If you're interested in comparing your result here to the original, there are several playable versions of Asteroids available on-line, including this one.

In the variant of Asteroids you will implement, there are only three kinds of objects: your ship, the bullets your ship fires, and the asteroids. All of these objects move in straight lines, although you can steer your ship and control its speed.

Your task is to write the four main classes: Ship, Bullet, Asteroid, and Space. You may write additional classes to structure your solution if you desire. Hint: consider consolidating common features of classes into one or more superclasses of your own design.

Unlike earlier assignments, here we will use a world with a cell size of 1 pixel by 1 pixel. In Greenfoot, actors by default have a size determined by their image, so the actors in this program will be much larger than a single cell. Actor locations--that is, cell coordinates--will be in pixel sizes here. Actors are drawn so that their image is centered on their location. Also, the getIntersectingObjects() method takes into account the Actor's physical size, not just its location, so it works as you would expect for actors that are larger than a single cell in size.

The Space Class

The Space class represents the world for your game. It must provide two constructors: a constructor that takes a width and a height, and a default constructor. Both constructors should ensure that the world is created with a cell size of 1 pixel square. For the default constructor, you pick your own default world size--you might start with a size like 500x500 pixels, and then adjust the size larger or smaller so that it looks good on your screen.

For the Space image, you can use the backgrounds/space1.jpg image provided in Greenfoot's image library, or you can import another image from a file to customize the look of your game (use the "Import from file..." button when setting the image, and provide a PNG, JPG, or GIF image that you have found on the web or created yourself--even a photo will work).

Finally, your Space class should provide a method called populate() method that creates one ship in the center of the world facing north, and creates 5 randomly placed asteroids, each of which has a random speed between 1-5, and a random orientation from 0-359. Write your default constructor so that it calls populate() to set up the world in a ready-to-play configuration.

The Asteroid Class

The Asteroid class represents the "hazard" in your game. It is simply a rock floating through space. This class must provide a constructor that takes two integer parameters: a speed (in pixels per turn), and a rotation (in degrees).

The Asteroid class should provide a method called getSpeed() that returns the asteroid's speed. Note that the Actor class already provides a getter and setter for the object's rotation.

For the Asteroid image, you can download and import the image below, or you can import another image from a file to customize the look of your game:

rock.gif

The behavior of an Asteroid is simple: it moves ahead on each call to act() the distance specified by its first constructor parameter (its speed). Remember that the Actor class provides a move(int) method that moves a specified distance forward in the direction the actor is currently facing.

There is one extra twist to moving an asteroid--if, after moving the asteroid forward, it is located on any edge of the world, it should "wrap around" to the other side. In other words, if after moving, the asteroid ends up on the northern edge of space, it should be transported to the corresponding spot on the southern edge, as if it flew off the top edge and re-entered the world on the bottom edge. Implement the same processing for the left/right edges of the world as well.

Finally, if the asteroid collides with a ship or bullet, both the asteroid and the ship should be removed from the world (but asteroids harmlessly pass through each other :-)).

The Bullet Class

The Bullet class represents the shots your ship fires at the asteroids. It is simply a projectile flying through space. This class must provide a constructor that takes two integer parameters: a speed (in pixels per turn), and a rotation (in degrees).

The Bullet class should provide a method called getSpeed() that returns the bullet's speed. Note that the Actor class already provides a getter and setter for the object's rotation.

For the Bullet image, you can download and import the image below, or you can import another image from a file to customize the look of your game:

bullet.png <-- It's a really small red streak right there!

The behavior of a Bullet is simple: it moves ahead on each call to act() the distance specified by its first constructor parameter (its speed). When a bullet reaches the edge of the world, it is removed from the world--bullets do not "wrap around" like asteroids do. Also, if the bullet collides with an asteroid, both should be removed from the world.

The Ship Class

The Ship class represents your ship in space. Unlike the other objects, it is steerable using an on-screen thumbstick (on an Android device) or the keyboard (on a PC). Like the other objects, it has both a speed and a rotation. It must provide a getSpeed() method to get its current speed, but can use the existing getter and setter for rotation that it inherits from the Actor class.

The Ship class must provide a default constructor: a ship always starts with a speed of zero, facing directly north (a rotation of -90 degrees).

Movement of the ship is just like for asteroids, with "wrap around" at the borders of the world.

Unlike the other actors, however, the ship is controlled by your actions. The thumbstick, or directional pad (D-pad), allows you to use your finger to touch on the north, south, east, or west sides of a thumb control on-screen. On your PC's keyboard, you can use the arrow keys, or the W/A/S/D keys, which Greenfoot4Sofia treats the same way as the on-screen D-pad on an Android device.

Implement the following methods in your Ship class to respond to D-pad actions:

Implement your ship so that it turns (rotates) 5 degrees left or right if the west or east side of the D-pad is down. Your ship should also speed up by 1 (accelerate) if the north side is pressed, or slow down by 1 (decelerate) if the south side is pressed. Be sure not to allow your ship's speed to become negative.

Finally, to shoot, your ship must create a new Bullet. For simplicity, create the bullet at the same location as the ship, with the same rotation as the ship, and a speed of 10. Do this if the user taps/touches the screen (or, on a PC, clicks the mouse). Screen touches cause the following method to be invoked (if it exists):

For the Ship image, you can download and import the image below, or you can import another image from a file to customize the look of your game:

rocket.png

All program assignments are submitted to Web-CAT. Use the Controls->Submit... menu command to submit your work.

After you complete the requirements described above and are happy with your Web-CAT submission, you may wish to add other features to your solution. There are many ways you can do this. Here are some possibilities you might want to think about: