Python——pygame 面向对象的飞行小鸟(Flappy bird)
飞行小鸟(Flappy bird)
- 一些想法
- 分析需要的功能
- 构建整体框架
- 着手完整代码
一些想法
基本游戏界面就是这样
分析需要的功能
我的构思是将游戏分成三个部分
- 初始游戏菜单界面
- 游戏进行界面
- 游戏结束界面
游戏里的角色和道具则使用类
- 小鸟类
- 管道类
因为是使用pygame模块 我对这个模块也很不熟悉 很多功能都是论坛参考其他大神的 比如
pygame.transform 里面的各种变化功能
pygame.sprite 精灵模块里面的方法
构建整体框架
导入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个随机距离# 写的途中的全局变量都可以写在最上面
全局变量
我一般喜欢使用大写来区分
- 游戏窗口的设置
pygame.init() # 进行初始化
SCREEN = pygame.display.set_mode((MAP_WIDTH, MAP_HEIGHT)) # 屏幕大小
pygame.display.set_caption('飞行小鸟') # 标题
CLOCK = pygame.time.Clock()
- 加载素材
加载游戏图片和音乐
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')
- 执行函数
就是执行程序的函数
def main():menu_window()result = game_window()end_window(result)
- 程序入口
if __name__ == '__main__':main()
我将游戏分成了三个界面
- 初始游戏菜单界面
- 游戏进行界面
- 游戏结束界面
def menu_window():passdef game_window():passdef end_window(result):pass# 这里就是写运行三种游戏界面的代码
因为要显示游戏得分
所以专门写一个方法在游戏主界面代码里面直接调用这个方法 让代码不会显得冗余
最后就是我们游戏角色和道具的类方法
- 小鸟类
- 管道类
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)相关推荐
- JAVA项目:Java实现飞扬的小鸟(Flappy Bird)
飞扬的小鸟(Flappy Bird) 需求描述 游戏加载完毕点击界面即可开始游戏. 鼠标点击控制小鸟飞行,或者通过键盘控制小鸟的前后上下也可以,不要撞到管道哦! 控制好小鸟越过障碍飞得更远,获得更高的 ...
- Unity快速入门之傻瓜小鸟“Flappy Bird”(三)
目的:掌握基本2D游戏开发技巧 知识点: 1.学习UI界面的开发(UGUI) 2.循环往复简单算法 3.脚本之间的常用数据传值 4.2D游戏开发环境 5.2D精灵动画与层的设置 开发步骤 建立良好的目 ...
- 【Pygame】细致讲解开发Flappy Bird小游戏
加载素材(图片.音效) 方式1: # 加载图片 Picture = pygame.image.load("picture.png") # 加载音乐 Sound = pygame.m ...
- 飞翔的小鸟 Flappy Bird
C语言实现飞翔的小鸟游戏 操纵小鸟使其不要掉下来或着撞上烟囱 windows平台实现 代码如下: game.h: #pragma once#include <stdio.h> #inclu ...
- 《Flappy Bird》 Python Clone 学习之路
目录 背景 准备 获取游戏资源包 工程搭建 代码编写 背景 前阵学习了一些python的简单语法,前两天又了解到有个pygame库可以用python写些简单的2D游戏,昨晚无意中从GitHub上搜的了 ...
- The Angry Flappy Bird - 愤怒的飞翔小鸟
您是否在飞翔的小鸟flappy bird中被管道虐得很惨,您是否被它影响了正常生活?复仇的机会终于来了,飞翔的小鸟愤怒了! [下载地址] ios appstore下载: https://itunes. ...
- 【Python】使用Pygame做一个Flappy bird小游戏(二)
需要图片素材,音乐素材的朋友可以到我公众号[拇指笔记]后台回复"FPB"自取 做一个Flappy bird游戏的第二步就是按键检测.Flappy bird只需要用一个按键控制小鸟的 ...
- python之flappy bird(飞扬的小鸟)小游戏分享,内附源码哦~
导语: 哈喽,哈喽~今天小编又来分享小游戏了--flappy bird(飞扬的小鸟),这个游戏非常的经典,游戏中玩家必须控制一只小鸟,跨越由各种不同长度水管所组成的障碍.这个游戏能对于小编来说还是有点 ...
- cmd小游戏_使用pygame制作Flappy bird小游戏
原文链接: [Python]使用Pygame做一个Flappy bird小游戏(一)mp.weixin.qq.com 最近看到很多大佬用强化学习玩Flappy bird.所以打算也上手玩一玩,但是苦 ...
最新文章
- Win10环境下,在Matlab R2016a上的SPM12安装教程
- 写文件 追加_总结Java中创建并写文件的5种方式
- Chrome控制台用法
- 结束语:投递简历和选公司的策略
- Python List sort()方法
- Linux CentOS 编译LUA。。搞半天终于对了= =
- 拜董明珠“闺蜜”刘姝威所赐 广东证监局向美的方洪波出具警示函
- oracle手注,oracle手注
- msf后渗透之获取登入password、远程控制、调用摄像头
- MySQL恢复数据库(mysql命令)
- 面试题:用两个栈实现一个队列 Java语言实现
- html+css仿写小米商城
- 百词斩不复习_有人用过百词斩和不背单词两款背单词app吗?良心推荐哪一个好一点?...
- 医疗险十大常见误区,你中了几个?
- RTK如何进行面积测量,跟攻略学就对了
- IOS界面元素四栏(状态栏、导航栏、工具栏、TAB栏)设计规范
- 信息学奥赛一本通 1354:括弧匹配检验
- 如何使用eclipse开发android
- 计算机usb口不识别读卡器,windows7系统下usb读卡器读不出来如何解决
- 超详细|算法岗学习路线大总结