Learn How to Create a Game in Python with PyGame

how to create a game in python using the pygame library

Introduction

Do you ever wondered how to make your own computer game? Well, Python is like the magic wand that makes it happen. In this article, we’re going to show How to Create a Game in Python. Whether you’re a coding pro or just starting out, I’ll guide you through the fun process of turning your ideas into a real game.

In Python, when it comes to game development, Pygame is a popular choice. Pygame is a set of Python modules designed for writing video games. It helps developers create fun and interactive games more easily.

To cover this game development topic, showing an example is very important. Therefore, I’ve selected an engaging and enjoyable game that I named the “Apple Catcher Game”. This Python game is packed with numerous features, offering a clear insight into the entire concept of game development using programming.

By following this guide, you’ll learn the basics of making games and get practical experience with PyGame. So, let’s dive in and discover how Python can help you make something awesome! Get ready to have some coding fun!

Concepts of the Game

This Apple Catcher Game is very easy to play. Before a beautiful background, there is a basket on the ground and it can move left or right through buttons. After the game starts, random apples drop from the sky and we have to collect those into the basket. Each collection makes the score higher with two. After a certain period of time and score the game levels up and the speed of the apple drop increases. There are three chances to miss the apple from catching unless the game will be over.

apple catcher game in python
The Apple Catcher Game

The Project Details

The main project folder contains two directories with corresponding files and eight program files. The project file hierarchy looks like the following:

  • Apple_Catcher
    • Images
      • apple.bmp
      • basket.bmp
      • background.png
    • Sounds
      • bg_sound.mp3
      • apple_dropped.mp3
      • apple_catched.mp3
      • game_over.mp3
    • main.py
    • settings.py
    • basket.py
    • apple.py
    • game_stats.py
    • button.py
    • sounds.py
    • scoreboard.py

The primary project folder is named ‘Apple_Catcher,’ and within it, there are two additional folders called ‘Images’ and ‘Sounds.’ These folders store various images and sound effects used in the game. The remaining files are Python scripts, and their names suggest their respective purposes.

To ensure the game runs smoothly, all the folders and program files must be present in the original folder. Without them, you won’t be able to play the game.

Download the Resources

Download the game resources, including Images and Sounds, in zip format. Once downloaded, extract the files. This will reveal the primary project folder named ‘Apple_Catcher.’ Inside ‘Apple_Catcher,’ you’ll find two additional folders (‘Images’ and ‘Sounds’) containing image and music files.

Within the ‘Apple_Catcher’ folder, all the program files or modules for the Apple Catcher game will be organized.

Requirements and Installations

Please ensure Python is installed on your system. Once you’ve met this initial requirement, proceed to install the PyGame library using the provided command:

pip install pygame

Start the Coding

Now open the previously downloaded ‘Apple_Catcher’ folder with your preferred code editor. As the game concept is a little bit tricky and includes various features, it’s beneficial to view the entire program file or module in a concise format. Each file’s purpose and working principle are explained, ensuring clarity in understanding the logic.

So, without delaying further, let’s start with the main program file.

main.py

In the main.py, we define a Python class called AppleCatcher using the Pygame library. It includes methods for initializing the game, running the game loop, handling various events, updating the screen, and managing various game elements such as the basket, apples, score, and game stats.

As we discussed earlier, the game offers catching falling apples from the sky, and it has features like scoring points, increasing difficulty levels, and handling game over conditions. When you run the main program, it creates an instance of the AppleCatcher class and you can start playing the game.

# Developed by Subhankar Rakshit
# PySeek

import pygame as pg
import sys
from apple import Apple
from settings import Settings
from basket import Basket
from game_stats import GameStats
from button import Button
from scoreboard import Scoreboard
from sounds import Music

class AppleCatcher:
    def __init__(self):
        pg.init()

        self.settings = Settings()
        self.screen = pg.display.set_mode((self.settings.screen_width, \
        self.settings.screen_height), self.settings.flag)
        pg.display.set_caption('Apple Catcher Game')

        # Background Window Image
        self.background = pg.image.load('Images/background.png')

        self.music = Music()

        self.stats = GameStats(self)
        self.sb = Scoreboard(self)
        self.basket = Basket(self)
        self.apples = pg.sprite.Group()
        # Make the Play button
        self.play_button = Button(self, "Play")

        # Getting the Screen's Rectangular
        self.screen_rect = self.screen.get_rect()

       
    def run_game(self):
        while True:
            self._check_events()
            if self.stats.game_active:
                self.basket.update()
                self._drop_apples()
                self.apples.update()
                self._check_apples_bottom()
                self._update_apples()
            self._update_screen()


    def check_for_level_up(self):
        # The game level up when the scores reach multiple of 20.
        if self.stats.score!=0 and self.stats.score%20 == 0:
            self.settings.increase_speed()
            # Increase Level
            self.stats.level += 1
            self.sb.prep_level()


    def _update_apples(self):
        '''If a apple crosses the window, it disappears'''
        for apple in self.apples.copy():
            if apple.rect.bottom >= self.screen_rect.bottom:
                self.apples.remove(apple)
        self._check_basket_apple_collisions()


    def _check_basket_apple_collisions(self):
        '''If the basket and a apple collide, add a point.'''
        collisions = pg.sprite.spritecollide(self.basket, self.apples, True)
        if collisions:
            # If collision detected add a point
            self.stats.score += self.settings.apple_points
            self.check_for_level_up()
            self.music.apple_catched.play()
            self.sb.prep_score()


    def _check_apples_bottom(self):
        '''It checks if the apple crosses the screen bottom'''
        screen_rect = self.screen.get_rect()
        for apple in self.apples.sprites():
            if apple.rect.bottom >= screen_rect.bottom:
                self._apple_hit()
                break


    def _apple_hit(self):
        '''It checks the remaining chances to miss the apple 
        from being catched and play the drop sound. If chances over, it
        plays a 'game over' sound.'''
        if self.stats.apples_left > 0:
            self.stats.apples_left -= 1
            self.music.apple_droped.play()
            self.sb.prep_apples()
        else:
            self.music.game_over.play()
            self.stats.game_active = False
            pg.mouse.set_visible(True)
            self.music.bg_music.stop()

        
    def _drop_apples(self):
        '''Drop apples from the top, randomly'''
        if len(self.apples) == 0:
                new_apple = Apple(self)
                self.apples.add(new_apple)
        if len(self.apples) == 1:
            for apple in self.apples.sprites():
                if apple.rect.bottom > 300:
                    new_apple = Apple(self)
                    self.apples.add(new_apple)
        if len(self.apples) == 2:
            for apple in self.apples.sprites():
                if apple.rect.bottom > 600:
                    new_apple = Apple(self)
                    self.apples.add(new_apple)
        if len(self.apples) == 3:
            for apple in self.apples.sprites():
                if apple.rect.bottom > 900:
                    new_apple = Apple(self)
                    self.apples.add(new_apple)
                    

    def _check_play_button(self, mouse_pos):
        """Start a new game when the player clicks Play."""
        button_clicked = self.play_button.rect.collidepoint(mouse_pos)
        if button_clicked and not self.stats.game_active:
            self.settings.initialize_dynamic_settings()
            # Reset the game statistics.
            self.stats.reset_stats()
            self.stats.game_active = True
            # Play the Background Music
            self.music.bg_music.play()

            self.sb.prep_score()
            self.sb.prep_apples()
            self.sb.prep_level()
            # Get rid of any remaining apples
            self.apples.empty()
            # Hide the mouse cursor
            pg.mouse.set_visible(False)
        
        
    def _check_events(self):
        """Respond to keypresses and mouse events."""
        for event in pg.event.get():
            if event.type == pg.QUIT:
                sys.exit()
            elif event.type == pg.MOUSEBUTTONDOWN:
                mouse_pos = pg.mouse.get_pos()
                self._check_play_button(mouse_pos)
            elif event.type == pg.KEYDOWN:
                self._check_keydown_events(event)
            elif event.type == pg.KEYUP:
                self._check_keyup_events(event)
            
                
    def _check_keydown_events(self, event):
        """Respond to keypresses."""
        if event.key == pg.K_RIGHT:
            self.basket.moving_right = True
        elif event.key == pg.K_LEFT:
            self.basket.moving_left = True
        elif event.key == pg.K_SPACE:
            self._drop_apples()

    
    def _check_keyup_events(self, event):
        """Respond to key releases."""
        if event.key == pg.K_RIGHT:
            self.basket.moving_right = False
        elif event.key == pg.K_LEFT:
            self.basket.moving_left = False


    def _update_screen(self):
        """Update images on the screen, and flip to the new screen."""
        self.screen.blit(self.background, (0,0))
        self.basket.blitme()

        for apple in self.apples.sprites():
            apple.blitme()

        # Draw the score information.
        self.sb.show_score()
        # Draw the play button if the game is inactive.
        if not self.stats.game_active:
            self.play_button.draw_button()

        pg.display.flip()


if __name__ == '__main__':
    ec = AppleCatcher()
    ec.run_game()

settings.py

In the settings.py, we define all the game settings for the Apple Catcher game. Here, we set screen dimensions, background color, resizable screen flag, apple-related settings (allowed, limit, points), game-over condition, scoring, level-up scale, and dynamic settings for basket and apple drop speed.

Here, you can dynamically adjust these settings during the gameplay. For example, you can cheat the game by increasing the moving speed of the basket or slowing down the apple dropping speed.

import pygame as pg

class Settings:
    def __init__(self):
        screen_info = pg.display.Info()
        self.screen_width = screen_info.current_w
        self.screen_height = screen_info.current_h
        self.bg_color = (230, 230, 230)
        self.flag = pg.RESIZABLE

        # Initialize static settings
        self.apples_allowed = 3
        self.apple_limit = 3
        self.game_over = False

        # Scoring
        self.apple_points = 2

        # Levelup Scale
        self.levelup_scale = 1.1

        self.initialize_dynamic_settings()

    def initialize_dynamic_settings(self):
        self.basket_speed = 1
        self.apple_drop_speed = 0.4

    def increase_speed(self):
        self.basket_speed *= self.levelup_scale
        self.apple_drop_speed *= self.levelup_scale

basket.py

In the basket.py, we define a class called Basket to control the behaviour of the basket used in the game. Here, we set up the basket’s initial position, load its image, and handle its movement based on user input.

The update method adjusts the basket’s horizontal position, while blitme draws the basket on the screen. Overall, the Basket class ensures smooth control and rendering of the basket within the game environment.

import pygame

class Basket:
    '''A class to manage the Basket'''
    def __init__(self, ac_game):
        '''Initialize the basket and set its starting position.'''
        self.screen = ac_game.screen
        self.settings = ac_game.settings
        self.screen_rect = ac_game.screen.get_rect()

        # Load the Basket image
        self.image = pygame.image.load('Images/basket.bmp')
        self.rect = self.image.get_rect()
        self.rect.midbottom = self.screen_rect.midbottom
        
        # Store the decimal value for the basket's horizontal position.
        self.x = float(self.rect.x)

        # Movement flag
        self.moving_right = False
        self.moving_left = False

    def update(self):
        """Update the basket position based on the movement flag."""
        # Update the basket's x value, not the rect.
        if self.moving_right and self.rect.right < self.screen_rect.right:
            self.x += self.settings.basket_speed
        if self.moving_left and self.rect.left > 0:
            self.x -= self.settings.basket_speed

        # Update rect object from self.x
        self.rect.x = self.x

    def blitme(self):
        """Draw the basket at its current location"""
        self.screen.blit(self.image, self.rect)

apple.py

In the apple.py, we define the behavior of the apples similar to the basket. Here, we set up the apple’s initial position, loads its image, and specifies the location from which the apple enters the screen.

The update method handles the apple’s downward movement, while blitme draws the apple on the screen.

import pygame
import random
from pygame.sprite import Sprite

class Apple(Sprite):
    '''A class to manage the Apples'''
    def __init__(self, ac_game):
        '''Initialize the apple and set its starting position.'''
        super().__init__()
        self.screen = ac_game.screen
        self.settings = ac_game.settings
        self.screen_rect = ac_game.screen.get_rect()

        # Load the Apple Image
        self.image = pygame.image.load('Images/apple.bmp')
        self.rect = self.image.get_rect()

        # Define the location from where the apple will enter
        self.rect.x = random.randrange(20, self.screen_rect.right-30)
        self.rect.y = 0
        
        # Store the decimal value for the apple's vertical position.
        self.y = float(self.rect.y)


    def update(self):
        self.y += self.settings.apple_drop_speed
        self.rect.y = self.y


    def blitme(self):
        """Draw the basket at its current location"""
        self.screen.blit(self.image, self.rect)

game_stats.py

Inside the game_stats.py, we define a class called GameStats to track statistics for the Apple Catcher game. Specifically, in this class, we set up initial game settings, check if the game is currently active, and reset statistics like the number of remaining apples, the score, and the game level.

class GameStats:
    '''Track statistics for Apple Catcher.'''
    def __init__(self, ac_game):
        self.settings = ac_game.settings
        self.game_active = False
        self.reset_stats()

    def reset_stats(self):
        self.apples_left = self.settings.apple_limit
        self.score = 0
        self.level = 1

button.py

In the welcome and game over screens, we use a “Start” button to start the game. The Button class creates a graphical button with specified dimensions, colors, and text. Here, we define methods to display text on the button and draw the button on the screen.

import pygame.font

class Button:
    def __init__(self, ac_game, text):
        self.screen = ac_game.screen
        self.screen_rect = ac_game.screen.get_rect()

        # Set the dimensions and properties of the button.
        self.width, self.height = 200, 50
        self.button_color = (0, 255, 0)

        self.text_color = (255, 255, 255)
        self.font = pygame.font.SysFont(None, 48)

        # Build the button's rect object and center it
        self.rect = pygame.Rect(0, 0, self.width, self.height)
        self.rect.center = self.screen_rect.center

        self._show_text(text)


    def _show_text(self, text):
        self.text_image = self.font.render(text, True, \
        self.text_color, self.button_color)
        self.text_image_rect = self.text_image.get_rect()
        self.text_image_rect.center = self.rect.center
        

    def draw_button(self):
        # Draw blank button and then draw blank message.
        self.screen.fill(self.button_color, self.rect)
        self.screen.blit(self.text_image, self.text_image_rect)

sounds.py

We’re almost done putting together the Apple Catcher Game. To make everything more immersive, think about adding some cool sound effects – like background music, the sound of apples dropping, the satisfying crunch of catching apples, and a game over sound, among others.

Here, we define a class called Music to add various sound effects to our game.

from pygame import mixer

class Music:
    def __init__(self):
        # Msuics: Used in the Game
        self.bg_music = mixer.Sound('Sounds/bg_sound.mp3')
        self.apple_droped = mixer.Sound('Sounds/apple_dropped.mp3')
        self.apple_catched = mixer.Sound('Sounds/apple_catched.mp3')
        self.game_over = mixer.Sound('Sounds/game_over.mp3')

scoreboard.py

Lastly, we need to define a Scoreboard class for the Apple Catcher game. It manages the display of the current game level, remaining chances to drop apples, and the total score. In this class, we define methods to prepare and show these elements on the screen and positioning them appropriately.

import pygame.font
from apple import Apple
from pygame.sprite import Group

class Scoreboard:
    def __init__(self, ac_game):
        self.ac_game = ac_game
        self.screen = ac_game.screen
        self.screen_rect = self.screen.get_rect()
        self.settings = ac_game.settings
        self.stats = ac_game.stats

        self.text_color = (30, 30, 30)
        self.font = pygame.font.SysFont(None, 48)

        self.prep_score()
        self.prep_apples()
        self.prep_level()

    # It Shows the Current Game Level
    def prep_level(self):
        level_str = str(self.stats.level)
        self.level_image = self.font.render(level_str, True,
        self.text_color, self.settings.bg_color)
        # Position the level below the score.
        self.level_rect = self.level_image.get_rect()
        self.level_rect.right = self.score_rect.right
        self.level_rect.top = self.score_rect.bottom + 10

    # It shows the remainning chances to drop the apple again.
    def prep_apples(self):
        """Show how many apples are left"""
        self.apples = Group()
        for apple_number in range(self.stats.apples_left):
            apple = Apple(self.ac_game)
            apple.rect.x = 10 + apple_number * apple.rect.width
            apple.rect.y = 10
            self.apples.add(apple)

    # It shows the total score at the top right corner of the screen.
    def prep_score(self):
        score_str = str(self.stats.score)
        self.score_image = self.font.render(score_str, True,
        self.text_color, self.settings.bg_color)
        self.score_rect = self.score_image.get_rect()
        self.score_rect.right = self.screen_rect.right - 20
        self.score_rect.top = 20

    def show_score(self):
        """Draw score to the screen."""
        self.screen.blit(self.score_image, self.score_rect)
        self.apples.draw(self.screen)
        self.screen.blit(self.level_image, self.level_rect)

Run the Game

Congratulations, you’ve reached the end of the exciting coding journey for the Apple Catcher Game! Now, let the fun begin. To kick off the game, simply run the main.py file among the eight Python modules. It’s your moment to take charge and launch the game for an exhilarating experience!

How to Play?

Make sure to watch the complete video to understand how to play this Apple Catcher Game.

Summary

In this article, we learned How to Create a Game in Python, specifically using the Pygame library. The whole tutorial focuses on the “Apple Catcher Game” as an example to teach various aspects of game development, from coding to organizing the project and adding features like scoring, levels, sounds, etc.

You’ll get a detailed look at the game’s concept, structure, and the purpose of each Python program or module, including instructions on downloading game resources and setting up Python and Pygame. The main program file (main.py) and supporting modules (settings, basket, apple, game_stats, button, sounds, and scoreboard) are explained step by step.

At the end, you can run the game by executing the main.py file and the instructions on playing the “Apple Catcher Game” are provided through a video tutorial. So, what are you waiting for? Get ready to code and play.

For more lovely Python topics, explore the dedicated page exclusively designed for Python Projects. Below are a few instances to spark your interest.

If you got any burning questions about the topic, don’t be hesitate—drop them in the comments below! I’m here and ready to help you out.

Happy Gaming!

Share your love
Subhankar Rakshit
Subhankar Rakshit

Hey there! I’m Subhankar Rakshit, the brains behind PySeek. I’m a Post Graduate in Computer Science. PySeek is where I channel my love for Python programming and share it with the world through engaging and informative blogs.

Articles: 147