使用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。愿你在游戏编程之旅中越飞越高,创作出属于自己的精彩作品!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/68719.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java求职学习day23

MySQL 单表 & 约束 & 事务 1. DQL操作单表 1.1 创建数据库,复制表 1) 创建一个新的数据库 db2 CREATE DATABASE db2 CHARACTER SET utf8; 2) 将 db1 数据库中的 emp 表 复制到当前 db2 数据库 1.2 排序 通过 ORDER BY 子句 , 可以将查询出的结果进行排序 ( 排序只…

markdown公式特殊字符

个人学习笔记 根号 在 Markdown 中&#xff0c;要表示根号 3&#xff0c;可以使用 LaTeX 语法来实现。常见的有以下两种方式&#xff1a; 行内公式形式&#xff1a;使用一对美元符号 $ 将内容包裹起来&#xff0c;即 $\sqrt{3}$ &#xff0c;在支持 LaTeX 语法渲染的 Markdow…

git笔记-简单入门

git笔记 git是一个分布式版本控制系统&#xff0c;它的优点有哪些呢&#xff1f;分为以下几个部分 与集中式的版本控制系统比起来&#xff0c;不用担心单点故障问题&#xff0c;只需要互相同步一下进度即可。支持离线编辑&#xff0c;每一个人都有一个完整的版本库。跨平台支持…

系统学习算法: 专题七 递归

递归算法简而言之就是当一个大问题拆分为多个子问题时&#xff0c;如果每个子问题的操作步骤都一样&#xff0c;就可以用递归&#xff0c;其中递归在递的时候要有结束条件&#xff0c;不能一直递下去&#xff0c;结束条件后就归 这里不建议学习递归的时候抠细节&#xff0c;还…

C++中常用的十大排序方法之1——冒泡排序

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【&#x1f60a;///计算机爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于C中常用的排序方法之——冒泡排序的相关…

OpenEuler学习笔记(十五):在OpenEuler上搭建Java运行环境

一、在OpenEuler上搭建Java运行环境 在OpenEuler上搭建Java运行环境可以通过以下几种常见方式&#xff0c;下面分别介绍基于包管理器安装OpenJDK和手动安装Oracle JDK的步骤。 使用包管理器安装OpenJDK OpenJDK是Java开发工具包的开源实现&#xff0c;在OpenEuler上可以方便…

【二叉搜索树】

二叉搜索树 一、认识二叉搜索树二、二叉搜索树实现2.1插入2.2查找2.3删除 总结 一、认识二叉搜索树 二叉搜索树&#xff08;Binary Search Tree&#xff0c;简称 BST&#xff09;是一种特殊的二叉树&#xff0c;它具有以下特征&#xff1a; 若它的左子树不为空&#xff0c;则…

洛谷P3372 【模板】线段树 1以及分块

【模板】线段树 1 题目描述 如题&#xff0c;已知一个数列&#xff0c;你需要进行下面两种操作&#xff1a; 将某区间每一个数加上 k k k。求出某区间每一个数的和。 输入格式 第一行包含两个整数 n , m n, m n,m&#xff0c;分别表示该数列数字的个数和操作的总个数。 …

Linux运维之Linux的安装和配置

目录 Linux的基本概念&#xff1a; 1.为什么要使用Linux&#xff1f; 2.什么是Linux&#xff1f; Linux的安装和配置&#xff1a; 1.下载Linux的虚拟机和镜像文件&#xff1a; 1.1下载虚拟机 1.2下载镜像文件 2.在虚拟机或者物理机中安装Linux操作系统 3.配置虚拟机的…

【ArcMap零基础训练营】01 ArcMap使用入门及绘图基础

ArcMap入门及使用技巧 230106直播录像 ArcMap使用技巧及制图入门 ArcGIS的安装 本次教学使用的ArcMap版本为10.7&#xff0c;建议各位安装ArcGIS10.0及其以上版本的英文版本。 下载及安装详细教程可参考ArcGIS 10.8 for Desktop 完整安装教程 麻辣GIS 改善使用体验的几个操作…

程序员学英文之At the Airport Customs

Dialogue-1 Making Airline Reservation预定机票 My cousin works for Xiamen Airlines. 我表哥在厦航上班。I’d like to book an air ticket. 我想预定一张机票。Don’t judge a book by its cover. 不要以貌取人。I’d like to book / re-serve a table for 10. 我想预定一…

Python 写的几个经典游戏 新年放烟花、 贪吃蛇、俄罗斯方块、超级玛丽、五子棋、蜘蛛纸牌

0、新年放烟花 import pygame import random import math# 初始化Pygame pygame.init()# 设置窗口 WIDTH 800 HEIGHT 600 screen pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("新年放烟花")# 颜色定义 BLACK (0, 0, 0) WHITE (255, 2…

Python Typing: 实战应用指南

文章目录 1. 什么是 Python Typing&#xff1f;2. 实战案例&#xff1a;构建一个用户管理系统2.1 项目描述2.2 代码实现 3. 类型检查工具&#xff1a;MyPy4. 常见的 typing 用法5. 总结 在 Python 中&#xff0c;静态类型检查越来越受到开发者的重视。typing 模块提供了一种方式…

14-8C++STL的queue容器

一、queue容器 (1)queue容器的简介 queue为队列容器&#xff0c;“先进先出”的容器 (2)queue对象的构造 queue<T>q; queue<int>que Int;//存放一个int的queue容器 queue<string>queString;//存放一个string的queue容器 (3)queue容器的push()与pop()方…

计算机毕业设计Python+CNN卷积神经网络高考推荐系统 高考分数线预测 高考爬虫 协同过滤推荐算法 Vue.js Django Hadoop 大数据毕设

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

PyCharm接入DeepSeek实现AI编程

目录 效果演示 创建API key 在PyCharm中下载CodeGPT插件 配置Continue DeepSeek 是一家专注于人工智能技术研发的公司&#xff0c;致力于开发高性能、低成本的 AI 模型。DeepSeek-V3 是 DeepSeek 公司推出的最新一代 AI 模型。其前身是 DeepSeek-V2.5&#xff0c;经过持续的…

C语言指针专题一 -- 指针基础原理

目录 1. 指针概念 地址和变量 指针 2. 指针的声明与初始化 3. 指针的使用 指针访问 指针的运算 指针与数组 指针与函数 4. 编程实例 5. 指针的常见陷阱与防御 6. 总结 1. 指针概念 地址和变量 在C语言中&#xff0c;地址和变量是两个基本但非常重要的概念。 1. 变…

【Python】已解决:ModuleNotFoundError: No module named ‘cv2’

个人简介&#xff1a;某不知名博主&#xff0c;致力于全栈领域的优质博客分享 | 用最优质的内容带来最舒适的阅读体验&#xff01;文末获取免费IT学习资料&#xff01; &#x1f345; 文末获取更多信息 &#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅收藏 &#x…

从0开始,来看看怎么去linux排查Java程序故障

一&#xff0c;前提准备 最基本前提&#xff1a;你需要有liunx环境&#xff0c;如果没有请参考其它文献在自己得到local建立一个虚拟机去进行测试。 有了虚拟机之后&#xff0c;你还需要安装jdk和配置环境变量 1. 安装JDK&#xff08;以OpenJDK 17为例&#xff09; 下载JDK…

设计模式-建造者模式、原型模式

目录 建造者模式 定义 类图 优缺点 角色 建造者模式和工厂模式比较 使用案例 原型模式 定义 类图 优缺点 应用场景 应用类型 浅克隆 深克隆 建造者模式 定义 将一个复杂的对象的构造与它的表示分离&#xff0c;使同样的构建过程可以创建不同的表示&#xff0c;…