飞行小鸟(Flappy bird)

  • 一些想法
    • 分析需要的功能
    • 构建整体框架
    • 着手完整代码

一些想法

基本游戏界面就是这样

分析需要的功能

我的构思是将游戏分成三个部分

  1. 初始游戏菜单界面
  2. 游戏进行界面
  3. 游戏结束界面

游戏里的角色和道具则使用类

  1. 小鸟类
  2. 管道类

因为是使用pygame模块 我对这个模块也很不熟悉 很多功能都是论坛参考其他大神的 比如

pygame.transform 里面的各种变化功能
pygame.sprite 精灵模块里面的方法

构建整体框架

  1. 导入pygame和random

    pygame拥有丰富的制作游戏的功能

    random是随机模块 游戏里各种随机事件就是通过这个模块功能实现

import pygame
import random

2.我们写一个小的项目之前 需要将每个功能分成不同的代码块

  • 定义的变量都写到最上面
MAP_WIDTH = 288  # 地图大小
MAP_HEIGHT = 512
FPS = 30  # 刷新率
PIPE_GAPS = [110, 120, 130, 140, 150, 160]  # 缺口的距离 有这6个随机距离# 写的途中的全局变量都可以写在最上面

全局变量我一般喜欢使用大写来区分

  1. 游戏窗口的设置
pygame.init()  # 进行初始化
SCREEN = pygame.display.set_mode((MAP_WIDTH, MAP_HEIGHT))  # 屏幕大小
pygame.display.set_caption('飞行小鸟')  # 标题
CLOCK = pygame.time.Clock()
  1. 加载素材
    加载游戏图片和音乐
SPRITE_FILE = './images'
IMAGES = {}
IMAGES['guide'] = pygame.image.load(SPRITE_FILE + 'guide.png')
IMAGES['gameover'] = pygame.image.load(SPRITE_FILE + 'gameover.png')
IMAGES['floor'] = pygame.image.load(SPRITE_FILE + 'floor.png')SPRITE_SOUND = './audio/'
SOUNDS = {}
SOUNDS['start'] = pygame.mixer.Sound(SPRITE_SOUND + 'start.wav')
SOUNDS['die'] = pygame.mixer.Sound(SPRITE_SOUND + 'die.wav')
SOUNDS['hit'] = pygame.mixer.Sound(SPRITE_SOUND + 'hit.wav')
SOUNDS['score'] = pygame.mixer.Sound(SPRITE_SOUND + 'score.wav')
  1. 执行函数
    就是执行程序的函数
def main():menu_window()result = game_window()end_window(result)
  1. 程序入口
if __name__ == '__main__':main()
  1. 我将游戏分成了三个界面

    1. 初始游戏菜单界面
    2. 游戏进行界面
    3. 游戏结束界面
def menu_window():passdef game_window():passdef end_window(result):pass# 这里就是写运行三种游戏界面的代码
  1. 因为要显示游戏得分

    所以专门写一个方法在游戏主界面代码里面直接调用这个方法 让代码不会显得冗余

  2. 最后就是我们游戏角色和道具的类方法

    1. 小鸟类
    2. 管道类
class Bird(pygame.sprite.Sprite):def __init__(self, x, y):# super(Bird, self).__init__(x, y)pygame.sprite.Sprite.__init__(self)passdef update(self, flap=False):passdef go_die(self):passclass Pipe(pygame.sprite.Sprite):def __init__(self, x, y, upwards=True):pygame.sprite.Sprite.__init__(self)passdef update(self):pass

我们把整体框架搭建好之后 就可以着手完善代码

着手完整代码

"""
Project: pygame
Creator: stan Z
Create time: 2021-03-08 19:37
IDE: PyCharm
Introduction:
"""
import pygame
import random######################################## 定义变量
MAP_WIDTH = 288  # 地图大小
MAP_HEIGHT = 512
FPS = 30  # 刷新率
PIPE_GAPS = [90, 100, 110, 120, 130, 140]  # 缺口的距离 有这6个随机距离
# PIPE_GAPS1 = []
PIPE_HEIGHT_RANGE = [int(MAP_HEIGHT * 0.3), int(MAP_HEIGHT * 0.7)]  # 管道长度范围
PIPE_DISTANCE = 120  # 管道之间距离######################################## 游戏基本设置
pygame.init()  # 进行初始化
SCREEN = pygame.display.set_mode((MAP_WIDTH, MAP_HEIGHT))  # 调用窗口设置屏幕大小
pygame.display.set_caption('飞行小鸟byStanZ')  # 标题
CLOCK = pygame.time.Clock()  # 建立时钟######################################## 加载素材
SPRITE_FILE = './images'
# 列表推导式 获得三种不同的鸟和三种状态
BIRDS = [[f'{SPRITE_FILE}{bird}-{move}.png' for move in ['up', 'mid', 'down']] for bird in ['red', 'blue', 'yellow']]
BGPICS = [SPRITE_FILE + 'day.png', SPRITE_FILE + 'night.png']
PIPES = [SPRITE_FILE + 'green-pipe.png', SPRITE_FILE + 'red-pipe.png']
NUMBERS = [f'{SPRITE_FILE}{n}.png' for n in range(10)]# 将图片设置成一个大字典 里面通过key-value存不同的场景图
IMAGES = {}
IMAGES['numbers'] = [pygame.image.load(number) for number in NUMBERS]  # 数字素材有10张 因此遍历
IMAGES['guide'] = pygame.image.load(SPRITE_FILE + 'guide.png')
IMAGES['gameover'] = pygame.image.load(SPRITE_FILE + 'gameover.png')
IMAGES['floor'] = pygame.image.load(SPRITE_FILE + 'floor.png')# 地板的高是一个很常用的变量 因此我们专门拿出来
FLOOR_H = MAP_HEIGHT - IMAGES['floor'].get_height()  # 屏幕高减去floor图片的高 就是他在屏幕里的位置SPRITE_SOUND = './sound'
SOUNDS = {}  # 同理声音素材也这样做
SOUNDS['start'] = pygame.mixer.Sound(SPRITE_SOUND + 'start.wav')
SOUNDS['die'] = pygame.mixer.Sound(SPRITE_SOUND + 'die.wav')
SOUNDS['hit'] = pygame.mixer.Sound(SPRITE_SOUND + 'hit.wav')
SOUNDS['score'] = pygame.mixer.Sound(SPRITE_SOUND + 'score.wav')
SOUNDS['flap'] = pygame.mixer.Sound(SPRITE_SOUND + 'flap.wav')
SOUNDS['death'] = pygame.mixer.Sound(SPRITE_SOUND + 'death.wav')
SOUNDS['main'] = pygame.mixer.Sound(SPRITE_SOUND + 'main_theme.ogg')
SOUNDS['world_clear'] = pygame.mixer.Sound(SPRITE_SOUND + 'world_clear.wav')# 执行函数
def main():while True:IMAGES['bgpic'] = pygame.image.load(random.choice(BGPICS))  # random的choice方法可以随机从列表里返回一个元素 白天或者黑夜IMAGES['bird'] = [pygame.image.load(frame) for frame in random.choice(BIRDS)]  # 列表推导式 鸟也是随机pipe = pygame.image.load(random.choice(PIPES))IMAGES['pipe'] = [pipe, pygame.transform.flip(pipe, False, True)]  # flip是翻转 将管道放下面和上面 Flase水平不动,True上下翻转SOUNDS['start'].play()# SOUNDS['main'].play()menu_window()result = game_window()end_window(result)def menu_window():SOUNDS['world_clear'].play()floor_gap = IMAGES['floor'].get_width() - MAP_WIDTH  # 地板间隙 336 - 288 = 48floor_x = 0# 标题位置guide_x = (MAP_WIDTH - IMAGES['guide'].get_width()) / 2guide_y = MAP_HEIGHT * 0.12# 小鸟位置bird_x = MAP_WIDTH * 0.2bird_y = MAP_HEIGHT * 0.5 - IMAGES['bird'][0].get_height() / 2bird_y_vel = 1  # 小鸟飞行的速率 按y坐标向下max_y_shift = 50  # 小鸟飞行的最大幅度y_shift = 0  # 小鸟起始幅度为0idx = 0  # 小鸟翅膀煽动频率frame_seq = [0] * 5 + [1] * 5 + [2] * 5 + [1] * 5  # 控制小鸟翅膀运动上中下while True:for event in pygame.event.get():  # 监控行为if event.type == pygame.QUIT:quit()elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:returnif floor_x <= -floor_gap:  # 当地板跑到最大间隔的时候floor_x = floor_x + floor_gap  # 刷新地板的x轴else:floor_x -= 4  # 地板 x轴的移动速度if abs(y_shift) == max_y_shift:  # 如果y_shift的绝对值 = 最大幅度bird_y_vel *= -1  # 调转方向飞 同时飞行速度为1else:bird_y += bird_y_vely_shift += bird_y_vel  # 小鸟y轴正负交替 上下飞# 小鸟翅膀idx += 1  # 翅膀煽动频率idx %= len(frame_seq)  # 通过取余得到 0 1 2frame_index = frame_seq[idx]  # 小鸟图片的下标 就是翅膀的状态SCREEN.blit(IMAGES['bgpic'], (0, 0))SCREEN.blit(IMAGES['floor'], (floor_x, FLOOR_H))SCREEN.blit(IMAGES['guide'], (guide_x, guide_y))SCREEN.blit(IMAGES['bird'][frame_index], (bird_x, bird_y))pygame.display.update()CLOCK.tick(FPS)  # 以每秒30帧刷新屏幕def game_window():SOUNDS['world_clear'].stop()SOUNDS['main'].play()score = 0floor_gap = IMAGES['floor'].get_width() - MAP_WIDTH  # 地板间隙 336 - 288 = 48floor_x = 0# 小鸟位置bird_x = MAP_WIDTH * 0.2bird_y = MAP_HEIGHT * 0.5 - IMAGES['bird'][0].get_height() / 2bird = Bird(bird_x, bird_y)n_pair = round(MAP_WIDTH / PIPE_DISTANCE)  # 四舍五入取整数 屏幕宽度/两个管道之间的距离 这个距离时候刷新第二个管道  2.4pipe_group = pygame.sprite.Group()  # 是一个集合# 生成前面的管道pipe_x = MAP_WIDTHpipe_y = random.randint(PIPE_HEIGHT_RANGE[0], PIPE_HEIGHT_RANGE[1])  # 管道长度随机从153.6 到 358.4pipe1 = Pipe(pipe_x, pipe_y, upwards=True)  # 创建一个管道对象pipe_group.add(pipe1)  # 将对象添加到这个精灵集合里面pipe2 = Pipe(pipe_x, pipe_y - random.choice(PIPE_GAPS), upwards=False)  # 翻转的管道pipe_group.add(pipe2)SOUNDS['flap'].play()while True:flap = Falsefor event in pygame.event.get():if event.type == pygame.QUIT:quit()elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:  # 空格拍翅膀SOUNDS['flap'].play()flap = Truebird.update(flap)if floor_x <= -floor_gap:  # 当地板跑到最大间隔的时候floor_x = floor_x + floor_gap  # 刷新地板的x轴else:floor_x -= 4  # 地板 x轴的移动速度# 生成最后一个管道if len(pipe_group) / 2 < n_pair:  # 当管道组长度<2.4 时 意思就是两个半管道的时候# sprites()将管道组返回成列表last_pipe = pipe_group.sprites()[-1]pipe_x = last_pipe.rect.right + PIPE_DISTANCEpipe_y = random.randint(PIPE_HEIGHT_RANGE[0], PIPE_HEIGHT_RANGE[1])pipe1 = Pipe(pipe_x, pipe_y, upwards=True)pipe_group.add(pipe1)pipe2 = Pipe(pipe_x, pipe_y - random.choice(PIPE_GAPS), upwards=False)pipe_group.add(pipe2)pipe_group.update()# 鸟的矩形y坐标如果大于地板的高度 就死亡# pygame.sprite.spritecollideany 碰撞函数 如果bird和pipe_group碰撞了 就死亡if bird.rect.y > FLOOR_H or bird.rect.y < 0 or pygame.sprite.spritecollideany(bird, pipe_group):SOUNDS['score'].stop()SOUNDS['main'].stop()SOUNDS['hit'].play()SOUNDS['die'].play()SOUNDS['death'].play()# 保存死亡时的鸟儿 分数 管道 继续显示在结束窗口result = {'bird': bird, 'score': score, 'pipe_group': pipe_group}return result# 当小鸟左边大于 管道右边就得分if pipe_group.sprites()[0].rect.left == 0:SOUNDS['score'].play()score += 1SCREEN.blit(IMAGES['bgpic'], (0, 0))pipe_group.draw(SCREEN)SCREEN.blit(IMAGES['floor'], (floor_x, FLOOR_H))SCREEN.blit(bird.image, bird.rect)show_score(score)pygame.display.update()CLOCK.tick(FPS)def end_window(result):# 显示gameover的图片gameover_x = MAP_WIDTH * 0.5 - IMAGES['gameover'].get_width() / 2gameover_y = MAP_HEIGHT * 0.4bird = result['bird']pipe_group = result['pipe_group']while True:for event in pygame.event.get():if event.type == pygame.QUIT:quit()elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE and bird.rect.y > FLOOR_H:SOUNDS['death'].stop()return# 使用类go_die方法 鸟儿撞墙后 旋转往下bird.go_die()SCREEN.blit(IMAGES['bgpic'], (0, 0))pipe_group.draw(SCREEN)SCREEN.blit(IMAGES['floor'], (0, FLOOR_H))SCREEN.blit(IMAGES['gameover'], (gameover_x, gameover_y))show_score(result['score'])SCREEN.blit(bird.image, bird.rect)pygame.display.update()CLOCK.tick(FPS)# 显示得分
def show_score(score):score_str = str(score)w = IMAGES['numbers'][0].get_width()x = MAP_WIDTH / 2 - 2 * w / 2y = MAP_HEIGHT * 0.1for number in score_str:  # IMAGES['numbers'] = [pygame.image.load(number) for number in NUMBERS]SCREEN.blit(IMAGES['numbers'][int(number)], (x, y))x += wclass Bird(pygame.sprite.Sprite):def __init__(self, x, y):# super(Bird, self).__init__(x, y)pygame.sprite.Sprite.__init__(self)self.frames = IMAGES['bird']  # 鸟儿框架self.frame_list = [0] * 5 + [1] * 5 + [2] * 5 + [1] * 5  # 控制小鸟翅膀运动上中下self.frame_index = 0self.image = self.frames[self.frame_list[self.frame_index]]  # 和菜单界面小鸟扇翅膀一个原理self.rect = self.image.get_rect()  # 鸟儿的矩形self.rect.x = xself.rect.y = yself.gravity = 1  # 重力self.flap_acc = -10  # 翅膀拍打往上飞 y坐标-10self.y_vel = -10  # y坐标的速度self.max_y_vel = 15  # y轴下落最大速度self.rotate = 0  # 脑袋朝向self.rotate_vel = -3  # 转向速度self.max_rotate = -30  # 最大转向速度self.flap_rotate = 45  # 按了空格只会脑袋朝向上30度def update(self, flap=False):if flap:self.y_vel = self.flap_acc  # 拍打翅膀 则y速度-10向上self.rotate = self.flap_rotateelse:self.rotate = self.rotate + self.rotate_velself.y_vel = min(self.y_vel + self.gravity, self.max_y_vel)self.rect.y += self.y_vel  # 小鸟向上移动的距离self.rorate = max(self.rotate + self.rotate_vel, self.max_rotate)self.frame_index += 1  # 扇翅膀的速率self.frame_index %= len(self.frame_list)  # 0~20self.image = self.frames[self.frame_list[self.frame_index]]self.image = pygame.transform.rotate(self.image, self.rotate)  # transform变形方法 旋转def go_die(self):if self.rect.y < FLOOR_H:self.y_vel = self.max_y_velself.rect.y += self.y_velself.rotate = -90self.image = self.frames[self.frame_list[self.frame_index]]self.image = pygame.transform.rotate(self.image, self.rotate)# 管道类
class Pipe(pygame.sprite.Sprite):def __init__(self, x, y, upwards=True):pygame.sprite.Sprite.__init__(self)self.x_vel = -4  # 管道移动速度# 默认属性为真 则是正向管道if upwards:self.image = IMAGES['pipe'][0]self.rect = self.image.get_rect()self.rect.x = xself.rect.top = y# 利用flip方法 旋转管道成为反向管道else:self.image = IMAGES['pipe'][1]self.rect = self.image.get_rect()self.rect.x = xself.rect.bottom = ydef update(self):self.rect.x += self.x_vel  # 管道x轴加移动速度if self.rect.right < 0:self.kill()if __name__ == '__main__':main()

我把每行复杂的代码都写了注释

Python——pygame 面向对象的飞行小鸟(Flappy bird)相关推荐

  1. JAVA项目:Java实现飞扬的小鸟(Flappy Bird)

    飞扬的小鸟(Flappy Bird) 需求描述 游戏加载完毕点击界面即可开始游戏. 鼠标点击控制小鸟飞行,或者通过键盘控制小鸟的前后上下也可以,不要撞到管道哦! 控制好小鸟越过障碍飞得更远,获得更高的 ...

  2. Unity快速入门之傻瓜小鸟“Flappy Bird”(三)

    目的:掌握基本2D游戏开发技巧 知识点: 1.学习UI界面的开发(UGUI) 2.循环往复简单算法 3.脚本之间的常用数据传值 4.2D游戏开发环境 5.2D精灵动画与层的设置 开发步骤 建立良好的目 ...

  3. 【Pygame】细致讲解开发Flappy Bird小游戏

    加载素材(图片.音效) 方式1: # 加载图片 Picture = pygame.image.load("picture.png") # 加载音乐 Sound = pygame.m ...

  4. 飞翔的小鸟 Flappy Bird

    C语言实现飞翔的小鸟游戏 操纵小鸟使其不要掉下来或着撞上烟囱 windows平台实现 代码如下: game.h: #pragma once#include <stdio.h> #inclu ...

  5. 《Flappy Bird》 Python Clone 学习之路

    目录 背景 准备 获取游戏资源包 工程搭建 代码编写 背景 前阵学习了一些python的简单语法,前两天又了解到有个pygame库可以用python写些简单的2D游戏,昨晚无意中从GitHub上搜的了 ...

  6. The Angry Flappy Bird - 愤怒的飞翔小鸟

    您是否在飞翔的小鸟flappy bird中被管道虐得很惨,您是否被它影响了正常生活?复仇的机会终于来了,飞翔的小鸟愤怒了! [下载地址] ios appstore下载: https://itunes. ...

  7. 【Python】使用Pygame做一个Flappy bird小游戏(二)

    需要图片素材,音乐素材的朋友可以到我公众号[拇指笔记]后台回复"FPB"自取 做一个Flappy bird游戏的第二步就是按键检测.Flappy bird只需要用一个按键控制小鸟的 ...

  8. python之flappy bird(飞扬的小鸟)小游戏分享,内附源码哦~

    导语: 哈喽,哈喽~今天小编又来分享小游戏了--flappy bird(飞扬的小鸟),这个游戏非常的经典,游戏中玩家必须控制一只小鸟,跨越由各种不同长度水管所组成的障碍.这个游戏能对于小编来说还是有点 ...

  9. cmd小游戏_使用pygame制作Flappy bird小游戏

    原文链接: [Python]使用Pygame做一个Flappy bird小游戏(一)​mp.weixin.qq.com 最近看到很多大佬用强化学习玩Flappy bird.所以打算也上手玩一玩,但是苦 ...

最新文章

  1. Win10环境下,在Matlab R2016a上的SPM12安装教程
  2. 写文件 追加_总结Java中创建并写文件的5种方式
  3. Chrome控制台用法
  4. 结束语:投递简历和选公司的策略
  5. Python List sort()方法
  6. Linux CentOS 编译LUA。。搞半天终于对了= =
  7. 拜董明珠“闺蜜”刘姝威所赐 广东证监局向美的方洪波出具警示函
  8. oracle手注,oracle手注
  9. msf后渗透之获取登入password、远程控制、调用摄像头
  10. MySQL恢复数据库(mysql命令)
  11. 面试题:用两个栈实现一个队列 Java语言实现
  12. html+css仿写小米商城
  13. 百词斩不复习_有人用过百词斩和不背单词两款背单词app吗?良心推荐哪一个好一点?...
  14. 医疗险十大常见误区,你中了几个?
  15. RTK如何进行面积测量,跟攻略学就对了
  16. IOS界面元素四栏(状态栏、导航栏、工具栏、TAB栏)设计规范
  17. 信息学奥赛一本通 1354:括弧匹配检验
  18. 如何使用eclipse开发android
  19. 计算机usb口不识别读卡器,windows7系统下usb读卡器读不出来如何解决
  20. 超详细|算法岗学习路线大总结

热门文章

  1. php多用户商城系统推荐
  2. 关于认证Steamworks注意事项。
  3. Java入门教程笔记(一)
  4. ARM单进程脱壳之FtpRush v1.0
  5. 微信公众号 扫码自动回复消息
  6. 建站四部曲之移动端篇(Android+上线)
  7. 解决现在无法停止‘通用卷’设备,请稍候再停止该设备的方法
  8. linux里/是主分区,Linux主分区和扩展分区及逻辑分区的最大区别
  9. 工作新手需要注意的:新人在试用期间的工作态度和心态很重要【摘自一位朋友的话,不断更新】
  10. 一张图看懂docker容器的所有状态