Open In App

Angry Bird Game Using PyGame

Last Updated : 26 Sep, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Let’s discuss the angry bird game using Pygame, I hope this article will be very interesting as it provides a holistic gaming experience at the end. We begin by describing the modules necessary to develop this game.

Angry Birds Game Using PyGame

The objective of the game is to hit as many enemy birds as possible to score points. Your score increases by 100 points each time you hit an enemy bird. The game also features a “Level Cleared” condition if you score 500 points or more, and a “Game Over” condition if your score reaches 0 after three unsuccessful attempts. The below code was developed to achieve this gaming objective.

Folder Structure

The folder structure should look like this and you can download the images from the GitHub Repository given at the end of the article. Pygame should be installed

Angry Bird Game Using PyGame

Folder Structure Of The Project

Steps to Implement Angry Birds Game

Below are the step-by-step approaches for developing an angry bird game using Python

Step 1: Import all the necessary libraries

For this interactive game, four libraries are required.

Python3




# Import necessary libraries
import pygame
import sys
import random
import math


Output:

pygame 2.5.0 (SDL 2.28.0, Python 3.10.6)
Hello from the pygame community. https://www.pygame.org/contribute.html

Step 2: Initialize Pygame, Set Screen Dimensions, and Load Images

This initializes the Pygame library, allowing you to use its functionalities to build your game. Then create the game window with the specified dimensions and set its title to “Angry Birds”

Python3




# Initialize Pygame
pygame.init()
 
# Set up screen dimensions and colors
SCREEN_WIDTH = 1400
SCREEN_HEIGHT = 700
 
# Create the game window
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Angry Birds")


Next, we load images for the player bird, enemy birds, and the background. The background image is also resized to fit the screen dimensions. You can download images from the GitHub repo given at the last of the article.

Python3




# Load bird and background images
player_bird_image = pygame.image.load(
    "angry_bird_pygame/Images/player_bird1.png")
enemy_bird_image = pygame.image.load(
    "angry_bird_pygame/Images/enemy_bird1.png")
background_image = pygame.image.load("angry_bird_pygame/Images/background.png")
 
# Scale the background image to fit the screen dimensions
background_image = pygame.transform.scale(
    background_image, (SCREEN_WIDTH, SCREEN_HEIGHT))


Step 3: Defining Bird Class

Here we define the Bird class. It inherits from pygame.sprite.Sprite, which is a base class for all sprites in Pygame. The constructor __init__ initializes various properties of the bird, including its image, position, velocity, and dragging status.

Python3




# Define the Bird class
class Bird(pygame.sprite.Sprite):
    def __init__(self, x, y, image):
        super().__init__()
        # Initialize properties
        self.image = image
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)
        self.velocity = [0, 0]
        self.dragging = False
        self.drag_start_pos = (0, 0)


In this Bird class, we define separate methods such as update(), start_drag(), end_drag() and hit_enemy(). The update method, updates the bird’s position based on its dragging status or velocity. If the bird is being dragged by the player, its position follows the mouse cursor. Otherwise, its position changes according to its velocity.

Python3




def update(self):
    # Update bird's position based on dragging or velocity
    if self.dragging:
        mouse_pos = pygame.mouse.get_pos()
        self.rect.centerx = mouse_pos[0]
        self.rect.centery = mouse_pos[1]
    else:
        self.rect.x += self.velocity[0]
        self.rect.y += self.velocity[1]


This method, start_drag, is called when the player clicks on the bird. It sets the bird’s dragging status to True and stores the initial position for reference. This method, end_drag, is called when the player releases the bird. It calculates the velocity of the bird based on the direction in which it was dragged and assigns it a constant speed.

Python3




def start_drag(self):
        # Start dragging the bird
        self.dragging = True
        self.drag_start_pos = self.rect.center
 
    def end_drag(self):
        # Release the bird and set its velocity based on drag direction
        self.dragging = False
        mouse_pos = pygame.mouse.get_pos()
        direction = math.atan2(self.drag_start_pos[1] - mouse_pos[1],
                               self.drag_start_pos[0] - mouse_pos[0])
        speed = 10
        self.velocity = [speed * math.cos(direction),
                         speed * math.sin(direction)]


This method, hit_enemy, is called when the player’s bird collides with an enemy bird. It increases the score by 100 points.

Python3




def hit_enemy(self):
    # Handle collision with enemy bird
    global score
    score += 100


Step 4: Defining Button class and Creating Enemy Birds

This is the definition of the Button class. Similar to the Bird class, it inherits from pygame.sprite.Sprite. The constructor initializes the button’s image, position, and an action associated with the button.

Python3




# Define the Button class
class Button(pygame.sprite.Sprite):
    def __init__(self, x, y, image, action):
        super().__init__()
        # Initialize properties
        self.image = image
        self.rect = self.image.get_rect()
        self.rect.topleft = (x, y)
        self.action = action


Here, you create instances of the player bird and multiple enemy birds. Their positions are randomly generated within specified ranges.

Python3




# Create the player bird
player_bird = Bird(100, SCREEN_HEIGHT // 2, player_bird_image)
 
# Create enemy birds
enemy_birds = pygame.sprite.Group()
for _ in range(5):
    x = random.randint(SCREEN_WIDTH // 2, SCREEN_WIDTH - 50)
    y = random.randint(50, SCREEN_HEIGHT - 50)
    enemy_bird = Bird(x, y, enemy_bird_image)
    enemy_birds.add(enemy_bird)


These lines define variables for button positions and the player’s score. The score_position variable specifies where the score will be displayed on the screen.

Python3




# Calculate button positions and initialize score
button_margin = 10
button_top = button_margin
button_left = button_margin
button_spacing = 5
 
# Initialize player's score
score = 0
 
# Calculate position for displaying the score
score_position = (1260, 80)


These lines load images for the quit and refresh buttons and create instances of the Button class for them.

Python3




# Create quit and refresh buttons
quit_button_image = pygame.image.load(
    "angry_bird_pygame/Images/quit_button.png")
refresh_button_image = pygame.image.load(
    "angry_bird_pygame/Images/refresh_button.png")
 
quit_button = Button(button_left, button_top, quit_button_image, "quit")
refresh_button = Button(button_left + quit_button_image.get_width() +
                        button_spacing, button_top,
                        refresh_button_image, "refresh")


Step 5: Initialize Game Loop and Game State Variables

Here, we set up a font for displaying messages and initialize the game loop, clock, and various game state variables.

Python3




# Initialize game loop and state
clock = pygame.time.Clock()
try_again_counter = 0
max_try_again = 3
level_cleared = False
game_over = False


In this part, the game loop processes events, such as quitting the game, clicking on buttons and interacting with the player bird. If the “Quit” button is clicked, the game exits. If the “Refresh” button is clicked, the player bird’s position, enemy bird positions, and game state are reset. If the player bird is clicked, dragging is initiated. When the mouse button is released, the dragging ends, and the “try_again_counter” is incremented if no collisions occur.

Python3




# Enter the game loop
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
 
        # Handle button clicks and player interactions
        if event.type == pygame.MOUSEBUTTONDOWN:
            # Check if the Quit button was clicked
            if quit_button.rect.collidepoint(event.pos):
                pygame.quit()
                sys.exit()
 
            # Check if the Refresh button was clicked
            elif refresh_button.rect.collidepoint(event.pos):
                # Reset player bird's position and velocity
                player_bird.rect.center = (100, SCREEN_HEIGHT // 2)
                player_bird.velocity = [0, 0]
 
                # Reset enemy birds and their positions
                enemy_birds.empty()
                for _ in range(5):
                    x = random.randint(SCREEN_WIDTH // 2, SCREEN_WIDTH - 50)
                    y = random.randint(50, SCREEN_HEIGHT - 50)
                    enemy_bird = Bird(x, y, enemy_bird_image)
                    enemy_birds.add(enemy_bird)
 
                # Reset game state
                level_cleared = False
                game_over = False
                try_again_counter = 0
                score = 0
 
            # Check if the player bird was clicked
            elif player_bird.rect.collidepoint(event.pos):
                player_bird.start_drag()
 
        elif event.type == pygame.MOUSEBUTTONUP:
            if player_bird.dragging:
                player_bird.end_drag()
 
                # Increment try_again_counter if no hits occurred
                if not hits:
                    try_again_counter += 1
            else:
                break


In this part, we update enemy bird positions and handle collisions between the player bird and enemy birds. If a collision occurs, the hit enemy bird is removed and the hit_enemy method is called to update the score. The code also resets enemy bird positions that go off-screen and resets the player bird’s position if it goes off-screen.

Python3




# Update enemy bird positions and handle collisions
  hits = pygame.sprite.spritecollide(player_bird, enemy_birds, True)
 
   if hits:
        for hit_enemy in hits:
            hit_enemy.hit_enemy()
 
    # Reset enemy bird positions
    for enemy_bird in enemy_birds:
        if enemy_bird.rect.right < 0:
            enemy_bird.rect.left = SCREEN_WIDTH
            enemy_bird.rect.top = random.randint(50, SCREEN_HEIGHT - 50)
 
    # Reset player bird's position if it goes off-screen
    if player_bird.rect.left > SCREEN_WIDTH or player_bird.rect.right < 0 or \
            player_bird.rect.top > SCREEN_HEIGHT or player_bird.rect.bottom < 0:
        player_bird.rect.center = (100, SCREEN_HEIGHT // 2)
        player_bird.velocity = [0, 0]


Step 6: Display Level Cleared and Game Over

Here we provide the “Level Cleared” condition if we score 500 points or more, and a “Game Over” condition if the score is still 0 after three unsuccessful attempts. Based on this logic, the display message will be shown on the game screen.

Python3




# Clear the screen and draw the background
screen.blit(background_image, (0, 0))
 
# Draw player bird and enemy birds
player_bird.update()
screen.blit(player_bird.image, player_bird.rect)
 
# Update and draw enemy birds
enemy_birds.update()
enemy_birds.draw(screen)
 
# Display font
font = pygame.font.Font(None, 50)
 
# Score font
score_font = pygame.font.Font(None, 36)
 
# Draw player's score and buttons
score_text = score_font.render(f"Score: {score}", True, (0, 0, 0))
screen.blit(score_text, score_position)
 
 screen.blit(quit_button.image, quit_button.rect)
  screen.blit(refresh_button.image, refresh_button.rect)
 
   # Display "Level Cleared" message if score is 500
   if score >= 500 and not level_cleared:
        level_cleared_text = font.render("LEVEL CLEARED", True, (0, 0, 0))
        text_rect = level_cleared_text.get_rect(
            center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
        screen.blit(level_cleared_text, text_rect)
        level_cleared = True
 
    # Display "Game Over" message if score is 0 after three hits
    if score == 0 and try_again_counter >= max_try_again and not game_over:
        game_over_text = font.render("GAME OVER", True, (0, 0, 0))
        text_rect = game_over_text.get_rect(
            center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
        screen.blit(game_over_text, text_rect)
        game_over = True
 
    # Update the display and control the frame rate
    pygame.display.flip()
    clock.tick(60)
 
pygame.quit()


Controls to play Angry Birds Game

1. Drag the Player Bird: Click and hold the left mouse button on the player bird. While holding the mouse button, move the mouse to drag the player bird around the screen.

2. Release the Player Bird: Release the left mouse button to release the player bird. The bird will be launched in the direction you dragged it, and it will move with a constant speed.

3. Quit Button: Click the “Quit” button in the top-left corner of the screen to exit the game.

4. Refresh Button: Click the “Refresh” button next to the “Quit” button to restart the game. This resets the player bird’s position, resets the enemy birds, and clears the current score and game state.

Gameplay

Enemy birds will be randomly placed on the screen. Your goal is to launch the player bird to hit these enemy birds and score points.
If you hit an enemy bird, your score increases by 100 points. The hit enemy bird will be removed from the screen, and a new one will appear in a random position.
If the player bird goes off-screen, its position will be reset to its initial position.
If you manage to score 500 points or more, a "LEVEL CLEARED" message will appear at the center of the screen, indicating that you have completed the level.
If your score reaches 0 after three unsuccessful attempts (no hits), a "GAME OVER" message will appear at the center of the screen, indicating that the game is over.

Full Code Implementation

The entire code, combining all the above steps to start playing our angry bird game using Python is ready. The below code includes defining classes for the birds and buttons, creating instances of those classes, and preparing the game loop and related state variables in order to create an interactive seamless gaming experience. Further, improve this code with additional features, and more features to make this very interesting. Let’s start the game now.

Python3




# Import necessary libraries
import pygame
import sys
import random
import math
 
# Initialize Pygame
pygame.init()
 
# Screen dimensions
SCREEN_WIDTH = 1400
SCREEN_HEIGHT = 700
 
# Initialize the screen
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Angry Birds")
 
# Load bird images
player_bird_image = pygame.image.load("angry_bird_pygame/Images/player_bird.png"# Replace path if needed
enemy_bird_image = pygame.image.load("angry_bird_pygame/Images/enemy_bird.png")    # Replace path if needed
 
# Load background image
background_image = pygame.image.load("angry_bird_pygame/Images/background.png"# Replace path if needed
 
# Scale the background image to fit the screen dimensions
background_image = pygame.transform.scale(background_image, (SCREEN_WIDTH, SCREEN_HEIGHT))
 
# Bird class
class Bird(pygame.sprite.Sprite):
    def __init__(self, x, y, image):
        super().__init__()
        self.image = image
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)
        self.velocity = [0, 0]
        self.dragging = False
        self.drag_start_pos = (0, 0)
 
    def update(self):
        if self.dragging:
            mouse_pos = pygame.mouse.get_pos()
            self.rect.centerx = mouse_pos[0]
            self.rect.centery = mouse_pos[1]
        else:
            self.rect.x += self.velocity[0]
            self.rect.y += self.velocity[1]
 
    def start_drag(self):
        self.dragging = True
        self.drag_start_pos = self.rect.center
 
    def end_drag(self):
        self.dragging = False
        mouse_pos = pygame.mouse.get_pos()
        direction = math.atan2(self.drag_start_pos[1] - mouse_pos[1], self.drag_start_pos[0] - mouse_pos[0])
        speed = 10
        self.velocity = [speed * math.cos(direction), speed * math.sin(direction)]
 
    def hit_enemy(self):
        global score
        score += 100  # Increase the score by 100 when an enemy is hit
 
# Button class
class Button(pygame.sprite.Sprite):
    def __init__(self, x, y, image, action):
        super().__init__()
        self.image = image
        self.rect = self.image.get_rect()
        self.rect.topleft = (x, y)
        self.action = action
 
# Create player bird
player_bird = Bird(100, SCREEN_HEIGHT // 2, player_bird_image)
 
# Create enemy birds
enemy_birds = pygame.sprite.Group()
for _ in range(5):
    x = random.randint(SCREEN_WIDTH // 2, SCREEN_WIDTH - 50)
    y = random.randint(50, SCREEN_HEIGHT - 50)
    enemy_bird = Bird(x, y, enemy_bird_image)
    enemy_birds.add(enemy_bird)
 
# Calculating button positions
button_margin = 10
button_top = button_margin
button_left = button_margin
button_spacing = 5
 
# Initialize player's score
score = 0
 
# Calculate 1 inch offset in pixels (assuming standard DPI of 96)
score_position = (1260, 80)
 
# Create buttons
quit_button_image = pygame.image.load("angry_bird_pygame/Images/quit_button.png")        # Replace path if needed
refresh_button_image = pygame.image.load("angry_bird_pygame/Images/refresh_button.png"# Replace path if needed
 
quit_button = Button(button_left, button_top, quit_button_image, "quit")
refresh_button = Button(button_left + quit_button_image.get_width() + button_spacing, button_top, refresh_button_image, "refresh")
 
# Game loop
clock = pygame.time.Clock()
 
# Initialize game state
try_again_counter = 0
max_try_again = 3
level_cleared = False
game_over = False
 
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
 
        # ... (Event handling code for buttons and player bird dragging remains the same)
        if event.type == pygame.MOUSEBUTTONDOWN:
            if quit_button.rect.collidepoint(event.pos):
                # Quit button clicked - exit the game
                pygame.quit()
                sys.exit()
 
            elif refresh_button.rect.collidepoint(event.pos):
                # Refresh button clicked - reset game
                player_bird.rect.center = (100, SCREEN_HEIGHT // 2# Reset player bird position
                player_bird.velocity = [0, 0]
 
                enemy_birds.empty()
                for _ in range(5):
                    x = random.randint(SCREEN_WIDTH // 2, SCREEN_WIDTH - 50)
                    y = random.randint(50, SCREEN_HEIGHT - 50)
                    enemy_bird = Bird(x, y, enemy_bird_image)
                    enemy_birds.add(enemy_bird)
 
                # Reset flags
                level_cleared = False
                game_over = False
                try_again_counter = 0
                score = 0
 
            elif player_bird.rect.collidepoint(event.pos):
                # Player bird clicked - start dragging
                player_bird.start_drag()
 
        elif event.type == pygame.MOUSEBUTTONUP:
            if player_bird.dragging:
                # Release the player bird
                player_bird.end_drag()
 
                if not hits:
                    try_again_counter += 1  # Increment try_again_counter when no hits occur
            else:
                break
 
    # Update enemy bird positions and collisions
    hits = pygame.sprite.spritecollide(player_bird, enemy_birds, True)
 
    if hits:
        for hit_enemy in hits:
            hit_enemy.hit_enemy()  # Call hit_enemy method to update score and reset enemy position
 
    # Reset enemy birds that go out of the screen
    for enemy_bird in enemy_birds:
        if enemy_bird.rect.right < 0:
            enemy_bird.rect.left = SCREEN_WIDTH
            enemy_bird.rect.top = random.randint(50, SCREEN_HEIGHT - 50)
 
    # Reset player bird to origin position if it goes out of the screen
    if player_bird.rect.left > SCREEN_WIDTH or player_bird.rect.right < 0 or \
            player_bird.rect.top > SCREEN_HEIGHT or player_bird.rect.bottom < 0:
        player_bird.rect.center = (100, SCREEN_HEIGHT // 2)
        player_bird.velocity = [0, 0]
 
    # Clear the screen and draw the background
    screen.blit(background_image, (0, 0))
 
    # Update and draw player bird
    player_bird.update()
    screen.blit(player_bird.image, player_bird.rect)
 
    # Update and draw enemy birds
    enemy_birds.update()
    enemy_birds.draw(screen)
 
    # Display font
    font = pygame.font.Font(None, 50)
 
    # Score font
    score_font = pygame.font.Font(None, 36)
 
    # Draw and update player's score
    score_text = score_font.render(f"Score: {score}", True, (0, 0, 0))
    screen.blit(score_text, score_position)  # Display score at specified position
 
    # Draw buttons
    screen.blit(quit_button.image, quit_button.rect)
    screen.blit(refresh_button.image, refresh_button.rect)
 
 
# Display "Level Cleared" if score is 500
    if score >= 500:
        level_cleared_text = font.render("LEVEL CLEARED", True, (0, 0, 0))
        text_rect = level_cleared_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
        screen.blit(level_cleared_text, text_rect)
        level_cleared = True  # Update the level_cleared flag
 
    # Display "Game Over" if score is 0 after three hits
    if score == 0 and try_again_counter >= max_try_again:
        game_over_text = font.render("GAME OVER - REPLAY", True, (0, 0, 0))
        text_rect = game_over_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
        screen.blit(game_over_text, text_rect)
        game_over = True  # Update the game_over flag
 
    pygame.display.flip()
    clock.tick(60)
 
pygame.quit()


Output:

pygame 2.5.0 (SDL 2.28.0, Python 3.10.6)
Hello from the pygame community. https://www.pygame.org/contribute.html

Game Repository Link:

Kindly check the GitHub game repository link attached, “https://github.com/automprojects/AngryBirdPygame.git”

Screenshots:

Screenshot-(226)_11zon

Angry Bird Game Screen

Screenshot-(227)_11zon

Angry Bird Game Screen – Level Cleared



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads