Hello aspiring game developers and Python enthusiasts! Have you ever wanted to create your own game, even a simple one? Today, we’re going to dive into the exciting world of Pygame and build a fun, basic maze game. Don’t worry if you’re new to game development or even Python; we’ll break down every step into easy-to-understand chunks.
What is Pygame?
Before we start, let’s quickly explain what Pygame is.
Pygame is a popular set of Python modules designed for writing video games. Think of it as a toolkit that provides functions and classes to handle graphics, sounds, user input (like keyboard presses or mouse clicks), and other common game development tasks. It makes it much easier to create games without having to worry about the really low-level details.
A module or library is simply a collection of pre-written code that you can use in your own Python programs to perform specific actions, saving you time and effort.
What Will We Build?
Our goal is to create a simple maze game where:
* You control a player character (a colored square).
* You navigate through a static maze.
* The player cannot pass through walls.
* The game ends when you reach a specific “exit” point.
This project is fantastic for beginners because it covers fundamental game development concepts like drawing shapes, handling user input, creating a game loop, and basic collision detection.
Getting Started: Prerequisites
Before we write any code, you’ll need two things:
- Python: Make sure you have Python installed on your computer. You can download it from the official Python website (python.org). Python 3.6 or newer is recommended.
-
Pygame: Once Python is installed, you can install Pygame using
pip, Python’s package installer. Open your terminal or command prompt and type:bash
pip install pygameIf you’re using a specific Python version, you might use
pip3 install pygame.
That’s it for the setup! Now, let’s get into the code.
The Foundation: Setting Up Our Pygame Window
Every Pygame application starts by initializing Pygame and setting up a display window.
Step 1: Import Pygame and Initialize
First, we import the Pygame library and initialize all its modules.
import pygame
pygame.init()
Step 2: Define Game Constants
It’s a good practice to define constants for things like screen dimensions, colors, and player speed. This makes your code cleaner and easier to modify.
Constants are values that don’t change throughout the program’s execution. We often write them in UPPER_CASE to distinguish them from regular variables.
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
CELL_SIZE = 40
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0) # For our player!
PLAYER_SIZE = CELL_SIZE - 10 # Slightly smaller than a cell
PLAYER_SPEED = CELL_SIZE # Player moves one cell at a time
WALL_THICKNESS = 5
Step 3: Create the Game Window
Now, we create the actual window where our game will be displayed.
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Simple Maze Game")
Designing Our Maze
How do we represent a maze in code? A common and easy way for simple grid-based games is to use a 2D list (or “list of lists”) where each element represents a cell in the maze. We can use numbers to signify different types of cells:
* 0: Path (empty space)
* 1: Wall
* 2: Player start position
* 3: Exit point
Let’s define a simple maze layout. Remember, each 1 (wall) will be CELL_SIZE by CELL_SIZE pixels.
maze_layout = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
]
MAZE_WIDTH_CELLS = len(maze_layout[0])
MAZE_HEIGHT_CELLS = len(maze_layout)
SCREEN_WIDTH = MAZE_WIDTH_CELLS * CELL_SIZE
SCREEN_HEIGHT = MAZE_HEIGHT_CELLS * CELL_SIZE
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) # Re-set screen after recalculating
The Game Loop: The Heart of Every Game
Every game has a game loop. This is a while loop that runs continuously, doing three main things:
1. Event Handling: Checking for user input (like keyboard presses) or system events (like closing the window).
2. Updating Game State: Changing positions of objects, checking for collisions, etc.
3. Drawing: Redrawing everything on the screen in its new position.
player_grid_x = 0
player_grid_y = 0
for y in range(MAZE_HEIGHT_CELLS):
for x in range(MAZE_WIDTH_CELLS):
if maze_layout[y][x] == 2:
player_grid_x = x
player_grid_y = y
break # Found player, no need to search more in this row
if maze_layout[player_grid_y][player_grid_x] == 2: # If player found, break outer loop too
break
player_pixel_x = player_grid_x * CELL_SIZE + (CELL_SIZE - PLAYER_SIZE) // 2
player_pixel_y = player_grid_y * CELL_SIZE + (CELL_SIZE - PLAYER_SIZE) // 2
game_over = False
running = True # This variable controls our game loop
while running:
# 1. Event Handling
for event in pygame.event.get():
if event.type == pygame.QUIT: # If the user clicks the 'X' to close the window
running = False # Stop the game loop
if event.type == pygame.KEYDOWN and not game_over: # If a key is pressed and game is not over
# Try to move the player based on arrow keys
new_player_grid_x = player_grid_x
new_player_grid_y = player_grid_y
if event.key == pygame.K_LEFT:
new_player_grid_x -= 1
elif event.key == pygame.K_RIGHT:
new_player_grid_x += 1
elif event.key == pygame.K_UP:
new_player_grid_y -= 1
elif event.key == pygame.K_DOWN:
new_player_grid_y += 1
# Check for collision with walls
# "Collision detection" is the process of figuring out if two objects in a game are overlapping or touching.
if 0 <= new_player_grid_x < MAZE_WIDTH_CELLS and \
0 <= new_player_grid_y < MAZE_HEIGHT_CELLS and \
maze_layout[new_player_grid_y][new_player_grid_x] != 1: # 1 is a wall
player_grid_x = new_player_grid_x
player_grid_y = new_player_grid_y
# Update player's pixel position
player_pixel_x = player_grid_x * CELL_SIZE + (CELL_SIZE - PLAYER_SIZE) // 2
player_pixel_y = player_grid_y * CELL_SIZE + (CELL_SIZE - PLAYER_SIZE) // 2
# Check if player reached the exit
if maze_layout[player_grid_y][player_grid_x] == 3:
game_over = True
print("You won!")
# 2. Drawing
# Clear the screen by filling it with a background color
screen.fill(BLACK)
# Draw the maze
for y in range(MAZE_HEIGHT_CELLS):
for x in range(MAZE_WIDTH_CELLS):
cell_type = maze_layout[y][x]
rect = pygame.Rect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE) # A `Rect` object represents a rectangular area.
if cell_type == 1: # Wall
pygame.draw.rect(screen, BLUE, rect)
elif cell_type == 3: # Exit
pygame.draw.rect(screen, GREEN, rect)
# Draw the player
player_rect = pygame.Rect(player_pixel_x, player_pixel_y, PLAYER_SIZE, PLAYER_SIZE)
pygame.draw.rect(screen, YELLOW, player_rect)
# If game is over, display a message
if game_over:
font = pygame.font.Font(None, 74) # `pygame.font.Font` creates a font object; `None` uses default font.
text = font.render("YOU WIN!", True, GREEN) # `render` creates a surface with the text. `True` is for anti-aliasing.
text_rect = text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
screen.blit(text, text_rect) # `blit` draws one image onto another.
# Update the full display Surface to the screen
# This makes everything we've drawn actually appear on the window.
pygame.display.flip()
pygame.quit()
How the Code Works (Detailed Explanations)
Let’s break down some key parts of the code:
pygame.init(): This function initializes all the Pygame modules necessary for game development. Without it, many Pygame functions won’t work.pygame.display.set_mode((width, height)): This creates the actual window where your game will run. The(width, height)tuple specifies the size in pixels. A pixel is the smallest unit of a digital image or display.pygame.display.set_caption("Title"): This sets the text that appears in the title bar of your game window.while running:: This is our main game loop. Therunningvariable (a boolean – true/false value) controls whether the loop continues or stops. WhenrunningbecomesFalse, the loop finishes.for event in pygame.event.get():: Pygame collects all user actions (like key presses, mouse clicks, closing the window) as “events.” This loop goes through each event that happened since the last frame.event.type == pygame.QUIT: This checks if the specific event was the user clicking the ‘X’ button to close the window.event.type == pygame.KEYDOWN: This checks if a key was pressed down.event.key == pygame.K_LEFT: This checks which key was pressed (e.g., the left arrow key). Pygame provides constants for many keys (e.g.,K_RIGHT,K_UP,K_DOWN).maze_layout[new_player_grid_y][new_player_grid_x] != 1: This is our simple collision detection. Before moving the player, we check themaze_layoutat the target cell. If it’s1(a wall), we don’t allow the move.screen.fill(BLACK): Before drawing anything new in each frame, we “clear” the screen by filling it with a background color (black in our case). This prevents “ghosting” effects where old drawings remain.pygame.Rect(x, y, width, height): Pygame usesRectobjects to represent rectangular areas. These are very useful for drawing and for collision detection.xandyare the coordinates (position on the screen).pygame.draw.rect(surface, color, rect_object): This function draws a rectangle on a givensurface(ourscreen), with a specifiedcolor, and at the position and size defined by therect_object.pygame.display.flip(): This command updates the entire screen to show everything that has been drawn since the lastflip()orupdate(). Without this, you wouldn’t see anything!pygame.quit(): This uninitializes all Pygame modules and cleans up resources, which is good practice when your program finishes.
Running Your Game!
Save the code above as a Python file (e.g., maze_game.py). Then, open your terminal or command prompt, navigate to the directory where you saved the file, and run it using:
python maze_game.py
You should see a window pop up with your maze! Use the arrow keys to move your yellow square player through the maze. Try to reach the green exit square.
Ideas for Improvement
This is a very basic maze game, but it’s a great starting point! Here are some ideas to make it even better:
- More Complex Mazes: Implement an algorithm to generate random mazes.
- Timer/Score: Add a timer to see how fast the player can complete the maze, or a score.
- Sound Effects: Add sounds for movement, reaching the exit, or hitting a wall.
- Different Player Graphics: Instead of a square, use an image for the player.
- Multiple Levels: Create an array of
maze_layouts and switch between them. - Smoother Movement: Instead of moving one
CELL_SIZEat a time, move a few pixels per frame for smoother animation. (This requires more complex collision detection). - Start Screen/End Screen: Add proper title screens and game over screens.
Conclusion
Congratulations! You’ve just built your very own simple maze game using Pygame. You’ve learned about setting up a game window, handling user input, drawing shapes, and the essential game loop. These are fundamental skills that will serve you well in any future game development adventures. Keep experimenting, keep coding, and most importantly, have fun!
Leave a Reply
You must be logged in to post a comment.