CS 111 f21 — Advanced Objects

1 Practice

1.1 Give a definition for the following words in the context of Python classes1

  • Class
  • Instance
  • Instance Variables
  • Methods
  • Constructor

1.2 Extend Point class so we can add two points together2

2 Alien Clicker game

# Alien Clicker game, requires pgl.py
# demonstrates class inheritance, static variables, and handling animation and mouse actions with pgl
# (c) 2020 Aaron Bauer, Carleton College

from pgl import GImage, GWindow, GRect
import random

class Alien(GImage): # inherit from the GImage class
    population = 0

    def __init__(self, gw, x, y):
        # first thing we should do is construct the GImage (the superclass)
        super().__init__("alien-small.png", x, y) # call the GImage constructor
        self.xvel = 1
        self.yvel = 1
        self.gw = gw # each instance needs to keep track of the graphics window to refer to in other methods
        gw.add(self) # add this instance to the window
        Alien.population += 1 # increment our static variable

    def get_speed_factor(self):
        # use our static variable to return a multiplier for the velocity
        # Aliens move faster the fewer there are
        if Alien.population > 10:
            return 1
        if Alien.population > 5:
            return 1.5
        if Alien.population > 2:
            return 2
        if Alien.population > 1:
            return 4
        return 8

    def update(self):
        # move this instance
        self.move(self.xvel * self.get_speed_factor(), self.yvel * self.get_speed_factor())

        # bounce off window edges
        if self.x < 0 or self.x > self.gw.getWidth() - self.getWidth():
            self.xvel *= -1
        if self.y < 0 or self.y > self.gw.getHeight() - self.getHeight():
            self.yvel *= -1

    def mousedown_action(self, objects):
        # when an Alien is clicked on, remove it and decrement the population
        self.gw.remove(self)
        objects.remove(self)
        Alien.population -= 1


if __name__ == "__main__":
    # create the window and use a GRect to provide a black background
    gw = GWindow(600, 800)
    background = GRect(0, 0, 600, 800)
    background.setFilled(True)
    background.setFillColor("black")
    gw.add(background)

    # keep a list of the moving objects so we can call their update method
    objects = []
    def update():
        for obj in objects:
            obj.update()
    gw.setInterval(update, 10) # call the update function every 10 milliseconds

    # define a function for what to do when the user presses the mouse button
    def mousedown_action(e):
        elem = gw.getElementAt(e.getX(), e.getY()) # get the element at the location of the mouse
        if elem != None: # if there is an element there (i.e., getElementAt did not return None)
            print("mouse down on", elem)
            if hasattr(elem, "mousedown_action"): # if this element has a mousedown_action method, call it
                elem.mousedown_action(objects)
            else: # otherwise, create a new Alien (i.e., clicks on the background will create new Aliens)
                objects.append(Alien(gw, random.randint(0, 500), random.randint(0, 700)))

    # the GWindow object can associate functions with mouse actions
    # in this case, we tell it to call mousedown_action every time the user presses the mouse button
    gw.addEventListener("mousedown", mousedown_action)

Footnotes:

1
  • Class: the definition of an object, including its functions (methods) and data (instance variables)
  • Instance: a specific object in memory. A program might have many instances of the Point class (i.e., many Point objects), each with their own data (i.e., values for x and y)
  • Instance Variables: a piece of data associated with a particular instance. A class will define what instance variables exist for objects of that class, and all instances will have their own versions of those variables
  • Methods: a function associated with a class/object
  • Constructor: the __init__ method that assigns initial values to instance variables
2
# 2D point class with an x and y
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return str((self.x, self.y))

    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

p = Point(2, 3)
q = Point(-1, 10)
print(p + q)  # should print (1, 13)
print(p)      # p shold be unchanged, and this should print (2, 3)
print(q)      # same for q, should print (-1, 10)