前兩天寫了一個使用blit 實現動畫的文章.今天我們我們用 另一個方法surface來實現精靈動畫.這兩個方法本質上的區別在於. blit() 是直接把圖像繪製在surface表面.而subsurface()是先將圖像提取子表面.然後通過Sprite.draw, 或者Group.draw將自表面繪製出來.
在使用的時候主要還是看個人習慣.對於我來說一般在寫一些只做單詞循環的動畫,比如飛機爆炸產生的火花,我就用blit(),如果是需要不斷循環的動畫,比如英雄的動作.我喜歡用sub
關於surface.subfurface()方法的工作原理,我這裏有一張簡單的圖來說明.
在這裏要注意的是,要使用子表面實現動畫時,類中要有兩個rect參數,第一個是self.rect這個rect參數是實例的rect屬性,在使用sprite.draw(),或者group.draw()的時候,作爲位置參數傳遞給方法.第二個rect參數是框架參數,也就是你要提取的一個子表面的大小.在公式中,我們用
self.frame_rect.x = (self.frame % 4) * self.frame_rect.width
self.frame_rect.y = (self.frame // 4) * self.frame_rect.height
來計算子表面框架在剪切時所處的位置.
對了這裏有一個地方要說明一下.subsurface()這個方法在提取子表面的時候,默認的topleft是0,0. 也就是說,如果你想讓動畫繪製在屏幕某一個座標的時候.記得要在frame_rect(子表面框架)變量聲明瞭以後再去更改self.rect的座標值.
完整的代碼如下,這次用的是一個在網上找的爆炸火花.
完整的代碼如下:
#coding = utf-8
import pygame,sys
from pygame.sprite import Sprite
from pygame.sprite import Group
class Mysprite(Sprite):
def __init__(self):
super().__init__()
self.mast_image = pygame.image.load('2233.jpg') #讀取圖像
self.rect = self.mast_image.get_rect() #獲取圖像矩形參數
self.frame_rect = self.rect.copy() #聲明框架參數
self.rect.x,self.rect.y = 400,300 #這裏是我實驗的動畫座標繪製,如果把這兩個參數放在第12行之前,那麼就會報錯,顯示子表面繪製超出了範圍 .
self.frame_rect.width /= 4
self.frame_rect.height /= 4
self.frame = 0
self.last_frame = (self.rect.width // self.frame_rect.width) * (self.rect.height // self.frame_rect.height) - 1
self.old_frame = 1
self.last_time = 0
def update(self):
self.current_time = pygame.time.get_ticks()
rate = 100 #因爲這個屬性在別的地方不會有調用,所以這裏我就寫成了方法的局部變量
if self.current_time >= self.last_time + rate:
self.frame += 1
if self.frame > self.last_frame:
self.frame = 0
self.last_time = self.current_time
if self.old_frame != self.frame:
self.frame_rect.x = (self.frame % 4) * self.frame_rect.width
self.frame_rect.y = (self.frame // 4) * self.frame_rect.height
self.old_frame = self.frame
self.image = self.mast_image.subsurface(self.frame_rect) #這裏就是在生成子表面
pygame.init()
screen = pygame.display.set_mode((800,600))
color = (255,255,255)
mysprite = Mysprite()
group = Group()
group.add(mysprite)
tick = pygame.time.Clock()
while True:
tick.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
screen.fill(color)
group.update()
group.draw(screen)
pygame.display.update()