Flappy Bird In Python Pygame with source code

Flappy Bird In Python Pygame

MAKING THE GAME DYNAMIC FROM STATIC

Now, our task is to make the pipes movable we’ll move the pipes from right to left and it will give the illusion that the bird is moving. After then we also have to make our Flappy Bird flap. After then we’ll check for score and will show it on the screen we’ll check for collisions and after the collision, we’ll call our gameover function, and then we boom. Our Flappy Bird In Python Pygame will be completed.

So without any further delay let’s make our game static to dynamic. Look at the code that we are going to code in this particular section.

import random #for generating random numbers
import sys #To Exit the game
import pygame
from pygame.locals import * #Basic Pygame Imports

FPS = 32
SCREENWIDTH = 289
SCREENHEIGHT = 511
SCREEN = pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT))
GROUNDY = SCREENHEIGHT*0.8
GAME_SPRITES = {}
GAME_SOUNDS = {}
PLAYER = 'resources\SPRITES\\bird.png'
BACKGROUND = 'resources\SPRITES\\bg.jpeg'
PIPE = 'resources\SPRITES\pipe.png '

def welcomeScreen():

    #IT WIll Show Welcome Screen TO user to make the game more interactive and interesting
    playerx = int(SCREENWIDTH/5)
    playery = int(SCREENHEIGHT - GAME_SPRITES['player'].get_height())/2
    messagex = int(SCREENWIDTH - GAME_SPRITES['message'].get_width())/2
    messagey = int(SCREENHEIGHT * 0.13)
    basex = 0
    
    # Drawing Rectangle for playbutton
    playbutton = pygame.Rect(108,222,68,65)

    while True:
        for event in pygame.event.get():
             #If user clicks on Cross or presses the Escape button Close the Game
            if event.type== QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
                pygame.quit()
                sys.exit()

            elif event.type == KEYDOWN and (event.key == K_SPACE or event.key == K_UP):
                return

            pygame.mouse.set_cursor(pygame.SYSTEM_CURSOR_ARROW)
            if pygame.mouse.get_pos()[0] > playbutton[0]  and pygame.mouse.get_pos()[0] < playbutton[0] + playbutton[2]:
                if pygame.mouse.get_pos()[1] > playbutton[1]  and pygame.mouse.get_pos()[1] < playbutton[1] + playbutton[3]:
                    pygame.mouse.set_cursor(pygame.SYSTEM_CURSOR_HAND)

            if playbutton.collidepoint(pygame.mouse.get_pos()): #checking if mouse is collided with the play button
            
                if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: #checking if mouse has been clicked
                    mainGame()

            else :
                SCREEN.blit(GAME_SPRITES['background'],(0,0))
                SCREEN.blit(GAME_SPRITES['player'],(playerx,playery))
                SCREEN.blit(GAME_SPRITES['message'],(messagex,messagey))
                SCREEN.blit(GAME_SPRITES['base'],(basex,GROUNDY))
                pygame.display.update()
                FPSCLOCK.tick(FPS)

def mainGame():
    
    score = 0
    playerx = int(SCREENWIDTH/5)
    playery = int (SCREENHEIGHT/2)
    basex = 0

    #Creating upper and Lower Pipes for the game
    newPipe1 = getRandomPipe()
    newPipe2 = getRandomPipe()

    # Upper pipe List
    upperPipes = [
        {'x':SCREENWIDTH + 200, 'y': newPipe1[0]['y']},
        {'x':SCREENWIDTH + 200 + (SCREENWIDTH/2), 'y': newPipe2[0]['y']}
    ]

    #lists of Lower Pipe
    lowerPipes = [
        {'x':SCREENWIDTH + 200, 'y': newPipe1[1]['y']},
        {'x':SCREENWIDTH + 200 + (SCREENWIDTH/2), 'y': newPipe2[1]['y']}
    ]

    pipeVelX = -4
    playerVelY = -9
    playerMaxVelY = 10  
    playerMinVelY = -8
    playerAccY = 1

    playerFlapAccv = -8 # velocity while flapping
    playerFlapped = False # It is true only when the bird is flapping

    while True:

        for event in pygame.event.get():
           
            if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
                pygame.quit()
                sys.exit()

            if event.type == KEYDOWN and (event.key == K_SPACE or event.key == K_UP):
                if playery > 0:
                    playerVelY = playerFlapAccv
                    playerFlapped = True
                    GAME_SOUNDS['wing'].play()

        if playerVelY <playerMaxVelY and not playerFlapped:
            playerVelY += playerAccY

        if playerFlapped:
            playerFlapped = False            
        playerHeight = GAME_SPRITES['player'].get_height()
        playery = playery + min(playerVelY, GROUNDY - playery - playerHeight)

        # move pipes to the left
        for upperPipe , lowerPipe in zip(upperPipes, lowerPipes):
            upperPipe['x'] += pipeVelX
            lowerPipe['x'] += pipeVelX

        # Add a new pipe when the first is about to cross the leftmost part of the screen
        if 0<upperPipes[0]['x']<5:
            newpipe = getRandomPipe()
            upperPipes.append(newpipe[0])
            lowerPipes.append(newpipe[1])

        # if the pipe is out of the screen, remove it
        if upperPipes[0]['x'] < -GAME_SPRITES['pipe'][0].get_width():
            upperPipes.pop(0)
            lowerPipes.pop(0)

        # Lets blit our sprites now
        SCREEN.blit(GAME_SPRITES['background'], (0, 0))
        for upperPipe, lowerPipe in zip(upperPipes, lowerPipes):
            SCREEN.blit(GAME_SPRITES['pipe'][0], (upperPipe['x'], upperPipe['y']))
            SCREEN.blit(GAME_SPRITES['pipe'][1], (lowerPipe['x'], lowerPipe['y']))

        SCREEN.blit(GAME_SPRITES['base'], (basex, GROUNDY))
        SCREEN.blit(GAME_SPRITES['player'], (playerx, playery))
        pygame.display.update()
        FPSCLOCK.tick(FPS)

def getRandomPipe():
    """
    generating positions of the two pipes one upper pipe and other lower pipe 
    To blit on the Screen
    """
                
    pipeHeight = GAME_SPRITES['pipe'][0].get_height()
    offset = SCREENHEIGHT/4.5
    y2 = offset + random.randrange(0, int(SCREENHEIGHT - GAME_SPRITES['base'].get_height() - 1.2 *offset))
    pipeX = SCREENWIDTH + 10
    y1 = pipeHeight - y2 + offset
    pipe = [ 
        {'x': pipeX, 'y': -y1}, #Upper Pipes
        {'x': pipeX, 'y': y2}   #Lower Pipes
    ]
    return pipe 


 ### This is the point from Where Our Game is going to be Started ###
if __name__ == "__main__":

    pygame.init() #Initializing the Modules of Pygame 
    FPSCLOCK = pygame.time.Clock() #for controlling the FPS
    pygame.display.set_caption('Flappy Bird With Sameer') #Setting the Caption of The Game

    #### LOADING THE SPRITES ####

    GAME_SPRITES['numbers'] = (
        pygame.image.load('resources\SPRITES\\0.png').convert_alpha(),
        pygame.image.load('resources\SPRITES\\1.png').convert_alpha(),
        pygame.image.load('resources\SPRITES\\2.png').convert_alpha(),
        pygame.image.load('resources\SPRITES\\3.png').convert_alpha(),
        pygame.image.load('resources\SPRITES\\4.png').convert_alpha(),
        pygame.image.load('resources\SPRITES\\5.png').convert_alpha(),
        pygame.image.load('resources\SPRITES\\6.png').convert_alpha(),
        pygame.image.load('resources\SPRITES\\7.png').convert_alpha(),
        pygame.image.load('resources\SPRITES\\8.png').convert_alpha(),
        pygame.image.load('resources\SPRITES\\9.png').convert_alpha(),
    
    ) 
    
    
    GAME_SPRITES['background'] = pygame.image.load(BACKGROUND).convert_alpha()
    GAME_SPRITES['player'] = pygame.image.load(PLAYER).convert_alpha()
    GAME_SPRITES['message'] = pygame.image.load('resources\SPRITES\message.png').convert_alpha()
    GAME_SPRITES['base'] = pygame.image.load('resources\SPRITES\\base.png').convert_alpha()
    GAME_SPRITES['pipe'] = (
        
        
    pygame.transform.rotate(pygame.image.load(PIPE).convert_alpha(), 180), #### UPPER PIPES, WE JUST ROTATED THE PIPE BY 180deg
    pygame.image.load(PIPE).convert_alpha()   #### LOWER PIPES  
    )

    #Game Sounds
    GAME_SOUNDS['die'] = pygame.mixer.Sound('resources\AUDIO\die.wav')
    GAME_SOUNDS['hit'] = pygame.mixer.Sound('resources\AUDIO\hit.wav')
    GAME_SOUNDS['point'] = pygame.mixer.Sound('resources\AUDIO\point.wav')
    GAME_SOUNDS['swoosh'] = pygame.mixer.Sound('resources\AUDIO\swoosh.wav')
    GAME_SOUNDS['wing'] = pygame.mixer.Sound('resources\AUDIO\wing.wav')
    while True:
        welcomeScreen() #Shows a welcomescreen to the user until they starts the game
        mainGame() #This is our main game funtion

Now we will understand it by part wise

    pipeVelX = -4
    playerVelY = -9
    playerMaxVelY = 10 
    playerMinVelY = -8
    playerAccY = 1
 
    playerFlapAccv = -8 # velocity while flapping
    playerFlapped = False # It is true only when the bird is flapping

First, we declare the value of the pipe velocity which is -4 because we want to move our pipe from right to left not left to right. Then we set the player’s y velocity to -9 and the maximum and minimum velocity of the player’s y is 10 and -8 respectively.
And then we declared a Boolean variable of playerFlapped which will be True when the bird is flapping.

            if event.type == KEYDOWN and (event.key == K_SPACE or event.key == K_UP):
                if playery > 0:
                    playerVelY = playerFlapAccv
                    playerFlapped = True
                    GAME_SOUNDS['wing'].play()
 

This will check if the user has pressed the SPACE bar key or UP ARROW key and if playerY is greater than the 0 then update the player’s y velocity with player’s velocity while flapping.

After then changed the boolean value to true from false that the player is flapped and played the sound effect.

IF PLAYER HAS TOUCHED THE GROUND

if playerFlapped:
            playerFlapped = False           
        playerHeight = GAME_SPRITES['player'].get_height()
        playery = playery + min(playerVelY, GROUNDY - playery - playerHeight)

This will make sure that if the bird has touched the ground then don’t go further than that and set the value of the playerY to playerY because (GROUNDY – playery – playerHeight) this value will become zero if the bird will touch the ground and minimum of any no with zero will be zero. That’s the logic behind this.
If you are not understanding it you can check the value graphically by the rough diagram on your notebook and the bird should be in touch with the base or the ground.

# move pipes to the left
        for upperPipe , lowerPipe in zip(upperPipes, lowerPipes):
            upperPipe['x'] += pipeVelX
            lowerPipe['x'] += pipeVelX
 
        # Add a new pipe when the first is about to cross the leftmost part of the screen
        if 0<upperPipes[0]['x']<5:
            newpipe = getRandomPipe()
            upperPipes.append(newpipe[0])
            lowerPipes.append(newpipe[1])
 
        # if the pipe is out of the screen, remove it
        if upperPipes[0]['x'] < -GAME_SPRITES['pipe'][0].get_width():
            upperPipes.pop(0)
            lowerPipes.pop(0)

This will move our pipe from the right to left and when the pipe is going to cross the leftmost part of the screen then we created another pipe and it will be in an infinite loop.

The last line will remove the pipe if it’s out of the screen. Hope you understand. Now, look at the output of the code.

Now our work is to display the score and after that, we will detect the collision and make the game over. So we’ll look after it. After the collision, we will call our game over the function which we’ll create. And then we’ll add some background music in the game and the welcome screen as well.

Share:

Author: Sameer Pandey