CSC111 Lab10 Solution 1

From dftwiki3
Jump to: navigation, search

--D. Thiebaut 15:12, 9 April 2010 (UTC)


# carLab10.py
# D. Thiebaut
# A solution program for the first part of Lab 10.  The goal 
# is to create a list of car objects constructed from the Car
# class.  The Car class is made of a rectangular body, two
# wheels, a door, and a windshield.
# The cars are given a random direction (which cannot be
# 0) and move in that direction until all the cars have escaped
# the graphics window.
# This program uses Zelle's graphics library. 

from graphics import *
import random

W = 400   # width of the graphics window
H = 400   # height of the graphics window

#----------------------------------------------------------------
class Wheel:
    """A class with two concentric circles"""

    def __init__( self, center, r1, r2 ):
        """constructor"""
        self.radius1 = min( r1, r2 )
        self.radius2 = max( r1, r2 )
        self.circ1 = Circle( center, self.radius1 )
        self.circ2 = Circle( center, self.radius2 )
        
    def draw( self, win ):
        """draws the wheel on the graphics window win"""
        self.circ2.draw( win )
        self.circ1.draw( win )

    def move( self, dx, dy ):
        self.circ1.move( dx, dy )
        self.circ2.move( dx, dy )

    def setFill( self, color1, color2 ):
        self.circ1.setFill( color1 )
        self.circ2.setFill( color2 )

    def getRadius1( self ):
        """returns the smallest radius"""
        return self.radius1

    def getRadius2( self ):
        """returns the largest radius"""
        return self.radius2

#----------------------------------------------------------------
class Car:
    def __init__( self, P1, P2, dx ):
        """constructor.  Receives top-left and bottom-right point, and speed"""
        #--- create additional points needed for the car ---
        pp1 = Point( min( P1.getX(), P2.getX() ), min( P1.getY(), P2.getY() ) )
        pp2 = Point( max( P1.getX(), P2.getX() ), max( P1.getY(), P2.getY() ) )
        pp3 = Point( (pp1.getX()+pp2.getX())/2,  pp1.getY() )
        pp4 = Point( pp3.getX(), pp1.getY()-30 )
        pp5 = Point( (pp1.getX()+pp2.getX())/3, pp1.getY() )
        pp6 = Point( (pp1.getX()+pp2.getX())*2/3, pp1.getY() )

        #--- define the body ---
        self.body = Rectangle( pp1, pp2 )
        P1 = pp1
        P2 = pp2
         
        #--- the wheels ---
        w =abs( P2.getX()-P1.getX() )
        h =abs( P2.getY()-P1.getY() )
        center1 = Point( w/4+P1.getX(), P2.getY() )
        center2 = Point( P2.getX()-w/4, P2.getY() )
        r2      = w/8
        r1      = r2/2
        self.w1 = Wheel( center1, r1, r2 )
        self.w2 = Wheel( center2, r1, r2 )
        
        #--- adjust speed if equal to 0 ---
        if dx==0: dx = 2
        self.dx     = dx

        #--- put windshield in direction of motion ---
        if dx < 0:
            self.shield = Polygon( pp1, pp3, pp4 )
        else:
            self.shield = Polygon( Point( pp2.getX(), pp1.getY() ), pp3, pp4 )

        #--- create door ---
        self.door   = Rectangle( pp5, center2 )


    def setFill( self, bodyc, tirec, insidec ):
        """set the color of the body, and tires"""
        self.body.setFill( bodyc )
        self.shield.setFill( "lightblue" ) # windshield color fixed
        self.door.setFill( bodyc )
        self.w1.setFill( tirec, insidec )
        self.w2.setFill( tirec, insidec )

    def draw( self, win ):
        """draw all the parts, in the right order so that wheel overlap everything"""
        self.body.draw( win )
        self.door.draw( win )
        self.shield.draw( win )
        self.w1.draw( win )
        self.w2.draw( win )

    def move( self ):
        """move the car by its own speed"""
        self.body.move( self.dx, 0 )
        self.shield.move( self.dx, 0 )
        self.door.move( self.dx, 0 )
        self.w1.move( self.dx, 0 )
        self.w2.move( self.dx, 0 )

    def IsOutside(self, W, H):
        """returns True if car is outside the window defined by W and H"""

        #--- get leftmost and rightmost points ---
        P1 = self.body.getP1()
        P2 = self.body.getP2()
        leftX = P1.getX()
        rightX = P2.getX()

        #--- are they out? ---
        if leftX > W or rightX < 0:
            return True
        return False

#----------------------------------------------------------------
def waitForClick( win, message ):
    """ waitForClick: stops the GUI and displays a message.  
    Returns when the user clicks the window. The message is erased."""

    # wait for user to click mouse to start
    startMsg = Text( Point( win.getWidth()/2, win.getHeight()/2 ), message )
    startMsg.draw( win )    # display message
    win.getMouse()          # wait
    startMsg.undraw()       # erase


#----------------------------------------------------------------
def main():
    """demo program for a list of moving cars"""
    global W, H
    win = GraphWin( "wheel demo", W, H )
    waitForClick( win, "click to start" )

    #--- build a list of cars ---
    List = []
    for i in range( 3 ):
        car = Car( Point( 120, 60+i*50 ), Point( 20, 20+i*50 ), 3-random.randrange( 6 ) ) 
        car.setFill( "red", "yellow", "black" )
        car.draw( win )
        List.append( car )

    waitForClick( win, "click to move" )

    #--- move the cars ---
    while True:
        #--- as we move the cars, count the number of outside cars ---
        outsideCount = 0
        for car in List:
            car.move( 3, 0 )
            if car.IsOutside(W, H):
                outsideCount += 1

        #--- if they are all outside, we quit ---
        if outsideCount >= len(List):
            break

    waitForClick( win, "click to end" )

main()