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