# Moving smiley program to illustrate objects and how they can interact. # Claude Anderson. June 16, 2007 # Modified Nov 5, 2009 ''' description: This module illustrates how to define a class (the Smiley class) to generate custom objects. The Smiley class has a constructor, several instance variables and methods. The smiley_world module imports and uses this module to illustrate how objects are generated and interact with each other. @author: Claude Anderson, created on June 16, 2007. Modified by many others. ''' from zellegraphics import Point, Circle, Line import math #---------------------------------------------------------------------- # Auxiliary functions which are not part of the Smiley class #---------------------------------------------------------------------- def translate(point, dx, dy): 'return a Point that is a translation of point by deltas dx and dy' return Point(point.getX()+dx, point.getY()+dy) def distance (point1, point2): 'return the distance between point1 and point2' return math.sqrt((point1.getX() - point2.getX())**2 + (point1.getY() - point2.getY())**2) #---------------------------------------------------------------------- # We add a Smiley Class definition here. #---------------------------------------------------------------------- class Smiley: ''' A Smiley is a smiley-face object that is capable of moving. ''' # Constructor def __init__ (self, initX, initY, dx, dy, size=40, color='red', isSmiling=True): ''' The constructor of this class (and every Python class) is the __init__ function. The first parameter of the constructor (and any method) is self. self refers to the object in question, in this case the object being constructed. An object of type Smiley is instantiated by calling the Smiley() function, without the self parameter. This is an implicit parameter. Although there is no Smiley() function or method defined in this class, calling the Smiley() invokes the real constructor __init__() for this class. __init__ is never invoked directly. INSTANCE VARIABLES: - centerPoint: center of this smiley - dx, dy, amount the smiley moves each step - size: radius of this smiley - isSmiling, isMoving: booleans indicating current dynamic state. - parts: a list of all of the drawable parts. -- leftEye, etc.: the individual drawable parts ''' self.centerPoint = Point(initX, initY) self.dx = dx self.dy = dy self.size = size self.isSmiling = isSmiling self.moving = True self.color = color # now initialize drawable components: self.head = Circle(Point(initX, initY), size); self.head.setFill(color) self.head.setWidth(3) self.leftEye = Circle(translate(self.centerPoint, -size/4, -size/3), size/8) self.rightEye = Circle(translate(self.centerPoint, size/4, -size/3), size/8) self.smileBase = Line(translate(self.centerPoint, -size/4, size/2), translate(self.centerPoint, size/4, size/2)) # initialize the "corners of the mouth" in smile position self.smileLeft = Line(translate(self.centerPoint, -size/4, size/4), translate(self.centerPoint, -size/4, size/2)) self.smileRight = Line(translate(self.centerPoint, size/4, size/4), translate(self.centerPoint, size/4, size/2)) if not isSmiling: # move them to frown position. self.smileLeft.move(0, size/4) self.smileRight.move(0, size/4) # Collect all drawable parts into a list. self.parts = [self.head, self.leftEye, self.rightEye, self.smileBase, self.smileLeft, self.smileRight, self.centerPoint] #---------------------------------------------------------------------- # TODO: 2. add several methods to the Smiley class definition here. # 1. draw() # 2. move() # 3. smile() # 4. frown() # NOTE: each method must take a self parameter, even though you do not # explicitly supply one when you invoke the method. The way self gets # interpreted is follows. The self parameter applies to the object that # invokes its method. Say for example, we construct and object called # smiley1 and smiley1 invokes its draw method like this: # smiley1.draw(win). Notice that self is not passed as a parameter to # the draw method. Instead, self applies to smiley1. That assignment # takes place implicitly. It's like saying I am smiley1 and you asked me # to invoke my draw method, using the given window. #---------------------------------------------------------------------- def draw(self, win): pass def move(self): pass def smile(self): pass def frown(self): pass #---------------------------------------------------------------------- # In order to run the rest of the scenarios (scenes 2, 3, and 4 in # smiley_world), we need to implement and use the # following methods. #---------------------------------------------------------------------- def stop(self): 'Stop moving.' self.moving = False def isMoving(self): 'Is this object moving?' return self.moving def collidedWith (self, otherSmiley): 'Has this smiley collided with that other one?' return distance(self.centerPoint, otherSmiley.centerPoint) < self.size + otherSmiley.size