CoSc 200 Laboratory #7
It's not Easy Being Green
Objective: To gain experience with loops and concurrency.
For this lab, we would like you to write a program that plays the game Frogger. In this game, you control a frog that is trying to cross a busy 4-lane highway. Each lane has cars or trucks zooming by. The vehicles in a given lane all travel at the same speed, but vehicles in different lanes may travel at different speeds (and even in different directions if you would like). The user is in control of a frog. Clicking in front of the frog moves it forward one hop (one hop is the width of a lane of traffic), clicking behind moves it back, and similarly for clicking to the left and right of it. The goal is for the user to get the frog across the highway without it getting squished.
If the frog does get squished it should display an "OUCH!" message at the bottom of the screen. The user should be able to restart the frog from its original starting position by clicking the mouse once in the area below the lanes of the highway.
To start click on this link to download the Frogger starter. This is a 'zip' file containing several 'java' and 'gif' files. Once you have downloaded this file, you must double click on it from within Windows Explorer or My Computer to extract the individual files. If your computer does not have a tool to unzip zip files, you can also download the files one at a time by going to the following folder.
Here is a demo version.
Read this entire handout before doing anything else. In this handout we will begin by describing the classes you need to implement. After we describe the classes, we will outline one plan for proceeding with your implementation.
As you learned in the pushball, stars, and boxball labs, the key to good object design is the design of classes to represent the objects in your program. There are three different kinds of objects involved in the Frogger game. There is the frog, there are the lanes of traffic (four of them), and there are the vehicles which go on the road. (There are also some graphical objects on the screen to represent the lane markings on the highway, but we won't discuss these in detail as they are easily constructed. In fact, we have provided in the starter folder the code that draws the highway markings.)
The constructor for a Frog should create the VisibleImage and place it just below the lowest lane of the highway, approximately halfway from each end. Your constructor will require several parameters: the Image of the frog, the location where the frog should start, how wide a lane is (so the frog knows how far to hop), and the canvas.
The frog clearly needs to be able to hop in each of the four directions in response to a user click. We suggest writing a single method hopToward that takes a Location parameter (e.g., point). Depending on which side of the frog the point is on, the frog should move in the appropriate direction. To keep the testing required to determine how the frog should jump simple, we suggest you divide the space around the frog as shown in the diagram below.
Unfortunately, the other thing that happens to a frog is that it gets splattered on the road. A vehicle will be responsible for determining whether it has killed a frog. To do so, it will need to ask the frog if any part of the Frog's body overlaps the VisibleImage displayed to represent the vehicle. To make this possible, your Frog class should include the definition of an overlaps method that takes a VisibleImage as a parameter and returns a boolean.
If a vehicle hits the frog, it kills the frog by calling a kill method on the frog. This causes an "OUCH!" message to appear at the bottom of the screen.
Finally, through the miracles of medicine, we'd like our frog to be able to come back to life. Add a method reincarnate which moves the frog back to its starting point and shows the image. Of course, you should not reincarnate a frog unless it is dead. So, include a boolean instance variable that keeps track of the condition of the frog (alive or dead), and check this variable in reincarnate. As described above, the user will reincarnate the frog by clicking the mouse below the highway. The Frog class should include an isAlive accessor method that returns a boolean to enable the onMousePress method to determine whether the frog should hop or possibly be reincarnated.
The constructor for a vehicle will need parameters specifying where the vehicle should be located (two doubles or a single Location parameter), the Image used to display the vehicle on the screen, the velocity with which the vehicle should move, and the distance the vehicle should travel before disappearing. In order to check if the vehicle runs over the frog, you also need to pass the frog as a parameter to the Vehicle constructor.
Vehicle extends ActiveObject. This means you must define the method public void run(){...}. The while loop inside run should:
You may start by assuming that all vehicle velocities will be positive. That is, your highway may be a one-way street. However, by the time you finish, we would like you to add the ability to handle vehicles with negative velocities so that you can have some lanes where traffic goes from left to right and others where traffic moves from right to left.
The purpose of an object of the Lane class is to constantly generate the vehicles that travel in a particular lane on your highway. As such, the lane does not actually correspond to any drawing on the screen. Instead, a Lane will be an ActiveObject that creates Vehicles.
The constructor for a Lane is quite simple. The lane was already drawn as part of the background in our window controller so we do not need to update the display. One thing we know is that all the traffic in a lane should drive at the same speed so that cars do not run into each other. The lane should pick a random speed for all its cars to use. We have found speeds in the range .033 to .133 pixels/millisecond to be good. (That's approximately 1 pixel/30 milliseconds to 4 pixels/30 milliseconds.)
A lane's main responsibility is to periodically place a new car on the screen. It will do this inside the run method. In the while loop of the run method, the lane should generate a car, wait a while to allow a gap between cars, generate another car, and so on.
As you recall from above, the Vehicle constructor requires a lot of parameters: its starting location, its image, etc. So far all the lane knows is how fast the cars drive. Where will Lane get this other information? The car should be located at one end of the lane initially and should drive until it reaches the other end. If the lane knew where it was located, it could pass this information on to the car. Its location is relative to the entire highway. Our window controller can provide this information to the lane when it constructs it so that the lane can pass the information on to the vehicle.
What about the image? It turns out that the image can only be loaded from the window controller, so this information must also be passed down to the Vehicle by passing it to the Lane constructor. The Lane constructor remembers the image of the cars for its lane and passes this image to the Vehicle constructor. (Because of this limitation, it is simplest for all the cars in a lane to have the same image.)
Finally, the vehicle needs to know about the frog so it can tell if it hit the frog. Again, our window controller created the frog. It can pass the frog to the Lane in its constructor. The lane can remember the frog so that it can tell the vehicles about the frog in the Vehicle constructor call.
After generating one vehicle, the lane should pause for some time. The pause should be at least long enough so that there will be a one car-length gap between pairs of vehicles. You need to answer the question: if a vehicle is moving with a certain velocity, how long must it move before it's a full vehicle-length away from its original location? The pause should never be so long that it leaves more than about five car lengths between vehicles. For starters, make the separation a constant, say 3 car lengths. Eventually, we hope that you will allow the user to dynamically set this separation factor with a Swing Component, such as the combo box in the example (although any other Component will be acceptable).
There is an image file for the frog. We provide 8 images of vehicles. They show 4 different types of vehicles. For each type of vehicle there is an image of that vehicle facing right and another facing left. The image files are included in the starter folder. They all have extensions ".gif." You should eventually use two or more image files so that all your vehicles look the same and move in the same direction.
The frog is 83 pixels wide and 48 pixels tall. The widest vehicle is 139 pixels wide. The tallest vehicle is 66 pixels tall. This information should help you figure out how to place the vehicles and frog within the lanes. Remember to use constants effectively so that you would not need to change many values if we introduce a much taller vehicle for example.
For the last two correctness points, add GUI components and/or key listener that will allow the user to change some aspect of the game. The demo has (1) a combo box that sets the separation between cars in each lane, (2) a slider to set the size of the frog, and (3) a key listener so that the user can move the frog with the arrow keys and reincarnate a dead frog with the space bar. You only need to add two of these three or some other components. Be creative!
The "starter" folder contains several files intended to hold Java code. The file Frogger.java should be used to write the extension of the WindowController that will server as your "main program". The Frog.java file should be used to hold your code for the Frog class, Lane.java will hold the code for the Lane class, and Vehicle.java will hold the code for the Vehicle class. The Frogger.java file contains code that draws the highway background and markings for you. All the files contain skeletons of code which you will need to complete.
There are many ways of proceeding with this lab. Here is one suggested ordering:
| Value | Feature |
| Style and Design | |
| 2 |
Descriptive comments. |
| 2 |
Appropriate names, constants, scope, and formatting. |
| 2 |
Good use of boolean expressions. |
| 2 |
Parameters used appropriately. |
| 1 |
Uses efficient code. |
| Correctness | |
| 1 |
Frog moves correctly on clicks |
| 1 |
Vehicles move with a constant velocity within a lane |
| 1 |
Vehicles appear and disappear gradually at each end of lane |
| 1 |
Vehicles kill frog appropriately |
| 1 |
Frog says "ouch" when killed |
| 1 |
Frog reincarnated properly |
| 1 |
Vehicles spaced appropriately in lane |
1 |
At least two different vehicle images used |
1 |
Vehicles move in both directions |
1 |
GUI component or key listener controls some aspect of the game |
1 |
A different GUI component controls some aspect of the game |
As with previous lab assignments, you should submit your ".java" files through Blackboard. This time you will probably have four files to submit. You can either add these files separately before you submit, or you can first zip together these files into a single ".zip" file and submit this single ".zip" file.
Submission Deadline: 3:00pm on Tuesday, February 21. Note that once you submit, it is impossible to submit a revision.
Resubmission and Late Submission Deadline: 3:00pm on Tuesday, March 7. A 5 point penalty will be assessed for a resubmission or late submission.
May the power of green be with you!