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:精灵序列图动画效果及帧频、内存信息

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

clip_image004

图2:矢量动画

clip_image006

图3:矢量+cacheAsBitmap动画

clip_image008

图4:位图动画

clip_image010

图5:位图+导出类

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

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

clip_image011

图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,如下图所示:

clip_image012

图7:Flash cs6导出SpriteSheet设置

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

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

clip_image014

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

SpriteSheet类clip_image015

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

clip_image016

图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); } }

}
原文来自:技术之家

转载于:https://www.cnblogs.com/buntinginfo/p/7063223.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值