1. 引言
Flappy Bird 是一款曾经火爆全网的小游戏,玩家通过点按屏幕控制小鸟飞行,躲避上下移动的管道障碍,同时累积得分。
今天我们就来尝试用 Python 的 Pygame 库,从零开始开发一个 Flappy Bird 游戏。通过本篇教程,你可以:
复刻出一款经典 2D 小游戏
掌握 Pygame 的基本功能(如窗口创建、事件处理、绘图)
理解游戏开发的核心逻辑(游戏循环、碰撞检测、状态更新)
学习面向对象编程(类、对象、属性)
2. 环境搭建
2.1 安装 Python 和 Pygame
确保你的电脑已安装 Python 3.x(推荐 3.8 或以上)。通过 pip 命令安装 Pygame:
pip install pygame
2.2 创建项目目录
创建一个项目文件夹(如 flappy_bird),并在其中新建一个 Python 文件(如 flappy_bird.py)。为了美观游戏界面,准备以下资源(可从网络下载免费像素风格素材,或用简单颜色替代):
小鸟图片(bird.png)
管道图片(pipe.png)
背景图片(background.png)
地面图片(base.png)
将这些资源放在项目文件夹的 assets 子目录中。
2.3 测试 Pygame 窗口
让我们先创建一个简单的 Pygame 窗口,确认环境正常:
import pygamepygame.init()screen = pygame.display.set_mode((400, 600))pygame.display.set_caption("Flappy Bird")running = Truewhile running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False screen.fill((0, 0, 0)) pygame.display.flip()pygame.quit()
运行这段代码,你会看到一个 400x600 像素的黑色窗口。按关闭按钮退出。
3. 游戏设计
3.1 核心元素
Flappy Bird 包含以下主要元素:
小鸟:玩家控制的对象,可上下移动,受重力影响
管道:成对出现(上下管道),随机高度,水平移动
背景:静态背景,增加视觉效果
地面:滚动地面,模拟移动效果
得分:每次通过一对管道加 1 分
3.2 游戏规则
玩家按空格键或点击鼠标使小鸟向上飞
小鸟受重力影响不断下落
撞到管道、地面或屏幕顶部时游戏结束
通过每对管道加 1 分
3.3 技术要点
游戏循环:处理输入、更新状态、绘制画面
事件处理:响应键盘/鼠标输入
碰撞检测:检查小鸟是否撞到管道或地面
物理模拟:模拟小鸟的跳跃和下落
4. 代码实现
以下是逐步实现 Flappy Bird 的代码和讲解。我们将代码分为模块化部分,确保清晰且易于扩展。
4.1 初始化游戏
首先,设置游戏窗口、加载资源并初始化基本参数:
import pygameimport random
# 初始化 Pygamepygame.init()
# 游戏窗口设置SCREEN_WIDTH = 400SCREEN_HEIGHT = 600screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))pygame.display.set_caption("Flappy Bird")clock = pygame.time.Clock()FPS = 60
# 颜色WHITE = (255, 255, 255)
# 加载资源(替换为你的图片路径)try: BIRD_IMG = pygame.image.load("assets/bird.png").convert_alpha() PIPE_IMG = pygame.image.load("assets/pipe.png").convert_alpha() BG_IMG = pygame.image.load("assets/background.png").convert() BASE_IMG = pygame.image.load("assets/base.png").convert_alpha()except FileNotFoundError: print("资源文件未找到,请确保 assets 文件夹中有 bird.png, pipe.png, background.png, base.png") pygame.quit() exit()
# 游戏变量GRAVITY = 0.5JUMP_HEIGHT = -10PIPE_GAP = 150PIPE_SPEED = 3
这里我们定义了窗口大小(400x600)、帧率(60 FPS)、重力加速度、跳跃高度、管道间距和移动速度。如果没有图片资源,可以用简单的矩形代替(后续会说明)。
4.2 小鸟逻辑
创建一个 Bird 类,管理小鸟的位置、速度和绘制:
class Bird: def __init__(self): self.x = 100 self.y = SCREEN_HEIGHT // 2 self.velocity = 0 self.image = BIRD_IMG self.rect = self.image.get_rect(topleft=(self.x, self.y))
def jump(self): self.velocity = JUMP_HEIGHT
def update(self): self.velocity += GRAVITY self.y += self.velocity self.rect.y = self.y
def draw(self, screen): screen.blit(self.image, self.rect)
jump:按空格键或点击时,设置向上的速度。
update:每帧更新小鸟位置,模拟重力。
draw:绘制小鸟到屏幕。
如果没有图片,可以用矩形代替:
# 替代图片pygame.draw.rect(screen, (255, 255, 0), (self.x, self.y, 30, 30))
4.3 管道逻辑
创建一个 Pipe 类,管理管道的生成和移动:
class Pipe: def __init__(self): self.x = SCREEN_WIDTH self.height = random.randint(150, 400) self.passed = False self.top_rect = PIPE_IMG.get_rect(bottomleft=(self.x, self.height - PIPE_GAP)) self.bottom_rect = PIPE_IMG.get_rect(topleft=(self.x, self.height))
def update(self): self.x -= PIPE_SPEED self.top_rect.x = self.bottom_rect.x = self.x
def draw(self, screen): screen.blit(PIPE_IMG, self.top_rect) flipped_pipe = pygame.transform.flip(PIPE_IMG, False, True) screen.blit(flipped_pipe, self.bottom_rect)
管道随机生成高度(150-400 像素),上下管道间距为 PIPE_GAP。
update 使管道向左移动。
draw 绘制上下管道(上管道翻转图片)。
如果没有管道图片,可用绿色矩形:
pygame.draw.rect(screen, (0, 255, 0), (self.x, 0, 50, self.height - PIPE_GAP))pygame.draw.rect(screen, (0, 255, 0), (self.x, self.height, 50, SCREEN_HEIGHT - self.height))
4.4 游戏循环
整合小鸟、管道、背景和地面,添加游戏循环:
# 地面类class Base: def __init__(self): self.x = 0 self.y = SCREEN_HEIGHT - 100 self.image = BASE_IMG self.width = self.image.get_width()
def update(self): self.x -= PIPE_SPEED if self.x <= -self.width: self.x += self.width
def draw(self, screen): screen.blit(self.image, (self.x, self.y)) screen.blit(self.image, (self.x + self.width, self.y))
# 主游戏循环bird = Bird()pipes = []base = Base()score = 0font = pygame.font.SysFont("arial", 30)pipe_timer = 0running = True
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: bird.jump() if event.type == pygame.MOUSEBUTTONDOWN: bird.jump()
# 更新 bird.update() base.update()
# 生成管道 pipe_timer += 1 if pipe_timer > 90: # 每 1.5 秒生成一对管道 pipes.append(Pipe()) pipe_timer = 0
# 更新管道 for pipe in pipes[:]: pipe.update() if pipe.x < -pipe.top_rect.width: pipes.remove(pipe) if not pipe.passed and pipe.x < bird.x: pipe.passed = True score += 1
# 碰撞检测 for pipe in pipes: if bird.rect.colliderect(pipe.top_rect) or bird.rect.colliderect(pipe.bottom_rect): running = False if bird.y <= 0 or bird.y >= SCREEN_HEIGHT - 100: running = False
# 绘制 screen.blit(BG_IMG, (0, 0)) for pipe in pipes: pipe.draw(screen) base.draw(screen) bird.draw(screen)
# 显示得分 score_text = font.render(str(score), True, WHITE) screen.blit(score_text, (SCREEN_WIDTH // 2, 50))
pygame.display.flip() clock.tick(FPS)
pygame.quit()
事件处理:响应关闭窗口、空格键或鼠标点击。
管道生成:每 1.5 秒(90 帧)生成一对管道,移除超出屏幕的管道。
碰撞检测:检查小鸟与管道或边界的碰撞。
绘制:按顺序绘制背景、管道、地面、小鸟和得分。
如果没有地面图片,可用灰色矩形:
pygame.draw.rect(screen, (100, 100, 100), (self.x, self.y, self.width, 100))
5. 优化与扩展
5.1 添加开始/结束菜单
在游戏开始前显示“按空格开始”,结束时显示“游戏结束”和最终得分:
game_state = "start"start_text = font.render("Press SPACE to Start", True, WHITE)game_over_text = font.render("Game Over", True, WHITE)
while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if game_state == "start" and event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: game_state = "playing" if game_state == "game_over" and event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE: bird = Bird() pipes = [] score = 0 game_state = "playing"
if game_state == "start": screen.blit(BG_IMG, (0, 0)) screen.blit(start_text, (SCREEN_WIDTH // 2 - 100, SCREEN_HEIGHT // 2)) elif game_state == "playing": # 此处添加原有游戏循环代码 # 将原代码中 running = False 改为 game_state = "game_over" # ... elif game_state == "game_over": screen.blit(BG_IMG, (0, 0)) screen.blit(game_over_text, (SCREEN_WIDTH // 2 - 80, SCREEN_HEIGHT // 2)) final_score = font.render(f"Score: {score}", True, WHITE) screen.blit(final_score, (SCREEN_WIDTH // 2 - 50, SCREEN_HEIGHT // 2 + 50))
pygame.display.flip()
5.2 加入音效
添加跳跃、碰撞和得分音效(需要音频文件,如 jump.wav、hit.wav、point.wav):
try: JUMP_SOUND = pygame.mixer.Sound("assets/jump.wav") HIT_SOUND = pygame.mixer.Sound("assets/hit.wav") POINT_SOUND = pygame.mixer.Sound("assets/point.wav")except FileNotFoundError: print("音效文件未找到")
在对应事件中播放:
# 跳跃时(Bird类)def jump(self): self.velocity = JUMP_HEIGHT JUMP_SOUND.play()
# 得分时(更新管道)if not pipe.passed and pipe.x < bird.x: pipe.passed = True score += 1 POINT_SOUND.play()
# 碰撞时(碰撞检测)for pipe in pipes: if bird.rect.colliderect(pipe.top_rect) or bird.rect.colliderect(pipe.bottom_rect): game_state = "game_over" HIT_SOUND.play()if bird.y <= 0 or bird.y >= SCREEN_HEIGHT - 100: game_state = "game_over" HIT_SOUND.play()
5.3 其他扩展
最高分记录:使用文件保存最高分。
动画效果:为小鸟添加飞行动画(多帧图片切换)。
难度递增:随得分增加管道速度或缩小间距。
主题切换:提供白天/夜晚背景切换。
6. 总结
本教程讲解了如何用 Python 的 Pygame 模块开发一个 Flappy Bird 小游戏。通过这个游戏的开发,可以了解 Pygame 的使用,熟悉游戏开发的逻辑,并对面向对象编程有更深入的理解。
你可以进一步优化代码或尝试开发其他游戏。如果你有想要看的游戏案例,也可以直接告诉我,呼声高的游戏我会优先制作教程。
完整及分步骤代码已上传代码仓库,欢迎下载学习并根据你的创意进行二次开发!
如果教程对你有帮助,请点赞、评论、转发~
你的支持是我坚持更新的动力!
Crossin的新书《码上行动:用ChatGPT学会Python编程》已经上市了。本书以ChatGPT为辅助,系统全面地讲解了如何掌握Python编程,适合Python零基础入门的读者学习。【点此查看详细介绍】
购买后可加入读者交流群,Crossin为你开启陪读模式,解答你在阅读本书时的一切疑问。
Crossin的其他书籍:
添加微信 crossin123 ,加入编程教室共同学习~
感谢转发和点赞的各位~