Python实现GIF动图加载和降帧的方法详解
最近在使用pygame开发游戏,练习python编程。但遇到了一个问题,就是如何载入已有的GIF动图增强游戏的效果,在csdn搜索了一下,发现相关的文章比较少,缺少实例。于是自己研究了相关内容,找到了解决方案。本篇文章用游戏编程实例介绍pygame如何载入GIF动图。
一、准备一份透明背景的GIF动画素材
首先在网络上找一张背景透明的GIF动图,注意需要背景透明的,不然在游戏中就会显示一个矩形图片,会挡住游戏的背景。以下就是百度图片搜索找到的背景透明的GIF动图。
百度图片搜索的素材
二、使用pillow库对GIF动图进行解帧
使用pillow库的Image、ImageSequence包对图片进行解帧后发现,这张下载的GIF图片包含了10帧图片,图片以png格式保存在./images/bird/文件夹下面,文件名以gif1、gif2......等为后缀名。
GIF解帧后的文件情况
参考代码:
from PIL import Image, ImageSequence
class GameGifSprite(pygame.sprite.Sprite):
"""
小鸟游戏精灵
"""
def __init__(self, image_name, speed=1):
# 调用父类的初始化方法
super().__init__()
# 使用pillow的image打开GIF动图
pillow_image = Image.open(image_name)
index = 1
# 使用pillow的ImageSequence获取GIF动图所有帧对应的迭代器
for frame in ImageSequence.all_frames(pillow_image):
# 以png格式保存在./images/bird/文件夹下面,文件名以gif1、gif2......等为后缀名
frame.save(f"./images/bird/gif{index}.png", quality=100)
index = index + 1
三、使用pygame.image.load()读取所有解出来的帧并存入列表
然后使用pygame.image.load()按文件名字顺序读取这10张图片,并把返回的10个图像对象添加到列表中。
1)all_frame为GIF动图所包含的所有帧数,这里index循环结束后为11,由于数组从0开始计算,所以为11-2=9。
2)now_frame为当前游戏的帧,一开始设置为0。
3)gif_images为存储GIF动图的帧列表。
4)循环读取所有帧,添加到gif_images[]中。
5)游戏开始时设置显示第一帧图片。
参考代码:
# 定义对象的属性
# 1.all_frame为GIF动图所包含的所有帧数,这里index循环结束后为11,由于数组从0开始计算,所以为11-2=9
self.all_frame = index - 2
# 2.now_frame为当前游戏的帧,一开始设置为0
self.now_frame = 0
# 3.gif_images为存储GIF动图的帧列表
self.gif_images = []
# 4.循环读取所有帧,添加到gif_images[]中
for i in range(1, index):
self.gif_images.append(pygame.image.load(f"./images/bird/gif{i}.png"))
# 5.游戏开始时设置显示第一帧图片
self.image = self.gif_images[self.now_frame]
四、在精灵类的update()方法中循环播放列表中的帧
pygame在每次画面刷新时会调用每个精灵类的update()方法,所以我们只要在该方法下实现循环播放这10帧图片就可以实现含有GIF图片精灵的播放。以下是游戏运行效果图:
游戏运行效果图
1)当播放到gif最后一帧时,重置为gif第一帧
2)画面每次刷新更新gif的下一帧
参考代码:
def update(self):
# 在屏幕的水平方向上移动
self.rect.x -= self.speed
# 当播放到gif最后一帧时,重置为gif第一帧
if self.now_frame < self.all_frame:
# 画面每次刷新更新gif的下一帧
self.now_frame = self.now_frame + 1
else:
self.now_frame = 1
五、避免精灵帧率过快对精灵进行降帧
实现GIF在游戏中显示后又产生了一个新问题,由于游戏设置是60FPS帧率播放的,那么显示这张GIF图片时就过快了,我们需要对精灵对象降低帧率,这里使用了我自己写的公式。
1)self.now_frame = self.now_frame + 1改为self.now_frame = self.now_frame + self.FPS
2)update()方法中增加self.image = self.gif_images[math.floor(self.now_frame)],使用math.floor向下取整达到降帧的效果
PS:当sefl.FPS设置为0.25时则相当于把帧率降低了4倍,现在看上去就正常多了。
降帧后的效果图
参考代码:
def update(self):
# 在屏幕的水平方向上移动
self.rect.x -= self.speed
# 当播放到gif最后一帧时,重置为gif第一帧
if self.now_frame < self.all_frame:
# 画面每次刷新更新gif的一下一帧
self.now_frame = self.now_frame + self.FPS
else:
self.now_frame = 1
# 设置pygame当前显示的gif帧
# 使用math.floor向下取整达到降帧的效果
self.image = self.gif_images[math.floor(self.now_frame)]
到此这篇关于python实现GIF动图加载和降帧的方法详解的文章就介绍到这了,更多相关Python动图加载降帧内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
相关文章