파이썬 gui프로그래밍중 tkinter에 대한 질문입니다.

조회수 5712회

누구나 쉽게 배우는 파이썬 프로그래밍 이라는 책을 보며

아래의 이미지 같은 벽돌깨기 게임을 만드는 중입니다.

이미지

공이 움직이다 블록을 만나면 부딪히고 싶은데 공이 블록을 통과합니다.

벽돌깨기를 하려면 일단 부딪히는거라도 해야 할 텐데요 ㅋㅋㅋ

이 부분 도와주세요 아래 소스는 책의 소스중 바와 공의 충돌에 관한 부분입니다.

class Ball:

    def __init__(self,canvas,paddle,score,color):
        self.canvas = canvas
        self.paddle = paddle
        self.score = score
        self.id = canvas.create_oval(10,10,25,25,fill = color)
        self.canvas.move(self.id,245,100)
        starts = [-3,-2,-1,1,2,3]
        random.shuffle(starts)
        self.x = starts[0]
        self.y = -3
        self.canvas_height = self.canvas.winfo_height()
        self.canvas_width = self.canvas.winfo_width()
        self.hit_bottom = False

    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]:
                self.x += self.paddle.x
                self.score.hit()
                return True
        return False


    def draw(self):
        self.canvas.move(self.id,self.x,self.y)
        pos = self.canvas.coords(self.id)
        if pos[1] <= 0:
            self.y = 3
        if pos[3] >= self.canvas_height:
            self.hit_bottom = True
        if self.hit_paddle(pos) == True:
            self.y = -3
        if pos[0] <= 0:
            self.x = 3
        if pos[2] >= self.canvas_width:
            self.x = -3

이 부분이 책에 나와있는 공과 바가 부딪히는 부분입니다.

여기서부터는 제가 생각한대로 몇줄 추가해 보았습니다.

class Ball:

    def __init__(self,canvas,paddle,score,block,color):
        self.canvas = canvas
        self.paddle = paddle
        self.block = block
        self.score = score
        self.id = canvas.create_oval(10,10,25,25,fill = color)
        self.canvas.move(self.id,245,100)
        starts = [-3,-2,-1,1,2,3]
        random.shuffle(starts)
        self.x = starts[0]
        self.y = -3
        self.canvas_height = self.canvas.winfo_height()
        self.canvas_width = self.canvas.winfo_width()
        self.hit_bottom = False
        self.hit_block = False

    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]:
                self.x += self.paddle.x
                self.score.hit()
                return True
        return False

    def hit_block(self,pos):
        block_pos = self.canvas.coords(self.block.id)
        if pos[2] >= block_pos[0] and pos[0] <= block_pos[2]:
            if pos[3] >= block_pos[1] and pos[3] <= block_pos[3]:
                return True
        return False

    def draw(self):
        self.canvas.move(self.id,self.x,self.y)
        pos = self.canvas.coords(self.id)
        # pos2 = self.block.coords(self.id)
        if pos[1] <= 0:
            self.y = 3
        if pos[3] >= self.canvas_height:
            self.hit_bottom = True
        if self.hit_paddle(pos) == True:
            self.y = -3
        if pos[0] <= 0:
            self.x = 3
        if pos[2] >= self.canvas_width:
            self.x = -3
        if self.hit_block(pos) == True:
            self.x = -3

이미지

제가 몇줄 추가하면 이렇게 오류가 발생합니다. hit_block 부분에서 문제가 생기는거 같은데....

잘 모르겠지만 논리적으로?? 안맞는다는거죠?

다음은 책의 소스입니다.

from tkinter import *
import random
import time

class Ball:

    def __init__(self,canvas,paddle,score,color):
        self.canvas = canvas
        self.paddle = paddle
        self.score = score
        self.id = canvas.create_oval(10,10,25,25,fill = color)
        self.canvas.move(self.id,245,100)
        starts = [-3,-2,-1,1,2,3]
        random.shuffle(starts)
        self.x = starts[0]
        self.y = -3
        self.canvas_height = self.canvas.winfo_height()
        self.canvas_width = self.canvas.winfo_width()
        self.hit_bottom = False

    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]:
                self.x += self.paddle.x
                self.score.hit()
                return True
        return False

    def draw(self):
        self.canvas.move(self.id,self.x,self.y)
        pos = self.canvas.coords(self.id)
        if pos[1] <= 0:
            self.y = 3
        if pos[3] >= self.canvas_height:
            self.hit_bottom = True
        if self.hit_paddle(pos) == True:
            self.y = -3
        if pos[0] <= 0:
            self.x = 3
        if pos[2] >= self.canvas_width:
            self.x = -3

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)
        self.x = 0
        self.canvas_width = self.canvas.winfo_width()
        self.started = False
        self.canvas.bind_all('<KeyPress-Left>',self.turn_left)
        self.canvas.bind_all('<KeyPress-Right>', self.turn_right)
        self.canvas.bind_all('<Button-1>',self.start_game)

    def draw(self):
        self.canvas.move(self.id,self.x,0)
        pos = self.canvas.coords(self.id)
        if pos[0] <= 0:
            self.x = 0
        elif pos[2] >= self.canvas_width:
            self.x = 0

    def turn_left(self,evt):
        self.x = -2
    def turn_right(self,evt):
        self.x = 2
    def start_game(self,evt):
        self.started = True
class Score:

    def __init__(self,canvas,color):
        self.score = 0
        self.canvas = canvas
        self.id = canvas.create_text(450,10,text = self.score,\
                                     fill = color)
    def hit(self):
        self.score +=1
        self.canvas.itemconfig(self.id,text = self.score)

tk = Tk()

tk.title("Game") #게임 창에 제목 부여

tk.resizable(0,0)# 창 크기 고정

tk.wm_attributes("-topmost",1) #화면 제일 앞에 고정

canvas = Canvas(tk,width = 500,height=500,bd=0,highlightthickness=0) #캔버스 이쁘게

canvas.pack()

tk.update()     #필수!! 애니메이션을 위해 자기초기화

score = Score(canvas,'green')

paddle = Paddle(canvas,'black')

ball = Ball(canvas,paddle,score,'red')

game_over_text = canvas.create_text(250,200,text='GAME OVER',\
                                    state = 'hidden')

while 1:    #메인 루프

    if ball.hit_bottom == False and paddle.started == True:
        ball.draw()
        paddle.draw()
    if ball.hit_bottom == True:             #공이 바닥에 닿으면 0.1초 쉬고 gameover 출력->숨김모드->보이는 모드로
        time.sleep(0.1)
        canvas.itemconfig(game_over_text,state='normal')
        # time.sleep(2)
        # exit()
    tk.update_idletasks()
    tk.update()
    time.sleep(0.0000001)

글이 너무 길어서 읽는데 고생하셨습니다. 다 읽어주셔서 감사해요

잘 몰라도요 조금이라도 도움이 되지 않을까? 싶으면 다 댓글 달아주세요 감사합니다.

1 답변

  • 클래스에 hit_block이라는 이름의 멤버를 중복해서 쓰셨네요.

    1. __init__에 Boolean type hit_block
    2. 멤버함수 def hit_block

    둘 중 하나의 이름을 바꿔주세요. 코드를 보니 2번, 함수를 쓰고 싶어서 hit_block(...)을 쓰셨는데 python interpreter는 hit_block을 메소드가 아니라 1번 variable로 받아들여 에러가 발생합니다.

    예를 들어

    def __init__(self,canvas,paddle,score,block,color):
        self.canvas = canvas
        self.paddle = paddle
        self.block = block
        self.score = score
        self.id = canvas.create_oval(10,10,25,25,fill = color)
        self.canvas.move(self.id,245,100)
        starts = [-3,-2,-1,1,2,3]
        random.shuffle(starts)
        self.x = starts[0]
        self.y = -3
        self.canvas_height = self.canvas.winfo_height()
        self.canvas_width = self.canvas.winfo_width()
        self.hit_bottom = False
        #self.hit_block = False # 주석처리
    

    이렇게 init에 선언된 hit_block을 제거하시거나, hit_block의 이름을 다른 걸로 바꾸세요.

    • (•́ ✖ •̀)
      알 수 없는 사용자
    • 감사합니다 해보는중이에요 ㅎㅎㅎㅎ 이윤선 2017.7.4 12:05

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)