|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
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游戏的基本功能,但还有很多需要完善的地方,如设置游戏的难度,包括设置管道的高度、小鸟的飞行速度等,各位鱼油可以尝试完善该游戏。
|
评分
-
查看全部评分
|