首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >用Python写一个FlappyBird游戏

用Python写一个FlappyBird游戏

作者头像
Crossin先生
发布2026-03-11 21:46:43
发布2026-03-11 21:46:43
420
举报

1. 引言

Flappy Bird 是一款曾经火爆全网的小游戏,玩家通过点按屏幕控制小鸟飞行,躲避上下移动的管道障碍,同时累积得分。

今天我们就来尝试用 Python 的 Pygame 库,从零开始开发一个 Flappy Bird 游戏。通过本篇教程,你可以:

  • 复刻出一款经典 2D 小游戏
  • 掌握 Pygame 的基本功能(如窗口创建、事件处理、绘图)
  • 理解游戏开发的核心逻辑(游戏循环、碰撞检测、状态更新)
  • 学习面向对象编程(类、对象、属性)

2. 环境搭建

2.1 安装 Python 和 Pygame

确保你的电脑已安装 Python 3.x(推荐 3.8 或以上)。通过 pip 命令安装 Pygame:

代码语言:javascript
复制
pip install pygame

2.2 创建项目目录

创建一个项目文件夹(如 flappy_bird),并在其中新建一个 Python 文件(如 flappy_bird.py)。为了美观游戏界面,准备以下资源(可从网络下载免费像素风格素材,或用简单颜色替代):

  • 小鸟图片(bird.png)
  • 管道图片(pipe.png)
  • 背景图片(background.png)
  • 地面图片(base.png)

将这些资源放在项目文件夹的 assets 子目录中。

2.3 测试 Pygame 窗口

让我们先创建一个简单的 Pygame 窗口,确认环境正常:

代码语言:javascript
复制
import pygame
pygame.init()
screen = pygame.display.set_mode((400, 600))
pygame.display.set_caption("Flappy Bird")
running = True
while 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 初始化游戏

首先,设置游戏窗口、加载资源并初始化基本参数:

代码语言:javascript
复制
import pygame
import random

# 初始化 Pygame
pygame.init()

# 游戏窗口设置
SCREEN_WIDTH = 400
SCREEN_HEIGHT = 600
screen = 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.5
JUMP_HEIGHT = -10
PIPE_GAP = 150
PIPE_SPEED = 3

这里我们定义了窗口大小(400x600)、帧率(60 FPS)、重力加速度、跳跃高度、管道间距和移动速度。如果没有图片资源,可以用简单的矩形代替(后续会说明)。

4.2 小鸟逻辑

创建一个 Bird 类,管理小鸟的位置、速度和绘制:

代码语言:javascript
复制
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:绘制小鸟到屏幕。

如果没有图片,可以用矩形代替:

代码语言:javascript
复制
# 替代图片
pygame.draw.rect(screen, (255, 255, 0), (self.x, self.y, 30, 30))

4.3 管道逻辑

创建一个 Pipe 类,管理管道的生成和移动:

代码语言:javascript
复制
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 绘制上下管道(上管道翻转图片)。

如果没有管道图片,可用绿色矩形:

代码语言:javascript
复制
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 游戏循环

整合小鸟、管道、背景和地面,添加游戏循环:

代码语言:javascript
复制
# 地面类
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 = 0
font = pygame.font.SysFont("arial", 30)
pipe_timer = 0
running = 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 帧)生成一对管道,移除超出屏幕的管道。

碰撞检测:检查小鸟与管道或边界的碰撞。

绘制:按顺序绘制背景、管道、地面、小鸟和得分。

如果没有地面图片,可用灰色矩形:

代码语言:javascript
复制
pygame.draw.rect(screen, (100, 100, 100), (self.x, self.y, self.width, 100))

5. 优化与扩展

5.1 添加开始/结束菜单

在游戏开始前显示“按空格开始”,结束时显示“游戏结束”和最终得分:

代码语言:javascript
复制
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):

代码语言:javascript
复制
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("音效文件未找到")

在对应事件中播放:

代码语言:javascript
复制
# 跳跃时(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 的使用,熟悉游戏开发的逻辑,并对面向对象编程有更深入的理解。

你可以进一步优化代码或尝试开发其他游戏。如果你有想要看的游戏案例,也可以直接告诉我,呼声高的游戏我会优先制作教程。

完整及分步骤代码已上传代码仓库,欢迎下载学习并根据你的创意进行二次开发!

如果教程对你有帮助,请点赞、评论、转发~

你的支持是我坚持更新的动力!


感谢转发点赞的各位~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-06-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Crossin的编程教室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档