python带你成功复刻热门手机游戏——飞翔的小鸟
前言
大家早好、午好、晚好吖 ❤ ~欢迎光临本文章

飞翔的小鸟(游戏英文名:Flappy Bird)

一款由越南独立开发者开发的手机游戏,是之前非常流行的一款手机游戏
小游戏目标:让小鸟穿过管子,不要碰到任何物体,挑战更远距离

今天,就让我们一起用python来复刻一下这款游戏吧!!!
完整源码、素材皆可点击文章下方名片获取此处跳转
环境使用:
-
Python 3.8
–> 解释器 <执行python代码>
-
Pycharm
–> 编辑器 <写python代码的>
所需素材
音效素材

图片素材

效果展示


背景啊其他素材啊也是可以修改的
给你们看看博主魔改的背景

代码展示
(完整源码、素材皆可点击此处+获取)
‘’‘配置文件’‘’
导入模块
import os
# FPS
FPS = 60
屏幕
SCREENWIDTH = 288
SCREENHEIGHT = 512
管道之间的空隙
PIPE_GAP_SIZE = 100
图片
NUMBER_IMAGE_PATHS = {'0': os.path.join(os.getcwd(), 'resources/images/0.png'),'1': os.path.join(os.getcwd(), 'resources/images/1.png'),'2': os.path.join(os.getcwd(), 'resources/images/2.png'),'3': os.path.join(os.getcwd(), 'resources/images/3.png'),'4': os.path.join(os.getcwd(), 'resources/images/4.png'),'5': os.path.join(os.getcwd(), 'resources/images/5.png'),'6': os.path.join(os.getcwd(), 'resources/images/6.png'),'7': os.path.join(os.getcwd(), 'resources/images/7.png'),'8': os.path.join(os.getcwd(), 'resources/images/8.png'),'9': os.path.join(os.getcwd(), 'resources/images/9.png')
}
BIRD_IMAGE_PATHS = {'red': {'up': os.path.join(os.getcwd(), 'resources/images/redbird-upflap.png'),'mid': os.path.join(os.getcwd(), 'resources/images/redbird-midflap.png'),'down': os.path.join(os.getcwd(), 'resources/images/redbird-downflap.png')},'blue': {'up': os.path.join(os.getcwd(), 'resources/images/bluebird-upflap.png'),'mid': os.path.join(os.getcwd(), 'resources/images/bluebird-midflap.png'),'down': os.path.join(os.getcwd(), 'resources/images/bluebird-downflap.png')},'yellow': {'up': os.path.join(os.getcwd(), 'resources/images/yellowbird-upflap.png'),'mid': os.path.join(os.getcwd(), 'resources/images/yellowbird-midflap.png'),'down': os.path.join(os.getcwd(), 'resources/images/yellowbird-downflap.png')}
}
BACKGROUND_IMAGE_PATHS = {'day': os.path.join(os.getcwd(), 'resources/images/background-day.png'),'night': os.path.join(os.getcwd(), 'resources/images/background-night.png')
}
PIPE_IMAGE_PATHS = {'green': os.path.join(os.getcwd(), 'resources/images/pipe-green.png'),'red': os.path.join(os.getcwd(), 'resources/images/pipe-red.png')
}
OTHER_IMAGE_PATHS = {'gameover': os.path.join(os.getcwd(), 'resources/images/gameover.png'),'message': os.path.join(os.getcwd(), 'resources/images/message.png'),'base': os.path.join(os.getcwd(), 'resources/images/base.png')
}
音频路径
AUDIO_PATHS = {'die': os.path.join(os.getcwd(), 'resources/audios/die.wav'),'hit': os.path.join(os.getcwd(), 'resources/audios/hit.wav'),'point': os.path.join(os.getcwd(), 'resources/audios/point.wav'),'swoosh': os.path.join(os.getcwd(), 'resources/audios/swoosh.wav'),'wing': os.path.join(os.getcwd(), 'resources/audios/wing.wav')
}
主运行文件
导入模块
import cfg
import sys
import random
import pygame
from modules import *
‘’‘游戏初始化’‘’
def initGame():pygame.init()pygame.mixer.init()screen = pygame.display.set_mode((cfg.SCREENWIDTH, cfg.SCREENHEIGHT))pygame.display.set_caption('Bird Q群261823976')return screen
‘’‘显示当前分数’‘’
def showScore(screen, score, number_images):digits = list(str(int(score)))width = 0for d in digits:width += number_images.get(d).get_width()offset = (cfg.SCREENWIDTH - width) / 2for d in digits:screen.blit(number_images.get(d), (offset, cfg.SCREENHEIGHT*0.1))offset += number_images.get(d).get_width()
‘’‘主函数’‘’
def main():screen = initGame()# 加载必要的游戏资源# --导入音频sounds = dict()for key, value in cfg.AUDIO_PATHS.items():sounds[key] = pygame.mixer.Sound(value)# --导入数字图片number_images = dict()for key, value in cfg.NUMBER_IMAGE_PATHS.items():number_images[key] = pygame.image.load(value).convert_alpha()# --管道pipe_images = dict()pipe_images['bottom'] = pygame.image.load(random.choice(list(cfg.PIPE_IMAGE_PATHS.values()))).convert_alpha()pipe_images['top'] = pygame.transform.rotate(pipe_images['bottom'], 180)# --小鸟图片bird_images = dict()for key, value in cfg.BIRD_IMAGE_PATHS[random.choice(list(cfg.BIRD_IMAGE_PATHS.keys()))].items():bird_images[key] = pygame.image.load(value).convert_alpha()# --背景图片backgroud_image = pygame.image.load(random.choice(list(cfg.BACKGROUND_IMAGE_PATHS.values()))).convert_alpha()# --其他图片other_images = dict()for key, value in cfg.OTHER_IMAGE_PATHS.items():other_images[key] = pygame.image.load(value).convert_alpha()# 游戏开始界面game_start_info = startGame(screen, sounds, bird_images, other_images, backgroud_image, cfg)# 进入主游戏score = 0bird_pos, base_pos, bird_idx = list(game_start_info.values())base_diff_bg = other_images['base'].get_width() - backgroud_image.get_width()clock = pygame.time.Clock()# --管道类pipe_sprites = pygame.sprite.Group()for i in range(2):pipe_pos = Pipe.randomPipe(cfg, pipe_images.get('top'))pipe_sprites.add(Pipe(image=pipe_images.get('top'), position=(cfg.SCREENWIDTH+200+i*cfg.SCREENWIDTH/2, pipe_pos.get('top')[-1])))pipe_sprites.add(Pipe(image=pipe_images.get('bottom'), position=(cfg.SCREENWIDTH+200+i*cfg.SCREENWIDTH/2, pipe_pos.get('bottom')[-1])))# --bird类bird = Bird(images=bird_images, idx=bird_idx, position=bird_pos)# --是否增加pipeis_add_pipe = True# --游戏是否进行中is_game_running = Truewhile is_game_running:for event in pygame.event.get():if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):pygame.quit()sys.exit()elif event.type == pygame.KEYDOWN:if event.key == pygame.K_SPACE or event.key == pygame.K_UP:bird.setFlapped()sounds['wing'].play()# --碰撞检测for pipe in pipe_sprites:if pygame.sprite.collide_mask(bird, pipe):sounds['hit'].play()is_game_running = False# --更新小鸟boundary_values = [0, base_pos[-1]]is_dead = bird.update(boundary_values, float(clock.tick(cfg.FPS))/1000.)if is_dead:sounds['hit'].play()is_game_running = False# --移动base实现小鸟往前飞的效果base_pos[0] = -((-base_pos[0] + 4) % base_diff_bg)# --移动pipe实现小鸟往前飞的效果flag = Falsefor pipe in pipe_sprites:pipe.rect.left -= 4if pipe.rect.centerx < bird.rect.centerx and not pipe.used_for_score:pipe.used_for_score = Truescore += 0.5if '.5' in str(score):sounds['point'].play()if pipe.rect.left < 5 and pipe.rect.left > 0 and is_add_pipe:pipe_pos = Pipe.randomPipe(cfg, pipe_images.get('top'))pipe_sprites.add(Pipe(image=pipe_images.get('top'), position=pipe_pos.get('top')))pipe_sprites.add(Pipe(image=pipe_images.get('bottom'), position=pipe_pos.get('bottom')))is_add_pipe = Falseelif pipe.rect.right < 0:pipe_sprites.remove(pipe)flag = Trueif flag: is_add_pipe = True# --绑定必要的元素在屏幕上screen.blit(backgroud_image, (0, 0))pipe_sprites.draw(screen)screen.blit(other_images['base'], base_pos)showScore(screen, score, number_images)bird.draw(screen)pygame.display.update()clock.tick(cfg.FPS)endGame(screen, sounds, showScore, score, number_images, bird, pipe_sprites, backgroud_image, other_images, base_pos, cfg)
‘’‘run’‘’
if __name__ == '__main__':while True:main()
代码太多,我就没放完啦,完整源码、素材皆可点击文章下方名片获取此处跳转
尾语 💝
好了,今天的分享就差不多到这里了!
完整代码、更多资源、疑惑解答直接点击下方名片自取即可。
对下一篇大家想看什么,可在评论区留言哦!看到我会更新哒(ง •_•)ง
喜欢就关注一下博主,或点赞收藏评论一下我的文章叭!!!

相关文章:
python带你成功复刻热门手机游戏——飞翔的小鸟
前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 飞翔的小鸟(游戏英文名:Flappy Bird) 一款由越南独立开发者开发的手机游戏,是之前非常流行的一款手机游戏 小游戏目标:让小鸟穿过管子,不要碰到任何物体…...
YOLOv8初体验:检测、跟踪、模型部署
安装 YOLOv8有两种安装方式,一种是直接用pip命令安装: pip install ultralytics另外一种是通过源码安装: git clone https://github.com/ultralytics/ultralytics cd ultralytics pip install -e .[dev]安装完成后就可以通过yolo命令在命令…...
Vue 监听(watch handler)
普通监听 缺点:不能深度监听(对象属性的改变),刷新或首次加载不能执行。 watch: { carts: function (val, oldVal) { console.log(new: %s, old: %s, val, oldVal) } } 高级监…...
前端代码质量-圈复杂度原理和实践
1. 导读 你们是否也有过下面的想法? 重构一个项目还不如新开发一个项目…这代码是谁写的,我真想… 你们的项目中是否也存在下面的问题? 单个项目也越来越庞大,团队成员代码风格不一致,无法对整体的代码质量做全面的…...
汽车微控制器芯片F280039CPZRQ1、F280039CSPM、F280039CSPN规格参数
F280039CPZRQ1、F280039CSPM、F280039CSPN是C2000实时微控制器系列中的一款器件。C2000微控制器是可扩展、超低延迟器件,旨在提高电力电子设备的效率,包括但不限于:高功率密度、高开关频率,并支持使用 GaN和SiC技术。F280039CPZRQ…...
禾观科技三面经历
智力题 一天中时针和分钟重合多少次 由于时针1分钟旋转的圆心角度数为0.5度(30/60min) 分针1分钟旋转的圆心角度为6度(30/5min) 当两针第一次重合时后到第二次重合,分针比时针多旋转过的圆心角度数为360度。(快的比慢的多跑一圈,也就是360度) 这类问题实际上是分针追时…...
Spring Boot 实现接口幂等性的 4 种方案
一、什么是幂等性 幂等是一个数学与计算机学概念,在数学中某一元运算为幂等时,其作用在任一元素两次后会和其作用一次的结果相同。 在计算机中编程中,一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数或幂…...
Android Studio开发APP
1.下载Android Studio 官网下载:Android Studio for Window ... 百度云下载:android-studio-bundle-141.1903250-windows.exe Android Studio 是谷歌推出的一个Android集成开发工具,基于IntelliJ IDEA. 类似 Eclipse ADT,Android Studio 提供了集成的 Android 开发工具用…...
Spring之实例化Bean _ @Resource和@Autowired实现原理(3)
目录 1. 搜集注解信息 applyMergedBeanDefinitionPostProcessor(*) 2. 将实例化的Bean放入3级缓存中 addSingletonFactory(***)为循环依赖做准备 3. 根…...
华为HCIE学习之Openstack Cinder组件(cinder对接glusterfs)
文章目录一、MQ的作用二、cinder架构图三、各组件的作用四、cinder对接glusterfs一、MQ的作用 服务内各组件交互通过MQ进行 二、cinder架构图 IET,Linux用软件做存储,CNA识别过去就是IETTGT,物理存储,CNA识别过去就是TGT 三、…...
关于Go语言的底层,你想知道的都在这里!
文章目录1. GoLang语言1.1 Slice1.2 Map1.3 Channel1.4 Goroutine1.5 GMP调度1.6 垃圾回收机制1.7 其他知识点2. Web框架Gin和微服务框架Micro2.1 Gin框架2.2 Micro框架2.3 Viper2.4 Swagger2.5 Zap2.6 JWT文章字数大约1.95万字,阅读大概需要65分钟,建议…...
每日一问-ChapGPT-20230308-关于技术与思考的问题
文章目录每日一问-ChapGPT系列起因每日一问-ChapGPT-20230308-关于技术与思考的问题matplotlib_venn 中 venn2函数调用时,subsets传入A list (or a tuple) containing two set objects,怎么理解plt.pie() 包含哪些参数,以及每个参数的意义mat…...
Oracle表分区的创建、新增、拆分
Oracle中为了方便管理、查询数据当数据量大于500w或者2G时最好用分区表,常见的一种是使用时间作为分区。 分区表添加新的分区有 2 种情况: (1) 原分区里边界是 maxvalue 或者 default。 这种情况下,我们需要把边界分区 drop 掉,加…...
如何快速升级Java 8 到Java11
老板让我把一个项目从 Java 8 迁移到 Java 11,我该怎么办呢? 最简单的办法,当然是直接强行升级,遇到一个错就改一个错,别看它 low,但是对于一个小型且非核心的项目来说,已经足够了。 当然,对于比较重要的项目,且代码行数不少的情况,最标准的姿势就是对着官方文档进…...
内卷把同事逼成了“扫地僧”,把Git上所有面试题整理成足足24W字Java八股文
互联网大厂更多的是看重学历还是技术?毫无疑问,是技术,技术水平相近的情况下,肯定学历高/好的会优先一点,这点大家肯定都理解。说实话,学弟学妹们找工作难,作为面试官招人也难呀!&am…...
【计组】主存储器有关知识梳理
一、主存储器 主存储器可以直接和CPU进行通信,但是只能保存临时数据,在断电后数据就消失。还有一个特点是,主存储器的容量小,速度快,造价高。 1.构成 2.主存中存储体的构造 最小的存储单位是存储元,存储元…...
QT对象树
对象模型(对象树) 在Qt中创建对象的时候会提供一个Parent对象指针,下面来解释这个parent到底是干什么的。 l QObject是以对象树的形式组织起来的。 n 当你创建一个QObject对象时,会看到QObject的构造函数接收一个QObject指针作…...
什么是B+树
B树是一种树数据结构。B树索引是B树在数据库中的一种实现,是最常见也是数据库中使用最为频繁的一种索引。 先来了解一下什么是索引? 一、索引 数据都是存储在硬盘上的,查询数据不可避免的需要进行IO操作。 索引是一种数据结构,…...
【Unity游戏破解】外挂原理分析
文章目录认识unity打包目录结构游戏逆向流程Unity游戏攻击面可被攻击原因mono的打包建议方案锁血飞天无限金币攻击力翻倍以上统称内存挂透视自瞄压枪瞬移内购破解Unity游戏防御开发时注意数据安全接入第三方反作弊系统外挂检测思路狠人自爆实战查看目录结构用il2cpp dumper例子…...
windows 关闭指定端口进程
1、首先打开cmd 注意要用管理员身份打开cmd,否则可能出现无权访问的提示。 2、输入以下命令(以端口号9098为例) 查看端口信息 netstat -ano | findstr 90983、输入以下命令关闭这个进程 taskkill -PID 39716 -F...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
