Hey there, aspiring game developers and Python enthusiasts! Ever wanted to create your own simple game but felt overwhelmed? You’re in the right place! Today, we’re going to dive into the exciting world of game development using Python and a super friendly library called Pygame. Our mission? To build a basic version of the endlessly addictive Flappy Bird game!
Don’t worry if you’re new to this. We’ll break down everything step-by-step, using clear language and plenty of explanations. By the end of this tutorial, you’ll have a playable game and a solid understanding of fundamental game development concepts. Let’s get those virtual wings flapping!
What You’ll Need
Before we start coding, let’s gather our tools.
1. Python
Python: This is a popular, easy-to-read programming language that’s great for beginners and powerful enough for professionals. If you don’t have it installed, head over to python.org and download the latest version for your operating system. Make sure to check the box that says “Add Python to PATH” during installation – it makes things much easier later!
2. Pygame
Pygame: This is a fantastic set of Python modules designed for writing video games. It gives you all the tools you need to draw graphics, play sounds, handle user input (like keyboard presses), and much more, all without getting bogged down in complex details.
To install Pygame, open your command prompt (on Windows) or terminal (on macOS/Linux). You can usually find it by searching for “cmd” or “terminal.” Once open, type the following command and press Enter:
pip install pygame
pip: This is Python’s package installer. Think of it as an app store for Python libraries. When you type pip install pygame, you’re telling Python to download and set up the Pygame library for you.
If the installation is successful, you’re all set!
The Core Idea: How Flappy Bird Works
A game, at its heart, is just a series of things happening repeatedly. For Flappy Bird, here’s the basic loop:
- The Bird:
- It’s always falling due to gravity.
- When you press a key (like the spacebar), it “flaps” or jumps up.
- The Pipes:
- They continuously move from right to left.
- New pipes appear periodically on the right side of the screen.
- Collision:
- If the bird hits a pipe, the ground, or the top of the screen, it’s game over!
- Score:
- You get a point every time the bird successfully passes a pair of pipes.
Setting Up Our Game Window
Let’s start by getting a basic Pygame window up and running. This will be the canvas for our game.
import pygame
import random # We'll use this later for random pipe positions
pygame.init()
SCREEN_WIDTH = 400
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("My Simple Flappy Bird")
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREEN = (0, 255, 0) # For our pipes
BLUE = (0, 0, 255) # For our bird
SKY_BLUE = (135, 206, 235) # A nice background color
clock = pygame.time.Clock()
FPS = 60 # Frames Per Second. Our game will try to update 60 times every second.
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Drawing the background
screen.fill(SKY_BLUE) # Fills the entire screen with sky blue
# Update the display
pygame.display.flip() # Shows what we've drawn on the screen
# Control frame rate
clock.tick(FPS)
pygame.quit() # Uninitializes Pygame, like turning off the engine. Always do this at the end.
Explanation:
* import pygame: Brings all the Pygame tools into our script.
* pygame.init(): A must-do to get Pygame ready.
* SCREEN_WIDTH, SCREEN_HEIGHT: We define how big our game window will be.
* pygame.display.set_mode(): Creates the actual window.
* pygame.display.set_caption(): Puts text at the top of our window.
* Colors: We define common colors as RGB tuples.
* clock = pygame.time.Clock() and FPS: These work together to make sure our game runs smoothly, not too fast or too slow.
* running = True and while running:: This is our main game loop. It keeps the game running until we decide to close it.
* for event in pygame.event.get():: This checks for any actions the user takes, like closing the window or pressing a key.
* event.type == pygame.QUIT: If the user clicks the ‘X’ button, we set running to False to exit the loop.
* screen.fill(SKY_BLUE): This clears the screen in each frame and fills it with our chosen background color.
* pygame.display.flip(): This takes everything we’ve drawn in the current frame and makes it visible on the screen.
* pygame.quit(): Cleans up Pygame resources when the game ends.
If you run this code, you should see a sky-blue window appear!
The Bird: Our Hero!
Now, let’s create our bird. For simplicity, we’ll represent the bird as a blue rectangle.
Let’s add some variables for our bird right after our color definitions:
bird_x = 50 # X-coordinate of the bird's top-left corner
bird_y = SCREEN_HEIGHT // 2 # Y-coordinate, starting in the middle vertically
bird_width = 30
bird_height = 30
bird_velocity = 0 # How fast the bird is currently moving up or down
GRAVITY = 0.5 # How much the bird accelerates downwards each frame
JUMP_STRENGTH = -8 # How much the bird jumps upwards when flapped (negative for up)
# 1. Handle Bird movement
bird_velocity += GRAVITY # Apply gravity
bird_y += bird_velocity # Update bird's vertical position
# Keep bird on screen (simple boundaries)
if bird_y > SCREEN_HEIGHT - bird_height:
bird_y = SCREEN_HEIGHT - bird_height
bird_velocity = 0 # Stop falling if on ground
if bird_y < 0:
bird_y = 0
bird_velocity = 0 # Stop going above the top
# 2. Draw the bird
pygame.draw.rect(screen, BLUE, (bird_x, bird_y, bird_width, bird_height))
Explanation:
* bird_x, bird_y: The bird’s current position.
* bird_velocity: How fast and in which direction the bird is moving vertically. Positive means down, negative means up.
* GRAVITY: This constant value makes bird_velocity increase over time, simulating falling.
* JUMP_STRENGTH: A negative value that we’ll apply to bird_velocity when the player jumps.
* pygame.draw.rect(): This function draws a rectangle. Arguments are: surface (where to draw), color, and a rectangle tuple (x, y, width, height).
Now, if you run the game, you’ll see a blue square fall to the bottom of the screen! Progress!
Making the Bird Jump
Let’s add the jump functionality. We need to check for a key press within our event loop.
if event.type == pygame.KEYDOWN: # Checks if any key was pressed down
if event.key == pygame.K_SPACE: # Checks if the pressed key was the spacebar
bird_velocity = JUMP_STRENGTH # Make the bird jump!
Now, try running it! You can press the spacebar to make your blue square bird jump!
The Pipes: Our Obstacles
The pipes are a bit trickier because there are many of them, and they move. We’ll store them in a list. Each pipe will need an x position, a height for the top pipe, and a height for the bottom pipe, with a gap in between.
pipe_width = 50
pipe_gap = 150 # The vertical space between the top and bottom pipes
pipe_speed = 3 # How fast the pipes move left
pipes = [] # A list to hold all our active pipes
pipe_spawn_timer = 0
PIPE_SPAWN_INTERVAL = 90 # How many frames before a new pipe spawns (roughly 1.5 seconds at 60 FPS)
# 3. Handle Pipes
# Generate new pipes
pipe_spawn_timer += 1
if pipe_spawn_timer >= PIPE_SPAWN_INTERVAL:
# Random height for the top pipe
top_pipe_height = random.randint(50, SCREEN_HEIGHT - pipe_gap - 50)
# The bottom pipe starts after the gap
bottom_pipe_height = SCREEN_HEIGHT - top_pipe_height - pipe_gap
# Add new pipe (x-position, top_height, bottom_height)
pipes.append([SCREEN_WIDTH, top_pipe_height, bottom_pipe_height])
pipe_spawn_timer = 0
# Move pipes and remove if off-screen
pipes_to_remove = []
for pipe in pipes:
pipe[0] -= pipe_speed # Move pipe left
# Check if pipe is off-screen
if pipe[0] + pipe_width < 0:
pipes_to_remove.append(pipe)
# Draw pipes
# Top pipe
pygame.draw.rect(screen, GREEN, (pipe[0], 0, pipe_width, pipe[1]))
# Bottom pipe
pygame.draw.rect(screen, GREEN, (pipe[0], pipe[1] + pipe_gap, pipe_width, pipe[2]))
# Clean up old pipes
for pipe_to_remove in pipes_to_remove:
pipes.remove(pipe_to_remove)
Explanation:
* pipes = []: This list will hold our pipe information. Each item in the list will be another list: [x_position, top_pipe_height, bottom_pipe_height].
* pipe_spawn_timer: We count frames, and when it reaches PIPE_SPAWN_INTERVAL, we create a new pipe.
* random.randint(): This helps us create pipes with random heights, making the game more interesting.
* pipe[0] -= pipe_speed: This moves each pipe to the left.
* pipes_to_remove: We collect pipes that have gone off the left side of the screen and remove them to keep our game efficient.
Run the game now, and you’ll see pipes scrolling by!
Collision Detection and Game Over
This is where the game gets challenging! We need to check if the bird hits any pipes or the ground/ceiling.
# 4. Collision Detection
game_over = False
# Check collision with ground/ceiling (already handled this with bird_y boundaries)
# Re-check explicitly for game over state
if bird_y >= SCREEN_HEIGHT - bird_height or bird_y <= 0:
game_over = True
# Check collision with pipes
bird_rect = pygame.Rect(bird_x, bird_y, bird_width, bird_height) # Create a rectangle object for the bird for easier collision checking
for pipe in pipes:
top_pipe_rect = pygame.Rect(pipe[0], 0, pipe_width, pipe[1])
bottom_pipe_rect = pygame.Rect(pipe[0], pipe[1] + pipe_gap, pipe_width, pipe[2])
# `colliderect` is a Pygame function that checks if two rectangles overlap
if bird_rect.colliderect(top_pipe_rect) or bird_rect.colliderect(bottom_pipe_rect):
game_over = True
break # No need to check other pipes if we've already collided
# Handle Game Over state
if game_over:
# Display "Game Over!" message (basic for now)
font = pygame.font.Font(None, 74) # None uses default font, 74 is font size
text = font.render("Game Over!", True, BLACK) # Render text: "text", antialias, color
text_rect = text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)) # Center the text
screen.blit(text, text_rect) # Draw the text on the screen
pygame.display.flip() # Make sure the "Game Over" message is shown
pygame.time.wait(2000) # Wait for 2 seconds before quitting
running = False # Exit the game loop
Explanation:
* game_over = False: A boolean variable to track if the game has ended.
* pygame.Rect(): Pygame has a helpful Rect object that makes it easy to define rectangular areas and check for collisions.
* bird_rect.colliderect(other_rect): This method of the Rect object tells us if two rectangles are overlapping.
* pygame.font.Font(): Used to load a font. None uses the default system font.
* font.render(): Creates an image of your text.
* text.get_rect(center=...): Gets a Rect object for your text image and centers it.
* screen.blit(text, text_rect): Draws the text image onto our game screen.
* pygame.time.wait(2000): Pauses the game for 2000 milliseconds (2 seconds) before closing, so you can see the “Game Over!” message.
Now, if your bird hits a pipe or the ground/ceiling, the game will stop after a “Game Over!” message.
Adding a Score
Let’s make our game keep track of how many pipes the bird successfully passes.
score = 0
font = pygame.font.Font(None, 36) # Smaller font for the score
# 5. Update Score
for pipe in pipes:
# If the pipe has passed the bird's x-position AND the score hasn't been added for this pipe yet
if pipe[0] + pipe_width < bird_x and len(pipe) == 3: # 'len(pipe) == 3' means it's a new pipe without score info
score += 1
pipe.append(True) # Mark this pipe as 'scored' so we don't count it again
# 6. Display Score
score_text = font.render(f"Score: {score}", True, BLACK)
screen.blit(score_text, (10, 10)) # Draw score at top-left corner
Explanation:
* We add score = 0 and initialize a font for the score.
* Inside the loop, we check each pipe. If its right edge (pipe[0] + pipe_width) has moved past the bird’s left edge (bird_x), it means the bird has passed it.
* len(pipe) == 3: This is a simple trick. When we create a pipe, it has 3 values (x, top_height, bottom_height). After it’s scored, we append(True) to it, making its length 4. This way, we only count each pipe once.
* f"Score: {score}": This is an f-string, a convenient way to embed variables directly into strings in Python.
Now you have a working score!
Putting It All Together (Full Code)
Here’s the complete code for our simple Flappy Bird game:
import pygame
import random
pygame.init()
SCREEN_WIDTH = 400
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("My Simple Flappy Bird")
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
SKY_BLUE = (135, 206, 235)
clock = pygame.time.Clock()
FPS = 60
bird_x = 50
bird_y = SCREEN_HEIGHT // 2
bird_width = 30
bird_height = 30
bird_velocity = 0
GRAVITY = 0.5
JUMP_STRENGTH = -8
pipe_width = 50
pipe_gap = 150
pipe_speed = 3
pipes = [] # Format: [x, top_height, bottom_height, scored_status]
pipe_spawn_timer = 0
PIPE_SPAWN_INTERVAL = 90
score = 0
font = pygame.font.Font(None, 36)
game_over_font = pygame.font.Font(None, 74)
running = True
game_over = False
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE and not game_over: # Only jump if not game over
bird_velocity = JUMP_STRENGTH
if not game_over: # Only update game elements if game is not over
# 1. Handle Bird movement
bird_velocity += GRAVITY
bird_y += bird_velocity
# Keep bird on screen boundaries
if bird_y > SCREEN_HEIGHT - bird_height:
bird_y = SCREEN_HEIGHT - bird_height
bird_velocity = 0
game_over = True # Game over if bird hits the ground
if bird_y < 0:
bird_y = 0
bird_velocity = 0
game_over = True # Game over if bird hits the top
# 2. Handle Pipes
pipe_spawn_timer += 1
if pipe_spawn_timer >= PIPE_SPAWN_INTERVAL:
top_pipe_height = random.randint(50, SCREEN_HEIGHT - pipe_gap - 50)
bottom_pipe_height = SCREEN_HEIGHT - top_pipe_height - pipe_gap
pipes.append([SCREEN_WIDTH, top_pipe_height, bottom_pipe_height, False]) # False means not yet scored
pipe_spawn_timer = 0
pipes_to_remove = []
for pipe in pipes:
pipe[0] -= pipe_speed
if pipe[0] + pipe_width < 0:
pipes_to_remove.append(pipe)
for pipe_to_remove in pipes_to_remove:
pipes.remove(pipe_to_remove)
# 3. Update Score
for pipe in pipes:
if pipe[0] + pipe_width < bird_x and not pipe[3]: # Check if passed AND not yet scored
score += 1
pipe[3] = True # Mark as scored
# 4. Collision Detection (Bird with Pipes)
bird_rect = pygame.Rect(bird_x, bird_y, bird_width, bird_height)
for pipe in pipes:
top_pipe_rect = pygame.Rect(pipe[0], 0, pipe_width, pipe[1])
bottom_pipe_rect = pygame.Rect(pipe[0], pipe[1] + pipe_gap, pipe_width, pipe[2])
if bird_rect.colliderect(top_pipe_rect) or bird_rect.colliderect(bottom_pipe_rect):
game_over = True
break
# --- Drawing ---
screen.fill(SKY_BLUE) # Clear screen
# Draw Pipes
for pipe in pipes:
pygame.draw.rect(screen, GREEN, (pipe[0], 0, pipe_width, pipe[1]))
pygame.draw.rect(screen, GREEN, (pipe[0], pipe[1] + pipe_gap, pipe_width, pipe[2]))
# Draw Bird
pygame.draw.rect(screen, BLUE, (bird_x, bird_y, bird_width, bird_height))
# Display Score
score_text = font.render(f"Score: {score}", True, BLACK)
screen.blit(score_text, (10, 10))
# Display Game Over message if needed
if game_over:
game_over_text = game_over_font.render("Game Over!", True, BLACK)
game_over_text_rect = game_over_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
screen.blit(game_over_text, game_over_text_rect)
pygame.display.flip()
clock.tick(FPS)
if game_over:
pygame.time.wait(2000) # Give a moment to see the Game Over screen
pygame.quit()
Congratulations!
You’ve just built a fully functional (albeit simple) Flappy Bird game in Python using Pygame! You’ve touched upon many core game development concepts:
- Game Loop: The heart of any game.
- Sprites/Entities: Our bird and pipes.
- Movement & Physics: Gravity and jumping.
- Collision Detection: Checking for hits.
- Scorekeeping: Tracking player progress.
- User Input: Responding to key presses.
This is a fantastic foundation. Feel free to experiment further:
* Add different colors or even images for the bird and pipes.
* Implement a “Start Screen” or “Restart” option.
* Make the game harder as the score increases (e.g., faster pipes, smaller gaps).
* Add sound effects!
Keep coding, keep experimenting, and most importantly, keep having fun!
Leave a Reply
You must be logged in to post a comment.