如何通過精靈表單實作動畫
閱讀 3:32·字數 1063·發佈
Youtube 頻道
訂閱 375
訂閱 375
Pygame 使用精靈表單實作 Sprite 精靈動畫,以及控製動畫播放速度影片示範 YouTube
前言
因為 Pygame 沒有直接提供與精靈動畫相關的內建類別,因此,需要開發人員自行編寫程式碼實作動畫效果。本文將根據影像檔案的儲存方式,介紹兩種常見的動畫實作方式。
方式一:載入多個影像檔案實作動畫
載入多個影像檔案是一種相對簡單的動畫實作方式,每一個影像檔案可對應動畫中的一個影格。這一般需要呼叫image
模組的load
函式,所產生的Surface
物件會指派給精靈物件的image
變數。
當然,嚴格意義上來說,下面的範例所實作的並不像動畫,更像是狀態的切換。
# 載入門開關狀態的影像
img_closed = pygame.image.load('doors_leaf_closed.png').convert_alpha()
img_open = pygame.image.load('doors_leaf_open.png').convert_alpha()
class Door(pygame.sprite.Sprite):
def __init__(self, *groups):
super().__init__(*groups)
self.image = img_closed # 初始狀態為關閉
self.rect = self.image.get_rect()
def update(self, keys):
if keys[pygame.K_SPACE]:
self.image = img_open # 按下空格鍵顯示開門狀態
else:
self.image = img_closed # 釋放空格鍵顯示關門狀態
方式二:通過精靈表單實作動畫
精靈表單一般包含了動畫中的所有影格,因此,要完成一個動畫只需要載入一個影像檔案。這同樣需要呼叫image
模組的load
函式,並呼叫所傳回的Surface
物件的subsurface
方法,以獲得多個子表面,每個子表面對應了精靈表單中的一個影格。之後,可在遊戲迴圈或精靈的update
方法中,將不同的子表面指派給精靈物件的image
變數。
subsurface
方法有三種形式,本文使用的是四個浮點數參數的一種,前兩個浮點數確定子表面左上角在父表面中的座標,後兩個浮點數指定子表面的寬度和高度。
subsurface 方法傳回的子表面
subsurface
方法傳回的子表面與父表面共用像素資料,不會建立新的像素。你不需要對子表面呼叫convert_alpha
方法,因為,如何繪製像素通常取決於父表面。
在下面的範例中,由於沒有控製子表面的切換速度,因此,寶箱的播放速度可能會很快。
# 載入精靈表單
sprite_sheet = pygame.image.load('chest_001.png').convert_alpha()
# 建立子表面串列
img_cs = [sprite_sheet.subsurface(pygame.Rect(i*16, 0, 16, 32)) for i in range(6)]
class Chest(pygame.sprite.Sprite):
def __init__(self, *groups):
super().__init__(*groups)
self.image_index = 0 # 目前影格索引
self.image = img_cs[self.image_index]
self.rect = self.image.get_rect()
def update(self):
self.image_index = (self.image_index + 1) % len(img_cs) # 迴圈播放
self.image = img_cs[self.image_index]
控製動畫播放速度
如果遊戲的影格率為60
,那麽上面例子中的寶箱動畫,每秒可播放10
次。為了降低動畫的播放速度,可新增一些變數進行控製。
下面,為Chest
新增類別變數WAIT
和變數wait
,用於控製子表面的切換時間間隔,在update
方法判斷是否可以進行子表面的切換。
調整WAIT
的值可改變動畫播放速度。
class Chest(pygame.sprite.Sprite):
WAIT = 5 # 每 5 影格切換一次動畫影格
def __init__(self, *groups):
super().__init__(*groups)
self.wait = 0 # 影格計數器
# …
def update(self):
self.wait += 1
if self.wait >= self.WAIT:
self.wait = 0
self.image_index = (self.image_index + 1) % len(img_cs) # 迴圈播放
self.image = img_cs[self.image_index]