from tkinter import *
class BasicMovingSquare(object):
def __init__(self, x, y, r, fill):
self.x = x
self.y = y
self.r = r
self.fill = fill
def draw(self, canvas):
x,y,r = self.x, self.y, self.r
canvas.create_rectangle(x - r, y - r,x + r, y +r, fill=self.fill, width=0)
def move(self, dx, dy):
self.x += dx
self.y += dy
def intersects(self, other):
dx = abs(self.x - other.x)
dy = abs(self.y - other.y)
dis = self.r + other.r
return dx <= dis and dy <= dis
class Bullet(BasicMovingSquare):
def __init__(self, x, y):
super().__init__(x,y,5, "blue")
def move(self):
dy = -80
super().move(0, dy)
class Player(BasicMovingSquare):
def __init__(self,x,y,r):
self.bullets = []
self.dx = 30
super().__init__(x,y,r,"black")
def draw(self,canvas):
super().draw(canvas)
gunR = 50
canvas.create_line(self.x, self.y, self.x, self.y - gunR , width=4)
def moveLeft(self):
super().move(-self.dx, 0)
def moveRight(self):
super().move(self.dx, 0)
def getActiveBullets(self):
return self.bullets
def shoot(self):
self.bullets.append(Bullet(self.x, self.y))
class Enemy(BasicMovingSquare):
def __init__(self, x,y,r, health=1):
self.health = health
self.dir = 1
super().__init__(x,y,r,"red")
def isHit(self, bullet):
if self.health == 0:
return False
return self.intersects(bullet)
def kill(self):
self.health = 0
self.fill = "black"
def move(self, screenWidth):
if self.health == 0:
return
super().move(self.dir * 30, 0)
if self.x + self.r >= screenWidth:
self.dir = -1
self.x = screenWidth - self.r -1
if self.x - self.r <= 0:
self.dir = 1
self.x = self.r + 1
####################################
# customize these functions
####################################
def init(data):
playerR = 20
playerX = data.width // 2
playerY = data.height - playerR
data.player = Player(playerX,playerY, playerR)
enemyR = 40
enemyX = playerX
enemyY = 80
data.enemy = Enemy(enemyX, enemyY, enemyR)
data.score = 0
def keyPressed(event,data):
if event.keysym == "Left":
data.player.moveLeft()
elif event.keysym == "Right":
data.player.moveRight()
elif event.keysym == "space":
data.player.shoot()
def timerFired(data):
data.enemy.move(data.width)
for bullet in data.player.getActiveBullets():
bullet.move()
if data.enemy.isHit(bullet):
data.enemy.kill()
def mousePressed(event,data):
pass
def redrawAll(canvas, data):
canvas.create_text(20,20,text=str(data.score))
data.player.draw(canvas)
data.enemy.draw(canvas)
for bullet in data.player.getActiveBullets():
bullet.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.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)