/
Python Programming in Context Python Programming in Context

Python Programming in Context - PowerPoint Presentation

okelly
okelly . @okelly
Follow
342 views
Uploaded On 2022-06-15

Python Programming in Context - PPT Presentation

Chapter 13 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 ID: 918787

turtle def listing init def turtle init listing ymax xmax xmin screen ymin getscreen class newt hwall vwall part

Share:

Link:

Embed:

Download Presentation from below link

Download Presentation The PPT/PDF document "Python Programming in Context" is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.


Presentation Transcript

Slide1

Python Programming in Context

Chapter

13

Slide2

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

Slide3

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

Slide4

Figure 13.1

Slide5

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')

Slide6

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

Slide7

Figure 13.2

Slide8

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)

Slide9

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

Slide10

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

()

Slide11

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

()

Slide12

Redesign Etch-A-Sketch

Use Inheritance

Class Etch is-a Turtle

Slide13

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

()

Slide14

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()

Slide15

Placing Turtles

Use

onclick

method

Place a turtle where the click occurs

onclick

is a method of the Screen

Slide16

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()

Slide17

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)

Slide18

Animate the Turtles

Move the turtles

If they hit a wall, turn them around and “bounce” them in the other direction

Slide19

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)

Slide20

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

)

Slide21

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

)

Slide22

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

Slide23

Using a Static Variable

ClassName.methodname

AnimatedTurtle.allTurtles.append

(self

)

Slide24

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

):

Slide25

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)

Slide26

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

Slide27

Figure 13.3

Slide28

Figure 13.4

Slide29

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

()

Slide30

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.xmin

or

xpos

>

self.xmax

:

out = True

if

ypos

<

self.ymin

or

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

()

Slide31

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

()

Slide32

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

():

Slide33

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

Slide34

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)