python

벽돌깨기 오류 수정하

bumychoi 2025. 6. 2. 10:12
import tkinter as tk
from tkinter import Frame, Canvas

class BrickBreaker(Frame):
    def __init__(self,root):
        super().__init__(root)
        self.width = 640
        self.height = 480
        self.canvas = Canvas(self,bg="blue",
                            width=self.width,
                            height=self.height,
                            )
       
        self.canvas.pack()
        self.pack()
class Sprite():
    def __init__(self,canvas, item):
        self.canvas = canvas
        self.item = item
        self.speedx = 5
        self.speedy = 5
        self.x = 0
        self.y = 0

    def get_coords(self):
        return self.canvas.coords(self.item)        

    def get_position(self):
        pos = self.canvas.coords(self.item)
        x=pos[0]
        y=pos[1]
        return x,y
   
    def update(self):
        self.x = self.x+ self.speedx
        self.y = self.y+ self.speedy

    def move(self):
        self.canvas.move(self.item, self.speedx, self.speedy)

    def delete(self):
        self.canvas.delete(self.item)

class Ball(Sprite):
    def __init__(self,canvas,x,y,radius):
        self.radius = radius
        item = canvas.create_oval(x-self.radius,
                                y-self.radius,
                                x+self.radius,
                                y+self.radius,
                                fill='red')
        self.x= x
        self.y= y
        super().__init__(canvas,item)

    def update(self):
        x,y = self.get_position()
        width  = self.canvas.winfo_width()

        if x<=0 or x>= width:
            self.speedx *= -1
        if y<= 0:
            self.speedy *= 1

class Paddle(Sprite):
    def __init__(self,canvas, x, y):
        self.width = 100
        self.heigth = 20
        item = canvas.create_rectangle(x - self.width / 2,
                                    y - self.height / 2,
                                    x + self.width / 2,
                                    y + self.height / 2,
                                    fill='white')
        super().__init__(canvas,item)
        self.x = x
        self.y = y

    def move(self,dx,dy):
        self.x = self.x + dx
        self.y = self.y + dy
        self.canvas.move(self.item,dx,dy)

class Brick(Sprite):
    def __init__(self, canvas, x, y):
        self.width = 52
        self.height = 25
        item = canvas.create_rectangle(x - self.width / 2,
                                    y - self.height / 2,
                                    x + self.width / 2,
                                    y + self.height / 2,
                                    fill='yellow', tags='brick')
       
        super().__init__(canvas, item)
    # 벽돌과 공이 충돌하면 벽돌을 삭제한다.
    def handle_collision(self):
        self.delete()
        # Brick 객체를 2차원 모양으로 생성한다.
        for r in range(1, 4):
            for c in range(1, 10):
                brick = Brick(self.canvas, c*60, r*30)
                # Brick 객체를 shapes에 저장한다.
                self.shapes[brick.item] = brick
                # 캔버스가 키보드 이벤트를 받을 수 있도록 설정한다.
                self.canvas.focus_set()
                # 화살표키와 스페이스키에 이벤트를 붙인다.
                self.canvas.bind('<Left>',
                lambda _: self.paddle.move(-10, 0))
                self.canvas.bind('<Right>',
                lambda _: self.paddle.move(10, 0))
                self.canvas.bind('<space>', lambda _: self.start())
                coords = self.ball.get_coords() # Ball 객체의 위치를 구한다.
                # 겹치는 모든 도형을 찾는다. 식별 번호가 저장된다.
                items = self.canvas.find_overlapping(*coords)
                #*coords를 풀어서 인수로 전달
                # 겹치는 도형의 식별 번호로 객체를 찾아서 리스트에 저장한다.
                objects = [self.shapes[x] for x in items if x in self.shapes]
                # 충돌 처리 메소드를 호출한다.
                self.ball.collide(objects)
                self.ball.update()
                self.ball.move()
                # game_loop()를 50밀리초 후에 호출한다.
                self.after(50, self.game_loop)
                # 충돌을 처리하는 메소드
                # Ball과 충돌이 일어난 객체들의 리스트가 매개변수로 전달된다.
            def collide(self, obj_list):
                x, y = self.get_position()
                # 충돌이 하나라도 일어났으면
                if len(obj_list): # 충돌은 벽돌이나 패들
                    self.speedy *= -1 # y 방향 변경
                # 충돌이 일어난 객체가 벽돌이면 Brick의 충돌 처리 메소드를 호출한다.
                for obj in obj_list:
                    if isinstance(obj, Brick):
                        obj.handle_collision()



if __name__ =="__main__":
    root = tk.Tk()
    app = BrickBreaker(root)
    root.mainloop()