,

How To Make Flappy Bird Game Using Pygame in Python?

In this article, we will explore how to create a Flappy Bird game using Pygame.

We all know and love this game. The main objective is for the player to score the highest points by guiding the bird through obstacles. Here, we’ll build our very own Flappy Bird game with Python.

We’ll be using Pygame, a Python library specifically designed for making video games. Pygame is an open-source library that helps us create fully functional games and multimedia programs in Python.

First, you need to install the Pygame library using the command:

pip install pygame

Let’s get started

copy the code below and paste it in your code editor

Full Code:

import pygame, random, time
from pygame.locals import *

#VARIABLES
SCREEN_WIDHT = 400
SCREEN_HEIGHT = 600
SPEED = 20
GRAVITY = 2.5
GAME_SPEED = 15

GROUND_WIDHT = 2 * SCREEN_WIDHT
GROUND_HEIGHT= 100

PIPE_WIDHT = 80
PIPE_HEIGHT = 500

PIPE_GAP = 150

wing = 'wing.wav'
hit = 'hit.wav'

pygame.mixer.init()


class Bird(pygame.sprite.Sprite):

    def __init__(self):
        pygame.sprite.Sprite.__init__(self)

        self.images =  [pygame.image.load('bluebird-upflap.png').convert_alpha(),
                        pygame.image.load('bluebird-midflap.png').convert_alpha(),
                        pygame.image.load('bluebird-downflap.png').convert_alpha()]

        self.speed = SPEED

        self.current_image = 0
        self.image = pygame.image.load('bluebird-upflap.png').convert_alpha()
        self.mask = pygame.mask.from_surface(self.image)

        self.rect = self.image.get_rect()
        self.rect[0] = SCREEN_WIDHT / 6
        self.rect[1] = SCREEN_HEIGHT / 2

    def update(self):
        self.current_image = (self.current_image + 1) % 3
        self.image = self.images[self.current_image]
        self.speed += GRAVITY

        #UPDATE HEIGHT
        self.rect[1] += self.speed

    def bump(self):
        self.speed = -SPEED

    def begin(self):
        self.current_image = (self.current_image + 1) % 3
        self.image = self.images[self.current_image]




class Pipe(pygame.sprite.Sprite):

    def __init__(self, inverted, xpos, ysize):
        pygame.sprite.Sprite.__init__(self)

        self. image = pygame.image.load('pipe-green.png').convert_alpha()
        self.image = pygame.transform.scale(self.image, (PIPE_WIDHT, PIPE_HEIGHT))


        self.rect = self.image.get_rect()
        self.rect[0] = xpos

        if inverted:
            self.image = pygame.transform.flip(self.image, False, True)
            self.rect[1] = - (self.rect[3] - ysize)
        else:
            self.rect[1] = SCREEN_HEIGHT - ysize


        self.mask = pygame.mask.from_surface(self.image)


    def update(self):
        self.rect[0] -= GAME_SPEED

        

class Ground(pygame.sprite.Sprite):
    
    def __init__(self, xpos):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load('base.png').convert_alpha()
        self.image = pygame.transform.scale(self.image, (GROUND_WIDHT, GROUND_HEIGHT))

        self.mask = pygame.mask.from_surface(self.image)

        self.rect = self.image.get_rect()
        self.rect[0] = xpos
        self.rect[1] = SCREEN_HEIGHT - GROUND_HEIGHT
    def update(self):
        self.rect[0] -= GAME_SPEED

def is_off_screen(sprite):
    return sprite.rect[0] < -(sprite.rect[2])

def get_random_pipes(xpos):
    size = random.randint(100, 300)
    pipe = Pipe(False, xpos, size)
    pipe_inverted = Pipe(True, xpos, SCREEN_HEIGHT - size - PIPE_GAP)
    return pipe, pipe_inverted


pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDHT, SCREEN_HEIGHT))
pygame.display.set_caption('Flappy Bird')

BACKGROUND = pygame.image.load('background-day.png')
BACKGROUND = pygame.transform.scale(BACKGROUND, (SCREEN_WIDHT, SCREEN_HEIGHT))
BEGIN_IMAGE = pygame.image.load('message.png').convert_alpha()

bird_group = pygame.sprite.Group()
bird = Bird()
bird_group.add(bird)

ground_group = pygame.sprite.Group()

for i in range (2):
    ground = Ground(GROUND_WIDHT * i)
    ground_group.add(ground)

pipe_group = pygame.sprite.Group()
for i in range (2):
    pipes = get_random_pipes(SCREEN_WIDHT * i + 800)
    pipe_group.add(pipes[0])
    pipe_group.add(pipes[1])



clock = pygame.time.Clock()

begin = True

while begin:

    clock.tick(15)

    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
        if event.type == KEYDOWN:
            if event.key == K_SPACE or event.key == K_UP:
                bird.bump()
                pygame.mixer.music.load(wing)
                pygame.mixer.music.play()
                begin = False

    screen.blit(BACKGROUND, (0, 0))
    screen.blit(BEGIN_IMAGE, (120, 150))

    if is_off_screen(ground_group.sprites()[0]):
        ground_group.remove(ground_group.sprites()[0])

        new_ground = Ground(GROUND_WIDHT - 20)
        ground_group.add(new_ground)

    bird.begin()
    ground_group.update()

    bird_group.draw(screen)
    ground_group.draw(screen)

    pygame.display.update()


while True:

    clock.tick(15)

    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
        if event.type == KEYDOWN:
            if event.key == K_SPACE or event.key == K_UP:
                bird.bump()
                pygame.mixer.music.load(wing)
                pygame.mixer.music.play()

    screen.blit(BACKGROUND, (0, 0))

    if is_off_screen(ground_group.sprites()[0]):
        ground_group.remove(ground_group.sprites()[0])

        new_ground = Ground(GROUND_WIDHT - 20)
        ground_group.add(new_ground)

    if is_off_screen(pipe_group.sprites()[0]):
        pipe_group.remove(pipe_group.sprites()[0])
        pipe_group.remove(pipe_group.sprites()[0])

        pipes = get_random_pipes(SCREEN_WIDHT * 2)

        pipe_group.add(pipes[0])
        pipe_group.add(pipes[1])

    bird_group.update()
    ground_group.update()
    pipe_group.update()

    bird_group.draw(screen)
    pipe_group.draw(screen)
    ground_group.draw(screen)

    pygame.display.update()

    if (pygame.sprite.groupcollide(bird_group, ground_group, False, False, pygame.sprite.collide_mask) or
            pygame.sprite.groupcollide(bird_group, pipe_group, False, False, pygame.sprite.collide_mask)):
        pygame.mixer.music.load(hit)
        pygame.mixer.music.play()
        time.sleep(1)
        break

Note – If you wish You can download the images from here for the flappy bird game, the ones which i have used.

Output:

Explanation of the whole code:

Importing Libraries: The code starts by importing the necessary libraries: pygame for creating the game, random for generating random numbers, and time for handling time-related tasks.

import pygame, random, time
from pygame.locals import *

Setting Variables: Various game settings are defined, such as screen dimensions, speed, gravity, and dimensions for the ground and pipes.

SCREEN_WIDTH = 400
SCREEN_HEIGHT = 600
SPEED = 20
GRAVITY = 2.5
GAME_SPEED = 15
GROUND_WIDTH = 2 * SCREEN_WIDTH
GROUND_HEIGHT = 100
PIPE_WIDTH = 80
PIPE_HEIGHT = 500
PIPE_GAP = 150
wing = 'wing.wav'
hit = 'hit.wav'

Initializing Pygame’s Mixer: This initializes the sound mixer for playing sound effects.

pygame.mixer.init()

Creating the Bird Class: This class defines the bird’s behavior, such as loading its images, handling its movement, and updating its position based on gravity.

class Bird(pygame.sprite.Sprite):
    def __init__(self):
        # Initialize the bird sprite
        pygame.sprite.Sprite.__init__(self)
        self.images =  [pygame.image.load('bluebird-upflap.png').convert_alpha(),
                        pygame.image.load('bluebird-midflap.png').convert_alpha(),
                        pygame.image.load('bluebird-downflap.png').convert_alpha()]
        self.speed = SPEED
        self.current_image = 0
        self.image = pygame.image.load('bluebird-upflap.png').convert_alpha()
        self.mask = pygame.mask.from_surface(self.image)
        self.rect = self.image.get_rect()
        self.rect[0] = SCREEN_WIDTH / 6
        self.rect[1] = SCREEN_HEIGHT / 2

    def update(self):
        # Update the bird's position and image
        self.current_image = (self.current_image + 1) % 3
        self.image = self.images[self.current_image]
        self.speed += GRAVITY
        self.rect[1] += self.speed

    def bump(self):
        # Make the bird jump
        self.speed = -SPEED

    def begin(self):
        # Update the bird's image at the beginning
        self.current_image = (self.current_image + 1) % 3
        self.image = self.images[self.current_image]

Creating the Pipe Class: This class defines the pipes that the bird must avoid. It handles loading the pipe images, positioning them, and moving them across the screen.

class Pipe(pygame.sprite.Sprite):
    def __init__(self, inverted, xpos, ysize):
        # Initialize the pipe sprite
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load('pipe-green.png').convert_alpha()
        self.image = pygame.transform.scale(self.image, (PIPE_WIDTH, PIPE_HEIGHT))
        self.rect = self.image.get_rect()
        self.rect[0] = xpos
        if inverted:
            self.image = pygame.transform.flip(self.image, False, True)
            self.rect[1] = - (self.rect[3] - ysize)
        else:
            self.rect[1] = SCREEN_HEIGHT - ysize
        self.mask = pygame.mask.from_surface(self.image)

    def update(self):
        # Move the pipe leftward
        self.rect[0] -= GAME_SPEED

Creating the Ground Class: This class handles the ground’s behavior, including loading the ground image, positioning it, and moving it to create a scrolling effect.

class Ground(pygame.sprite.Sprite):
    def __init__(self, xpos):
        # Initialize the ground sprite
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load('base.png').convert_alpha()
        self.image = pygame.transform.scale(self.image, (GROUND_WIDTH, GROUND_HEIGHT))
        self.mask = pygame.mask.from_surface(self.image)
        self.rect = self.image.get_rect()
        self.rect[0] = xpos
        self.rect[1] = SCREEN_HEIGHT - GROUND_HEIGHT

    def update(self):
        # Move the ground leftward
        self.rect[0] -= GAME_SPEED

Helper Functions: These functions check if a sprite has moved off the screen and generate random pipes for the game.

def is_off_screen(sprite):
    return sprite.rect[0] < -(sprite.rect[2])

def get_random_pipes(xpos):
    size = random.randint(100, 300)
    pipe = Pipe(False, xpos, size)
    pipe_inverted = Pipe(True, xpos, SCREEN_HEIGHT - size - PIPE_GAP)
    return pipe, pipe_inverted

Initializing the Game: This section initializes Pygame, sets up the display window, loads the background image, and initializes sprite groups for the bird, ground, and pipes.

pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('Flappy Bird')
BACKGROUND = pygame.image.load('background-day.png')
BACKGROUND = pygame.transform.scale(BACKGROUND, (SCREEN_WIDTH, SCREEN_HEIGHT))
BEGIN_IMAGE = pygame.image.load('message.png').convert_alpha()

Setting Up Sprites: This section creates instances of the Bird, Ground, and Pipe classes, and adds them to their respective sprite groups.

bird_group = pygame.sprite.Group()
bird = Bird()
bird_group.add(bird)

ground_group = pygame.sprite.Group()
for i in range(2):
    ground = Ground(GROUND_WIDTH * i)
    ground_group.add(ground)

pipe_group = pygame.sprite.Group()
for i in range(2):
    pipes = get_random_pipes(SCREEN_WIDTH * i + 800)
    pipe_group.add(pipes[0])
    pipe_group.add(pipes[1])

Main Game Loop (Begin Screen): This loop displays the starting screen and waits for the player to press a key to start the game.

clock = pygame.time.Clock()
begin = True

while begin:
    clock.tick(15)

    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
        if event.type == KEYDOWN:
            if event.key == K_SPACE or event.key == K_UP:
                bird.bump()  # Make the bird jump
                pygame.mixer.music.load(wing)
                pygame.mixer.music.play()
                begin = False  # Exit the begin screen loop

    screen.blit(BACKGROUND, (0, 0))  # Draw the background
    screen.blit(BEGIN_IMAGE, (120, 150))  # Draw the beginning image

    if is_off_screen(ground_group.sprites()[0]):
        ground_group.remove(ground_group.sprites()[0])
        new_ground = Ground(GROUND_WIDTH - 20)
        ground_group.add(new_ground)

    bird.begin()  # Update bird animation
    ground_group.update()  # Update ground position

    bird_group.draw(screen)  # Draw bird
    ground_group.draw(screen)  # Draw ground

    pygame.display.update()  # Update the display

Main Game Loop (Gameplay): This is the main game loop where the actual game runs. It handles events, updates game objects, checks for collisions, and renders everything on the screen.

while True:
    clock.tick(15)

    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
        if event.type == KEYDOWN:
            if event.key == K_SPACE or event.key == K_UP:
                bird.bump()  # Make the bird jump
                pygame.mixer.music.load(wing)
                pygame.mixer.music.play()

    screen.blit(BACKGROUND, (0, 0))  # Draw the background

    if is_off_screen(ground_group.sprites()[0]):
        ground_group.remove(ground_group.sprites()[0])
        new_ground = Ground(GROUND_WIDTH - 20)
        ground_group.add(new_ground)

    if is_off_screen(pipe_group.sprites()[0]):
        pipe_group.remove(pipe_group.sprites()[0])
        pipe_group.remove(pipe_group.sprites()[0])
        pipes = get_random_pipes(SCREEN_WIDTH * 2)
        pipe_group.add(pipes[0])
        pipe_group.add(pipes[1])

    bird_group.update()  # Update bird position and animation
    ground_group.update()  # Update ground position
    pipe_group.update()  # Update pipes position

    bird_group.draw(screen)  # Draw bird
    pipe_group.draw(screen)  # Draw pipes
    ground_group.draw(screen)  # Draw ground

    pygame.display.update()  # Update the display

    # Check for collisions
    if (pygame.sprite.groupcollide(bird_group, ground_group, False, False, pygame.sprite.collide_mask) or
            pygame.sprite.groupcollide(bird_group, pipe_group, False, False, pygame.sprite.collide_mask)):
        pygame.mixer.music.load(hit)
        pygame.mixer.music.play()
        time.sleep(1)
        break

Explanation of Key Components

  • Variables: Constants like SCREEN_WIDTH, SCREEN_HEIGHT, and SPEED are defined to set the game’s dimensions and speeds.
  • Classes: Bird, Pipe, and Ground classes handle the game’s main objects, including their images, positions, and movements.
  • Helper Functions: is_off_screen checks if an object is off the screen, and get_random_pipes generates random pipes for the bird to navigate through.
  • Initialization: Pygame is initialized, and the display, background, and sprite groups are set up.
  • Begin Screen Loop: This loop displays the start screen and waits for player input to begin the game.
  • Main Game Loop: This loop handles the main gameplay, including event handling, updating positions, drawing objects, and checking for collisions.

This code essentially sets up and runs a simple version of the Flappy Bird game, where the player controls a bird that must navigate through gaps between pipes while avoiding the ground and pipes. The game includes basic animations, collision detection, and sound effects.

Creating a Flappy Bird game using Pygame in Python is a fantastic way to delve into game development and enhance your programming skills. By following the steps outlined in this tutorial, you’ve learned how to set up the game environment, manage game sprites, handle user inputs, and implement collision detection. This project not only demonstrates the power of Pygame for creating interactive applications but also provides a solid foundation for developing more complex games in the future. Keep experimenting and have fun as you continue your journey in game development!

Author

Sona Avatar

Written by

Leave a Reply

Trending

CodeMagnet

Your Magnetic Resource, For Coding Brilliance

Programming Languages

Web Development

Data Science and Visualization

Career Section

<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4205364944170772"
     crossorigin="anonymous"></script>