AIR 3.0针对移动设备的高性能渲染方案

  当我们一边正在等待Stage3D的发布时,很多开发者似乎还停留在这个印象中:即使AIR 3.0也无法在移动设备上开发出高性能的游戏。

      而事实上,只需要做一点点的工作,高性能的GPU加速功能已经为我们敞开了大门!

      在这片文章中,我将为您展示跟传统显示列表编程方式相比,能提升5倍以上的性能的优化方案。最终成果将会是一个用IOS5硬件加速的性能更高的渲染引擎(这点在后文跟进…)。

本文说的啥

        Adobe的工程师们在为AIR3.0重新设计GPU渲染模式的任务中做了出色的工作。现在我们开发者只需做很少量的工作,就可以从这些小小的移动设备上哄骗出超乎想象的性能。那么,我们到底需要做些什么呢?

1.在你的app.xml配置文件里找到节点并设置成这样:<renderMode>gpu</renderMode>

2.尽可能地使用位图来呈现你的显示对象

3.在类或应用程序之间缓存共享你的bitmapData

      这看起来是不是有点太简单了?但是请相信我,它绝对不坑爹 。微笑 Bitmap()这个类现在就是被出奇地优化了。在此夸奖一下整个AIR3.0团队,做出了如此惊人的一步改进。

      最 后,总结下来就是:首先使用bitmapData.draw()方法手动绘制你的显示对象,并把bitmapData数据保存在一个共享的缓存或静态属性 上。然后显示一个bitmap来取代你原先的显示对象。实际上,这相当于写一个自定义的cacheAsBitmap功能,不同之处在于使用了共享缓存。

基准测试

      首先,让我们请出我们的好工具–图表!

      我们在一系列的设备上都运行了同一个压力测试程序,结果如下表。每次测试都由包含旋转,透明度和缩放这三种变换的共同部分组成,并在保持跑满30fps的情况下不断添加Sprite显示对象。我们在相同测试条件下比较CPU渲染模式和GPU渲染模式性能。

      您可以点击此处查看HTML版本的测试示例,就能明白我说的是什么了:http://esdot.ca/examples/canvasTests/

您可以清晰地看到它们之间巨大的性能差距。同时,必须要注意到的一点,由于我们使用的仍然是共享BitmapData的位图优化技术,所以针对CPU的测试也是被较好的优化过了的。因此这并不是那种故意让CPU渲染显得性能低下的找茬的测试。

      [更 新]后来有人问我关于使用copyPixels方法的性能。copyPixels的性能将会介于以上两种方式之间。它比传统的显示列表速度快,但是比共享 位图数据方式性能低(而且使用非常不灵活)。随着新的设备出现,更高分辨率的显示屏的使用,copyPixels方法的性能将会越来越落后。

代码示例

      代码示例好吧,说的够多了,下面上代码!

      例子1,假设我有一个含有精美矢量雪球影片剪辑的FLA文件,已经导出了类名为SnowBallAsset。现在我想在GPU模式下以非常高的性能渲染它。

public class SnowBall extends Sprite { //声明一个静态数据变量,这个类的所有实例都可共享它。 protected static var data:BitmapData; public var clip:Bitmap; public function SnowBall() { if(!data) { var sprite:Sprite = new SnowBallAsset(); data = new BitmapData(sprite.width, sprite.height, true, 0x0); data.draw(sprite, null, null, null, null, true); } clip = new Bitmap(data, "auto", true); addChild(clip); //优化鼠标子项 mouseChildren = false; } }

  现在我可以方便地生成尽可能多的SnowBall()了。它们本质上都是完全由GPU加速渲染的。在这个简单的例子里,为了让它看起来正常,要注意你的素 材必须要设置一个相对于0,0点的内部坐标。(但是为了提高5倍的性能,增加的这几行代码是值得的吧?) 下一个例子里,我们将写一个相似的类。但它是可以被重用的,你只需要把你要使用的素材类名传入即可。然后,你有时候可能还希望能缩放素材,但同时保持它的 显示质量。这可以很容易地在上传到GPU之前,通过多倍重新采样的方式实现。

public class CachedSprite extends Sprite { //声明一个缓存数据的静态属性 protected static var cachedData:Object = {}; public var clip:Bitmap; public function CachedSprite(asset:Object, scale:int = 2) { //检测是否已经缓存过对应的素材了 var data:BitmapData = cachedData[getQualifiedClassName(asset)]; if(!data) { var instance:Sprite = new asset(); var bounds:Rectangle = instance.getBounds(this); //可选的操作,使用matrix对素材进行矩阵变换后重新采样, //这样可以让它被缩放后质量还是看起来比较不错。 var m:Matrix = new Matrix(); m.translate(-bounds.x, -bounds.y); m.scale(scale, scale); data = new BitmapData(bounds.width * scale, bounds.height * scale, true, 0×0); data = new BitmapData(instance.width, instance.height, true, 0x0); data.draw(instance, m, null, null, null, true); cachedData[getQualifiedClassName(asset)] = data; } clip = new Bitmap(data, "auto", true); //对Bitmap进行反向缩放,让最终效果看起来尺寸与原始一致 clip.scaleX = clip.scaleY = 1/scale;  addChild(clip); //优化鼠标子项 mouseChildren = false; } }

[更新] 后来因为一系列的留言评论,我已经更新了以上代码,让它也能适用于起始坐标不在(0,0)点的素材。这样能应该能避免任何截边现在了。

   现在我想创建这个类的多少实例就创建多少。第一次实例化这个类时,将会有一次绘制过程,紧接着还有一次将位图上传到GPU的过程。经过这一次实例化的过 程,之后再创建的所有实例,性能上几乎都是免费的。我同样可以将它们scale到2倍大小而察觉不到任何质量损失。不知道我前面是否提到过?不止是 scale,rotation和设置alpha在性能上也同样几乎是免费的。

  使用这个类的素材类型相同的所有实例将会共享同一份位图数据,只要位图数据保持缓存在GPU内,所有共享它的实例,都将运行地无比流畅,这真的就是这么简单!

  要将这项技术应用到SpriteSheet或者多帧的MovieClip上,复杂度实在是微不足道。我相信任何有两把刷子的AS程序员都不会有任何问题的。但我随后还是发一些辅助的类代码上来。

   注意:直接继承一个Bitmap作为素材显示类的方式确实非常诱人,并且还能减少显示列表多余的嵌套。但是我后来发现,在Bitmap外面包裹一层 Sprite会更有好处。首先一点就是Sprite具有鼠标事件,而Bitmap没有(我也明白为什么…)。其次是,在外部包裹一层Sprite可以让你 很容易地在内部重新采样位图数据,然后在内部设置Bitmap的Scale值,而父容器根本不需要关心。

内部细节

  那么,这种方式在底层究竟是怎么运作的?
  1.把renderMode设置为GPU后,当一个bitmapData对象被渲染时,它将会被上传到GPU内作为一个纹理贴图处理。
  2.只要你保持这份bitmapData数据在内存中,纹理贴图就会一直存储在GPU上。(这正是最本质的原因)

  3.当这个纹理贴图处于GPU上时,你将会获得3至5倍的渲染性能提高!(视具体的GPU性能而异)

  4.此时Scale, Alpha, Rotation等等操作都将极度节省开销。

这种方式的亮点之处就在于,你可以继续使用传统显示列表的强大接口。你可以让嵌套项目,缩放,旋转或者淡出都达到极高的渲染性能。这个的好处能让你非常容易地缩放你的应用或者游戏去同时适应各种尺寸屏幕的设备,同时使用标准的AS3布局逻辑。

一些陷阱
  现在还有一些要点需要注意的,GPU模式确实有一些怪癖:

  1.你应该尽可能地保持你的显示列表简洁,在每个地方都尽量减少显示列表嵌套层级数

  2.要完全避免使用blendMode,它们会影响性能。(如果你必须使用blendMode,可以把它先设置到你的显示列对象上,用draw()方法把它缓存下来,然后在bitmap中渲染这个缓存位图数据)

  3.同样的要避免使用滤镜,如果你需要使用一个滤镜,直接用applyFilter()把它应用到bitmapData上,或者应用到显示对象上,再绘制出来。

  在下一篇文章里,我们将会做更多的对比测试。这次会使用含有动画的素材。我们同样也会贴出匆忙中写的一个用于测试SpriteSheet的简单类。

  [更新]:关于SpriteSheet的文章链接在这: http://esdot.ca/site/2012/fast-rendering-in-air-cached-spritesheets

 在上一篇文章中,我展示了如何正确地使用AIR3.0的GPU加速模式,能让你在移动设备上的性能提高500%的方法。现在我们把目标设定为:怎样能以同一种方式,在影片剪辑动画播放上获取更大的性能提升。你感觉性能提升4000%这个数字咋样?

当我第一次看到这个运行结果时我都不敢相信自己的眼睛…我的IPad2竟然跑赢了我3.2Ghz的四核台式机CPU,并且是接近两倍的性能!欢迎来到移动设备GPU加速的世界…

如 果您还没有阅读过之前的那篇文章,简单介绍下将会帮助您明确我们下面用到的技术是什么。总结一下就是:首先,最基本的是要为每种素材(导出类或者嵌入素 材)使用单一的bitmapData实例。我们将bitmapData缓存在类静态属性上,然后这个素材类的所有实例都将共享同一个bitmapData 数据。

以下代码最简洁地表达了它的形式:

public class MyClass { protected static var cache:bitmapData; public function MyClass(){ if(!cache){ cache = createCache(); } //这将只会运行一次.  addChild(new Bitmap(cache)); //Bitmap包装器共享同一份bitmapData   } }

现在不同之处在于,我们要共享一个数组的bitmapData列表,而不是单一的bitmapData。再认真读一遍这句话的意思。好的,我们还要缓存下frameLabels数据,这样就可以使用gotoAndPlay()方法了。

现在实际上就有好几种实现方案了。你可以使用事先导出的PNG的位图序列,或者在运行时通过draw()和gotoAndPlay()方法动态地缓存影片剪辑的每一帧。两种方式各有利弊,但是为了简单起见,我将采用PNG位图序列实现的方式。

第一步:把MovieClip转换为SpriteSheet

第 一步是要确定你的哪些素材要转换为SpriteSheet。任何重复出现的或者长时间在屏幕上呈现的素材,应该转换为SpriteSheet。而对于那些 只短暂显示的,或只有一个实例的素材,你可以直接让普通的方式去渲染它。 这就是GPU渲染模式的好处之一,并不是所有素材都需要缓存为位图。你可以有很多方式取巧(比如直接嵌入导出的动画素材库),你只要优化重要的部分即可。
注 意:在GPU渲染模式下调用Transfroms的相关变换,性能是极其高的,所以如果你只是缩放,旋转或者移动显示对象,是没必要将它的变换过程转换为 SpriteSheet的,直接用Tween操作它即可。虽然会稍微慢一点,但是你可以为GPU节省一大块的内存(想想当年用copyPixels()方 法的时候,你必须要提前绘制好素材旋转的每个角度,才能让它运行的非常快,现在是不是不蛋疼了?哈哈~)

一旦决定了哪些动画素材需要被加速,你就需要将它们转换PNG位图序列了。我们将使用来自gskinner.com的一个小工具Zoe来导出。Zoe会读取一个swf文件,并将它的每一帧都输出为PNG位图。它还将检索时间轴上所有标签,并存储信息到json文件里。
接下来要做的步骤如下:

将你的动画导入FLA文件里,并储存这个FLA到某个位置,然后导出SWF文件。

下载并安装Zoe::http://easeljs.com/zoe.html

在Zoe里打开你刚刚导出的SWF文件,Zoe会自动检测边界,点击“Export”即可。

注意:Zoe是通过测量主时间轴来确定你的SpriteSheet中一共有多少帧。如果你把动画嵌套在一个影片剪辑里是可以的,但是要确保你的主时间轴帧长度要足够包含影片剪辑里的帧长度。

如果一切顺利的话,你现在应该能在素材目录得到一个JSON文件和PNG文件了。转向第二步:

第二步:在Flash中以非常非常高的性能播放SpriteSheet
下一步是加载JSON和PNG文件到Flash里,循环播放它们。然后,我们希望确保所每个特定动画的所有实例都在内存中共享同一份SpriteSheet。正是这个能给我们带来完全的GPU加速。

嵌入JSON和Bitmap非常简单:

[Embed("assets/Animation.png")] public var AnimationImage:Class; [Embed("assets/Animation.json", mimeType="application/octet-stream")] public var AnimationData:Class;

接下来你需要一个类来操作这些对象,然后想办法播放它们。必不可少的一步是分析Zoe导出的JSON文件,然后从大位图里裁剪出校位图序列。你还需要设计一个API来播放这些帧序列,用每帧切换位图的方法,作为你MovieClip的基本API。
我写了一个简单的类来辅助实现这个功能,命名为SpriteSheetClip.

//传入从Zoe导出的数据...  var mc:SpriteSheetClip = new SpriteSheetClip(AnimationImage, AnimationData); mc.gotoAndPlay("someLabel"); addChild(mc); //为了最大化性能,所有缓存的Sprite都必须要手动触发播放  function onEnterFrame(event:Event):void { cachedAnimation.step(); }

SpriteSheetClip 直接继承于Bitmap,并模拟了MovieClip的接口,完整的整个类就不过一遍了,下面代码的核心功能是缓存并裁切传入的SpriteSheet。 注意下这两部分:怎么通过JSON数据获得帧宽度与帧高度和利用getQualifiedClassName()方法获取素材的唯一标识符。剩下的都是简 单的循环了。

public static var frameCacheByAsset:Object = {}; public function SpriteSheetClip(bitmapAsset:Class, jsonAsset:Class){ _currentStartFrame = 1; var assetName:String = getQualifiedClassName(bitmapAsset); //如果已经存在缓存数据就直接使用它,位图数据很可能已经存在于GPU了。  if(frameCacheByAsset[assetName]){ frameCache = frameCacheByAsset[assetName].frames; frameLabels = frameCacheByAsset[assetName].labels; _frameWidth = frameCache[0].width; _frameHeight = frameCache[0].height; } //如果没有缓存过,从bitmap里剪切出帧序列并且转换JSON字符串为对象  else { //rip clip!  var data:Object = JSON.parse(new jsonAsset().toString()); var bitmap:Bitmap = new bitmapAsset(); var spriteSheet:BitmapData = bitmap.bitmapData; _frameWidth = data.frames.width; _frameHeight = data.frames.height; frameLabels = data.animations; var cols:int = spriteSheet.width/_frameWidth|0; var rows:int = spriteSheet.height/_frameHeight|0; var point = new Point(); var l:int = cols * rows; frameCache = []; _currentStartFrame = 1; var m:Matrix = new Matrix(); //遍历所有帧...  for(var i:int = 0; i < l; i++){ var col:int = i%cols; var row:int = i/cols|0;  m.identity(); //Reset matrix  m.tx = -_frameWidth * col; m.ty = -_frameHeight * row; //绘制每一帧并缓存它  var bmpData:BitmapData = new BitmapData(_frameWidth, _frameHeight, true, 0x0); bmpData.draw(spriteSheet, m, null, null, null, true); frameCache = bmpData; } _currentEndFrame = i; numFrames = _currentEndFrame; _frameWidth *= scale; _frameHeight *= scale; //添加帧数据到静态缓存    frameCacheByAsset[assetName] = { frames: frameCache, //Cache bitmapData's  labels: frameLabels //Cache frameLabels   }; } //显示第一帧Show frame 1  this.bitmapData = frameCache[_currentStartFrame-1]; }

现 在,利用这个类,我们能创建同一个动画的多个副本,然后以非常高的性能运行它们。你能够同屏播放100个动画,甚至在最古老的Android设备上。而在 较新一些的设备比如IPad2或者Galaxy Nexus,你可以一次跑满500至800个动画。并且缩放,调整透明度,旋转这些操作性能都非常高。

也 许你在代码里注意到了,出于性能考虑,我的类并不自己实现更新操作。所以如果你调用play()方法什么也不会发生。我让父级对象来负责统一调用它所有的 子项的step()方法,来代替在子项上添加一系列的EnterFrame事件监听,这样一个事件监听就可以代替上百个。

从帧管理功能上来说,这个类仍然还有挺多东西需要完善,如果需要的可以的话可以从附件源码里检出看看。事先声明,代码有一点小bug。我认为这只是一个示例参考而不是能投入生产使用的代码,但是你可以随意使用。

注:在工作流方面,一旦安装,这是相当不错的。Zoe会记住所有项目的设置,然后只需话大约10秒钟就能够完成Fla动画的更新并重新导出。

接下来让我们运行一些基准测试,来看看我们到底能跑多少个动画…

基准测试!
在这次测试中,我将在保持帧率30fps的情况下不断添加动画数量,直到帧率下降。

您可以下载这个Flash Builder项目自己运行一下:MobileRenderTests.zip

我 将SpriteSheetClip与普通影片剪辑以及CopyPixel方案做了对比测试。测试结果令人影响深刻,SpriteSheetClip运行的 动画超过了普通影片剪辑40倍,并且超过CopyPixels方案接近10倍。这比之前的所谓的Flash中“最快的”渲染方案还高出数量级的倍数。测试 结果如下表:

 

在 这里你可以看到,即使更古老的Android设备比如Nexus One,都能获取非常不错的测试结果。在30fps的帧率下同时播放150动画的性能足够制作几乎所有的2D游戏。而对于较新的一些设备,测试结果变得令 人印象非常深刻,在保持30fpsd的帧率下iPad 2跑满了735个动画?!

请下载上面提供的完整Flash Builder项目源码,以便在您自己的移动设备上测试运行一下,您可以通过留言评论让我知道运行结果。

关于内存管理的一些建议
最后一件我非常想要强调的事就是内存管理的重要性。因为现在你正在往GPU里载入东西。你需要时刻注意内存的使用。一旦你填满了GPU的内存,它将会强制切换图像纹理数据。如果这个持续发生,它将严重影响你的GPU性能。
这里有一点主要的改变是需要你注意的。这点即使你最终迁移到使用Stage3D也是要注意的。所有被渲染的对象都是一个图像纹理,而刷新纹理的性能消耗是巨大的。你必须清楚明白这个概念,然后以一个聪明的方式专注于管理你的纹理(也就是BitmapData)

好 吧,我们只有有限的内存,但到底多有限呢?我曾看到过对于IOS设备的推荐纹理内存大小是24MB,这对于一个32位的PNG图片来说,结果就是 4096×4096像素的一张大位图(我猜是这样)。所以,如果你能把当前场景用到的所有的bitmapData都填充到这张大位图里,并不超过 4096×4096。你的程序应该能轻松运行在所有IOS设备上。

现在,你可能还注意到一些更古老的Android设备有甚至更低的内存使用限制。所以你要尽可能保持最低的内存占用。
尽力去不断优化你的图像纹理管理,这可能是一个会影响到你渲染性能的最大因素。如果你将花一些时间去优化你的应用,值得你花时间去优化的最大的地方就是最小化你的纹理内存占用。你可以这么做,使用网格重复的图像,或者在组件之间共享位图数据。

我 在写SnowBomber游戏时,应用的一个技巧是根据设备来缩放我的缓存数据。为了让游戏能运行在GPU非常弱的Nexus One上,我把bitmapData都缩放到50%后再缓存它们。这让我即使在Nexus One上也达到了差不多25fps的帧率,这点在之前我是完全无法想象的。这似乎过于简单了,只需在绘制时传入一个简单的matrix对象大小的即可。 瞧,我这就拥有一个运行时动态调整大小的图像纹理了…

原文链接:http://www.cnblogs.com/sevenyuan/archive/2013/01/22/2870934.html

posted @ 2013-02-28 18:45 Tony0322 阅读(42) 评论(0) 编辑

Shawn Blais 让我了解到如何在移动平台上对AS3代码进行优化。他的博客(http://esdot.ca/site/category/blog)只有十来篇文章,但都是些很意思的信息,尤其适合我。这篇文章介绍的是关于图形方面的优化。
      下面三个步骤可以提高程序的性能,其实都围绕一个理论:一切皆bitmap。 或许你可以使用MovieClips 或者 Sprite序列动画,甚至可以继续保持使用Flash的渲染列表来保持代码简单整洁。但真正的图片数据是? Bitmap!一切皆bitmap。

步骤一: 使用GPU渲染
       当你创建一个移动程序的时候,你会找到一个包含所有基本程序设定的文件,叫”application.xml”(或者类似的名字)。其中有一段代码会告诉 移动设备使用CPU还是GPU渲染。大多默认(如FlashDevelop模版程序)会启用CPU渲染,这可能比较合适于矢量图渲染。但使用bitmap 并启动GPU渲染将会使性能大大提高!
打开application.xml并设置:

01.<initialWindow> <renderMode>gpu</renderMode> </initialWindow>

步骤二:降低舞台渲染质量
        AS3舞台渲染质量相对决定了你能渲染的图片多少。不过重点是,即使你设置了舞台渲染质量为低,bitmap的平滑(smoothing)属性仍然有效并且在表现上没多大区别。如此一来我们就没必要浪费CPU在这个地方了。

01.stage.quality = LOW;

  如果你的图片正在加载并想在运行中切换渲染模式(见步骤三),AS3可以允许你运行中改变,像这样:

01.stage.quality = HIGH; 02.convertMySprite(); // 处理函数 03.stage.quality = LOW;

步骤三: 使用Bitmaps,并缓存它们
       这可能是最好的优化方式,我的移动程序都应用上了这种方法。不过只有使用GPU渲染才能达到最佳效果。基本理念就是把全部的bitmap data 缓存到Dictionary里面供之后引用。在GPU渲染模式下,这些纹理数据保存在GPU存储器中。只要是从Dictionary获取的图片资源都是引 用唯一的一份bitmapData,不用耗费新的内存并且创建新的图片速度非常快!
       这种方式特别适合频繁使用的图片,如–提示,小怪,子弹和地图块等。不过我是全部都用上了。
       如果你还想了解更多的细节,Shawn的研究报告有源码和详细的解析。他的代码帮你做了很多自动化的底层,并又由很多人去完善了代码。我自己也做了细微的 调整,现在只要一个类我就可以使用任何我想要的图片资源。导入.PNG文件? 包含Sprite或MovieClip的.SWC?自己定制配置文件? 都不需要!!全自动底层实现~,轻快,使用简单。而且最酷的是:代码非常简短,而且简单易懂。
       说的有点多了,下面是我现在用的类的链接(http://www.andymoore.ca/code/CachedSprite.as)。完全免费使用,最好让我知道你导入了我这个类 。复制粘帖到工程上面就可以马上应用它了。

额外步骤:转换MovieCilps

      我还没试过这一步骤,不过这算是步骤三里的拓展吧。一个工具类(http://esdot.ca/site/2012/fast-rendering-in-air-cached-spritesheets)把MovieClip里面的每一帧都转化为bitmap data缓存(存储到GPU)。如果我最近手头上的游戏有需要动画的话,我将都会用上这个。

缺点
       我发现使用GPU渲染的最大弊端就是你会失去一些实时的filters和blendmodes的表现力。比如你想要一个漂亮的火焰发光效果的时候,预置效 果当然很容易。但是如果你想动态添加一些效果–如添加一些风力效果和文字,那是很难达到满意的效果(使用设备字体,基于spritesheet的渲 染)。如果你也有类似的难题可以来与我商讨,我会找到解决方案的(但不一定都能解决)。
       其次就是深层嵌套的渲染列表会比平时更降低你App的性能。尽量避免过深的渲染嵌套。不过我觉得你已经这样做了
       GPU渲染在非移动平台上并不一定运行结果一样(不包括Stage3D的官方例子)。这意味着当你在电脑中测试运行你的移动app的时候你仍然可以看到 filters和blendmodes的效果(在手机上不一定有)。这会导致一些混乱,特别是一个复杂的app程序在桌面上运行的时候。

优点
       使用我的方法即时是很复杂的游戏场景在用了2年的Nexus手机上依然可以跑的很流畅。我还在iPad上做了1个多小时的性能测试-不断地绘制新的动画(并且不移除它们)。测试最后降到了3FPS并且内存增长正常,app程序也没崩溃。
       最关键的是,在手机设备上这样的性能提升比用blitting要好的多。这意味着基于这3个步骤下来你将获得比Flixel 和FlashPunk 默认渲染引擎更好的性能。
       在大多情况下,在移动设备上由于使用GPU,可能要比电脑上运行起来性能更好。 希望Stage3D会做一些改良,那到时候blitting引擎(如 Flixel和 FlashPunk)可能会比较适合桌面和浏览器平台。

       更多图表,数据和测试报告,详情请查看Shawn的帖子,他认为移动性能提升能达到4000%。

原文链接:如何提高你的移动开发中AS3/AIR性能

英文链接:http://www.andymoore.ca/2012/01/how-to-improve-your-mobile-as3air-performance/

posted @ 2013-02-28 18:17 Tony0322 阅读(59) 评论(0) 编辑

概述
每个游戏或应用都必须有若干的资源——无论是纹理,声音,位图文字,或其它各种对象。这些资源可以是嵌入的(可以理解为所有资源都在一个文件的浏览器游戏)或随游戏进行的(适用于手机游戏保存RAM需要嵌入对象)。
在如何引入资源以不同的方式访问它们有许多选择。AssetManager帮助你做到这些。它是允许你以各种方式添加资源,并且很轻易地调用它们的类。
目前,AssetManager支持下列类型的资源:
·纹理
·纹理图集
·声音
·位图文字

加载资源
比方说你要从硬盘加载一些资源,并从嵌入类加载其它资源。这里是如何通过AssetManager来加载它们。
首先,创建一个具有嵌入声明的类。

public class EmbeddedAssets { // 纹理 [Embed(source="/textures/bird.png")] public static const bird:Class; // 声音 [Embed(source="/audio/explosion.mp3")] public static const explosion:Class; }

对于嵌入资源,遵循这些命名规范:
·嵌入图片的类名必须与文件名完全相同,不含扩展名。这是必须的以便从(图集,位图文字的)XMLs引用不会中断。
·图集和文字XML文件可以使用任意名字,因为它们永远不会通过文件名来引用。
然后让AssetManager实例化资源:

var assets:AssetManager = new AssetManager(); assets.verbose = true; // 对 "bird"纹理和"explosion"声音进行排队
assets.enqueue(EmbeddedAssets); // 对来自特定地址的文件进行排队
assets.enqueue("http://gamua.com/img/home/starling-flying.jpg"); // 对来自硬盘的文件进行排队(仅AIR)
var appDir:File = File.applicationDirectory; assets.enqueue(appDir.resolvePath("music.mp3")); // 对一个目录所有的内容进行递归排队(仅AIR)
assets.enqueue(appDir.resolvePath("textures")); // ->现在加载所有的队列中的资源。当“ratio”等于1时,完成加载.
assets.loadQueue(function(ratio:Number):void { trace("Loading assets, progress:", ratio); if (ratio == 1.0) startGame(); });

你可以用相同的方式来添加纹理图集和位图文字:只要把XML文件和它们引用的纹理加到队列中,它们将会被加载。位图文字将被马上在TextField类中注册。你不能通过AssetManager来访问它们。
调用资源
要调用资源,只要使用类的不同方法。每次资源通过资源不带扩展名的名称或嵌入对象的类名来引用。

// 这将首先搜索命名的纹理,然后再搜索图集
var texture:Texture = assets.getTexture("bird"); // 这将查看所有命名的纹理和图集
var textures:Vector.<Texture> = assets.getTextures("animation"); // 播放声音以及接收控制它的SoundChannel
var explosion:SoundChannel = assets.playSound("explosion");

注意
这个类已经用在Starling下载包中的“Demo”和“Scaffold”项目中。查看这些项目来看看在真实项目中是如何使用的。

原文链接:Starling之资源管理类

英文链接:http://wiki.starling-framework.org/manual/asset_management



发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

(Spamcheck Enabled)