【FlappyBird小游戏】编写游戏逻辑(三)——添加Bird和Pipe【源码】

提示:如果本文对您有帮助,欢迎点赞支持!


文章目录

前言

1、添加Pipe对象

(1)初始化

(2)重置

(3)帧渲染

(4)实现效果

2、添加Bird对象

(1)初始化

(2)重置

(3)帧渲染

(4)实现效果


前言

在之前的代码中,我们已经实现了一个用Pygame搭建FlappyBird的基本框架,其最终生成效果如下:

20210502_164334.gif

现在我们添加继续添加Bird和Pipe对象,让该游戏看起来更加完整。


1、添加Pipe对象

(1)初始化

在Flappy_Bird_Env的init中添加如下变量的初始化:

    # 管道图片相关设置
    self.pipeVelX = -4 # 管道移动速度
    self.PIPEGAPSIZE = 100  # 上下管道之间的间距
    self.PIPE_WIDTH = self.IMAGES['pipe'][0].get_width()
    self.PIPE_HEIGHT = self.IMAGES['pipe'][0].get_height()

(2)重置

获取一个随机管道的位置信息:

    def getRandomPipe(self):
        """随机获取一个管道的x和y的参数"""
        # 随机获取一个管道间距距离
        gapYs = [20, 30, 40, 50, 60, 70, 80, 90] #上管道的y坐标
        index = random.randint(0, len(gapYs) - 1)
        gapY = gapYs[index]

        gapY += int(self.BASEY * 0.2)
        pipeX = SCREENWIDTH + 10

        return [
            {'x': pipeX, 'y': gapY - self.PIPE_HEIGHT},  # 上管道
            {'x': pipeX, 'y': gapY + self.PIPEGAPSIZE},  # 下管道
        ]

在reset函数中继续写管道的初始信息,reset被Flappy_Bird_Env的init调用:

    def reset(self):
        # 获取2个新的pipes
        newPipe1 = self.getRandomPipe()
        newPipe2 = self.getRandomPipe()
        # 屏幕显示的上管道列表
        self.upperPipes = [
            {'x': SCREENWIDTH, 'y': newPipe1[0]['y']}, # 屏幕上第1个管道
            {'x': SCREENWIDTH + (SCREENWIDTH / 2), 'y': newPipe2[0]['y']},# 屏幕上第2个管道
        ]
        # 屏幕显示的下管道列表
        self.lowerPipes = [
            {'x': SCREENWIDTH, 'y': newPipe1[1]['y']},
            {'x': SCREENWIDTH + (SCREENWIDTH / 2), 'y': newPipe2[1]['y']},
        ]

(3)帧渲染

首先计算每个管道的位置:

# 计算上下管道的x坐标
        for uPipe, lPipe in zip(self.upperPipes, self.lowerPipes):
            uPipe['x'] += self.pipeVelX
            lPipe['x'] += self.pipeVelX

        # 如果第一个管道的x坐标小于5但是大于0时提前生成一个新管道到列表中
        if 0 < self.upperPipes[0]['x'] < 5:
            newPipe = self.getRandomPipe()
            self.upperPipes.append(newPipe[0])
            self.lowerPipes.append(newPipe[1])

        # 如果第一个管道的x坐标完全离开管道时就将其移除
        if self.upperPipes[0]['x'] < -self.PIPE_WIDTH:
            self.upperPipes.pop(0)
            self.lowerPipes.pop(0)

渲染管道图片,注意渲染顺序:

        # 绘制背景图像
        self.screen.blit(self.IMAGES['background'], (0, 0))  # 背景,元组参数表示绘制位置,也可以通过Rect矩形类来表示位置
        # 绘制上下管道图像
        for uPipe, lPipe in zip(self.upperPipes, self.lowerPipes):
            self.screen.blit(self.IMAGES['pipe'][0], (uPipe['x'], uPipe['y']))
            self.screen.blit(self.IMAGES['pipe'][1], (lPipe['x'], lPipe['y']))
        # 绘制地面图像
        self.screen.blit(self.IMAGES['base'], (self.BASEX, self.BASEY))  # 地面

(4)实现效果

最终我们的实现效果就是:

20210502_184743.gif

2、添加Bird对象

由于Bird比较复杂,所以我们要将其单独初始化为一个类

(1)初始化

class Bird(object):
    def __init__(self,_Player_Sprite,_screen):
        self.screen = _screen
        # 玩家图片相关设置
        self.Player_Sprite = _Player_Sprite # 加载图片资源
        self.PlayerInfo = {} # 创建一个玩家信息字典
        self.PlayerInfo['w'] = self.Player_Sprite[0].get_width() # 获取玩家图片的宽度
        self.PlayerInfo['h'] = self.Player_Sprite[0].get_height()  # 获取玩家图片的高度
        self.PLAYER_INDEX_GEN = cycle([0, 1, 2, 1]) # 图片序列的循环
        self.playerMaxVelY = 10  # 玩家在y轴上的最大速度
        self.playerMinVelY = -8  # 玩家在y轴上的最小速度
        self.playerAccY = 1  # 玩家在y轴上的下降的加速度
        self.playerFlapAcc = -7  # 玩家在y轴上的上升的加速度,向下为正方向
        # 重置游戏设置w
        self.reset()

(2)重置

重置游戏时Bird的调用函数:

    def reset(self):
        self.loopIter = 0
        self.PlayerInfo['x'] = int(SCREENWIDTH * 0.2)  # 玩家初始位置x
        self.PlayerInfo['y'] = int((SCREENHEIGHT - self.PlayerInfo['h']) / 2)  # 玩家初始位置y
        self.PlayerInfo['index'] = 0 # 玩家初始帧序列
        self.playerVelY = 0  # 玩家在y轴上的速度,向下为正方向
        self.playerFlapped = False  # 玩家是否上升

(3)帧渲染

我们在每帧中渲染的Bird图片是不一样的,这样就可以实现小鸟的动画效果:

    def frame_step(self, input_actions,BASEY):
        # 计算玩家序列帧
        if (self.loopIter + 1) % 3 == 0:
            self.PlayerInfo['index'] = next(self.PLAYER_INDEX_GEN)
        self.loopIter = (self.loopIter + 1) % 30
        # 绘制玩家图像
        self.screen.blit(self.Player_Sprite[self.PlayerInfo['index']],
                         (self.PlayerInfo['x'], self.PlayerInfo['y']))  # 玩家

(4)实现效果

最终我们的实现效果就是:

20210502_211029.gif

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔法攻城狮MRL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值