SpriteSheet精灵动画引擎

简介:

SpriteSheet精灵动画引擎

 

本文介绍FlashSpriteSheet精灵序列图与其它渲染方式的性能对比、SpriteSheet的原理及注意实现,最后实现了一个精灵序列图的渲染引擎。本文的SpriteSheet引擎及demo可以在github上下载:https://github.com/saylorzhu/SpriteSheet

动画渲染性能对比

Flash中动画制作方式有多种,如矢量动画、位图帧动画、精灵序列图等等。针对不同的制作方式,对同一个角色动画进行如下测试:一个角色在屏幕上显示5个实例,对应呼吸、施法、行走、受伤、普攻状态。

测试运行的环境:

l  Release version of Flash Player 12.0.159.1

l  AMD Phenom(tm) II X4 830 Processor(2800 Mhz)

l  Microsoft Windows 7 专业版 (32)

得出测试结果如下表所示,为了节约大小资源中所用位图均为png8

1:不同动画渲染效率对比(具体测试数据与所使用资源有关)

渲染方式

描述

CPU

内存(KB

文件大小(KB

时间轴

矢量

12

6m

24

矢量+cacheAsBitmap

12

6.2m

24

位图

2

6.8m

534

位图+导出类

2

13m

537

位图渲染

SpriteSheet精灵序列图

1

11m

220 png + 31 json/xml

从上表可以得出,精灵序列图消耗CPU最少,并且文件大小适中,但内存消耗较大。对于游戏来说,CPU销毁越小,帧频可以越大,游戏越流畅。

clip_image002

1:精灵序列图动画效果及帧频、内存信息

可以看出使用精灵序列图帧频和内存都非常稳定,内存没有频繁的gcgc非常消耗cpu会造成游戏卡顿现象。反观其它渲染方式,会发现内存不稳定,这对游戏性能是一个风险。

clip_image004

2:矢量动画

clip_image006

3:矢量+cacheAsBitmap动画

clip_image008

4:位图动画

clip_image010

5位图+导出类

下面详细介绍下精灵序列图的原理及注意事项。

精灵序列图

SpriteSheet精灵序列图是一种大的网格式位图,其中每一格都对应着一个动画截屏,每一动画截屏对应动画的一帧。精灵序列图通常采用PNG格式,这样可以使用Alpha通道。

clip_image011

6:角色受伤动画序列图

除了大位图之后,还必须有一个对应的数据描述文件,常用的格式有jsonjson-arrayxml。数据描述文件,用来指定每帧动画在大图中的位置(偏移位置、宽、高等等),如json格式如下:

JSON格式描述数据:

{"frames": {

 

"呼吸0000":

{

              "frame": {"x":0,"y":0,"w":110,"h":110},

              "rotated": false,

              "trimmed": false,

              "spriteSourceSize": {"x":0,"y":0,"w":110,"h":110},

              "sourceSize": {"w":110,"h":110}

},

"呼吸0001":

{

              "frame": {"x":110,"y":0,"w":110,"h":110},

              "rotated": false,

              "trimmed": false,

              "spriteSourceSize": {"x":0,"y":0,"w":110,"h":110},

              "sourceSize": {"w":110,"h":110}

},

},

"meta": {

              "app": "Adobe Flash CS6",

              "version": "12.0.0.481",

              "image": "jsonformat.png",

              "format": "RGB8",

              "size": {"w":1024,"h":1024},

              "scale": "1"

}

}

其中:

Key-"呼吸0000":表示帧的名字/对应图片文件名(json-array格式中,使用filename字段表示);

frame: 图片在大图中的偏移位置(左上角为原点)和大小(未旋转前)  需要注意这里的图片大小是图片未旋转前的大小;

rotated:  是否旋转(顺时针方向);

trimmed: 是否有去掉周围多余的透明部分;

spriteSourceSize: x,y表示图片未去掉周围透明部分的偏移量,这是如果需要还原图片原先的大小要用的;

sourceSize: 图片的原始大小,包含透明部分;

渲染机制

精灵序列图使用位块图像传输bit-blittingblit = Bit-Block Image Transfer)技术,它涉及到使用位图来渲染最终的显示效果。 将需要显示的效果,像素会绘制到一个已添加到舞台上的位图中。为了表现动画效果,会在一个循环中更新位图的像素。关键步骤如下:

1)     加载动画中需要的Sprite Sheet位图数据(.png文件)

2)     displayList中添加一个BitmapData目标位图数据(画布)

3)     向画布复制或者擦除游戏(copyPixel vs draw

4)     根据游戏显示层次顺序将Sprite Sheet复制到画布

5)     在游戏循环中重复第34

copyPixel的效率比draw高,所以一般情况下,使用copyPixel复制图像到画布。

内存占用

在所有动画渲染方式中,精灵序列图对帧频的影响是最小的。因为精灵序列图会预先被缓存到BitmapData实例中,这就可以使渲染速度变得更快。一定要随时注意内存的占用,仔细把控,详尽规划。精灵序列图之所以效率高,是由于位图序列都缓存在内存中从而可被快速调取。但这样也可能会导致巨大的内存开销。

注意:一张图片占用多少内存只取决于图像的尺寸,而与图像文件的类型和图像压缩无关。

位图所占内存(字节)= 位图宽度 x 位图高度 x 4

假设一帧的图片的大小为200x400像素,占用内存312.5KB。如果一个动画18帧,则占用内存约5.5M。如果一个角色包含4个方向或4个动作的动画,则占用内存约22M。同屏在线10个角色,则占用内存约220M

SpriteSheet工具

现在Flash cs6已经集成了将动画导出为SpriteSheet,如下图所示:

clip_image012

7Flash cs6导出SpriteSheet设置

TexturePacker也可以打包图片为SpriteSheet格式。

精灵序列图引擎

前面介绍了精灵序列图的原理及注意事项,下面实现一个精灵序列图动画的引擎,支持Flash Cs6/TexturePacker导出的JSONJSON-ArrayStarlingXML3种数据格式。

clip_image014

8:精灵序列图引擎类图

SpriteSheet

clip_image015

9SpriteSheet

SpriteSheet继承自flash.display.Sprite,包含一个bitmap成员用作画布。使用定时器Timer来驱动动画循环。

SpriteSheet使用类似Movieclip,提供play()stop()gotoAndPlay()gotoAndStop()接口,并支持鼠标事件。

mAnimation成员(Animation实例)用于描述SpriteSheet当前表示的动作,如游戏中一个角色包含呼吸、行走、施法、受伤动作。

mTextureAltas成员(TexureAtlas实例)用于维护整个精灵序列图数据,并负责将特定帧位图复制到画布显示。

TexureAtlas

TexureAtlas类保存了整个精灵序列图数据,并根据SpriteSheet的当前动作,生成构成动画的所有帧在精灵序列图中的偏移和大小。

Animation

Animation动画信息类。

l  seqName表示动画序列名(e.g. "walk")

l  delay表示帧间隔

l  loop表示动画是否循环播放

l  arFrames:Vector.<SpriteFrame>;// 帧信息数据

SpriteFrame

SpriteFrame类表示图片在大图中的偏移位置(左上角为原点)和大小(未旋转前)等等信息,根据数据描述文件生成。

clip_image016

10SpriteFra示意

JsonFormatJsonArrayFormatXmlFormat

SpriteSheet序列图数据解析类,分别解析对应格式的描述数据。

Demo实例

SpriteSheet使用非常简单,与原生Movieclip差异不大。下面的例子分别加载JSONJSON-ArrayXML格式的数据及对应的PNG资源,然后创建SpriteSheet实例。

Demo:

package

{

           import com.as3game.asset.AssetManager;

           import com.as3game.spritesheet.SpriteSheet;

           import com.as3game.spritesheet.vos.DataFormat;

           import flash.display.BitmapData;

           import flash.display.Sprite;

           import flash.events.MouseEvent;

           import flash.filters.ColorMatrixFilter;

           import flash.text.TextField;

          

           /**

            * ...

            * @author Tylerzhu

            */

           public class TestSpriteSheet extends Sprite

           {

                      

                       public function TestSpriteSheet()

                       {

                                  SWFProfiler.init(stage, this);

                                  AssetManager.getInstance().getGroupAssets("spritesheets-json", ["data/json/jsonformat.json", "data/json/jsonformat.png"], onAnimLoaded);

                                  AssetManager.getInstance().getGroupAssets("spritesheets-xml", ["data/xml/xmlformat.xml", "data/xml/xmlformat.png"], onAnimLoadedXML);

                                  AssetManager.getInstance().getGroupAssets("spritesheets-jsonarray", ["data/json-array/jsonarrayformat.json", "data/json-array/jsonarrayformat.png"], onAnimLoadedJsonArray);

                       }

                      

                      

                       private function onAnimLoaded():void

                       {

                                  var bitmapData:BitmapData = AssetManager.getInstance().bulkLoader.getBitmapData("data/json/jsonformat.png");

                                  var sheets:* = AssetManager.getInstance().getContent("data/json/jsonformat.json");

                                  var sp:SpriteSheet = new SpriteSheet(bitmapData, sheets, DataFormat.FORMAT_JSON);

                                  sp.setAction("呼吸", 14);

                                  sp.play();

                                  addChild(sp);

                       }

                      

                       private function onAnimLoadedXML():void

                       {

                                  var bitmapData:BitmapData = AssetManager.getInstance().bulkLoader.getBitmapData("data/xml/xmlformat.png");

                                  var sheets:* = AssetManager.getInstance().getContent("data/xml/xmlformat.xml");

                                  var sp:SpriteSheet = new SpriteSheet(bitmapData, sheets, DataFormat.FORMAT_XML);

                                  sp.setAction("呼吸", 15);

                                  sp.play();

                                  sp.y = 150;

                                  addChild(sp);

                       }

                      

                       private function onAnimLoadedJsonArray():void

                       {

                                  var bitmapData:BitmapData = AssetManager.getInstance().bulkLoader.getBitmapData("data/json-array/jsonarrayformat.png");

                                  var sheets:* = AssetManager.getInstance().getContent("data/json-array/jsonarrayformat.json");

                                  var sp:SpriteSheet = new SpriteSheet(bitmapData, sheets, DataFormat.FORMAT_JSON_ARRAY);

                                  sp.setAction("呼吸", 15);

                                  sp.play();

                                  sp.y = 300;

                                  addChild(sp);

                       }

           }

}

 

相关文章
|
存储 NoSQL 应用服务中间件
如何高效存储海量GPS数据
GPS数据使用越来越广,但如何高性能存储海量GPS数据仍然具有挑战,本文会介绍一种非常适合存储GPS数据的存储系统:阿里云NoSQL数据库TableStore,同时会介绍多个不同场景的技术方案。
23958 0
|
7月前
IPv4内网与公网地址范围
本文介绍了内网和公网IPv4地址的范围及用途。内网IP(私有地址)包括10.0.0.0/8、172.16.0.0/12和192.168.0.0/16,分别适用于大型、中型和小型网络。公网IP分为A、B、C类,分别支持大规模、中等规模和小规模网络;D类用于多播通信,E类保留实验用途。此外,127.0.0.0/8为环回地址,不用于公网。这些划分确保了IP地址的有效利用与网络通信的正常进行。
2509 10
|
8月前
|
Serverless Python
借助 serverless 将 MCP 服务部署到云端
本文介绍了如何将 MCP 服务通过 SSE 协议部署到云端,避免本地下载和启动的麻烦。首先,使用 Python 实现了一个基于 FastMCP 的网络搜索工具,并通过设置 `transport='sse'` 启用 SSE 协议。接着,编写客户端代码测试服务功能,确保其正常运行。随后,利用阿里云函数计算服务(FC 3.0)以 Serverless 方式部署该服务,包括创建函数、配置环境变量、添加依赖层以及部署代码。最后,提供了客户端测试方法和日志排查技巧,并展示了如何在不同工具(如 Cherry-Studio、Cline 和 Cursor)中配置云端 MCP 服务。
1374 10
借助 serverless 将 MCP 服务部署到云端
|
消息中间件 物联网 Java
开发者如何使用云消息队列 MQTT 版
【10月更文挑战第14天】开发者如何使用云消息队列 MQTT 版
947 102
Electron——electron-vue使用webworker
Electron——electron-vue使用webworker
314 4
|
数据采集 数据可视化 大数据
【优秀python大屏案例】基于python flask的前程无忧大数据岗位分析可视化大屏设计与实现
本文介绍了一个基于Python Flask框架的前程无忧大数据岗位分析可视化大屏系统,该系统通过爬虫技术采集招聘数据,利用机器学习算法进行分析,并以可视化大屏展示,旨在提高招聘市场数据分析的效率和准确性,为企业提供招聘决策支持和求职者职业规划参考。
621 2
|
存储 安全 Java
Java HashSet详解
`HashSet` 是 Java 中基于哈希表实现的 `Set` 接口集合,主要用于存储不重复元素,提供快速查找、插入和删除操作。它具有以下特点:不允许重复元素,元素无序,允许一个 `null` 元素,常用操作包括创建、添加、删除、检查元素及清空集合。由于其内部使用哈希表,基本操作的时间复杂度接近 O(1),性能高效。然而,`HashSet` 不保证元素顺序,也不是线程安全的,适用于需要快速访问和操作的场景。
530 10
|
存储 文件存储 数据安全/隐私保护
Windows部署开源文件管理器File Browser并实现远程访问本地文件
Windows部署开源文件管理器File Browser并实现远程访问本地文件
1056 1
|
芯片
FLStudio21中文试用体验版版本下载及新版本功能介绍
根据大众需求,FL STUDIO 21引入了令人兴奋的工作流程选项,包括分组乐器频道,播放列表轨道和混音器轨道; 直接录制到指定的播放列表曲目,前或后FX; Stepsequencer循环的返回等等。FL Studio的软件免费升级更新政策能坚持23年,因此所有FL Studio用户均可免费更新。2023年推出的FL STUDIO 21新版本将迎来主题更换新功能,水果用户们能随意更换自己心仪的主题色彩!FL STUDIO 21下载:http://t.csdn.cn/scw8f
977 2
|
存储 网络协议 算法
路由选择算法总结
路由选择算法总结
557 0

热门文章

最新文章