URLhttps://learnscript.net/zh/pygame/sprite/animation/
    复制链接转到说明  示例

    如何通过精灵图集实现动画

    我被代码海扁署名-非商业-禁演绎
    阅读 3:38·字数 1094·发布 

    引言

    因为 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]

    讲解视频

    如何在 Pygame 中实现精灵动画,控制播放速度·YouTube如何在 Pygame 中实现精灵动画,控制播放速度·Bilibili