15-112 Agenda 18-June

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)