原理
在遊戲中,需要如何將遊戲的背景實現交替滾動?
- 利用運動是相對的
遊戲啓動後,背景圖像會連續不斷地向下方移動,在視覺上就會產生英雄的飛機不斷向上方飛行的錯覺,這在很多跑酷類遊戲中是常見的
如果只是單單一張背景圖向下移動,如下圖所示,可以看到,如果只是一張背景圖向下移動的話,那麼遊戲主界面上方就會出現沒有背景圖的情況(紅色區域)
那麼要怎麼解決這個問題呢??
- 用兩張一樣的背景圖,另一張疊放在屏幕的正上方(如下圖)
讓兩張背景圖像同時向下移動,那麼上文所說的“紅色區域”就會被“暫時”遮住,但是在第1張背景圖完全移出背景圖像之後,第2張背景就又會產生沒有背景圖的情況
那麼怎麼解決這個問題呢?
當第一張圖像完全移出屏幕後,立馬又移到第二張圖像的正上方,這樣循環,周而復始,就可以實現背景圖的循環滾動了
解決辦法
- 創建兩張背景圖像精靈,第一張完全和圖像屏幕重合,第二張在屏幕的正上方
- 兩張圖一起向下方運動:
self.rect.y += self.speed
- 當任意背景精靈的
rect.y >= 屏幕高度
說明已經完全移出了屏幕 - 將移動到屏幕下方的這張圖像設置到屏幕的正上方
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)
上面的代碼中,創建的兩個背景精靈,傳入了相同的圖像文件路徑