前两天写了一个使用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()