前段时间就根据python书上写完这个了,但是没有什么时间写博客,因为现在正好在复习python的一些东西,可以写一下博客来复习梳理一下整个游戏的流程。
先从最主要的开始入手,做一个游戏的窗体,因为导入了pygame,感觉在python中做一个小游戏比Java中更加容易做。可以直接设置FPS什么的,很方便。
下面是窗体部分实现代码
import pygame
from pygame.locals import * # 导入pygame中的常量
SCREENWIDTH = 822
SCREENHEIGHT = 260
FPS = 30 # 更新画面的时间
def mainGame():
global SCREEN, FPSCLOCK
pygame.init() # 使用pygame前先初始化
# 要使用pygame时钟,先创建clock对象的实例
# 用于控制每个循环多长时间运行一次
FPSCLOCK = pygame.time.Clock()
# 先创建一个窗体
SCREEN = pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT))
pygame.display.set_caption('恐龙快跑')
while True:
# 判断是否单击关闭了窗体
for event in pygame.event.get():
# 单击关闭窗体就关闭窗体
if event.type == QUIT:
exit() # 关闭窗体
pygame.display.update() # 更新整个窗体
FPSCLOCK.tick(FPS) # 循环多久运行一次
if __name__ == '__main__':
mainGame()
恐龙快跑的游戏背景滚动其实是恐龙没有动,背景一直在动,这一点和飞机大战是一样的,所以实现原理也是一样,总共有两张图片,第一张图片放完后就放第二张,第二张图片放完后继续放第一张。这个和我以前写的飞机大战的绘制背景是一样的,在飞机大战里面有画图解释,链接如下:
飞机大战博客链接
先创建一个地图类
class Map():
def __init__(self, x, y):
# 背景图片加载
self.bg = pygame.image.load("images/bg.png").convert_alpha()
self.x = x
self.y = y
def map_move(self):
if self.x < -790: # 已经移动完毕
self.x = 800 # 再次开始
else:
self.x -= 5 # 一次左移动5个像素点
def map_update(self):
SCREEN.blit(self.bg, (self.x, self.y))
当游戏开始后,因为地图要移动,所以先在mainGame()定义两张背景图片的初始位置,然后在mainGame()的while True循环里面加入地图的更新
代码如下:
# 创建地图对象
bg1 = Map(0, 0)
bg2 = Map(800, 0)
if over == False:
bg1.map_update()
bg1.map_move()
bg2.map_update()
bg2.map_move()
在实现完背景图片的移动之后,我们应该考虑把恐龙的图片加进来了,并且加上键盘监听器,比如当按下空格键时实现恐龙的跳跃动作。
我们首先设置一个恐龙类,代码如下:
class Dragon():
def __init__(self):
self.rect = pygame.Rect(0, 0, 0, 0) # 小恐龙矩形图片的初始化,Rect(left,top,width,height)
self.jumpHeight = 130
self.jumpState = False # 跳跃状态,true为跳跃
self.lowest_y = 140 # 最低坐标
self.jumpValue = 0 # 跳跃增变量
# 小恐龙跳跃动作播放图片,连续放三张图片,造成一种gif的感觉
self.DragonIndex = 0
self.DragonIndexGen = cycle([0, 1, 2]) # 引入的迭代工具
# 加载恐龙图片,使用convert_alpha()背景图片才为透明,用convert则为黑色背景
self.dragon_img = (
pygame.image.load("images/dargon1.png").convert_alpha(),
pygame.image.load("images/dargon2.png").convert_alpha(),
pygame.image.load("images/dargon3.png").convert_alpha(),
)
self.rect.size = self.dragon_img[0].get_size()
self.x = 50 # 绘制恐龙x坐标
self.y = self.lowest_y # 绘制恐龙y坐标
self.rect.topleft = (self.x, self.y)
def jump(self):
self.jumpState = True
print("jump方法正在执行")
def move(self):
if self.jumpState== True: # 起跳的时候
if self.rect.y >= self.lowest_y:
self.jumpValue = -5 # 向上移动五个像素点
if self.rect.y <= self.lowest_y - self.jumpHeight: # 到顶后下降
self.jumpValue = 5
self.rect.y += self.jumpValue
if self.rect.y >= self.lowest_y: # 恐龙落地以后,跳跃状态改为False
self.jumpState = False
def draw(self):
# 匹配恐龙动图
DragonIndex = next(self.DragonIndexGen)
# 绘制小恐龙,blit()第一个为图片,第二个参数为位置
SCREEN.blit(self.dragon_img[DragonIndex], (self.x, self.rect.y))
因为恐龙一直在原地,所以并没有x轴上的移动,跳跃也只是在y轴上移动一下。只有背景图片一直在动
效果如下:
游戏的规则是恐龙越过障碍物就加一分,如果碰到障碍物则死亡,可以选择重开游戏,所以我们接下来要做的是障碍物的随机出现。
和恐龙一样,我们先建一个Obstacle障碍物类,然后实现Obstacle的move,draw方法。
代码如下:
class Obstacle():
def __init__(self):
# 初始化障碍物矩形
self.rect = pygame.Rect(0, 0, 0, 0)
# 加载障碍物图片
self.stone = pygame.image.load("images/stone.png").convert_alpha()
self.cacti = pygame.image.load("images/cacti.png").convert_alpha()
# 生成0到1的随机数
r = random.randint(0, 1)
if r == 0: # 随机数为0则为石头,1为仙人掌
self.image = self.stone
else:
self.image = self.cacti
# 根据障碍物位图的宽和高来显示仙人掌
self.rect.size = self.image.get_size()
# 获取图片宽高
self.width, self.height = self.rect.size
# 绘制障碍物的坐标
self.x = 800
self.y = 200 - (self.height / 2)
# self.y = 200
self.rect.center = (self.x, self.y)
def move(self):
self.rect.x -= 5
def draw(self):
SCREEN.blit(self.image, (self.rect.x, self.rect.y))
然后我们在mainGame()的whileTrue里面加入障碍物出现的时间和概率的判断,并在whileTrue里面调用Obstacle的move和draw方法
if addObstacleTimer >= 1000:
r = random.randint(0, 100)
if r > 40:
# 创建障碍物对象
obstacle = Obstacle()
# 添加到列表
list.append(obstacle)
# 重置时间,到下一次出现障碍物
addObstacleTimer = 0
# 循环遍历障碍物
for i in range(len(list)):
# 障碍物移动与绘制
list[i].move()
list[i].draw()
addObstacleTimer += 20
实现效果如下:
在上面的效果展示我们可以发现,恐龙碰到障碍物以后并没有发生预料中的游戏结束,因为我们还没有加入对碰撞的判断,所以我们现在可以加入对碰撞的判断过程。
我们可以直接在whileTrue里面加入对碰撞的判断
# 判断与障碍物是否碰撞
if pygame.sprite.collide_rect(dragon, list[i]):
over = True
game_over()
可以发现如果碰撞发生,则游戏结束,但是我们这里调用的game_over()方法还没有开始写,所以还需要写一个game_over()方法。
def game_over():
# 获取窗体宽度和高
screen_w = pygame.display.Info().current_w
screen_h = pygame.display.Info().current_h
# 加载游戏结束的图片
over_img = pygame.image.load("images/gameover.png").convert_alpha()
# 游戏结束的图片控制在窗体的中间位置
SCREEN.blit(over_img, ((screen_w - over_img.get_width()) / 2,
(screen_h - over_img.get_height()) / 2))
游戏做到这里基本已经结束了,但是我们可以再增加一个分数显示的功能,当恐龙跃过一个障碍时就加一分。所以我们先实现一个获取分数getScore()和显示分数showScore()的方法
def getScore(self):
tmp = self.score
self.score = 0
return tmp
def showScore(self, score):
# 在窗体顶部中间的位置显示分数
self.scoreDigits = [int(x) for x in list(str(score))]
totalWidth = 0 # 要显示所有数字的总宽度
for digit in self.scoreDigits:
# 获取积分图片的宽度
totalWidth += self.numbers[digit].get_width()
# 分数横向位置
Xoffset = (SCREENWIDTH - totalWidth) / 2
for digit in self.scoreDigits:
# 绘制分数
SCREEN.blit(self.numbers[digit], (Xoffset, SCREENHEIGHT * 0.1))
# 数字增加也改变位置
Xoffset += self.numbers[digit].get_width()
并且需要在是否碰撞的判断加上一个else,如果没有碰到的话,则加分
# 判断与障碍物是否碰撞
if pygame.sprite.collide_rect(dragon, list[i]):
over = True
game_over()
else:
if(list[i].rect.x + list[i].rect.width) < dragon.rect.x:
score += list[i].getScore()
# 显示分数
list[i].showScore(score)
游戏到这里就整体就完成啦,下面是效果图
有需要整份代码的可以留邮箱。
——————————————————————————————————
因为人有点多,博主已经把资源上传至csdn文件,大家自取哈。
https://download.csdn.net/download/qq_44807642/19556940