Python - - 项目实战 - - 游戏背景

目标

  • 背景交替滚动的思路确定
  • 显示游戏背景

01,背景交替滚动的思路确定

运行 备课代码,观察 背景图像的显示效果:

  • 游戏启动后,背景图像连续不断地 向下方 移动
  • 视觉上 产生英雄的飞机不断向上方飞行的 错觉 - - 在很多跑酷游戏中常用的套路
    • 游戏的背景 不断变化
    • 游戏的主角 位置保持不变

1.1 实现思路分析

解决方法
1,创建两张背景图像精灵

  • 1完全和屏幕重合
  • 2 张在 屏幕的正上方

2,两张图像 一起向下方运动

  • self.rect.y += self.speed

3,当 任意背景精灵rect.y >= 屏幕的高度 说明已经 移动到屏幕下方
4,将 移动到屏幕下方的这张图像 设置到 屏幕的正上方

  • rect.y = -rect.height

1.2 设计背景类

  • 初始化方法

    • 直接指定 背景图片
    • is_alt 判断是否是另一张图像
      • False 表示 第一张图像,需要与屏幕适合
      • True 表示 另一张图像,在屏幕的正上方
  • update() 方法
    -判断 是否移动出屏幕,如果是,将图像设置到 屏幕的正上方,从而实现 交替滚动

继承 如果是父类提供的方法,不能满足子类的需求:

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

02,显示游戏背景

2.1 背景精灵的基本实现

  • plane_sprites 新建 Background 继承自 GameSprite

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, *args):
        # 在屏幕的垂直方向上移动
        self.rect.y += self.speed


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

    def update(self, *args):
        # 1,调用父类的方法实现
        super().update()

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

2.2 在 plane_main.py 中显示背景精灵

1,在 __create_sprites 方法中创建 精灵精灵组
2,在 __update_sprites 方法中,让 精灵组 调用 update()draw() 方法
__create_sprites 方法

    def __update_sprites(self):
        self.back_group.update()
        self.back_group.draw(self.screen)

plane_main.py


import pygame
from Aircraft_War.plane_sprites import *

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

    def __init__(self):
        print("游戏初始化")
        # 1,创建游戏的窗口
        # self.screen = pygame.display.set_mode((480, 700))
        self.screen = pygame.display.set_mode(SCREEN_RECT.size)

        # 2,创建游戏的时钟
        self.clock = pygame.time.Clock()

        # 3,调用私有方法, 精灵和精灵组的创建
        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:
            # 1,设置刷新帧率
            self.clock.tick(FRAME_PER_SEC)

            # 2,事件监听
            self.__event_handler()

            # 3,碰撞检测
            self.__check_collide()

            # 4,更新/绘制精灵组
            self.__update_sprites()

            # 5,更新显示
            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()

2.3 利用初始化方法,简化背景精灵创建

思考 - - 上一小节完成的代码存在什么问题?是否可以简化?

  • 在主程序中,创建的 两个背景精灵,传入了相同的图像文件路径
  • 创建 第二个 背景精灵 时,在主程序中,设置背景精灵的图像位置

思考 - - 精灵 初始位置 的设置,应该 由主程序负责? 还是 由精灵自己负责
答案 - - 由精灵自己负责

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

  • 初始化方法
    • 直接指定 背景图片
    • is_alt 判断是否是另一张图像
      • False 表示 第一张图像,需要与屏幕重合
      • True 表示 另一张图像,在屏幕的正上方

plane_sprites.py 中实现 Background

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, *args):
        # 在屏幕的垂直方向上移动
        self.rect.y += self.speed


class Background(GameSprite):
    """游戏背景精灵"""
    def __init__(self, is_alt=False):
        # 1,调用父类方法实现精灵的创建(image/rect/speed)
        super().__init__("./images/background.png")

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

    def update(self, *args):
        # 1,调用父类的方法实现
        super().update()

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

plane_main.py


import pygame
from Aircraft_War.plane_sprites import *

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

    def __init__(self):
        print("游戏初始化")
        # 1,创建游戏的窗口
        # self.screen = pygame.display.set_mode((480, 700))
        self.screen = pygame.display.set_mode(SCREEN_RECT.size)

        # 2,创建游戏的时钟
        self.clock = pygame.time.Clock()

        # 3,调用私有方法, 精灵和精灵组的创建
        self.__create_sprites()

    def __create_sprites(self):
        bg1 = Background()
        bg2 = Background(True)

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

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

        while True:
            # 1,设置刷新帧率
            self.clock.tick(FRAME_PER_SEC)

            # 2,事件监听
            self.__event_handler()

            # 3,碰撞检测
            self.__check_collide()

            # 4,更新/绘制精灵组
            self.__update_sprites()

            # 5,更新显示
            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()

posted @ 2018-08-31 21:46  小Q渺晓  阅读(2251)  评论(0编辑  收藏  举报