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