CSC111 Lab 11 2018

From dftwiki3
Revision as of 10:57, 15 April 2018 by Thiebaut (talk | contribs) (Creating a second derived class: CarWithTop)
Jump to: navigation, search

D. Thiebaut (talk) 10:44, 15 April 2018 (EDT)


Problem 1: Class Inheritance in a Graphic Context


GenericCar1.png


GenericCar Class


This class will be our super class. Create a new program called genericCar.py with the code below:

# genericCar.py
# Your name here
#
# A module containing the definition for a graphic car with
# a rectangular body and two wheels.
from graphics import *
from random import *

class GenericCar:
    """Definition for a car with a body and two wheels"""

    def __init__(self, win, topLeft, width, height ):
        """constructs a car made of 1 rectangle with top-left
        point topLeft, dimension width x height, and two wheels
        away from left and right by 10 pixesl"""
        # save width and height of car
        self.width = width
        self.height = height
        
        # create bottom-right point
        x1 = topLeft.getX()
        y1 = topLeft.getY()
        P2 = Point( x1+width, y1+height )

        # body is a rectangle between topLeft and P2
        self.body = Rectangle( topLeft, P2 )
        self.body.setFill( "yellow" )

        # create wheel #1
        center1 = Point( x1+20, y1+height )
        self.wheel1 = Circle( center1, 20 )
        self.wheel1.setFill( "black" )

        # create wheel #2
        center2 = Point( x1+width-20, y1+height )
        self.wheel2 = Circle( center2, 20 )
        self.wheel2.setFill( "black" )

        # create random speed
        self.dx = randrange( -3, 3 )

        # save window width (so that a car can detect
        # that it's going outside the left or right
        # margins)
        self.windowWidth = win.getWidth()

    def setSpeed( self, sp ):
        '''sets the horizontal speed to sp.  Positive values will make
        the car go to the right.  Negative, to the left.'''
        self.dx = sp
        
    def setFill( self, color ):
        '''sets the color of the body of the car'''
        self.body.setFill( color )
        
    def draw( self, win ):
        """draw the car on the window"""
        self.body.draw( win )
        self.wheel1.draw( win )
        self.wheel2.draw( win )
            
    def move( self ):
        """move the body and wheels of the car by dx"""
        self.body.move( self.dx, 0 )
        self.wheel1.move( self.dx, 0 )
        self.wheel2.move( self.dx, 0 )


Main Module


Create another Python program called manyCars.py that will import the GenericCar module, and create a generic car:

# manyCars.py
# A program that use a generic car instantiated from
# the GenericCar class.

from genericCar import *
from graphics import *
WIDTH  = 700
HEIGHT = 500

def main():
    # open a graphic window
    win = GraphWin( "Cars Cars Cars", WIDTH, HEIGHT )

    # create a generic car, draw it, set its speed
    # and set its color to blue
    car = GenericCar( win, Point( 100, 100 ), 200, 50 )
    car.draw( win )
    car.setSpeed( -1.5 )
    car.setFill( "blue" )

    # keep on moving the car until the user clicks the mouse
    while win.checkMouse()==None:
        car.move( )

    # close the graphic window        
    win.close()

main()


  • Save your files in the same directory.
  • Run manyCars.py. Make sure your blue car moves out of the window. If your car is too fast, change the speed to 0.15.
  • Create a second generic car, at a different location in the window, with a different color and a positive speed.
  • Make sure your program still runs correctly.


Creating A Derived Class: TaxiClass


A taxi is a car with special features. In our case, its color will always be yellow (even if the user tries to change it to something else,) and it has the word T A X I printed on its side.

  • Edit the genericCar.py program, and add the following definition, at the bottom (below the GenericCar class):


class Taxi( GenericCar ):
   '''A class derived from the GenericCar class, with
   a yellow body, and the word "TAXI" on the side of its
   body.'''
   def __init__( self, win, topLeft, width, height ):
      super().__init__( win, topLeft, width, height )
      x = (self.body.getP1().getX() + self.body.getP2().getX() )//2
      y = (self.body.getP1().getY() + self.body.getP2().getY() )//2
      self.label = Text( Point( x, y ), "T A X I" )

Draw method

  • Add a draw() method to your taxi. It will call the draw() method of the super class (see how __init__() calls the __init__() constructor of the super class, and do the same for draw(). Your draw() method needs to call draw() of the super class to draw the body and wheels, and it needs to draw the self.label.
  • Save genericCar.py after your edit is done.
  • Modify manyCars.py and add a taxi object, instantiated from your new Taxi class. Mirror what you did with your first two cars, creating the taxi, setting its color to, say, "lightblue", drawing the taxi, and moving the taxi.
  • Run manyCars.py, and observe that some things are not quite working well...

Move method

  • You will have noticed that the default move method from the GenericClass needs to be overloaded, because it does more the car and the wheels, but not the "TAXI" label. Create a new move() method for your Taxi:


   def move( self ):
      super().move()
      self.label.move( self.dx, 0 )
  • Run manyCars.py again, and verify that your label now moves with the car.

setFill method

  • Make sure your manyCars.py program sets the color of your taxi to some color other than yellow. You will have noticed that your taxi gets painted that color, and not the default yellow we'd like for all our taxis. So you need to overload the setFill() method of Taxi so that it sets the color to "yellow," no matter what color the main program tries to set.
  • You may also set the color of the taxi in the constructor, to be safe.
  • Run manyCars.py again, and verify that your taxi now is yellow and that its label move with the body.


Creating a second derived class: CarWithTop


Using the same approach you did when you created your Taxi class, create a new class derived from GenericCar, and call it CarWithTop. This class will be used to create cars that have GenericCar as a super class, but that sport a top (see the pink car in the image at the top of this page).

  • Go ahead and create the class CarWithTop, with
  • a constructor
  • whatever other methods are required for the car to move nicely across the graphic window.
  • Add a new object of type CarWithTop to your manyCars.py module.
  • Verify that all cars are moving smoothly across the graphic window.







<showafterdate after="201800420 12:00" before="20180601 00:00">

Solution Programs


genericCar.py


from graphics import *
from random import *

class GenericCar:
    """Definition for a car with a body and two wheels"""

    def __init__(self, win, topLeft, width, height ):
        """constructs a car made of 1 rectangle with top-left
        point topLeft, dimension width x height, and two wheels
        away from left and right by 10 pixesl"""
        # save width and height of car
        self.width = width
        self.height = height
        
        # create bottom-right point
        x1 = topLeft.getX()
        y1 = topLeft.getY()
        P2 = Point( x1+width, y1+height )

        # body is a rectangle between topLeft and P2
        self.body = Rectangle( topLeft, P2 )
        self.body.setFill( "yellow" )

        # create wheel #1
        center1 = Point( x1+20, y1+height )
        self.wheel1 = Circle( center1, 20 )
        self.wheel1.setFill( "black" )

        # create wheel #2
        center2 = Point( x1+width-20, y1+height )
        self.wheel2 = Circle( center2, 20 )
        self.wheel2.setFill( "black" )

        # create random speed
        self.dx = randrange( -3, 3 )

        # save window width (so that a car can detect
        # that it's going outside the left or right
        # margins)
        self.windowWidth = win.getWidth()

    def setSpeed( self, speed ):
        self.dx = speed
        
    def setFill( self, color ):
        '''sets the color of the body of the car'''
        self.body.setFill( color )
        
    def draw( self, win ):
        """draw the car on the window"""
        self.body.draw( win )
        self.wheel1.draw( win )
        self.wheel2.draw( win )
            
    def move( self ):
        """move the body and wheels of the car by dx"""
        self.body.move( self.dx, 0 )
        self.wheel1.move( self.dx, 0 )
        self.wheel2.move( self.dx, 0 )

class Taxi( GenericCar ):
   '''A class derived from the GenericCar class, with
   a yellow body, and the word "TAXI" on the side of its
   body.'''
   def __init__( self, win, topLeft, width, height ):
      super().__init__( win, topLeft, width, height )
      x = (self.body.getP1().getX() + self.body.getP2().getX() )//2
      y = (self.body.getP1().getY() + self.body.getP2().getY() )//2
      self.label = Text( Point( x, y ), "T A X I" )

   def draw( self, win ):
     super().draw( win )
     self.label.draw( win )

   def move( self ):
      super().move()
      self.label.move( self.dx, 0 )
      

   def setFill( self, color ):
     return

   
class CarWithTop( GenericCar ):
   def __init__(self, win, topLeft, width, height ):
     super().__init__( win, topLeft, width, height )
     x1 = topLeft.getX()+20
     y1 = topLeft.getY()
     x2 = topLeft.getX()+self.width-20
     y2 = topLeft.getY()-30
     self.top = Rectangle( Point( x1, y1 ), Point( x2, y2 ) )
     
   def draw( self, win ):
     super().draw( win )
     self.top.draw( win )

   def setFill( self, color ):
     super().setFill( color )
     self.top.setFill( color )

   def move( self ):
     super().move()
     self.top.move( self.dx, 0 )

manyCars.py


# ManyCars.py
# A program that uses many different classes
# of cars, inherited from the GenericCar super
# class.
from genericCar import *
from graphics import *
WIDTH  = 700
HEIGHT = 500
def main():
    # open a graphic window
    win = GraphWin( "Cars Cars Cars", WIDTH, HEIGHT )

    # create a generic car, draw it, set its speed
    # and set its color to blue
    car = GenericCar( win, Point( 100, 100 ), 200, 50 )
    car.draw( win )
    car.setSpeed( -1.5 )
    car.setFill( "blue" )

    taxi = Taxi(  win, Point( 150, 200 ), 200, 50 )
    taxi.draw( win )
    taxi.setSpeed( 1.5 )
    taxi.setFill( "lightblue" )
    # keep on moving the car until the user clicks the mouse
    
    while win.checkMouse()==None:
        car.move( )
        taxi.move( )
        
    # close the graphic window        
    win.close()

main()


</showafterdate>