Computer Science 120
Introduction to Programming

Spring 2011, Siena College

Lab 8: Games
Due: 4:00 PM, Monday, May 2, 2011

For our last lab, you will get to develop one or more video games. Everyone should complete the "Follow the Barking Dog" program. The other is a simplified Frogger game or a video game of your choice (past projects have included Space Invaders, Pac Man, Tetris, and Minesweeper) and are optional. Should you complete one or more extra programs, your score on that program may be used to replace your grade on a previous lab assignment.

To help you get started, we have provided a file containing starter BlueJ projects for the programs.

Follow the Barking Dog

This program, found in the SaintShellGame folder of the starter, is a variation on the "three card monty" or shell game. You are presented with three Siena Saint Bernards. The one in the center barks when clicked, while the other two always remain silent. The challenge is that the dogs will get "shuffled" each time the mouse is clicked outside of any dog.

This program does not seem to be able to be placed in a browser applet, so instead, here is a BlueJ project of the working demo.

You are given the code that draws the dogs on the screen initially and which loads the sound file that will play when the barking dog is clicked. Your tasks are to implement the shuffling and the scoring.

Your program should be divided into two classes: the SaintShellGame window controller class and the Mover active object class that performs the shuffling. The SaintShellGame class creates the three dogs and handles the mouse interaction. The Mover moves the three dogs, as illustrated in our demo. It selects two dogs and gradually moves each of them from its original location to the opposite dog's location. Once those two dogs are repositioned, it randomly selects two new dogs and moves them again, repeating this process perhaps 10 or 20 times before stopping. While it is more natural to describe the shuffler as randomly picking two dogs to move, you may find it is easier to write the required code if you instead think of the shuffler as randomly picking one dog that it won't move and then moving the two that were not picked. The SaintShellGame class should prevent anything from happening if the user clicks while a Mover is shuffling the dogs. In other words, the window controller should not test whether you click on the correct dog or create a second Mover if a Mover is currently running.

You may wish to start by just moving the dogs horizontally until the shuffling works. The up-and-down motion makes the game more entertaining, but it can be added after the rest of the program is working. The motions of the dogs in the demo look like smooth curves, but they actually move in straight lines.

We provide you with a Siena-appropriate dog picture a barking noise noise in the starter folder, but feel free to shuffle your choice of animals, basketballs, or anything else. (Suggestion: you may find it useful to make the correct dog look different while testing your program.)

If the code for your Mover's run method begins to get complicated, remember that you can define additional methods in your class to perform common operations and then invoke these methods from run.

Frogger

The first optional/extra credit program you may choose to implement is the popular 1980's video game called Frogger.

A working solution for this program will appear below. Click inside the applet to interact with it.



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).

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 by a car or truck.

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 in the area below the lanes of the highway.

Frogger Overview

There are three important classes 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 that go on the road. (There are also some graphical objects on the screen to represent the lane markings on the highway, but we will not discuss these in detail as they are easily constructed. (In fact, the code that draws the highway markings is provided in the starter folder.)

The Frog

The frog will be displayed on the screen by creating a VisibleImage using an image file we will provide. The Frog class will need an instance variable to keep track of this VisibleImage.

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. Remember, only WindowController objects can call getImage. Thus, get the image in the Frogger class and pass it to the Frog constructor as we suggest.

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 (i.e., a point). Depending on which side of the frog the point is, 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 modern medicine, the frog can come back to life. Add a method reincarnate which moves the frog back to its starting point. 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 Vehicles

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, the distance the vehicle should travel before disappearing, and the DrawingCanvas. 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. Thus, you must define the method

public void run() { ... }

The while loop inside run should:

  1. Save the current time. (Get the current time by calling System.currentTimeMillis()).
  2. pause for (at least) 30 milliseconds.
  3. Determine how long it actually paused for (e.g., subtract the time saved earlier from the current time) and move the appropriate distance. (Remember your equation from physics: rate * time = distance.) You need to do this to ensure smooth motion of your vehicles. With so many active objects, the computer cannot ensure that the length of pauses will be very precise.
  4. Find out if the vehicle squished the frog and kill the frog with the kill method if it did.

You may assume that all vehicle velocities will be positive. That is, your highway may be a one-way street. You are free 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 Lane

The purpose of the Lane object is to continuously 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. This is similar to the way in which the Cloud objects were active objects that created FallingSnow objects in the FallingSnow example from lecture. We recommend refreshing your memory by looking at the code for that example while preparing your Lane class.

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 Frogger class should pick a random speed for each of the lanes and pass it in to the Lane constructor. We have found speeds in the range .033 to .133 pixels/millisecond to be good (though you may want to start with a slower set of speeds while you debug your program).

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.

Recall from above that 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? Since 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. Since 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. The pause should never be so long that it leaves more than about four car lengths between vehicles.

For simplicity, you may use a fixed value for the pause time when you first write your program, but eventually the pause time should be selected randomly. That is, the gaps between successive cars should not be the same, but should be distributed randomly with the constraint that there is at least one car length and no more than 4 car lengths between successive cars in the same lane. To do this, your code will have to use the speed with which vehicles travel and their lengths in pixels to compute the minimum and maximum amount of time you should pause between generating new cars.

The Image Files

There is an image file, names froggy.gif, 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 and are named:

jeep_left.gif

oldcar_left.gif taxi_left.gif van_left.gif
jeep_right.gif oldcar_right.gif taxi_right.gif van_right.gif

It is fine if you only use a single image file so that all your vehicles look the same and move in the same direction. Using multiple pictures is a feature that we hope you add (it does make the display look better), but it is not required.

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 introduced a much taller vehicle, for example.

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 serve 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 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.

Suggested Procedure

There are many ways of proceeding with this lab. Here is one suggested ordering:

  1. Read the begin method in Frogger.java to understand how we have drawn the highway background for you.
  2. Write the Frog class except for the kill and reincarnate methods.
  3. Modify the Frogger class to create the frog on the screen, and write onMousePress to control the movements of the frog. Make sure that the frog hops around appropriately.
  4. Write the Vehicle class.
  5. Test the Vehicle class by having the begin method in the Frogger class put one car on the road. (You do not want the code here in the end, but for now it lets you test the Vehicle class before you have written the Lane class.) Move the frog into the road to see if it gets killed by the car. Add code to reincarnate the frog and test it.
  6. Write the constructor of Lane. Move the code that creates a car from the Frogger class to the run method of the Lane class so that a lane generates a stream of cars on the lane. Make sure they do not bump into each other (they should not as they are all going the same speed). Make sure that the frog gets killed if hit by any of the cars (though our cars will be hit-and-run - they do not stop!).

Advanced Features

You may notice that the sample version of Frogger we have provided has more features than we have required. Vehicles move in both directions and several different images are used to represent vehicles. Feel free to incorporate these or any other extensions in your program. Only do so, however, after completing the construction of a program that meets the basic requirements.

Submitting Your Work

Before 4:00 PM, Monday, May 2, 2011, submit your Java program for grading. There are three things you need to do to complete the submission: (i) place a copy of your program(s) into your csis120/hw folder under hw10, (ii) print a copy of your program(s) and hand it (them) to your lab instructor, and (iii) demonstrate the execution of your program(s) for your instructor.

Grading Sheet

The required program for this lab (Follow the Barking Dog) is worth 25 points, which are distributed as follows:

> FeatureValueScore
Style, Design, and Efficiency
Appropriate comments 4
Good variable names and declaration types 3
Appropriate formatting 1
Good overall design 4
Correctness
Scores awareded and displayed properly 2
Correct dog barks when clicked, others do not 1
Shuffle at appropriate time 1
Next shuffle does not start during previous shuffle 2
Pairs chosen randomly to move 3
Motion of dogs animated correctly 2
Motion of dogs animated simultaneously 2
Extra Credit
Total 25