(六)通过pygame让游戏背景图像实现交替滚动


python飞机大战系列文章(按顺序)
(一)通过pygame 将自己的图像添加到游戏中
(二)通过pygame让游戏人物 动起来
(三)通过pygame处理用户的鼠标键盘操作(事件和监听
(四)详解pygame中的精灵和精灵组
(五)通过pygame搭建游戏框架
(六)通过pygame让游戏背景图像实现交替滚动
(七)通过pygame来设置飞机大战中 敌机 的速度、位置等
(八)通过pygame来操控游戏人物的移动
(九)通过pygame使游戏人物发射子弹
(十)通过pygame来进行碰撞检测



原理

在游戏中,需要如何将游戏的背景实现交替滚动?

  • 利用运动是相对的

游戏启动后,背景图像会连续不断地向下方移动,在视觉上就会产生英雄的飞机不断向上方飞行的错觉,这在很多跑酷类游戏中是常见的

如果只是单单一张背景图向下移动,如下图所示,可以看到,如果只是一张背景图向下移动的话,那么游戏主界面上方就会出现没有背景图的情况(红色区域)

在这里插入图片描述
那么要怎么解决这个问题呢??

  • 用两张一样的背景图,另一张叠放在屏幕的正上方(如下图)

在这里插入图片描述

让两张背景图像同时向下移动,那么上文所说的“红色区域”就会被“暂时”遮住,但是在第1张背景图完全移出背景图像之后,第2张背景就又会产生没有背景图的情况
在这里插入图片描述
那么怎么解决这个问题呢?
当第一张图像完全移出屏幕后,立马又移到第二张图像的正上方,这样循环,周而复始,就可以实现背景图的循环滚动了
在这里插入图片描述

解决办法

  1. 创建两张背景图像精灵,第一张完全和图像屏幕重合,第二张在屏幕的正上方
  2. 两张图一起向下方运动:self.rect.y += self.speed
  3. 当任意背景精灵的 rect.y >= 屏幕高度 说明已经完全移出了屏幕
  4. 将移动到屏幕下方的这张图像设置到屏幕的正上方 rect.y = -rect.height(将y值设置成图像高度的负值)

具体代码

因为之前的GameSprite类中的update方法只是让游戏精灵的y值跟游戏精灵的速度进行了相加,但是并没有根据精灵移出屏幕进行判断,我们想要的是当一个图像移出屏幕之后,将图像再移动到屏幕的正上方,从而实现交替滚动

所以如果在继承中,父类提供的方法不能满足子类的需求,我们需要怎么做?

  • 从父类中派生出一个子类
  • 在子类中针对特有的需求,重写父类方法,对父类的方法进行扩展

我们可以派生出一个背景类,在背景类中重写update方法

plane_sprites.py 代码为:

import pygame

#屏幕大小的常量
SCREEN_RECT = pygame.Rect(0,0,480,700)
#刷新的帧率
FRAME_PER_SEC = 60

class GameSprite(pygame.sprite.Sprite):
    """飞机大战游戏精灵"""
    def __init__(self, image_name, speed=1):

        #调用父类的初始化方法
        super().__init__()

        #定义对象属性
        self.image = pygame.image.load(image_name)
        self.rect = self.image.get_rect()
        self.speed = speed

    def update(self):

        #在屏幕垂直方向上移动
        self.rect.y += self.speed


class Background(GameSprite):
    """游戏背景精灵"""

    def update(self):

        #调用父类的方法实现:垂直移动
        super().update()

        #判断是否移出屏幕,若移出屏幕,应该将图像设置到图像上方
        if self.rect.y >= SCREEN_RECT.height:
            self.rect.y = -self.rect.height


plane_main.py 代码为:

import pygame
from plane_sprites import *


class PlaneGame(object):
    """飞机大战主游戏"""

    def __init__(self):
        print("游戏初始化")

        #创建游戏窗口
        self.screen = pygame.display.set_mode(SCREEN_RECT.size)
        #创建游戏的时钟
        self.clock = pygame.time.Clock()
        #调用私有方法,精灵和精灵组的创建
        self.__create_sprites()


    def __create_sprites(self):

        #创建背景精灵和精灵组
        bg1 = Background('./images/background.png')
        bg2 = Background('./images/background.png')
        bg2.rect.y = -bg2.rect.height
        self.back_group = pygame.sprite.Group(bg1, bg2)

    def start_game(self):
        print("游戏开始")

        while True:
            #设置刷新帧率
            self.clock.tick(FRAME_PER_SEC)
            #事件监听
            self.__event_handler()
            #碰撞检测
            self.__check_collide()
            #更新/绘制精灵组
            self.__update_sprites()
            #更新显示
            pygame.display.update()

    def __event_handler(self):

        for event in pygame.event.get():

            #判断是否退出游戏
            if event.type == pygame.QUIT:
                PlaneGame.__game_over()

    def __check_collide(self):
        pass

    def __update_sprites(self):

        self.back_group.update()
        self.back_group.draw(self.screen)

    #没有使用对象属性和类属性,所以定义为静态方法
    @staticmethod
    def __game_over():
        print("游戏结束")

        pygame.quit()
        exit()


if __name__ == '__main__':

    #创建游戏对象
    game = PlaneGame()

    #启动游戏
    game.start_game()

改进

 def __create_sprites(self):

        #创建背景精灵和精灵组
        bg1 = Background('./images/background.png')
        bg2 = Background('./images/background.png')
        bg2.rect.y = -bg2.rect.height
        self.back_group = pygame.sprite.Group(bg1, bg2)

上面的代码中,创建的两个背景精灵,传入了相同的图像文件路径,精灵的初始位置应该由精灵自己负责,而不是由主程序负责。

  • 根据面向对象设计原则,应该将对象的职责,封装到类的代码内部
  • 尽量简化程序调用一方的代码调用

在这里插入图片描述
is_alt判断是否是另一张图像

  • False 表示第一张图像,需要与屏幕重合
  • True 表示另一张图像,在屏幕正上方

修改后的代码为:

class Background(GameSprite):
    """游戏背景精灵"""

    def __init__(self, is_alt=False):

        # 调用父类方法实现精灵的创建(image/rect/speed)
        super().__init__("./images/background.png")

        # 判断是否是交替图像,如果是,需要设置初始位置
        if is_alt:
            self.rect.y = -self.rect.height

    def update(self):

        #调用父类的方法实现:垂直移动
        super().update()

        #判断是否移出屏幕,若移出屏幕,应该将图像设置到图像上方
        if self.rect.y >= SCREEN_RECT.height:
            self.rect.y = -self.rect.height
    def __create_sprites(self):

        #创建背景精灵和精灵组
        bg1 = Background()
        bg2 = Background(is_alt=True)

        self.back_group = pygame.sprite.Group(bg1, bg2)

完整代码如下:
plane_sprites.py

import pygame

#屏幕大小的常量
SCREEN_RECT = pygame.Rect(0,0,480,700)
#刷新的帧率
FRAME_PER_SEC = 60

class GameSprite(pygame.sprite.Sprite):
    """飞机大战游戏精灵"""
    def __init__(self, image_name, speed=1):

        #调用父类的初始化方法
        super().__init__()

        #定义对象属性
        self.image = pygame.image.load(image_name)
        self.rect = self.image.get_rect()
        self.speed = speed

    def update(self):

        #在屏幕垂直方向上移动
        self.rect.y += self.speed


class Background(GameSprite):
    """游戏背景精灵"""

    def __init__(self, is_alt=False):

        # 调用父类方法实现精灵的创建(image/rect/speed)
        super().__init__("./images/background.png")

        # 判断是否是交替图像,如果是,需要设置初始位置
        if is_alt:
            self.rect.y = -self.rect.height

    def update(self):

        #调用父类的方法实现:垂直移动
        super().update()

        #判断是否移出屏幕,若移出屏幕,应该将图像设置到图像上方
        if self.rect.y >= SCREEN_RECT.height:
            self.rect.y = -self.rect.height


plane_main.py

import pygame
from plane_sprites import *


class PlaneGame(object):
    """飞机大战主游戏"""

    def __init__(self):
        print("游戏初始化")

        #创建游戏窗口
        self.screen = pygame.display.set_mode(SCREEN_RECT.size)
        #创建游戏的时钟
        self.clock = pygame.time.Clock()
        #调用私有方法,精灵和精灵组的创建
        self.__create_sprites()


    def __create_sprites(self):

        #创建背景精灵和精灵组
        bg1 = Background()
        bg2 = Background(is_alt=True)

        self.back_group = pygame.sprite.Group(bg1, bg2)

    def start_game(self):
        print("游戏开始")

        while True:
            #设置刷新帧率
            self.clock.tick(FRAME_PER_SEC)
            #事件监听
            self.__event_handler()
            #碰撞检测
            self.__check_collide()
            #更新/绘制精灵组
            self.__update_sprites()
            #更新显示
            pygame.display.update()

    def __event_handler(self):

        for event in pygame.event.get():

            #判断是否退出游戏
            if event.type == pygame.QUIT:
                PlaneGame.__game_over()

    def __check_collide(self):
        pass

    def __update_sprites(self):

        self.back_group.update()
        self.back_group.draw(self.screen)

    #没有使用对象属性和类属性,所以定义为静态方法
    @staticmethod
    def __game_over():
        print("游戏结束")

        pygame.quit()
        exit()


if __name__ == '__main__':

    #创建游戏对象
    game = PlaneGame()

    #启动游戏
    game.start_game()
  • 10
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实现背景滚动效果,可以按照以下步骤进行: 1. 加载背景图片,并创建一个屏幕对象。 2. 在屏幕对象上绘制背景图片。 3. 创建一个矩形对象,用于表示背景图片的位置和大小。 4. 循环更新矩形对象的位置,使其向左移动(或向右移动,视情况而定)。 5. 在每次循环中,先在屏幕对象上绘制背景图片,再绘制前一次位置的背景图片,以填补移动后留下的空白。 6. 控制循环速度,以达到平滑滚动的效果。 具体的代码实现可以参考下面的示例: ```python import pygame pygame.init() # 设置屏幕大小和背景图片 SCREEN_WIDTH = 640 SCREEN_HEIGHT = 480 BG_IMAGE = pygame.image.load('bg.png').convert() # 创建屏幕对象和矩形对象 screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) bg_rect = BG_IMAGE.get_rect() # 初始化背景位置 bg_x = 0 # 创建时钟对象 clock = pygame.time.Clock() # 游戏循环 while True: # 处理事件 for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit() # 更新背景位置 bg_x -= 5 if bg_x < -bg_rect.width: bg_x = 0 # 在屏幕上绘制背景图片 screen.blit(BG_IMAGE, (bg_x, 0)) screen.blit(BG_IMAGE, (bg_x + bg_rect.width, 0)) # 刷新屏幕 pygame.display.update() # 控制帧率 clock.tick(60) ``` 在这个示例中,我们加载了一张背景图片,并将其绘制到屏幕上。然后创建了一个矩形对象,用于表示背景图片的位置和大小。在游戏循环中,我们不断更新矩形对象的位置,使其向左移动,并在每次循环中绘制背景图片,以填补移动后留下的空白。最后,我们控制帧率,以达到平滑滚动的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值