欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 锐评 > 使用Pygame制作“Flappy Bird”游戏

使用Pygame制作“Flappy Bird”游戏

2025/11/5 8:32:41 来源:https://blog.csdn.net/weixin_41793160/article/details/145405508  浏览:    关键词:使用Pygame制作“Flappy Bird”游戏

1. 前言

Flappy Bird 是一款“点击上浮松手下落”的横向卷轴游戏:

  • 场景中持续出现上下成对的管道,玩家需要让小鸟在管道之间穿行;
  • 每穿过一对管道记 1 分;
  • 若小鸟碰到管道或掉到地面,则游戏结束;
  • 一旦上手,就会体会到“魔性”且容易让人“上头”的乐趣。

在本篇中,我们使用 Python + Pygame 来从零开始构建一个精简版的 Flappy Bird,主要关注以下要点:

  • 重力/速度:小鸟受“重力”影响不断向下,下落速度随时间加快;
  • 点击上浮:每次按键或点击,即让小鸟速度向上,模拟腾空;
  • 管道生成:随机生成多组上下管道,让它们从右向左移动;
  • 碰撞与得分:检测小鸟是否与管道矩形或地面碰撞;若小鸟成功穿过管道中间的缺口,则得分 +1;
  • 游戏结束:当小鸟撞到管道或地面,游戏停止,显示分数或重来选项。

2. 开发环境

  1. Python 3.x
  2. Pygame 库:若尚未安装,可通过 pip install pygame 来获取。
  3. 图形界面:Windows、macOS、Linux 桌面环境皆可。

确认 import pygame 无报错后,即可开始项目编写。


3. 简要实现思路

  1. 小鸟(Bird)

    • 记录小鸟的 x, y 位置以及 velocity(竖直方向速度);
    • 受“重力”影响,每帧更新时给速度增加一固定值,如 gravity = 0.4,再更新 y 位置;
    • 当按键(如空格)或鼠标点击时,让速度变为负值(如 -6),模拟向上飞。
  2. 管道(Pipe)

    • 管道由上下两根部分组成,中间留有空隙让小鸟通过;
    • 随机生成管道时,可随机空隙位置(上下波动),管道整体从屏幕右侧出现后向左移动。
    • 若管道完全离开屏幕左侧,则可将其移除。
  3. 碰撞检测

    • 小鸟若 y 越过地面(例如 y + bird_height >= 地面高度)或 < 0(飞出屏幕上端),则判定失败;
    • 小鸟若与任意管道矩形重叠,同样判定失败;
    • 可以用 pygame.Rectcolliderect 来检测。
  4. 得分判定

    • 当管道刚好穿过小鸟的 x 位置时,可以认为小鸟成功通过中间的空隙,这时分数 +1。
    • 常见做法是检测小鸟的中心点是否越过某个管道的“通过线”。
  5. 游戏循环

    • 初始化小鸟、管道、分数等;
    • 不断更新(小鸟坐标、管道移动、碰撞检测)和绘制(背景、小鸟、管道、分数);
    • 知道小鸟死亡或玩家退出,结束循环,显示结算画面。

4. 完整示例代码

将以下内容保存为 flappy_bird.py 并运行即可。该示例使用简单的矩形、颜色和文字来模拟 Flappy Bird 的玩法,后期可以替换成更精美的贴图与音效。

import pygame
import sys
import random# 初始化 Pygame
pygame.init()# -----------------------
# 全局参数
# -----------------------
WIDTH, HEIGHT = 400, 600
FPS = 60# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREEN = (0, 200, 0)
RED   = (255, 0, 0)# 窗口与时钟
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Flappy Bird - Pygame 示例")
clock = pygame.time.Clock()# 字体
font = pygame.font.SysFont("arial", 32)# 地面高度(小鸟碰到地面即失败)
GROUND_LEVEL = HEIGHT - 50# -----------------------
# 小鸟类
# -----------------------
class Bird:def __init__(self, x, y):self.x = xself.y = yself.radius = 15self.color = REDself.velocity = 0  # 垂直速度self.gravity = 0.4  # “重力”加速度def update(self):# 重力作用self.velocity += self.gravityself.y += self.velocitydef flap(self):# 按键或点击时,让鸟向上冲self.velocity = -6def draw(self, surface):pygame.draw.circle(surface, self.color, (int(self.x), int(self.y)), self.radius)def get_rect(self):# 方便碰撞检测return pygame.Rect(self.x - self.radius, self.y - self.radius,self.radius * 2, self.radius * 2)# -----------------------
# 管道类
# -----------------------
class Pipe:def __init__(self, x, gap_y, gap_height=150, width=60):"""x: 管道出现的x坐标gap_y: 空隙的中心Ygap_height: 空隙的总高度width: 管道宽"""self.x = xself.width = widthself.color = GREENself.gap_y = gap_yself.gap_height = gap_height# 两部分管道的矩形# 上管道: 从顶部到 gap_y - gap_height/2# 下管道: 从 gap_y + gap_height/2 到地面self.top_height = gap_y - gap_height // 2self.bottom_y = gap_y + gap_height // 2self.speed = 3  # 管道向左移动速度def update(self):self.x -= self.speeddef draw(self, surface):# 画上管道top_rect = pygame.Rect(self.x, 0, self.width, self.top_height)pygame.draw.rect(surface, self.color, top_rect)# 画下管道bottom_rect = pygame.Rect(self.x, self.bottom_y, self.width, HEIGHT - self.bottom_y)pygame.draw.rect(surface, self.color, bottom_rect)def get_top_rect(self):return pygame.Rect(self.x, 0, self.width, self.top_height)def get_bottom_rect(self):return pygame.Rect(self.x, self.bottom_y, self.width, HEIGHT - self.bottom_y)def is_off_screen(self):# 如果管道完全移出屏幕左侧return self.x + self.width < 0# -----------------------
# 主函数
# -----------------------
def main():bird = Bird(x=100, y=HEIGHT//2)pipes = []score = 0# 首先生成一组初始管道for i in range(3):gap_y = random.randint(100, GROUND_LEVEL - 100)pipe_x = 400 + i * 200  # 每 200 像素出现一对管道pipes.append(Pipe(pipe_x, gap_y))# 用于检测是否已经计分# 当鸟的x > 某个管道的x+width,就说明顺利通过管道 -> score+1passed_pipe_indices = set()running = Truewhile running:clock.tick(FPS)# 1) 事件处理for event in pygame.event.get():if event.type == pygame.QUIT:running = Falseelif event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN:# 点击或按任意键让小鸟向上bird.flap()# 2) 更新小鸟bird.update()# 检查小鸟是否撞地面或飞出屏幕上方if bird.y + bird.radius >= GROUND_LEVEL or bird.y - bird.radius <= 0:running = False# 3) 更新管道for p in pipes:p.update()# 管道移除 & 新管道生成if pipes and pipes[0].is_off_screen():pipes.pop(0)# 生成新的管道gap_y = random.randint(100, GROUND_LEVEL - 100)pipe_x = pipes[-1].x + 200  # 相隔200像素出现新管道pipes.append(Pipe(pipe_x, gap_y))# 4) 碰撞检测: 小鸟与管道bird_rect = bird.get_rect()for idx, p in enumerate(pipes):if bird_rect.colliderect(p.get_top_rect()) or bird_rect.colliderect(p.get_bottom_rect()):running = False# 得分判定:如果小鸟已超过管道的右边缘,且还未记分if bird.x > p.x + p.width and idx not in passed_pipe_indices:score += 1passed_pipe_indices.add(idx)# 5) 绘制场景screen.fill(BLACK)# 地面pygame.draw.rect(screen, WHITE, (0, GROUND_LEVEL, WIDTH, HEIGHT - GROUND_LEVEL))# 管道for p in pipes:p.draw(screen)# 小鸟bird.draw(screen)# 分数显示score_surf = font.render(f"Score: {score}", True, WHITE)screen.blit(score_surf, (10, 10))pygame.display.flip()game_over(score)def game_over(score):# 游戏结束场景screen.fill(BLACK)msg = f"Game Over! Your Score: {score}"label = font.render(msg, True, WHITE)rect = label.get_rect(center=(WIDTH // 2, HEIGHT // 2))screen.blit(label, rect)pygame.display.flip()pygame.time.wait(3000)pygame.quit()sys.exit()if __name__ == "__main__":main()

代码解析

  1. Bird 类

    • velocity 表示当前的垂直速度,每帧都增加一定重力 gravity
    • update() 用于更新小鸟的 y 坐标;
    • flap()velocity 设置为负值(比如 -6),让小鸟立刻向上冲。
    • 使用 get_rect() 得到小鸟的矩形边界,用于与管道进行 colliderect 碰撞判断。
  2. Pipe 类

    • 包含上下两根管道,通过 gap_ygap_height 确定中间空隙的位置与大小;
    • update() 向左移动管道,若离开屏幕则 is_off_screen() 返回 True 以便移除;
    • get_top_rect()get_bottom_rect() 返回上下管道的 Rect 边界,用于碰撞检测。
  3. 管道队列

    • 程序开始时先生成 3 个管道,让画面中一开始就有管道出现。
    • 当最左侧的管道移出屏幕后,移除它并在最右侧补充一个新管道。
    • 这样,场景就能源源不断地产生新管道。
  4. 得分逻辑

    • 当小鸟 x 坐标超过管道右边 x + width,说明已安全穿过该管道 -> 分数 + 1。
    • 用一个 passed_pipe_indices 集合来记录已经计分的管道,避免重复加分。
  5. 游戏结束

    • 若小鸟超出上下边界或与管道碰撞,立刻退出主循环;
    • 最后进入 game_over() 显示成绩并延时退出。

5. 实现效果

image.png

image.png


6. 总结

本示例通过 Pygame 带你体验了一个简化版的 Flappy Bird 开发流程:

  • 利用重力模拟按键上浮实现小鸟的控制;
  • 管道队列完成场景的动态生成与回收;
  • 借助碰撞检测得分机制让游戏规则更加完善。

如果你能理解并实现这些核心逻辑,相信对于 2D 横版卷轴类游戏的基础也会有了更多体会。你可以进一步在此游戏上进行创意改造,实现更完善、更具可玩性的 Flappy Bird。愿你在游戏编程之旅中越飞越高,创作出属于自己的精彩作品!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词