CS 149: Introduction to Programming
James Madison University, Spring 2018 Semester

Lab21: Simulation of mutable objects

Background

Object-oriented programming changes the view of a program as a series of steps to an interaction between objects. You design the objects by specifying what they should look like (attributes) and what behaviors they should have (methods). Your program will control how those objects interact in the "world" (which in the case of Greenfoot, is just another object).

Objectives

Part 1 - Create a scenario

Last time, we took our first look at game design with Greenfoot. Today we will create a new simulation from scratch.

  1. Run Greenfoot (from the Linux menu) and select "Scenario > New Java Scenario..." (from the Greenfoot menu). Name your scenario Lab21 (under your CS149 directory).

  2. Right-click the "MyWorld" rectangle on the right, and select "Delete". We'll create a different World in the next step.

  3. Right-click the "World" rectangle on the right, and select "New subclass..." Name the subclass Road and select a suitable image from the "backgrounds" category.

  4. Right-click the "Actor" rectangle on the right, and select "New subclass..." Name the subclass Car and select a suitable image from the "transport" category.

  5. Press the Reset button, and then add a new Car() to the world. After placing the car, select "Controls > Save the World" from the menu. If that menu is disabled, try running and resetting the program.

When you click "Save the World", a new editor window should open with Road.java. Saving the world automatically creates (or edits) the prepare method which is invoked by the constructor.

Part 2 - Basic Car methods

  1. Double-click the Car rectangle (on the right) to open Car.java. Write the code for the following steps above the act() method.

  2. Create three private variables within the class: an integer that holds the car's year, a string that holds the car's make, and an integer that holds the car's speed.

  3. Create a constructor that accepts the model year and make, and sets the speed to 0. Make the constructor's parameters the same names as the private attributes, and use the this keyword when assigning the values.

  4. Create a toString() method that accepts no parameters and returns a string in the format "A %d %s that is going %d mph".

    1. Do NOT print anything in the method (no System.out). It should only create and return the string.

    2. String.format() operates just like printf(). You should use this method to create the string.

  5. Compile your Car class and correct any errors. You may want to ask a TA to check over your code.

  6. At this point, you should have a compiler error in your Road.java file. Fix this error by providing info about your car.

The compiler error (should have) happened when you added a constructor that required parameters. When there is no constructor, Java automatically generates a default constructor (without parameters) that does nothing.

Part 3 - Test your Car

  1. Create a second car object of your choice in the Road.prepare() method using the year and make of your "dream" car.

  2. Go back to Car.java and add the following line at the top:

    import javax.swing.JOptionPane;
    
  3. Add the following code to the Car.act() method:

    // handle mouse click events
    if (Greenfoot.mouseClicked(this)) {
        JOptionPane.showMessageDialog(null, this.toString());
    }
    

    Remember, you can press Ctrl+Shift+I to fix the indenting of your code.

  4. From the main screen, compile the project and click "Run". Then click on each car and see what happens.

Part 4 - Go cars, go!

  1. Pause or reset the simulation before writing new code. Right-click one of the car objects, and see what methods are in the context menu.
  2. For this lab, you do NOT have to write documentation comments for each method. But double check that you have written your name and today's date in both files.

  3. Create accessor methods that let you access each individual attribute of the Car. They should be named with "get" followed by the name of the attribute. So one of your accessor methods would be getSpeed(). Each accessor should take no parameters and return the value of that attribute.

  4. Create two mutator methods, accelerate() and brake(). These methods take no parameters and return no values. When called, the accelerate() method should increase the speed variable by 1 mile per hour. The brake() method should decrease the speed variable by 1 mile per hour.

  5. Add the following code to the Car.act() method:

    // update speed and move the car
    if (Greenfoot.isKeyDown("up")) {
        accelerate();
    }
    if (Greenfoot.isKeyDown("down")) {
        brake();
    }
    move(speed);
    
  6. Compile and run the simulation, then click on a car while it's moving. You may need to adjust the simulation speed slider at the bottom.

Part 5 - Stop cars, stop!

  1. Add a private boolean named crash to the Car class. Set this variable to false in the constructor.

  2. In the act method, surround the "update speed and move the car" code with a decision that checks if the car has not crashed.

  3. After the line move(speed); (i.e., just before the closing brace of the if block) add the following code:

    // check if the car has crashed
    Actor other = getOneIntersectingObject(Car.class);
    if (other != null) {
        crash = true;
    }
    
  4. Test your code by moving and rotating your cars so that they will collide. If everything is correct, they should stop.

  5. Add sound effects to your project! Download a wav or mp3 file to your scenario/sounds directory. (Not all files are supported; if one doesn't work, try another one.) Then add the following example code where applicable:

    Greenfoot.playSound("crash.wav");
    

At some point, you should try running your scenario with "lots" of cars. Don't forget to save the world! :) Submit your Car.java and Road.java files via Canvas by the end of the day. Make sure you wrote your name and today's date in the Javadoc comments of both source files.