편집 기록

편집 기록
  • 프로필 nowp님의 편집
    날짜2021.03.09

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


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

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

    이미지

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

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

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

    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)
    

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

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

  • 프로필 이윤선님의 편집
    날짜2017.06.30

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


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

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

    이미지

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

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

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

    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)
    

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

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