基于Pygame实现谷歌浏览器的恐龙快跑小游戏(Python)

其实前段时间就写完这个了,但是没有什么时间写博客,因为现在正好在复习python的一些东西,可以写一下博客来复习梳理一下整个游戏的流程。

1.效果展示

在这里插入图片描述

2.实现主窗体

先从最主要的开始入手,做一个游戏的窗体,因为导入了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()

我们可以看下运行效果
在这里插入图片描述

3.游戏背景的滚动

恐龙快跑的游戏背景滚动其实是恐龙没有动,背景一直在动,这一点和飞机大战是一样的,所以实现原理也是一样,总共有两张图片,第一张图片放完后就放第二张,第二张图片放完后继续放第一张。这个和我以前写的飞机大战的绘制背景是一样的,在飞机大战里面有画图解释,链接如下:
飞机大战博客链接

先创建一个地图类

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()

实现效果如下:
在这里插入图片描述

3.加入恐龙图片和加入键盘监听实现恐龙跳跃动作

在实现完背景图片的移动之后,我们应该考虑把恐龙的图片加进来了,并且加上键盘监听器,比如当按下空格键时实现恐龙的跳跃动作。
我们首先设置一个恐龙类,代码如下:

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轴上移动一下。只有背景图片一直在动
效果如下:
在这里插入图片描述

4.障碍物的实现

游戏的规则是恐龙越过障碍物就加一分,如果碰到障碍物则死亡,可以选择重开游戏,所以我们接下来要做的是障碍物的随机出现。
和恐龙一样,我们先建一个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

实现效果如下:
在这里插入图片描述

5.碰撞判断

在上面的效果展示我们可以发现,恐龙碰到障碍物以后并没有发生预料中的游戏结束,因为我们还没有加入对碰撞的判断,所以我们现在可以加入对碰撞的判断过程。
我们可以直接在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))

这下就大功告成了,大家可以看下效果图
在这里插入图片描述

6.分数的显示

游戏做到这里基本已经结束了,但是我们可以再增加一个分数显示的功能,当恐龙跃过一个障碍时就加一分。所以我们先实现一个获取分数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)

游戏到这里就整体就完成啦,下面是效果图
在这里插入图片描述

有需要整份代码的可以留邮箱。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章