import random, math
class Dot(object):
def __init__(self, cx, cy, r):
self.cx = cx
self.cy = cy
self.r = r
self.color = random.choice(["hotPink", "green2",
"purple", "dodgerBlue"])
self.direction = random.choice([(0, 1), (0, -1),
(1, 0), (-1, 0)])
self.speed = 5
def moveDot(self):
dx, dy = self.direction
self.cx, self.cy = (self.cx + dx*self.speed,
self.cy + dy*self.speed)
def isCollisionWithWall(self, width, height):
r = self.r
return (self.cx + r >= width or self.cx - r <= 0
or self.cy + r >= height or self.cy - r <=0)
def stopDot(self):
self.speed = 0
def clickedInsideDot(self, mx, my):
return math.sqrt((self.cx - mx)**2 + (self.cy - my)**2) <= self.r
def collidedWithDot(self, other):
if(isinstance(other, Dot)):
cx1, cy1, r1 = self.cx, self.cy, self.r
cx2, cy2, r2 = other.cx, other.cy, other.r
return math.sqrt((cx1 - cx2)**2 + (cy1 - cy2)**2) <= (r1 + r2)
else:
return False
def grow(self):
self.r += 5
def isEaten(self, other):
if(isinstance(other, Dot)):
return self.r < other.r
return False
def __eq__(self, other):
if(not isinstance(other, Dot)): return False
return (self.cx == other.cx and self.cy == other.cy and
self.color == other.color and self.r == other.r and
self.direction == other.direction)
def checkCollision(self, data):
for dot in data.dots:
if(dot != self):
if(self.collidedWithDot(dot)):
if(self.isEaten(dot)):
data.dots.remove(self)
dot.grow()
return
else:
data.dots.remove(dot)
self.grow()
def draw(self, canvas):
cx, cy, r = self.cx, self.cy, self.r
canvas.create_oval(cx - r, cy - r, cx + r, cy + r, fill=self.color)
class BouncingDot(Dot):
def __init__(self, cx, cy, r):
super().__init__(cx, cy, r)
def bounce(self):
dx, dy = self.direction
self.direction = dx*-1, dy*-1
def onTimerFired(self, data):
if(self.isCollisionWithWall(data.width, data.height)):
self.bounce()
self.moveDot()
self.checkCollision(data)
class WrapAroundDot(Dot):
def __init__(self, cx, cy, r):
super().__init__(cx, cy, r)
def wrapAround(self, width, height):
self.cx = self.cx%width
self.cy = self.cy%height
def onTimerFired(self, data):
self.moveDot()
self.wrapAround(data.width, data.height)
self.checkCollision(data)
# Animation Starter Code, Focus on timerFired
from tkinter import *
####################################
# customize these functions
####################################
def init(data):
# load data.xyz as appropriate
data.paused = False
data.timer = 0
data.dots = []
def mousePressed(event, data):
# use event.x and event.y
if(data.paused): return
for dot in data.dots:
if(dot.clickedInsideDot(event.x, event.y)):
dot.stopDot()
return
radius = random.randint(5, 50)
if(radius % 2 == 0):
dot = WrapAroundDot(event.x, event.y, radius)
else:
dot = BouncingDot(event.x, event.y, radius)
data.dots.append(dot)
def keyPressed(event, data):
# use event.char and event.keysym
if(event.keysym == "p"):
data.paused = not data.paused
def timerFired(data):
if(data.paused): return
data.timer += 1
if(data.timer % 100 == 0):
data.dots = []
for dot in data.dots:
dot.onTimerFired(data)
def redrawAll(canvas, data):
# draw in canvas
for dot in data.dots:
dot.draw(canvas)
####################################
# use the run function as-is
####################################
def run(width=300, height=300):
def redrawAllWrapper(canvas, data):
canvas.delete(ALL)
canvas.create_rectangle(0, 0, data.width, data.height,
fill='white', width=0)
redrawAll(canvas, data)
canvas.update()
def mousePressedWrapper(event, canvas, data):
mousePressed(event, data)
redrawAllWrapper(canvas, data)
def keyPressedWrapper(event, canvas, data):
keyPressed(event, data)
redrawAllWrapper(canvas, data)
def timerFiredWrapper(canvas, data):
timerFired(data)
redrawAllWrapper(canvas, data)
# pause, then call timerFired again
canvas.after(data.timerDelay, timerFiredWrapper, canvas, data)
# Set up data and call init
class Struct(object): pass
data = Struct()
data.width = width
data.height = height
data.timerDelay = 100 # milliseconds
root = Tk()
init(data)
# create the root and the canvas
canvas = Canvas(root, width=data.width, height=data.height)
canvas.configure(bd=0, highlightthickness=0)
canvas.pack()
# set up events
root.bind("<Button-1>", lambda event:
mousePressedWrapper(event, canvas, data))
root.bind("<Key>", lambda event:
keyPressedWrapper(event, canvas, data))
timerFiredWrapper(canvas, data)
# and launch the app
root.mainloop() # blocks until window is closed
print("bye!")
run(600, 600)