按键精灵后台鼠标点击在执行按键精灵后台鼠标点击帧动画过程中没有点击事件为什吗

SpriteSheet精灵动画引擎   本文介绍Flash中SpriteSheet精灵序列图与其它渲染方式的性能对比、SpriteSheet的原理及注意实现,最后实现了一个精灵序列图的渲染引擎。本文的SpriteSheet引擎及demo可以在github上下载:
动画渲染性能对比 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:不同动画渲染效率对比(具体测试数据与所使用资源有关)
内存(KB)
文件大小(KB)
<font style="font-size: 12pt" color="#
<font style="font-size: 12pt" color="#m
<font style="font-size: 12pt" color="#
矢量+cacheAsBitmap
<font style="font-size: 12pt" color="#
<font style="font-size: 12pt" color="#.2m
<font style="font-size: 12pt" color="#
<font style="font-size: 12pt" color="#
<font style="font-size: 12pt" color="#.8m
<font style="font-size: 12pt" color="#4
位图+导出类
<font style="font-size: 12pt" color="#
<font style="font-size: 12pt" color="#m
<font style="font-size: 12pt" color="#7
SpriteSheet精灵序列图
<font style="font-size: 12pt" color="#ff 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&: { &#160; &呼吸0000&: { &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &frame&: {&x&:0,&y&:0,&w&:110,&h&:110}, &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &rotated&: false, &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &trimmed&: false, &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &spriteSourceSize&: {&x&:0,&y&:0,&w&:110,&h&:110}, &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &sourceSize&: {&w&:110,&h&:110} }, &呼吸0001&: { &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &frame&: {&x&:110,&y&:0,&w&:110,&h&:110}, &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &rotated&: false, &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &trimmed&: false, &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &spriteSourceSize&: {&x&:0,&y&:0,&w&:110,&h&:110}, &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &sourceSize&: {&w&:110,&h&:110} }, … }, &meta&: { &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &app&: &Adobe Flash CS6&, &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &version&: &12.0.0.481&, &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &image&: &jsonformat.png&, &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &format&: &RGB8&, &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &size&: {&w&:1024,&h&:1024}, &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &scale&: &1& } }
其中: Key-&呼吸0000&:表示帧的名字/对应图片文件名(json-array格式中,使用filename字段表示); frame: 图片在大图中的偏移位置(左上角为原点)和大小(未旋转前)&#160; 需要注意这里的图片大小是图片未旋转前的大小; rotated: &#160;是否旋转(顺时针方向); trimmed: 是否有去掉周围多余的透明部分; spriteSourceSize: x,y表示图片未去掉周围透明部分的偏移量,这是如果需要还原图片原先的大小要用的; sourceSize: 图片的原始大小,包含透明部分; 渲染机制 精灵序列图使用位块图像传输(bit-blitting,blit = Bit-Block Image Transfer)技术,它涉及到使用位图来渲染最终的显示效果。 将需要显示的效果,像素会绘制到一个已添加到舞台上的位图中。为了表现动画效果,会在一个循环中更新位图的像素。关键步骤如下: 1)&#160;&#160;&#160;&#160; 加载动画中需要的Sprite Sheet位图数据(.png文件) 2)&#160;&#160;&#160;&#160; 在displayList中添加一个BitmapData目标位图数据(画布) 3)&#160;&#160;&#160;&#160; 向画布复制或者擦除游戏(copyPixel vs draw) 4)&#160;&#160;&#160;&#160; 根据游戏显示层次顺序将Sprite Sheet复制到画布 5)&#160;&#160;&#160;&#160; 在游戏循环中重复第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&#160; seqName表示动画序列名(e.g. &walk&) l&#160; delay表示帧间隔 l&#160; loop表示动画是否循环播放 l&#160; arFrames:Vector.&SpriteFrame&;// 帧信息数据 SpriteFrame类 SpriteFrame类表示图片在大图中的偏移位置(左上角为原点)和大小(未旋转前)等等信息,根据数据描述文件生成。
图10:SpriteFra示意 JsonFormat、JsonArrayFormat、XmlFormat类 SpriteSheet序列图数据解析类,分别解析对应格式的描述数据。 Demo实例 SpriteSheet使用非常简单,与原生Movieclip差异不大。下面的例子分别加载JSON、JSON-Array、XML格式的数据及对应的PNG资源,然后创建SpriteSheet实例。
package { &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; import com.as3game.asset.AssetM &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; import com.as3game.spritesheet.SpriteS &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; import com.as3game.spritesheet.vos.DataF &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; import flash.display.BitmapD &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; import flash.display.S &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; import flash.events.MouseE &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; import flash.filters.ColorMatrixF &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; import flash.text.TextF &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; /** &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;* ... &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;* @author Tylerzhu &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;*/ &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; public class TestSpriteSheet extends Sprite &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; { &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; public function TestSpriteSheet() &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; { &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; SWFProfiler.init(stage, this); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AssetManager.getInstance().getGroupAssets(&spritesheets-json&, [&data/json/jsonformat.json&, &data/json/jsonformat.png&], onAnimLoaded); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AssetManager.getInstance().getGroupAssets(&spritesheets-xml&, [&data/xml/xmlformat.xml&, &data/xml/xmlformat.png&], onAnimLoadedXML); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AssetManager.getInstance().getGroupAssets(&spritesheets-jsonarray&, [&data/json-array/jsonarrayformat.json&, &data/json-array/jsonarrayformat.png&], onAnimLoadedJsonArray); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; } &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; private function onAnimLoaded():void &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; { &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; var bitmapData:BitmapData = AssetManager.getInstance().bulkLoader.getBitmapData(&data/json/jsonformat.png&); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; var sheets:* = AssetManager.getInstance().getContent(&data/json/jsonformat.json&); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; var sp:SpriteSheet = new SpriteSheet(bitmapData, sheets, DataFormat.FORMAT_JSON); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; sp.setAction(&呼吸&, 14); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; sp.play(); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; addChild(sp); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; } &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; private function onAnimLoadedXML():void &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; { &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; var bitmapData:BitmapData = AssetManager.getInstance().bulkLoader.getBitmapData(&data/xml/xmlformat.png&); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; var sheets:* = AssetManager.getInstance().getContent(&data/xml/xmlformat.xml&); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; var sp:SpriteSheet = new SpriteSheet(bitmapData, sheets, DataFormat.FORMAT_XML); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; sp.setAction(&呼吸&, 15); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; sp.play(); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; sp.y = 150; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; addChild(sp); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; } &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; private function onAnimLoadedJsonArray():void &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; { &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; var bitmapData:BitmapData = AssetManager.getInstance().bulkLoader.getBitmapData(&data/json-array/jsonarrayformat.png&); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; var sheets:* = AssetManager.getInstance().getContent(&data/json-array/jsonarrayformat.json&); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; var sp:SpriteSheet = new SpriteSheet(bitmapData, sheets, DataFormat.FORMAT_JSON_ARRAY); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; sp.setAction(&呼吸&, 15); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; sp.play(); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; sp.y = 300; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; addChild(sp); &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; } &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; } }
&#160; &#160;
与本文相关的文章cocos2dx动画Animation介绍
一、帧动画
你可以通过一系列图片文件,像如下这样,创建一个动画:
CCAnimation *animation = CCAnimation::create(); &
//从本地文件中加载图片文件到CCSpriteFrame中区,然后添加到CCAnimation中 &
for (int i = 1; i & 15; i++) &
& & char szImageFileName[128] = {0}; &
& & sprintf(szImageFileName, &Images/grossini_dance_%02d.png&, i); &
& & animation-&addSpriteFrameWithFileName(szImageFileName); & &
animation-&setDelayPerUnit(2.8f / 14.0f); // 这个动画包含14帧,将会持续2.8秒. &
animation-&setRestoreOriginalFrame(true); // 14帧播放完之后返回到第一帧 &
CCAnimate *action = CCAnimate::create(animation); &
sprite-&runAction(action); &// 运行精灵对象 &
注意CCAnimation是由许多精灵帧组成,可以设置间隔时间,持续时间等,它实际上是包含着一组数据。CCAnimate是一个动作,它是通过CCAnimation对象创建。
二、精灵表动画
尽管手工动画很容易理解,但它很少用在游戏开发中。相反的,精灵表动画的方式在2D动画中经常使用。
这是一个精灵表。它实际上就是一系列动画帧图片,或者是一个能用于一个场景的图片集。
在OpenGLES1.1阶段,精灵表因为以下几点被广泛应用:
1、减少文件读写时间。读取一张图片比读取一堆小文件肯定要快。
2、减少内存消耗。OpenGL ES 1.1仅仅能够使用2的几次方大小的图片(也就是宽度或者高度是2,4,864,128,256,512,1024,...)。也就是说,OpenGL ES1.1将会分配给每个图片2的几次方大小的内存空间,即使你这张图片达不到这样的宽度和高度也会分配大于此图片的2的n次方大小的空间。那么运用这种图片集的方式将会减少内存碎片。
3、减少OpenGL ES绘制调用并且加速渲染。
Cocos2d-x v2.0升级到了OpenGL ES2.0.OpenGL ES2.0不会再分配2的几次方的内存块了,但是减少读取时间和绘制调用的优势依然存在。
那么生成的动画效果如何呢?正如我们所见,精灵表不是动画的一个必须条件。但是考虑到以上的一些优势,精灵表还是很有效率的。在Cocos2dx中,有许多不同的方式来创建精灵表。
三、通过.png 和 .plist文件创建精灵表
在cocos2dx 0.x和1.x版本中,CCSpriteSheet就是为以上的目的设计。在V2.0中CCSpriteBatchNode替代了CCSpriteSheet。
CCSpriteBatchNode对象包含了所有精灵帧的图片纹理。即使它不会绘制,你也必须要把它添加到场景中,例如:
CCSpriteBatchNode* spritebatch = CCSpriteBatchNode::create(&animations/grossini.png&); &
下一步,你需要运用CCSpriteFrameCache实例来确保帧名字对应帧边界。也就是说,图片在哪一块矩形区域中。例如:
CCSpriteFrameCache* cache = CCSpriteFrameCache::sharedSpriteFrameCache(); &
cache-&addSpriteFramesWithFile(&animations/grossini.plist&); &
一旦你的精灵表和帧加载完成,并且精灵表已经被添加到了场景中,你可以通过createWithSpriteFrameName方法来创建精灵。并且通过addChild要添加到精灵表中:
m_pSprite1 = CCSprite::createWithSpriteFrameName(&grossini_dance_01.png&); &
spritebatch-&addChild(m_pSprite1); &
addChild(spritebatch); &
createWithSpriteFrameName 方法将会从grossini.plist中找到对应的坐标以及矩形区域,之后再裁剪grossini.png的纹理成一个精灵帧。
现在我们创建一个CCArray对象并且天剑所有的帧动画进去。在这个动画的例子中,我们发现所有的14帧都有相同的大小,所以我们可以用一个嵌套的循环遍历它们,并且当完成添加14帧之后结束掉循环。
CCArray* animFrames = CCArray::createWithCapacity(15); &
char str[100] = {0}; &
for(int i = 1; i & 15; i++) &&
& & sprintf(str, &grossini_dance_%02d.png&, i); &
& & CCSpriteFrame* frame = cache-&spriteFrameByName( str ); &
& & animFrames-&addObject(frame); &
最后,我们需要创建一个CCAnimate动作实例来运行CCSprite。下面我们可以在CCRepeatForever动作中包裹CCAnimate动作来让它一直执行下去,像这样:
CCAnimation* animation = CCAnimation::createWithSpriteFrames(animFrames, 0.3f); &
m_pSprite1-&runAction( CCRepeatForever::create( CCAnimate::create(animation) ) ); &
四、文件动画
CCAnimateCache能够加载一个描述一批节点的xml/plist文件,包括帧名和他们的矩形区域。这个借口非常容易使用。
CCAnimationCache *cache = CCAnimationCache::sharedAnimationCache(); // 缓存在cocos2dx中一直是单例模式 &
cache-&addAnimationsWithFile(&animations/animations-2.plist&); &
CCAnimation animation = cache-&animationByName(&dance_1&); &
CCAnimate animate = CCAnimate::create(animation); &
sprite-&runAction(animate); &
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'

我要回帖

更多关于 按键精灵后台鼠标点击 的文章

 

随机推荐