Write the FlappyBird game in Python (full source code)
Flappy Bird is a very popular game with a simple but very fun gameplay. This article will teach you to implement this classic game using Python.
First, we need to import the necessary libraries and modules. We will use the PyGame library to create game windows, draw game elements, etc. We also need the random module to generate random numbers.
import pygame import random pygame.init() # Set the game window size WINDOW_WIDTH = 288 WINDOW_HEIGHT = 512 # create game window WINDOW = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) pygame.display.set_caption("Flappy Bird") # load game resources Background_IMAGE = pygame.image.load("assets/background.png").convert() BIRD_IMAGES = [pygame.image.load("assets/bird1.png").convert_alpha(), pygame.image.load("assets/bird2.png").convert_alpha(), pygame.image.load("assets/bird3.png").convert_alpha()] PIPE_IMAGE = pygame.image.load("assets/pipe.png").convert_alpha() FONT = pygame.font.Font("assets/font.ttf", 36)
Next, we need to define some constants and variables. These constants and variables are needed for the position, velocity, etc. of the different elements in the game. We use UPPER_PIPE_Y to represent the y-coordinate of the top of the upper pipe, and LOWER_PIPE_Y to represent the y-coordinate of the bottom of the lower pipe. BIRD_X and BIRD_Y represent the x-coordinate and y-coordinate of the bird, respectively.
# define constants and variables FPS = 60 GRAVITY = 1.5 BIRD_X = 50 BIRD_Y = 200 BIRD_SPEED = 0 UPPER_PIPE_Y = -320 LOWER_PIPE_Y = 220 PIPE_GAP = 140 PIPE_SPEED=4
Now we can create the game loop. In the game loop, we first handle game events. If the player presses the space bar, we need to make the bird fly up a certain distance. We also need to update the bird’s position and velocity, and check if the bird collided with the pipe or went out of bounds. If the bird collides with the pipe or goes out of bounds, it’s game over. Finally, we need to draw all the game elements in the game window.
# game loop while True: # Handle game events for event in pygame.event.get(): if event.type == pygame.QUIT: pygame. quit() sys. exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: BIRD_SPEED = -10 # Update bird position and velocity BIRD_SPEED += GRAVITY BIRD_Y += BIRD_SPEED # Check if the bird collides with the pipe or goes out of bounds if BIRD_Y < 0 or BIRD_Y > WINDOW_HEIGHT - 40: print("Game over!") pygame. quit() sys. exit() # draw game elements WINDOW.blit(BACKGROUND_IMAGE, (0, 0)) WINDOW.blit(BIRD_IMAGES[0], (BIRD_X, BIRD_Y)) pygame.display.update()
We’ve now created the game loop and handled the spacebar events, updating the bird’s position and velocity. Next we need to add the pipeline element. We will use the pipes list to store the pipe objects. Each pipe object has two parts, an upper pipe and a lower pipe. We first randomly generate a y coordinate value, and then calculate the position and size of the upper and lower pipes based on the y coordinate value.
# add pipeline element class Pipe: def __init__(self): self.x = WINDOW_WIDTH self.y = random.randint(-200, 100) self.upper_pipe_rect = PIPE_IMAGE.get_rect(midbottom=(self.x, self.y)) self.lower_pipe_rect = PIPE_IMAGE.get_rect(midtop=(self.x, self.y + PIPE_GAP)) def update(self): self.x -= PIPE_SPEED self.upper_pipe_rect.centerx = self.x self.lower_pipe_rect.centerx = self.x if self.x < -PIPE_IMAGE.get_width() / 2: pipes. remove(self) def create_pipe(): pipe = Pipe() pipes.append(pipe)
We also need to maintain a pipes list to store all pipe objects. In the game loop, we need to update and draw the pipes in the pipes list. If a pipeline object is out of window bounds, we need to remove it from the list. We also need to periodically create new pipeline elements.
# Define the pipeline list pipes = [] # create pipeline create_pipe() pipe_create_event = pygame.USEREVENT + 1 pygame.time.set_timer(pipe_create_event, 2000) # main loop while True: # Handle game events for event in pygame.event.get(): if event.type == pygame.QUIT: pygame. quit() sys. exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: BIRD_SPEED = -10 elif event.type == pipe_create_event: create_pipe() # Update bird position and velocity BIRD_SPEED += GRAVITY BIRD_Y += BIRD_SPEED # Check if the bird collides with the pipe or goes out of bounds bird_rect = BIRD_IMAGES[0].get_rect(center=(BIRD_X, BIRD_Y)) for pipe in pipes: if bird_rect.colliderect(pipe.upper_pipe_rect) or bird_rect.colliderect(pipe.lower_pipe_rect): print("Game over!") pygame. quit() sys. exit() if BIRD_Y < 0 or BIRD_Y > WINDOW_HEIGHT - 40: print("Game over!") pygame. quit() sys. exit() # Update pipe positions and remove pipes that are outside the window for pipe in pipes: pipe. update() # draw game elements WINDOW.blit(BACKGROUND_IMAGE, (0, 0)) for pipe in pipes: WINDOW.blit(PIPE_IMAGE, pipe.upper_pipe_rect) WINDOW.blit(pygame.transform.flip(PIPE_IMAGE, False, True), pipe.lower_pipe_rect) WINDOW.blit(BIRD_IMAGES[0], (BIRD_X, BIRD_Y)) pygame.display.update() # set the frame rate CLOCK.tick(FPS)
Finally, we display the score at the end of the game. We calculate the score based on the number of birdies that pass through the pipe.
# display score score = 0 def update_score(): global score for pipe in pipes: if pipe.x + PIPE_IMAGE.get_width() < BIRD_X and not pipe.scored: score + = 1 pipe.scored = True while True: # Handle game events for event in pygame.event.get(): ... # Update bird position and velocity ... # Check if the bird collides with the pipe or goes out of bounds ... # Update pipe positions and remove pipes that are outside the window ... # draw game elements ... # show score update_score() score_surface = FONT. render(str(score), True, (255, 255, 255)) score_rect = score_surface.get_rect(center=(WINDOW_WIDTH / 2, 50)) WINDOW.blit(score_surface, score_rect) pygame.display.update() # set the frame rate ...
Full source code:
import pygame import random import sys pygame.init() # Set the game window size WINDOW_WIDTH = 288 WINDOW_HEIGHT = 512 # create game window WINDOW = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) pygame.display.set_caption("Flappy Bird") # load game resources Background_IMAGE = pygame.image.load("assets/background.png").convert() BIRD_IMAGES = [pygame.image.load("assets/bird1.png").convert_alpha(), pygame.image.load("assets/bird2.png").convert_alpha(), pygame.image.load("assets/bird3.png").convert_alpha()] PIPE_IMAGE = pygame.image.load("assets/pipe.png").convert_alpha() FONT = pygame.font.Font("assets/font.ttf", 36) # define constants and variables FPS = 60 GRAVITY = 1.5 BIRD_X = 50 BIRD_Y = 200 BIRD_SPEED = 0 UPPER_PIPE_Y = -320 LOWER_PIPE_Y = 220 PIPE_GAP = 140 PIPE_SPEED=4 # add pipeline element class Pipe: def __init__(self): self.x = WINDOW_WIDTH self.y = random.randint(-200, 100) self.upper_pipe_rect = PIPE_IMAGE.get_rect(midbottom=(self.x, self.y)) self.lower_pipe_rect = PIPE_IMAGE.get_rect(midtop=(self.x, self.y + PIPE_GAP)) self. scored = False def update(self): self.x -= PIPE_SPEED self.upper_pipe_rect.centerx = self.x self.lower_pipe_rect.centerx = self.x if self.x < -PIPE_IMAGE.get_width() / 2: pipes. remove(self) def create_pipe(): pipe = Pipe() pipes.append(pipe) # Define the pipeline list pipes = [] # create pipeline create_pipe() pipe_create_event = pygame.USEREVENT + 1 pygame.time.set_timer(pipe_create_event, 2000) # show score score = 0 def update_score(): global score for pipe in pipes: if pipe.x + PIPE_IMAGE.get_width() < BIRD_X and not pipe.scored: score + = 1 pipe.scored = True # main loop CLOCK = pygame. time. Clock() while True: # Handle game events for event in pygame.event.get(): if event.type == pygame.QUIT: pygame. quit() sys. exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: BIRD_SPEED = -10 elif event.type == pipe_create_event: create_pipe() # Update bird position and speed BIRD_SPEED += GRAVITY BIRD_Y += BIRD_SPEED # Check if the bird collides with the pipe or goes out of bounds bird_rect = BIRD_IMAGES[0].get_rect(center=(BIRD_X, BIRD_Y)) for pipe in pipes: if bird_rect.colliderect(pipe.upper_pipe_rect) or bird_rect.colliderect(pipe.lower_pipe_rect): print("Game over!") pygame. quit() sys. exit() if BIRD_Y < 0 or BIRD_Y > WINDOW_HEIGHT - 40: print("Game over!") pygame. quit() sys. exit() # Update pipe positions and remove pipes that are outside the window for pipe in pipes: pipe. update() # Draw game elements WINDOW.blit(BACKGROUND_IMAGE, (0, 0)) for pipe in pipes: WINDOW.blit(PIPE_IMAGE, pipe.upper_pipe_rect) WINDOW.blit(pygame.transform.flip(PIPE_IMAGE, False, True), pipe.lower_pipe_rect) WINDOW.blit(BIRD_IMAGES[0], (BIRD_X, BIRD_Y)) pygame.display.update() # show score update_score() score_surface = FONT. render(str(score), True, (255, 255, 255)) score_rect = score_surface.get_rect(center=(WINDOW_WIDTH / 2, 50)) WINDOW.blit(score_surface, score_rect) # set the frame rate CLOCK.tick(FPS)