CSCI 161 Homework Assignment 8 - The Long Road

Due Fri Nov 16 at 11:59pm

Introduction

For this assignment, you'll be practicing using inheritance in order to make a small graphical animation. This work will draw on skills you've developed in previous assignments.

Assignment

You will make a short animation of a number of vehicles driving down a long, straight road. An example screenshot is shown below:

(You can also download an executable jar of the demo).

To make things easier to handle, we'll be using inheritance to quickly and easily create all the different vehicles to help run this animation. You'll be making three vehicles: a Car, a Truck, and a Batmobile, as well as a Vehicle superclass to encompass them all.

Once again, be sure to download and unzip a copy of the the Homework 8 project. so that you can submit your project once completed. This project also contains some extra classes you'll be able to use to build your animation.

Remember to read all the way through the instructions carefully! I reserve the right to not answer questions that are already answered in the assignment.

For the assignment, I have broken each class you need to make into its own step following a logical order. However, you may need to go back to previous classes and modify them as new functionality is added. Figuring out how to design this interaction is part of the goal!

  1. Read the assignment

    Read all the way through the assignment carefully. Make sure you understand the big picture and what each step will accomplish. Then when you get to each step, focus on just that step, testing it until you have it right!

  2. Do step 1 carefully

    Seriously, make sure you read the assignment through!

  3. Create a LongRoad class

    The first thing you'll need to do is create a LongRoad class to give you something to work list. This class will need a Canvas object that can be used to draw the vehicles.

    • Note that I've modified the Canvas somewhat from the last assignment, in order to give you some helpful methods (like drawing a Circle without forcing it to be filled in!) and to try and reduce the "flicker" problem. Take a look at the documentation--it should be pretty clear and very similar to what you've already done. The one change you'll need to consider is that because the Canvas does force redrawing as often, you may need to call the new refresh() method once you are done drawing to make sure that all the things you drew show up!
    • You'll want to be sure to draw the "road" on the canvas!
    • You'll also need to write an animate() method to run the animation loop, similar to the loops you made for the Bouncing Ball program and the Marquee program. This method will take whatever vehicles you have created and "drive" them a certain distance each tick. It will likely help to use the wait() method at the end of the loop so that you don't animate too fast--I got good results with a wait time of 5ms.
    • Because your Vehicles will need to turn around at the end of the road, you should keep track of the road's length as a static constant that other classes can access.

    You can begin testing this class by instantiating a new LongRoad object and making sure your Canvas shows up.

  4. Create a Vehicle class

    Next, you'll need to create a new Vehicle class to represent any vehicle on the road. Vehicles should keep track of a couple of attributes: their position on the road, whether they are facing left or right (since some vehicles will turn around), and how fast they are moving (a speed of "2" works well for me).

    • Important Note #1 The Vehicle class will have a draw() method, but this method will be empty--the general Vehicle class can't be drawn, only specific kinds of vehicles!
      • Bonus: because Vehicles themselves can't be drawn, it might be cleaner to make the Vehicle class abstract. But since we won't talk about abstract classes until near the due date, it is acceptable to make Vehicle a regular class for this assignment.
    • Important Note #2: Because you'll want Vehicle's fields to be accessible to subclasses (which you'll make shortly), you can't make them private like you normally do. Instead, you'll need to make them protected, which means that they're private to everyone EXCEPT subclasses.
    • I'm specifically leaving the instructions for how to implement drive() and turn() out of this listing; you should be able to figure it out from reading the documentation and thining about similar projects you have made. But if you get stuck, ask (and ask early)!

    You should test this class by make a new Vehicle object (possibly in your LongRoad class) and then using BlueJ's inspector or System.out.println() to confirm that your fields change as expected when you call methods. Don't worry; once we make a drawable Vehicle testing will be easier!

  5. Create the Car class

    Now make a specific type of vehicle--a subclass called Car. The Car class should extend the Vehicle class. This allows it to use the same methods and fields of the Vehicle class without needing to rewrite that code. As the car drives down the road, it changes color (it's a... "char"-meleon?)

    • The Car class will need an additional field to keep track of its current color. Should this field be public, private, or protected? You can specify what color the car is when drawing it by using the Canvas's setForegroundColor() method.
      • Remember to keep track of the previous paint color (using getForegroundColor()), and reset the paint color after you're done drawing the car!
    • Remember that you can call a parent class's version of a method (including a constructor) by using super.methodName()
    • Be sure to override the Vehicle's empty draw() method to give drawing instructions to the Car.
      • Note that you'll need to draw the Car relative to its position on the road. Consider how you drew your Robot or the Bouncing Balls in previous assignments!
      • You will also need to vary your drawing based on what direction the car is facing (for example, I put a little headlight on the front of my car). Don't simply write two copies of the same draw code: avoid duplicating code as much as possible!
    • You will also need to override the Vehicle's drive() method. You'll want to call the parent class's version of drive (to do the actual movement), but then also have code that changes the car's color as it drives. A car should change color 4 or 5 times as it drives down the road. Think about at least strategy you can use to implement this before you ask for help!. Changing to a random color might be fun.

    You can test this class by making a new Car object in your LongRoad class, then making sure it drives down the road during the animation and turns around when it hits the other end.

  6. Create the Truck class

    Make a second type of vehicle--a subclass called Truck. Just like Cars, Trucks should also change color as they drive--what other class should you make Truck extend in order to reduce code repetition? Note that Trucks are slower than other Vehicles, and so should have a lower speed. Similarly Trucks are big and unwieldy, so when they get to the end of the road they don't turn around.

    • Just like with the car, you'll need to write the draw() method so that the truck can turn around. I showed the facing by what side of the truck the cab is on.
    • Since you need to modify the parent class's turning behavior, what do need to do with the turn method? What should the truck do instead? (Hint: if we want it to not turn, then when we tell it to turn it should do _ _ _ _ _ _ _).

    You should be able to test this the same way you tested the Car class. You can even test both at once!

  7. Create the Batmobile class

    Wait, you need to do something else first!

  8. Comment the ImageUtils class

    In order to draw a neat looking Batmobile, you'll want to draw an existing picture (rather than trying to make a Batmobile using drawCircle()). I have included code that will load a BufferedImage from a file; this code can be found in the ImageUtils class (along with another helpful yet eerily familiar method). However, this class currently lacks proper documentation. Add extensive comments to the ImageUtils class.

    • Remember to add a comment at the top of the class, method comments (including Javadoc tags), and inline comments explaining each line of code.
    • The syntax of this class should be familiar, though the specific classes used may be new. In order to understand how this class works, be sure to look up these new classes in the core Java documentation.

    Once you have loaded the BufferedImage from a file, you can draw it on the canvas using the drawImage() method. Note that a BufferedImage is itself an extension of "java.awt.Image"!

    Do not proceed until you have completed this step and understand what classes are used to make a BufferedImage out of a file!

  9. Create the Batmobile class

    NOW you can create the Batmobile class! This class should extend Vehicle (why not Car or Truck?). A Batmobile should be slightly faster than a normal Car. Like other vehicles, a Batmobile can drive and turn around. However, after a Batmobile turns around, it hits the rocket boosters and "zooms" for a short period of time (so that it can get away from whoever is chasing it!)

    • See the previous step for notes about drawing the Batmobile. The image of the Batmobile is included in the project file (image adapted from bagera3005 )
    • After the Batmobile turns, you'll want to increase its speed (changing speed to 7 worked well for me). However, it should only stay this speed for a short time (maybe 1/3 of the road length, or 50 calls to drive(), or thereabouts). Consider how you can add this functionality (again, come up with at least one option before you ask for help). This is a problem-solving challenge :)

    Test your Batmobile class the same way you tested your Car and Truck classes. Remember to test all of the Batmobile's functionality!

  10. Clean up your demo

    For your final submission, you should have at least one of each type of Vehicle driving down the road (just having the three vehicles will make testing easier). You can keep track of these Vehicles, no matter what subclass, by putting them in an ArrayList of Vehicles--after all, they are all Vehicles (even if they are also Cars or Trucks or Batmobiles). You can then iterate through this list and call drive() on each item inside your animation loop. This is similar to how you animated multiple Bouncing Balls, except now we're talking about multiple Vehicles (and LongRoad doesn't care that they have different subclasses).

    Test that your program animates all 3 vehicles moving at once. Make sure it runs long enough for each vehicle to turn a couple times!

  11. Make a main class to run your code

    Make a Tester class with a main method to run your code, just like in the previous assignment. This main method may need to call the LongRoad's animate method.

    • You do not need to package this code in a .jar file.
      • In fact, the image loading probably won't work (just like how the WordList broke for the HangmanGUI). However, if you look at the fixed WordList class and carefully read through the ImageIO methods, you may be able to make it work. This is NOT required
  12. Make sure your code works and is documented

    Again and again, be sure to test your code thoroughly and to document all your code. Include Javadoc comments and tags for each class and method. Include inline comments explaining how your code works--the more the better!

  13. Submit your animation!

Extensions

These extensions are not worth any extra credit, but they might be fun or interested to complete. Remember to save a working copy of your code before trying any extensions, just in case something breaks! Note also that since these involved creating new classes, you won't be able to submit them through BlueJ (but I'm happy to look at neat things you do if you want to bring it by my office or email me)!

Submitting

Once again (and again and again), before submitting, test each of your methods and classes thoroughly. Make sure your animation runs exactly as expected! When you're convinced it's ready to go, submit the project through BlueJ just like you did in the previous Assignments (selecting Hwk8 of course). Submitter will look for the files: LongRoad.java, Vehicle.java, Car.java, Truck.java, Batmobile.java, ImageUtils.java, and LongRoadTester.java [7 total!].

Grading

This assignment will be graded on roughly the following criteria:

Documentation

Documentation of all the classes in this project can be found here.