马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 xenli 于 2019-12-25 16:46 编辑
源代码在二楼
1、游戏简介
Flappy Bird 是一款鸟类 飞行游戏,由越南河内独立游戏开发者阮哈东(Dong Nguyen)开发。在 Flappy Bird这款游戏中,玩家只需要用一根手指来操控,单击触摸手机屏幕,小鸟就会往上飞。不断地单击屏幕,小鸟就会不断地往高处飞;放松手指,则会快速下降。玩家要控制小鸟一直向前飞行,并且注意躲避途中高低不平的管子。如果小鸟碰到了障碍物,游戏就会结束。每当小鸟飞过一组管道,玩家就会获得1分。
成品效果
2、游戏分析
在Flappy Bird游戏中,主要有两个对象:小鸟和管道。可以创建Bird类和Pineline类来分别表示这两个对象。小鸟可以通过上下移动来躲避管道,所以在Bird类中创建一个birdUpdate()方法,实现小鸟的上下移动。为了体现小鸟向前飞行的特征,可以让管道一直向左侧移动,这样在窗口中就好像小鸟在向前飞行。所以,在Pineline类中也创建一个updatePipeline()方法,实现管道的向左移动。此外,还创建了3个函数:createMap()函数用于绘制地图;checkDead()函数用于判断小鸟的生命状态;getResult()函数用于获取最终分数。最后在主逻辑中,实例化类并调用相关方法,实现相应功能。
3、搭建主框架
通过前面的分析,我们可以搭建起Flappy Bird游戏的主框架。Flappy Bird游戏有两个对象:小鸟和管道。先来创建这两个类,类中具体的方法可以先使用pass语句代替。然后创建一个绘制地图的函数createMap()。最后,在主逻辑中绘制背景图片。关键代码如下:# -*- coding:utf-8 -*-
import pygame
import sys
import random
import os
class Bird(object):
'''定义一个鸟类'''
def __init__(self):
'''定义初始化方法'''
pass
def birUpdate(self):
pass
class Pipeline(object):
'''定义一个管道类'''
def __init__(self):
'''定义初始化方法'''
pass
def updatePipeline(self):
'''水平移动'''
pass
def createMap():
'''定义创建地图的方法'''
screen.fill((255,255,255)) #填充颜色
screen.blit(background,(0,0)) #填入到背景
pygame.display.update() #更新显示
if __name__ == '__main__':
pygame.init() #初始化pygame
os.environ["SDL_VIDEO_WINDOW_POS"] = "%d, %d" % (800, 200)
size = width,height = 400,650 #设置窗口
screen = pygame.display.set_mode(size) #显示窗口
clock = pygame.time.Clock() #设置时钟
Pipeline = Pipeline() #实例化管道类
Bird = Bird() #实例化鸟类
while True:
clock.tick(50) #每秒执行50次
# 轮询事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
background = pygame.image.load('assets/background.png') #加载背景图片
createMap() #绘制地图
pygame.quit() #退出
运行效果如下图:
4、创建小鸟类
下面来创建小鸟类。该类需要初始化很多参数,所以定义一个__init__() 方法,用来初始化各种参数,包括鸟飞行的几种状态、飞行的速度、跳跃的高度等。然后定义birdUpdate()方法,该方法用于实现小鸟的跳跃和坠落。接下来,在主逻辑的轮询事件中添加键盘按下事件或鼠标单击事件,如按下鼠标,使小鸟上升等。最后,在createMap()方法中,显示小鸟的图像。关键代码如下:# -*- coding:utf-8 -*-
import pygame
import sys
import random
import os
class Bird(object):
'''定义一个鸟类'''
def __init__(self):
'''定义初始化方法'''
self.birdRect = pygame.Rect(65,50,50,50) #鸟的矩形
# 定义鸟的3种状态列表
self.birdStatus = [pygame.image.load('assets/1.png'),
pygame.image.load('assets/2.png'),
pygame.image.load('assets/dead.png')]
self.status = 0 #默认飞行状态
self.birdX = 120 #鸟所在的X轴坐标,即是向右飞行的速度
self.birdY = 350 #鸟所在的Y轴坐标,即是上下飞行的高度
self.jump = False #默认情况小鸟自动降落
self.jumpSpeed = 10 #跳跃高度
self.gravity = 5 #重力
self.dead = False #默认小鸟生命状态为活着
def birUpdate(self):
if self.jump:
#小鸟跳跃
self.jumpSpeed -= 1 #速度递减,上升越来越慢
self.birdY -= self.jumpSpeed #鸟的Y轴坐标减少,小鸟上升
else:
#小鸟坠落
self.gravity += 0.2 #重力递增,下降越来越快
self.birdY += self.gravity #鸟的Y轴坐标增加,小鸟下降
self.birdRect[1] = self.birdY #更改Y轴位置
class Pipeline(object):
'''定义一个管道类'''
def __init__(self):
'''定义初始化方法'''
pass
def updatePipeline(self):
'''水平移动'''
pass
def createMap():
'''定义创建地图的方法'''
screen.fill((255,255,255)) #填充颜色
screen.blit(background,(0,0)) #填入到背景
#显示小鸟
if Bird.dead: #撞管道状态
Bird.status = 2
elif Bird.jump: #起飞状态
Bird.status = 1
screen.blit(Bird.birdStatus[Bird.status],(Bird.birdX,Bird.birdY)) #设置小鸟的坐标
Bird.birUpdate() #鸟移动
pygame.display.update() #更新显示
if __name__ == '__main__':
'''主程序'''
pygame.init() #初始化pygame
os.environ["SDL_VIDEO_WINDOW_POS"] = "%d, %d" % (800, 200)
size = width,height = 400,650 #设置窗口
screen = pygame.display.set_mode(size) #显示窗口
clock = pygame.time.Clock() #设置时钟
Pipeline = Pipeline() #实例化管道类
Bird = Bird() #实例化鸟类
while True:
clock.tick(50) #每秒执行50次
# 轮询事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
Bird.jump = True #跳跃
Bird.gravity = 5 #重力
Bird.jumpSpeed = 10 #跳跃速度
background = pygame.image.load('assets/background.png') #加载背景图片
createMap() #绘制地图
pygame.quit()
上述代码在Bird类中设置了birdStatus 属性,该属性是一个鸟类图片的列表,列表中显示鸟类3种飞行状态,根据小鸟的不同状态加载相应的图片。在birdUpdate()方法中,为了达到较好的动画效果,使jumpSpeed 和gravity两个属性逐渐变化。运行上述代码,在窗体内创建一只小鸟, 默认情况小鸟会一直下降。当单击一下鼠标或按一下键盘, 小鸟会跳跃一下,高度上升。运行效果如下图所示。
5、创建管道类
创建完鸟类后,接下来创建管道类。同样,在__init__()方法中初始化各种参数,包括设置管道的坐标,加载上下管道图片等。然后在updatePipeline()方法中,定义管道向左移动的速度,并且当管道移出屏幕时,重新绘制下一组管道。最后,在createMap()函数中显示管道。关键代码如下:# -*- coding:utf-8 -*-
import pygame
import sys
import random
import os
class Bird(object):
#省略部分代码……
class Pipeline(object):
'''定义一个管道类'''
def __init__(self):
'''定义初始化方法'''
self.wallx = 400 #管道所在X轴坐标
self.pineUp = pygame.image.load('assets/top.png') #加载上管道图片
self.pineDown = pygame.image.load('assets/bottom.png') #加载下管道图片
def updatePipeline(self):
'''管道移动方法'''
self.wallx -= 5 #管道X轴坐标递减,即管道向左移动
# 当管道运行到一定位置,即小鸟飞跃管道,分数+1,并且重置管道
if self.wallx < -80:
self.wallx = 400
def createMap():
'''定义创建地图的方法'''
screen.fill((255,255,255)) #填充颜色
screen.blit(background,(0,0)) #填入到背景
#显示管道
screen.blit(Pipeline.pineUp,(Pipeline.wallx,-300)) #上管道坐标位置
screen.blit(Pipeline.pineDown,(Pipeline.wallx,500)) #下管道坐标位置
Pipeline.updatePipeline() #管道移动
#显示小鸟
if Bird.dead: #撞管道状态
Bird.status = 2
elif Bird.jump: #起飞状态
Bird.status = 1
screen.blit(Bird.birdStatus[Bird.status],(Bird.birdX,Bird.birdY)) #设置小鸟的坐标
Bird.birUpdate() #鸟移动
pygame.display.update() #更新显示
if __name__ == '__main__':
#省略部分代码……
while True:
clock.tick(50) #每秒执行50次
# 轮询事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if (event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN) and not Bird.dead:
Bird.jump = True #跳跃
Bird.gravity = 5 #重力
Bird.jumpSpeed = 10 #跳跃速度
background = pygame.image.load('assets/background.png') #加载背景图片
createMap() #绘制地图
pygame.quit() #退出
上述代码中,在createMap()函数内,设置先显示管道,再显示小鸟。这样做的目的是为了当小鸟与管道图像重合时,小鸟的图像显示在上层,而管道的图像显示在底层。运行结果如下图:
6、计算得分
当小鸟飞过管道时,玩家得分+1.这里对于飞过管道的逻辑做了简化处理:当管道移动到窗体左侧一定距离后,默认为小鸟飞过管道,使分数+1,并显示在屏幕上。在updatePipeline()方法中已经实现该功能,关键代码如下:# -*- coding:utf-8 -*-
import pygame
import sys
import random
import os
class Bird(object):
#省略部分代码……
class Pipeline(object):
#省略部分代码……
def updatePipeline(self):
'''管道移动方法'''
self.wallx -= 5 #管道X轴坐标递减,即管道向左移动
# 当管道运行到一定位置,即小鸟飞跃管道,分数+1,并且重置管道
if self.wallx < -80:
global score
score += 1
self.wallx = 400
def createMap():
#省略部分代码……
#显示分数
screen.blit(font.render('Score:'+str(score),-1,(255,255,255)),(100,50)) #设置颜色及坐标位置
pygame.display.update() #更新显示
if __name__ == '__main__':
#省略部分代码……
while True:
#省略部分代码……
pygame.quit() #退出
运行效果如下图:
7、碰撞检测
当小鸟与管道相撞时,小鸟颜色变为灰色,游戏结束,并且显示总分数。在checkDead()函数中通过pygame.Rect()可以分别获取小鸟的矩形区域对象和管道的矩形区域对象,该对象有一 个onlliderect()方法可以判断两个矩形区域是否相撞。如果相撞,设置Bird.dead属性为True。 此外,当小鸟飞出窗体时,也设置Bird.dead属性为True。 最后,用两行文字显示游戏得分。关键代码如下:# -*- coding:utf-8 -*-
import pygame
import sys
import random
import os
class Bird(object):
#省略部分代码……
class Pipeline(object):
#省略部分代码……
def createMap():
#省略部分代码……
def checkDead():
#上方管子的矩形位置
upRect = pygame.Rect(Pipeline.wallx,-300,
Pipeline.pineUp.get_width() - 10,
Pipeline.pineUp.get_height())
#下方管子的矩形位置
downRect = pygame.Rect(Pipeline.wallx,500,
Pipeline.pineDown.get_width() - 10,
Pipeline.pineDown.get_height())
#检测小鸟与上下方管子是否碰撞
if upRect.colliderect(Bird.birdRect) or downRect.colliderect(Bird.birdRect):
Bird.dead = True
#检测小鸟是否飞出上下边界
if not 0 < Bird.birdRect[1] < height:
Bird.dead = True
return True
else:
return False
def getResutl():
final_text1 = 'Game Over'
final_text2 = 'Your final score is ' + str(score)
ft1_font = pygame.font.SysFont('Arial',70) #设置第一行文字字体
ft1_surf = font.render(final_text1,1,(242,3,36)) #设置第一行文字颜色
ft2_font = pygame.font.SysFont('Arial',50) #设置第二行文字字体
ft2_surf = font.render(final_text2,1,(253,177,6)) #设置第二行文字颜色
#设置第一行文字显示位置
screen.blit(ft1_surf,[screen.get_width()/2 - ft1_surf.get_width()/2,100])
#设置第二行文字显示位置
screen.blit(ft2_surf,[screen.get_width()/2 - ft2_surf.get_width()/2,200])
pygame.display.flip() #更新整个待显示的Surface对象到屏幕上
if __name__ == '__main__':
#省略部分代码……
while True:
#省略部分代码……
background = pygame.image.load('assets/background.png') #加载背景图片
if checkDead(): #检测小鸟生命状态
getResutl() #如果小鸟死亡,显示游戏总分
else:
createMap() #绘制地图
pygame.quit() #退出
上述代码的checkDead()方法中,upRect.colliderect(Bird.birdRect)用于检测小鸟的矩形区域是否与上面的管道的矩形区域相撞, colliderect()函数的参数是另一个矩形区域对象。
说明:本实例已经实现了Flappy Bird游戏的基本功能,但还有很多需要完善的地方,如设置游戏的难度,包括设置管道的高度、小鸟的飞行速度等,各位鱼油可以尝试完善该游戏。
|