SpriteSheet精灵动画引擎

SpriteSheet精灵动画引擎

 

本文介绍Flash中SpriteSheet精灵序列图与其它渲染方式的性能对比、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销毁越小,帧频可以越大,游戏越流畅。

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

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

图2:矢量动画

图3:矢量+cacheAsBitmap动画

图4:位图动画

图5:位图+导出类

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

精灵序列图

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

图6:角色受伤动画序列图

除了大位图之后,还必须有一个对应的数据描述文件,常用的格式有json、json-array、xml。数据描述文件,用来指定每帧动画在大图中的位置(偏移位置、宽、高等等),如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-blitting,blit = Bit-Block Image Transfer)技术,它涉及到使用位图来渲染最终的显示效果。 将需要显示的效果,像素会绘制到一个已添加到舞台上的位图中。为了表现动画效果,会在一个循环中更新位图的像素。关键步骤如下:

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

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

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

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

5)     在游戏循环中重复第3、4步

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

内存占用

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

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

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

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

SpriteSheet工具

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

图7:Flash cs6导出SpriteSheet设置

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

精灵序列图引擎

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

图8:精灵序列图引擎类图

SpriteSheet类

图9:SpriteSheet类

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

图10:SpriteFra示意

JsonFormat、JsonArrayFormat、XmlFormat类

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

Demo实例

SpriteSheet使用非常简单,与原生Movieclip差异不大。下面的例子分别加载JSON、JSON-Array、XML格式的数据及对应的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);

                       }

           }

}

 

时间: 2024-11-08 23:29:18

SpriteSheet精灵动画引擎的相关文章

Android精灵动画用法实例_Android

本文实例讲述了Android精灵动画用法.分享给大家供大家参考.具体如下: ElaineAnimated.java文件如下: package net.obviam.walking.model; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; public class ElaineAnimated

Android精灵动画用法实例

本文实例讲述了Android精灵动画用法.分享给大家供大家参考.具体如下: ElaineAnimated.java文件如下: package net.obviam.walking.model; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; public class ElaineAnimated

Android LibGDX游戏引擎开发教程(九) 动画类的使用

对于一款成功的游戏,动画效果也是整个游戏中不可或缺的元素之一,那下面我们就来讲解一下动画类的 使用方法. 一.Animation类 1.Animation介绍 开发教程(九) 动画类的使用-android 动画引擎"> 该类存放在 com.badlogic.gdx.graphics.g2d的包下,该类继承自Object. 2.Animation定义 这 是官方API的定义,大概的意思是说:一个动画就是存放了一个列表的图片表示在设定的时间间隔序列的显示 .比如,一个正在跑步或者正在跳动的人.

js动画(animate)简单引擎代码示例_javascript技巧

用惯了jquery的同学,相信都很欣赏其动画引擎.确实相对比较完善!如果,如果想像力足够丰富的话,相信可以做出超出想像的效果.当然,跟2d库比起来,还是相差相当一段距离.jquery压根也不是专门为动画而设计的.模拟真实世界方面,还是不足的.但在web世界里还是游刃有余的.动画其实一直是flash的专属领地(web区哉).只是它常常沦为黑客攻击的漏洞所在,而且要装插件,有时候文件实在太大,而且性耗实在是高啊.html5出现后,其实adobe自己都转移阵地到html5了.当然,我觉得很长一段时间内

阿里自主研发的互动游戏引擎Hilo开源啦!【内有详解】

目前,Hilo已经开源,并入到Hilo Team中.开源地址 https://github.com/hiloteam/Hilo (欢迎Star) Hilo的特点: 极简内核: Hilo核心模块极精简,保留了2D游戏引擎最必要的模块,同时采用模块化管理. 完善接入&扩展: Hilo 支持多种模块范式的包装版本,包括AMD,CMD,Standalone多种方式接入.另外,你可以新增和扩展需要的模块和类型. 多种渲染方式:提供DOM,Canvas,Flash,WebGL等多种渲染方案,可以做到跨全端,

Android 8款开源游戏引擎

1.Angle  (2D Java) Angle是一款专为Android平台设计的,敏捷且适合快速开发的2D游戏引擎,基于OpenGLES技术开发.该引擎全部用Java代码编写,并且可以根据自己的需要替换里面的实现,缺陷在于文档不足,而且下载的代码中仅仅包含有少量的示例教程. 最低运行环境要求不详. 项目地址:http://code.google.com/p/angle/ 2.Rokon  (2D Java) rokon是一款Android 2D游戏引擎,基于OpenGL ES技术开发,物理引擎

或许您还不知道的八款Android开源游戏引擎

原文: http://blog.csdn.net/cping1982/article/details/5788921 很多初学Android游戏开发的朋友,往往会显得有些无所适从,他们常常不知道该从何处入手,每当遇到自己无法解决的难题时,又往往会一边羡慕于iPhone下有诸如Cocos2d-iphone之类的免费游戏引擎可供使用,一边自暴自弃的抱怨Android平台游戏开发难度太高,又连个像样的游戏引擎也没有,甚至误以为使用Java语言开发游戏是一件费力不讨好且没有出路的事情. 事实上,这种想法

【IOS(译)】游戏引擎剖析

本站文章均为 李华明Himi 原创,转载务必在明显处注明:  转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/iphone-cocos2d/406.html 为了解决"如何在IPHONE上创建一个游戏"这个大问题,我们需要首先解决诸如"如何显示图像"与"如何播放声音"等一系列小问题.这些问题关系到创建部分游戏引擎.就像人类的身体一样,游戏引擎的每个部分虽然不同,但是却都不可或缺.因此,首先从游戏引擎剖

畅想动画制作的乐趣

为什么要制作动画? 现在的营销活动,用一个很简单的图片去吸引消费者已经远远不够.想让消费者创造GMV,肯定需要让消费者觉得眼前一亮或是有视觉冲击的东西,或者在动画过程中提供更好的引导部分,比如红包,引导消费者去戳红包,他们自然而然就进入到角色当中.历年双十一手淘动画层出不穷,去年一些比较典型的动画.场景,其实也是给大家展示了一次事件: 这些提供给消费者或者用户的动画,其实就是一个入口,让他们知道手淘正在做某活动. 制作动画的方式很多,以前会让视觉设计师或动画设计师去做一个视频.GIF, FLAS