플래피 버드 코드에서 파이프 속도가 빨라져요

플래피 버드 코드에서 파이프 속도가 빨라져요

작성일 2024.04.11댓글 1건
    게시물 수정 , 삭제는 로그인 필요

플래피 버드 코드를 만드는데 게임이 끝나고 리스타트 할때마다 파이프 속도가 빨라져요
아마 게임오버가 되면 게임을 멈췄다가 이제 다시 def start_game으로 넘어가는데 그때 또 self.move_pipes가 실행되서 점점 빨라지는거 같은데.. 이걸 어떻게 고쳐야 할지 모르겠어요
코드-->
from tkinter import *
import random
class GUI:
    WINDOW_HEIGHT = 500
    WINDOW_WIDTH = 700
    BIRD_STARTING_POINT_X = 50
    BIRD_STARTING_POINT_Y = (WINDOW_HEIGHT // 2) + 50
    PIPE_STARTING_POINT_X = 500
    PIPE_STARTING_POINT_Y = 500
    PIPE_WIDTH = 50
    PIPE_GAP = 150
    FLOOR_COORD_X = 0
    FLOOR_COORD_Y = WINDOW_HEIGHT
    FLOOR_HEIGHT = 30
    Velocity = -5

    def __init__(self):
        self.window = Tk()
        self.window.title("Flippy Bird")
        self.window.geometry(f"{GUI.WINDOW_WIDTH}x{GUI.WINDOW_HEIGHT}")
        self.canvas = Canvas(self.window, height=GUI.WINDOW_WIDTH, width=GUI.WINDOW_HEIGHT, background="#87CEEB")
        self.canvas.pack()
        self.click_to_start_text_bg = self.canvas.create_rectangle(GUI.WINDOW_WIDTH // 2 - 120, GUI.WINDOW_HEIGHT // 2 - 30,
GUI.WINDOW_WIDTH // 2 + 120, GUI.WINDOW_HEIGHT // 2 + 30,
fill="#336699", outline="")
        self.click_to_start_text = self.canvas.create_text(GUI.WINDOW_WIDTH//2, GUI.WINDOW_HEIGHT//2, text="Click to start",
fill="white", font=("Arial", 20, "bold"))
        self.game_started = 0
        self.pipes = []
        self.score = 0
        self.score_display = None
        self.floor_create = None
        self.bird_create = None
        self.canvas.bind("<Button-1>", self.start_game)
        self.canvas.mainloop()

    def create_pipes(self):
        x = GUI.PIPE_STARTING_POINT_X
        while x < GUI.WINDOW_WIDTH:
            gap_start_top = random.randint(50, GUI.WINDOW_HEIGHT - GUI.PIPE_GAP - 150)
            gap_start_bottom = gap_start_top + GUI.PIPE_GAP
            self.pipes.append(Pipe(x, gap_start_top, gap_start_bottom, self.canvas, GUI.WINDOW_HEIGHT))
            x += GUI.PIPE_WIDTH + GUI.PIPE_GAP

    def move_pipes(self):
        for pipe in self.pipes:
            pipe.move()
        self.window.after(16, self.move_pipes)

    def update_game(self):
        if self.bird_create and not self.bird_create.hit_floor:
            self.bird_create.update()
            self.check_score()
            self.window.after(16, self.update_game)
        else:
            self.reset_game()

    def bird_flap(self, _):
        if self.bird_create:
            self.bird_create.flap()

    def start_game(self, _):
        if not self.game_started:
            self.game_started = 1
            self.canvas.delete(self.click_to_start_text_bg)
            self.canvas.delete(self.click_to_start_text)
            self.create_pipes()
            self.bird_create = Bird(GUI.BIRD_STARTING_POINT_X, GUI.BIRD_STARTING_POINT_Y, self.canvas, self.update_game, self.pipes)
            self.move_pipes()
            self.floor = self.canvas.create_rectangle(0, GUI.WINDOW_HEIGHT, GUI.WINDOW_WIDTH,
GUI.WINDOW_HEIGHT - GUI.FLOOR_HEIGHT, fill="#AAAA33")
            self.score_display = self.canvas.create_text(GUI.WINDOW_WIDTH//2, 50, text=f"Score: {self.score}",
font=("Arial", 20, "bold"), fill="black")
            self.update_game()
            self.canvas.bind("<Button-1>", self.bird_flap)
            self.window.bind("<space>", self.bird_flap)

    def reset_game(self):
        self.game_started = 0
        self.canvas.delete(ALL)
        self.click_to_start_text_bg = self.canvas.create_rectangle(GUI.WINDOW_WIDTH // 2 - 120, GUI.WINDOW_HEIGHT // 2 - 30,
GUI.WINDOW_WIDTH // 2 + 120, GUI.WINDOW_HEIGHT // 2 + 30,
fill="#336699", outline="")
        self.click_to_start_text = self.canvas.create_text(GUI.WINDOW_WIDTH // 2, GUI.WINDOW_HEIGHT // 2,
text="Click to Start", font=("Helvetica", 24), fill="white")
        self.canvas.bind("<Button-1>", self.start_game)
        self.score = 0
        self.pipes = []

    def check_score(self):
        if self.bird_create:
            bird_coords = self.canvas.coords(self.bird_create.bird_shape)
        if bird_coords:
            bird_x, bird_y = bird_coords[0], bird_coords[1] + 25
            for pipe in self.pipes:
                pipe_coords = self.canvas.coords(pipe.top_pipe)
                pipe_x, pipe_y = pipe_coords[0], pipe_coords[1]
                if pipe_x < bird_x < pipe_x + GUI.WINDOW_WIDTH:
                    if pipe_y < bird_y < pipe.bottom_height:
                        if not pipe.scored:
                            self.score += 1
                            self.canvas.itemconfig(self.score_display, text=f"Score: {self.score}")
                            pipe.scored = 1
class Pipe:
    def __init__(self, x, gap_start_top, gap_start_bottom, canvas, window_height):
        self.canvas = canvas
        self.top_height = gap_start_top
        self.window_height = window_height
        self.bottom_height = gap_start_bottom
        self.top_pipe = self.canvas.create_rectangle(x, 0, x + GUI.PIPE_WIDTH, self.top_height, fill="#AAFF00")
        self.bottom_pipe = self.canvas.create_rectangle(x, self.bottom_height, x + GUI.PIPE_WIDTH, self.window_height + GUI.FLOOR_HEIGHT, fill="#AAFF00")
        self.scored = 0

    def move(self):
        self.canvas.move(self.top_pipe, GUI.Velocity, 0)
        self.canvas.move(self.bottom_pipe, GUI.Velocity, 0)
        top_pipe_coords = self.canvas.coords(self.top_pipe)
        if top_pipe_coords:
            if top_pipe_coords[2] < 0:
                self.reset_pipe()

    def reset_pipe(self):
        gap_start_top = random.randint(50, self.window_height - GUI.PIPE_GAP - 150)
        gap_start_bottom = gap_start_top + GUI.PIPE_GAP
        self.top_height = gap_start_top
        self.bottom_height= gap_start_bottom
        x = GUI.WINDOW_WIDTH + GUI.PIPE_WIDTH
        self.canvas.coords(self.top_pipe, x, 0, x + GUI.PIPE_WIDTH, self.top_height)
        self.canvas.coords(self.bottom_pipe, x, self.bottom_height, x + GUI.PIPE_WIDTH, self.window_height)
        self.scored = 0
class Bird:
    def __init__(self, x, y, canvas, update_game, pipes):
        self.canvas = canvas
        self.update_game = update_game
        self.pipes = pipes
        self.x = x
        self.y = y
        self.velocity = 0
        self.gravity = 0.7
        self.flap_strength = -9.8
        self.bird_shape = self.canvas.create_rectangle(x, y, x + 50, y + 50, fill="#FFFF00")
        self.hit_floor = 0

    def update(self):
        self.velocity += self.gravity
        self.y += self.velocity
        self.canvas.move(self.bird_shape, 0 , self.velocity)
        if self.y >= GUI.FLOOR_COORD_Y - 75:
            self.hit_floor = 1
        elif self.y <= 0:
            self.hit_floor = 1
            self.update_game()
        else:
            for pipe in self.pipes:
                if self.canvas.coords(self.bird_shape)[2] >= self.canvas.coords(pipe.top_pipe)[0] and self.canvas.coords(self.bird_shape)[0] <= self.canvas.coords(pipe.top_pipe)[2]:
                    if (self.y <= self.canvas.coords(pipe.top_pipe)[3]
                            or self.y + 50 >= self.canvas.coords(pipe.bottom_pipe)[1]):
                        self.hit_floor = 1
                        self.update_game()
                        return

    def flap(self):
        self.velocity = self.flap_strength
if __name__ == "__main__":
    GUI()


#플래피 버드 #플래피 버드 만들기 #플래피 버드 수익 #플래피 버드 게임 #플래피 버드 게임하기 #플래피 버드 코드 #플래피 버드 파이썬 #플래피 버드 파이프 #플래피 버드 리소스 #플래피 버드 엔트리

profile_image 익명 작성일 -

위의 문제는 move_pipes 메소드가 게임이 재시작될 때마다 중복해서 호출되어 발생하는 것으로 보입니다.

move_pipes 메소드가 게임의 프레임마다 파이프를 움직이도록 설정되어 있기 때문에, 게임이 다시 시작될 때마다 이 메소드의 호출이 중첩되어 파이프가 이동하는 속도가 기하급수적으로 증가하는 것으로 보입니다.

위의 문제를 해결하기 위한 방법 중 하나는 move_pipes 메소드의 중복 호출을 방지하는 것입니다.

게임이 시작될 때 move_pipes가 이미 실행되고 있는지를 확인하는 플래그 변수를 사용할 수 있습니다.

만약 move_pipes가 이미 실행 중이라면 다시 호출하지 않도록 합니다.

아래는 수정된 start_game 메소드와 move_pipes 메소드를 포함한 코드의 일부입니다:

def start_game(self, _):

if not self.game_started:

self.game_started = 1

self.moving_pipes = False # 파이프가 움직이는 중인지 확인하는 새로운 플래그 추가

self.canvas.delete(self.click_to_start_text_bg)

self.canvas.delete(self.click_to_start_text)

self.create_pipes()

self.bird_create = Bird(GUI.BIRD_STARTING_POINT_X, GUI.BIRD_STARTING_POINT_Y, self.canvas, self.update_game, self.pipes)

if not self.moving_pipes: # 만약 파이프가 움직이지 않는다면, move_pipes를 호출

self.move_pipes()

self.moving_pipes = True # 파이프가 움직이고 있다고 표시

self.floor = self.canvas.create_rectangle(0, GUI.WINDOW_HEIGHT, GUI.WINDOW_WIDTH,

GUI.WINDOW_HEIGHT - GUI.FLOOR_HEIGHT, fill="#AAAA33")

self.score_display = self.canvas.create_text(GUI.WINDOW_WIDTH//2, 50, text=f"Score: {self.score}",

font=("Arial", 20, "bold"), fill="black")

self.update_game()

self.canvas.bind("<Button-1>", self.bird_flap)

self.window.bind("<space>", self.bird_flap)

def reset_game(self):

self.game_started = 0

self.moving_pipes = False # 게임을 리셋할 때, 파이프 움직임도 리셋

self.canvas.delete(ALL)

self.click_to_start_text_bg = self.canvas.create_rectangle(GUI.WINDOW_WIDTH // 2 - 120, GUI.WINDOW_HEIGHT // 2 - 30,

GUI.WINDOW_WIDTH // 2 + 120, GUI.WINDOW_HEIGHT // 2 + 30,

fill="#336699", outline="")

self.click_to_start_text = self.canvas.create_text(GUI.WINDOW_WIDTH // 2, GUI.WINDOW_HEIGHT // 2,

text="Click to Start", font=("Helvetica", 24), fill="white")

self.canvas.bind("<Button-1>", self.start_game)

self.score = 0

self.pipes = []

위 코드에서는 moving_pipes라는 새로운 플래그를 GUI 클래스에 추가하여 move_pipes 메소드의 중복 실행을 방지할 수 있을 것으로 보입니다.

이 플래그는 start_game 메소드에서 True로 설정되며, reset_game 메소드에서 False로 재설정됩니다.

이를 통해 게임이 재시작될 때 move_pipes 메소드가 중복해서 실행되는 것을 방지할 수 있을 것입니다.