Download presentation
Presentation is loading. Please wait.
Published byMaria Holland Modified over 9 years ago
1
Python Programming in Context Chapter 13
2
Objectives To write an event driven program To understand and write callback functions To practice with lists of objects To see another pattern for using inheritance To learn about static variables
3
Event Driven Programming Events are placed on a queue While the queue is not empty – Take an event off of the queue – Execute a callback function for that event
4
Figure 13.1
5
Listing 13.1 class EventHandler: def __init__(self): self.queue = [] self.eventKeeper = {} def addEvent(self,eventName): self.queue.append(eventName) def registerCallback(self,event,func): self.eventKeeper[event] = func def run(self): while(True): if len(self.queue) > 0: nextEvent = self.queue.pop(0) self.eventKeeper[nextEvent]() else: print('queue is empty')
6
Multithreading the Event Loop Multiple things can happen at the same time Import Thread from the threading module Define a class that inherits from Thread Implement a run method that will be executed when the thread is started
7
Figure 13.2
8
Listing 13.2 from threading import Thread import time class EventHandler(Thread): def __init__(self): super().__init__() self.queue = [] self.eventKeeper = {} def addEvent(self,eventName): self.queue.append(eventName) def registerCallback(self,event,func): self.eventKeeper[event] = func def run(self): while(True): if len(self.queue) > 0: nextEvent = self.queue.pop(0) callBack = self.eventKeeper[nextEvent] callBack() else: time.sleep(1)
9
Etch-A-Sketch Create a simple event controlled drawing program Model after the Etch-A-Sketch drawing toy Use arrow keys to control a drawing turtle Event controlled since the turtle will only move when a key event occurs
10
Listing 13.3 (Part 1) import turtle class Etch: def __init__(self): self.myT = turtle.Turtle() self.myScreen = turtle.Screen() self.myT.color('blue') self.myT.pensize(2) self.myT.speed(0) self.distance = 5 self.turn = 10 self.myScreen.onkey(self.fwd,"Up") self.myScreen.onkey(self.bkwd,"Down") self.myScreen.onkey(self.left,"Left") self.myScreen.onkey(self.right,"Right") self.myScreen.onkey(self.quit,"q") self.myScreen.listen()
11
Listing 13.3 (Part 2) def fwd(self): self.myT.forward(self.distance) def bkwd(self): self.myT.backward(self.distance) def left(self): self.myT.left(self.turn) def right(self): self.myT.right(self.turn) def quit(self): self.myScreen.bye() def main(self): turtle.mainloop()
12
Redesign Etch-A-Sketch Use Inheritance Class Etch is-a Turtle
13
Listing 13.4 (Part 1) from turtle import Turtle, mainloop class Etch(Turtle): def __init__(self): super().__init__() self.screen = self.getscreen() self.color('blue') self.pensize(2) self.speed(0) self.distance = 5 self.turn = 10 self.screen.onkey(self.fwd,"Up") self.screen.onkey(self.bkwd,"Down") self.screen.onkey(self.left5,"Left") self.screen.onkey(self.right5,"Right") self.screen.onkey(self.quit,"q") self.screen.listen() self.main()
14
Listing 13.4 (Part 2) def fwd(self): self.forward(self.distance) def bkwd(self): self.backward(self.distance) def left5(self): self.left(self.turn) def right5(self): self.right(self.turn) def quit(self): self.screen.bye() def main(self): mainloop() if __name__ == '__main__': etch = Etch()
15
Placing Turtles Use onclick method Place a turtle where the click occurs onclick is a method of the Screen
16
Listing 13.5 (Part 1) from turtle import Turtle, mainloop import random class TurtlePlace: def __init__(self,maxTurtles,hWall=200,vWall=200): self.bigT = Turtle() self.bigTscreen = self.bigT.getscreen() self.bigT.shape('turtle') self.turtleList = [] self.bigTscreen.onclick(self.placeTurtle) self.bigT.hideturtle() self.numTurtles = 0 self.maxTurtles = maxTurtles self.hWall = hWall self.vWall = vWall self.drawField(hWall,vWall) mainloop() def placeTurtle(self,x,y): newT = Turtle()
17
Listing 13.5 (Part 2) newTscreen = newT.getscreen() newTscreen.tracer(0) newT.up() newT.goto(x,y) newT.shape('turtle') newT.setheading(random.randint(1,359)) newTscreen.tracer(1) self.numTurtles = self.numTurtles + 1 self.turtleList.append(newT) if self.numTurtles >= self.maxTurtles: self.bigTscreen.onclick(None) def drawField(self,hWall,vWall): self.bigTscreen.tracer(0) self.bigT.up() self.bigT.goto(-hWall,-vWall) self.bigT.down() for i in range(4): self.bigT.forward(2*hWall) self.bigT.left(90) self.bigTscreen.tracer(1)
18
Animate the Turtles Move the turtles If they hit a wall, turn them around and “bounce” them in the other direction
19
Listing 13.6 (Part 1) class AnimatedTurtle(Turtle): def __init__(self,hWall,vWall): super().__init__() self.scr = self.getscreen() self.xmin = -vWall self.xmax = vWall self.ymin = -hWall self.yMax = hWall self.scr.ontimer(self.__moveOneStep,100) def __moveOneStep(self): self.__computeNewHeading() self.forward(5)
20
Listing 13.6 (Part 2) self.scr.ontimer(self.__moveOneStep,100) def __computeNewHeading(self): xpos,ypos = self.position() oldHead = self.heading() newHead = oldHead if xpos > 190 or xpos < -190: newHead = 180-oldHead if ypos > 190 or ypos < -190: newHead = 360-oldHead if newHead != oldHead: self.setheading(newHead)
21
Listing 13.7 def placeTurtle(self,x,y): newT = AnimatedTurtle(self.hWall,self.vWall) newTscreen = newT.getscreen() newTscreen.tracer(0) newT.up() newT.goto(x,y) newT.shape('turtle') newT.setheading(random.randint(1,359)) newTscreen.tracer(1) self.numTurtles = self.numTurtles + 1 self.turtleList.append(newT) if self.numTurtles >= self.maxTurtles: self.bigTscreen.onclick(None)
22
Collisions If two turtles “collide”, bounce them off one another Need to have a list of all the turtles. List must be available to all other turtles Need it to be Static – One instance, belongs to the class, not an instance – All objects share it
23
Using a Static Variable ClassName.methodname AnimatedTurtle.allTurtles.append(self)
24
Listing 13.8 (Part 1) class AnimatedTurtle(Turtle): allTurtles = [] def __init__(self,hWall,vWall): super().__init__() self.scr = self.getscreen() self.xmin = -vWall+10 self.xmax = vWall-10 self.ymin = -hWall+10 self.ymax = hWall-10 self.scr.ontimer(self.__moveOneStep,100) AnimatedTurtle.allTurtles.append(self) def __moveOneStep(self): self.__computeNewHeading() self.forward(5) self.__checkCollisions() self.scr.ontimer(self.__moveOneStep,100) def __computeNewHeading(self):
25
Listing 13.8 (Part 2) xpos,ypos = self.position() oldHead = self.heading() newHead = oldHead if xpos > self.xmax or xpos < self.xmin: newHead = 180-oldHead if ypos > self.ymax or ypos < self.ymin: newHead = 360-oldHead if newHead != oldHead: self.setheading(newHead) def __checkCollisions(self): for otherT in AnimatedTurtle.allTurtles: if self != otherT: if self.distance(otherT) < 20: tempHeading = self.heading() self.setheading(otherT.heading()) otherT.setheading(tempHeading) while self.distance(otherT) < 20: self.forward(1) otherT.forward(1)
26
Simple Video Game Modeled after space invaders Aliens Laser Cannon, Bombs Aiming the Cannon Bomb moves in the direction it was fired Need to know when a bomb collides with an alien
27
Figure 13.3
28
Figure 13.4
29
Listing 13.9 class LaserCannon(Turtle): def __init__(self,xmin,xmax,ymin,ymax): super().__init__() self.screen = self.getscreen() self.screen.bgcolor('light green') self.screen.setworldcoordinates(xmin,ymin,xmax,ymax) self.screen.onclick(self.aim,1) self.screen.onkey(self.shoot,"s") self.screen.onkey(self.quit,'q') def aim(self,x,y): heading = self.towards(x,y) self.setheading(heading) def shoot(self): Bomb(self.heading(),5) def quit(self): self.screen.bye()
30
Listing 13.10 class BoundedTurtle(Turtle): def __init__(self, speed, xmin=-200,xmax=200,ymin=0,ymax=400): super().__init__() self.xmin = xmin self.xmax = xmax self.ymin = ymin self.ymax = ymax self.speed = speed def outOfBounds(self): xpos,ypos = self.position() out = False if xpos self.xmax: out = True if ypos self.ymax: out = True return out def move(self): self.forward(self.speed) if self.outOfBounds(): self.remove() else: self.getscreen().ontimer(self.move,200) def remove(self): self.hideturtle()
31
Listing 13.11 class Alien(BoundedTurtle): alienList = [] @staticmethod def getAliens(): return [x for x in Alien.alienList if x.alive] def __init__(self,speed,xmin,xmax,ymin,ymax): super().__init__(speed,xmin,xmax,ymin,ymax) self.getscreen().tracer(0) self.up() if 'PurpleAlien.gif' not in self.getscreen().getshapes(): self.getscreen().addshape('PurpleAlien.gif') self.shape('PurpleAlien.gif') self.goto(random.randint(xmin-1,xmax-1),ymax-20) self.setheading(random.randint(250,290)) self.getscreen().tracer(1) Alien.alientList = [x for x in Alien.alienList if x.alive] Alien.alienList.append(self) self.alive = True self.getscreen().ontimer(self.move,200) def remove(self): self.alive = False self.hideturtle()
32
Listing 13.12 (Part 1) class Bomb(BoundedTurtle): def __init__(self, initHeading,speed): super().__init__(speed) self.initHeading = initHeading self.resizemode('user') self.color('red','red') self.shape('circle') self.setheading(initHeading) self.up() self.turtlesize(.25) self.getscreen().ontimer(self.move,100) def move(self): exploded = False self.forward(self.speed) for i in Alien.getAliens():
33
Listing 13.12 (Part 2) if self.distance(i) < 5: i.remove() exploded = True if self.outOfBounds() or exploded: self.remove() else: self.getscreen().ontimer(self.move,100) def distance(self,other): p1 = self.position() p2 = other.position() a = p1[0]-p2[0] b = p1[1]-p2[1] dist = math.sqrt(a**2 + b**2) return dist
34
Listing 13.13 class AlienInvaders: def __init__(self,xmin,xmax,ymin,ymax): super().__init__() self.xmin = xmin self.xmax = xmax self.ymin = ymin self.ymax = ymax def play(self): self.mainWin = LaserCannon(self.xmin,self.xmax,self.ymin,self.ymax).getscreen() self.mainWin.ontimer(self.addAlien,1000) self.mainWin.listen() mainloop() def addAlien(self): if len(Alien.getAliens()) < 7: Alien(1,self.xmin,self.xmax,self.ymin,self.ymax) self.mainWin.ontimer(self.addAlien,1000)
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.