Assignment 5: Feeding Frenzy
Goals: Design a game.
Instructions
Tuesday May 27th, 9:00pm
Introduction
In this assignment, you’ll design and develop a simple version of the game Feeding Frenzy. In this game, you start off as a small fish in a pond of smaller and larger fish, and to survive you must eat the smaller fish while avoiding being eaten by the larger ones. Move your fish with the arrow keys. You win when you are larger than all the other fish in the pond.
As always, you may only use techniques that have been covered in lectures so far in your solutions. To implement this game, you will need to complete the following tasks:
Design one or more classes to represent the player fish and the background fish. Design a representation of a collection of fish.
Design a class that extends World.
Render the world state as a WorldScene by implementing the makeScene method in the class that extends World.
Allow the player fish to move with the arrow keys. It should be able to move up, down, left or right.
Correctly handle fish movement. Both the player fish and the background fish loop around, so when they exit from one side they re-enter the screen on the other. Background fish can enter the scene from the right or the left.
Determine when the player fish can eat another fish.
Determine when the player has been eaten by another fish.
Make the player fish grow based on how many fish it has eaten (and how big they are).
New background fish should be added to the list periodically with a random y-position and a random direction. You may decide how often this happens, but it should not make the game too easy or too difficult.
End the game when the player is the largest fish in the pond or has been eaten.
Display an end scene which shows if the player has won or lost.
Include a README.txt file with directions for playing the game. Include descriptions of any extra credit features you implemented (see below for ideas.
Be sure to test your game’s behavior thoroughly.
Add inertia: Once you let go of an arrow key, the player fish should not stop immediately, but should drift along until it slows to a halt.
Add more inertia: The bigger the player gets, the harder it should become to accelerate the fish...and also to stop!
Keep score: eating bigger fish is worth more than eating several little fish.
Add size snacks: eating these can make the player’s size grow immediately.
Add speed snacks: eating these can give the player a speed boost.
Add multiple lives.
If you decide to implement any extra features, make sure to document them well. Remember – you will be graded for your program design, not making a cool video game. So whatever you add, make sure it’s well-designed. But have fun with it, too! Add information about any extra features you implement to your README file.
5.1 The javalib library
The javalib library provides the support for the design of interactive games and creating images composed by combining geometric shapes as well as image files. See The Image Library for more information.
To use the library, download the javalib file above and add it to your project the same way you have added the tester library.
At the top of the .java file where the library is used, add the following import statements:
import tester.*; // The tester library import javalib.worldimages.*; // images, like RectangleImage or OverlayImages import javalib.funworld.*; // the abstract World class and the big-bang library import java.awt.Color; // general colors (as triples of red,green,blue values) // and predefined colors (Red, Green, Yellow, Blue, Black, White)
5.2 A note about randomness
There are two ways to generate random numbers in Java. The easiest is to use Math.random(), which generates a double between 0 (inclusive) and 1 (exclusive). You can multiply this number by some integer to make it bigger, then coerce to an int to produce a random integer in the range you wish. However, this is not easily testable: you’ll get different random values every time.
The better way to generate random numbers is: First, import java.util.Random at the top of your file. Next, create a new Random() object, and use its nextInt(int maxVal) method, which will give you a random integer between zero (inclusive) and maxVal (exclusive).
This is known as a "pseudorandom number generator", since the numbers aren’t really random if they can be reliably repeated...
One of them, to be used for testing, should take in a Random object whose seed value you specify. This way your game will be utterly predictable every single time you test it.
The second constructor should not take in a Random object, but should call the other constructor, and pass along a really random object:
import java.util.Random; class YourWorld { Random rand // The constructor for use in "real" games YourWorld() { this(new Random()); } // The constructor for use in testing, with a specified Random object YourWorld(Random rand) { this.rand = rand; ... } } Now, your tests can be predictable while your game can still be random, and the rest of your code doesn’t need to change at all.