GUI componentsTopObject-Oriented DesignObject-Oriented Design of Frogger

Object-Oriented Design of Frogger

As we have seen above, when we design a class, we create a model of some object in the real world. The key points were that:

We also mentioned that you need to distinguish those parts of the real world that you want to model from those that you do not.

Now, recall frogger.

First, what objects appear in the frogger game?

Frog

Let's focus on the frog initially. What are the properties of a frog?

How do we represent these? With instance variables.

What are the behaviors of a frog?

How do we represent these behaviors? With methods.

Let's also think about whether we need getters and setters for our instance variables. Should we allow other classes to change the appearance of the frog? No. Should they be able to access the appearance? Probably not necessary. What about location? Again, we probably don't want any other classes to set the location arbitrarily. Instead our hop and reincarnate methods will move the frog in more controlled ways. What about setting its alive/dead status? Well, when a car hits the frog, we probably want the car to tell the frog it is dead. The frog becomes alive again when it is reincarnated. Is it useful for other classes to know if a frog is alive or not? Maybe cars should interact differently with alive and dead frogs. So, we probably do want an accessor method for the aliveness property.

Finally, we need to think about how we will construct a frog. We must give each instance variable a value. In some cases, we need information outside of the frog to determine reasonable values for those instance variables. How do we communicate that information to the frog? By passing parameters to the frog constructor. How will we initialize each instance variable?

We have now figured out a lot of pieces of the Frog class. Let's see what we have so far:

   class frog(...) -> Frog {
      def frogImage: Graphic2D (from drawableImage)
      var isAlive: Boolean is readable := true  // readable means generates method

      method hopToward (??what goes here??)-> Done{}
  
   
      method reincarnate (??what goes here??) -> -> Done {
          isAlive = true;
          anything else?
      }
       
      method kill (??what goes here??)  -> Done {
          alive = false;
          ??anything else??
      }
       

}

Questions about the design so far:

Are we done with the design of Frog? Probably not. As we think about what we need to do to implement these methods we are likely to uncover more details. But we have designed a good abstraction. Now is a good time to move on to another part of the problem.

Vehicle Class

We can go through the same exercise with the vehicle class thinking about its properties and its behaviors. What are its properties:

What are its behaviors:

What kind of thing is a vehicle? It is self-animated; it moves without requiring user input. How do we implement such things? By importing and using module "animation". How do we animate an object?

This design provides all the behavior we want except for killing the frog. How will we do that? Whenever we move the car, we should check to see if it hit the frog? How does the Vehicle know where the frog is? It doesn't. We need to communicate this information to the Vehicle. When should we tell it about the frog? The only time we interact with an animated object is when we create it, so we have to tell it about the frog then. How does that information get to the while method? We save it in an instance variable. In this case the frog instance variable is not really a property of the vehicle but it is information that the vehicle needs to know in order to give us the behavior we want. This is an example of how we need to not just understand the object in isolation but its context in the larger program to design it correctly.

LaneFiller class

Now, where do vehicles come from? They are a lot like the falling leaves that we saw. There are many of them on the screen at once. How did we create falling leaves? With a tree class. The tree class was itself an animated object that continuously generated leaves. We want the same thing here - something that will continuously generate vehicles. What is that class? A highway?

Watch the cars driving across the screen. What do you observe? They drive in lanes. Some lanes go one direction; some go the other. Different types of vehicles drive in each lane. All the vehicles in a lane go the same speed, but the vehicles in different lanes go at different speeds. In short, there are similarities among the vehicles in a lane and differences when we look at different lanes. How can we capture that? By creating a laneFiller class.

What are the properties of laneFiller?

What is its behavior?

Let's think carefully about what the parameters to the laneFiller constructor should be. Recall that we need to initialize all the instance variables. As a result, we need parameters describing:

What kind of class is laneFiller? It's another animated object. What does it do? It creates Vehicles:

    animator.while {??what???} pauseVarying{... } do {
       create a vehicle
    }
   what do we do when we are done?

How do we create a vehicle? We call its class constructor. What information does the vehicle class need? Appearance, location, speed, direction, and the frog. The laneFiller already received all of this in its constructor except for the frog. Where does it get information about the frog? It needs to be communicated to the laneFiller. How? In the class parameter. So, we need to have a Frog parameter in our laneFiller class. The frog can then be passed to the Vehicle constructor in the Lane's run method.

Handling user input

We need one more class to make our program complete. We need to handle the user input. What user input do we care about? Just mouse clicks. We call this class Frogger. Its responsibility is to get the program started and then call the appropriate methods when the user clicks the mouse. What kind of object is it? It is our familiar friend, an object that inherits graphicApplication.


GUI componentsTopObject-Oriented DesignObject-Oriented Design of Frogger