from tkinter import *
import random
import time
class Paddle:
def __init__(self, canvas, color):
self.canvas = canvas
self.id = canvas.create_rectangle(0, 0, 100, 10, fill=color) # 패들의 높이와 넓이 그리고 색깔
self.canvas.move(self.id, 200, 300) # 패들 사각형을 200,300 에 위치
self.x = 0 # 패들이 처음 시작할때 움직이지 않게 0으로 설정
self.y = 0
self.canvas_width = self.canvas.winfo_width() # 캔버스의 넓이를 반환한다. 캔버스 밖으로 패들이 나가지 않도록
self.canvas_height = self.canvas.winfo_height() # 캔버스의 넓이를 반환한다. 캔버스 밖으로 패들이 나가지
self.canvas.bind_all('<KeyPress-Left>', self.turn_left) # 왼쪽 화살표 키를 '<KeyPress-Left>' 라는 이름로 바인딩
self.canvas.bind_all('<KeyPress-Right>', self.turn_right) # 오른쪽도 마찬가지로 바인딩한다.
self.canvas.bind_all('<KeyPress-Up>', self.turn_up) # 오른쪽도 마찬가지로 바인딩한다.
self.canvas.bind_all('<KeyPress-Down>', self.turn_down) # 오른쪽도 마찬가지로 바인딩한다.
def draw(self):
pos = self.canvas.coords(self.id)
if pos[0] <= 0 and self.x < 0: # 패들의 위치가 왼쪽 끝이고, 이동하려는 방향이 왼쪽이면 함수 종료
return # return 뒤에 아무것도 안쓰면 패들이 끝으로 갔을 때 멈춰라는 의미
elif pos[2] >= self.canvas_width and self.x > 0: # 패들의 위치가 오른쪽 끝이고, 이동하려는 방향이
return # 오른쪽 끝으로 갔을 때 멈추라는 의미
elif pos[1] <= 0 and self.y <0 :
return
elif pos[3] >= self.canvas_height and self.y > 0 :
return
self.canvas.move(self.id, self.x, self.y)
# print(pos)
#self.canvas.move(self.id, self.x, 0) # 패들은 위아래가 아니라 양 옆으로 움직이기 때문에 Y좌표는 0으로 두었다.
# 패들이 화면의 끝에 부딪히면 공처럼 튕기는게 아니라 움직임이 멈춰야한다.
# 그래서 왼쪽 x 좌표(pos[0]) 가 0 과 같거나 작으면 self.x = 0 처럼 x 변수에 0 을
# 설정한다. 같은 방법으로 오른쪽 x 좌표(pos[2]) 가 캔버스의 폭과 같거나 크면
# self.x = 0 처럼 변수에 0 을 설정한다.
def turn_left(self, evt): # 패들의 방향을 전환하는 함수
self.x = -3
def turn_right(self, evt):
self.x = 3
def turn_up(self,evt):
self.y = -2
def turn_down(self,evt):
self.y = 2
# def move(self, x):
# self.x = x
class Ball:
def __init__(self, canvas, paddle, color):
self.canvas = canvas
self.paddle = paddle
self.id = canvas.create_oval(10, 10, 25, 25, fill=color) #공 좌표 및 색깔(oval : object 형태 타입)
# ↑ ↑ ↑ ↑
#좌측상단 구석에서 시작하는 x y 우측 하단 구석에서 시작하는 x y
self.canvas_height = self.canvas.winfo_height()
print('높이', self.canvas_height)
self.canvas_width = self.canvas.winfo_width()
print('높이', self.canvas_width)
self.canvas.move(self.id, 245, 100) #공을 캔버스 중앙으로 이동
starts = [-3, -2, -1, 1, 2, 3] # 6개의 숫자를 담는 리스트 생성
random.shuffle(starts) # 리스트를 shuffle함
self.x = starts[0]
self.y = -3
self.hit_bottom = False
self.canvas.bind_all('<Key>', self.turn_space)
def hit_paddle(self,pos):
paddle_pos = self.canvas.coords(self.paddle.id)
if pos[2] >= paddle_pos[0] and pos[0] <= paddle_pos[2]:
if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]:
return True
return False
# self.x = 0
# self.y = 0
# self.canvas.bind_all('<KeyPress-Left>',self.turn_left) # 키보드를 움직이기 위한 명령어
# self.canvas.bind_all('<KeyPress-Right>',self.turn_right)
# self.canvas.bind_all('<KeyPress-Up>',self.turn_up)
# self.canvas.bind_all('<KeyPress-Down>',self.turn_down)
def draw(self):
self.canvas.move(self.id, self.x, self.y)
# 볼 자신(id)이 x, y의 좌표로 이동한다.
# [ 2, 3, 4, 2]
# ↑ ↑
# 좌측 상단의 좌표, 우측 하단의 좌표
pos = self.canvas.coords(self.id)
print(pos)
# 0은 가로로 움직이지 마라
# -1은 화면의 위쪽으로 1픽셀 움직여라
# pos = self.canvas.coords(self.id)
if pos[1] <= 0: # 좌측 상단의 y 좌표가 0보다 작거나 같다면
self.y = 3 # 3만큼 내려가게 해라.
if pos[3] >= self.canvas_height: # 우츨 하단의 y좌표가 canvas의 높이보다 크다면
self.y = -3 # 3만큼 올라가게 해라.
if pos[0] <= 0:
self.x = 3
if pos[2] >= self.canvas_width:
self.x = -3
if self.hit_paddle(pos) == True: #판에 부딪히면 위로 튕겨올라가게
self.y = -3
def turn_left(self,evt):
self.x = -5
def turn_right(self,evt):
self.x = 5
def turn_up(self,evt):
self.y = -5
def turn_down(self,evt):
self.y = 5
def turn_space(self, evt):
starts = [-9,-8,-7,-4,-3,-2,-1]
random.shuffle(starts)
self.y = -3
self.x = start[0]
tk = Tk() # 1. tk 를 인스턴스화 한다.
tk.title("Game") # 2. tk 객체의 title 메소드(함수)로 게임창에 제목을 부여한다.
tk.resizable(0, 0) # 3. 게임창의 크기는 가로나 세로로 변경될수 없다라고 말하는것이다.
tk.wm_attributes("-topmost", 1) #4. 다른 모든 창들 앞에 캔버스를 가진 창이 위치할것을 tkinter 에게 알려준다.
canvas = Canvas(tk, width=500, height=400, bd=0, highlightthickness=0)
# bg=0,highlightthickness=0 은 캔버스 외곽에 둘러싼
# 외곽선이 없도록 하는것이다. (게임화면이 좀더 좋게)
canvas.pack() # 앞의 코드에서 전달된 폭과 높이는 매개변수에 따라 크기를 맞추라고 캔버스에 말해준다.
tk.update() # tkinter 에게 게임에서의 애니메이션을 위해 자신을 초기화하라고 알려주는것이다.
paddle = Paddle(canvas, 'blue')
ball = Ball(canvas, paddle, 'red')
ball2 = Ball(canvas, paddle, 'blue')
start = False
while 1:
if ball.hit_bottom == False:
ball.draw()
ball2.draw()
paddle.draw()
#그림을 다시 그려라! 라고 쉴새없이 명령
tk.update_idletasks()
tk.update()
#시작 전 2초간 sleep
if not start:
time.sleep(2)
start = True
time.sleep(0.01)