实验:使用AIR技术将复杂代码动画生成位图序列(降低CPU负荷)

在这篇文章中,我们将探讨如何使用AIR技术将复杂代码产生的动画(比如粒子爆炸效果)生成位图序列,然后经过Flash加工做成逐帧动画,以减轻客户端的CPU负荷。

问题的引出:

有时候在Flash项目中,我们会借助代码来生成一些比较炫的效果(比如游戏中常见的爆炸效果,见下面Flash演示),或许我们单独运行这段代码的时候,没有什么问题,但是在真正的客户端,已经有大量的电影剪辑或其它素材在渲染(还不包括大量逻辑判断的代码在运行),此时CPU的负载已经在一个很高的水平,这个时候再运行代码产生的特效,明显效果已经不如预期(看起来会卡,不连贯),如果是一个游戏战斗场景,那么可以想像,多处代码特效都在执行,搞不好Flash Player都会停止响应了。

示例:爆炸动画,由代码生成,鼠标单击播放动画

那么如何解决这个问题呢,我们可以巧妙的做一下“预处理”,将代码生成的特效,以位图序列的方式保存下来,然后我们可以再用代码加载位图合成这段动画,或者干脆通过Flash CS加工为电影剪辑素材在代码中直接调用,这样可以很大程度上缓解上面所说的问题。

具体实现过程:

既然是生成位图,当然会涉及到图片保存的问题,实际上在Flash Player里面我们就可以做到生成图片,但是保存的时候会有麻烦,因为安全限制我们不能隐式的保存图片,所以这里我们要借助AIR技术来实现这个过程。

这里我们将以最新的Flash Builder 4 和 AIR2.0 Beta来完成这个例子,你可以从这里下载Flash Builder4和了解Flash Builder4的详细信息,也可以从这里下载AIR2Beta和了解AIR2Beta的新特性

因为特效我们会应用到不同的场合,所以要求我们生成的图片必须是背景透明(PNG格式),这里我们可以在网上寻找一个PNGEncoder即可。

下面是完成后的效果截图(点击查看大图):

发布后的AIR项目,你可以下载到本地安装体验这个Demo:

http://www.riameeting.com/examples/image_collection_tool/ImageCollectionTool.air

项目源码查看:

http://www.riameeting.com/examples/image_collection_tool/

项目下载:

http://www.riameeting.com/examples/image_collection_tool/ImageCollectionTool.zip

关键代码片段:

  1. protected function createBitmap(...args):void {
  2. if(imgCount < imgNum) {
  3. var bmd:BitmapData = new BitmapData(imgWidth,imgHeight,true,0x000000);
  4. bmd.draw(swfContent,null,null,null,null,true);
  5. var bmp:Bitmap = new Bitmap(bmd,"auto",true);
  6. bmpContainer.addChild(bmp);
  7. var encoder:AsPngEncoder = new AsPngEncoder();
  8. var png:ByteArray = encoder.encode(bmd, new Strategy32BitAlpha());
  9. pngCollection.push(png);
  10. imgCount++;
  11. } else {
  12. swfContent.removeEventListener(Event.ENTER_FRAME,createBitmap);
  13. for each(var item:ByteArray in pngCollection) {
  14. var pngFile:File = saveDIR.resolvePath((pngCollection.indexOf(item)+1)+".png");
  15. var fileStream:FileStream = new FileStream();
  16. fileStream.open(pngFile, FileMode.WRITE);
  17. fileStream.writeBytes(item);
  18. fileStream.close();
  19. }
  20. Alert.show("complete");
  21. saveDIR.openWithDefaultApplication();
  22. }
  23. }

这段代码也比较简单,我们在动画每一帧播放的时候,都截取屏幕,保存为位图,然后用PNGEncoder做一下编码,生成字节数组备用。当图片生成足够的数量的时候,我们就用File类提供的方法,将图片保存的设定的位置。

最后的步骤,熟悉Flash CS的设计师就很清楚了,将这些图片导入到Flash(注意Flash CS4可以提示你是否每一帧放一个图片,即生成逐帧动画),然后发布一下,看看效果吧。

源文件下载:

http://www.riameeting.com/examples/image_collection_tool/bmp_test.fla

riadevID: 
您给予的分值: None 平均分: 7.5 ( 4 票)

技术很好~

学习了。 不过感觉这个方法用在粒子效果上面不太合适,粒子效果的作用就是生成多变的效果,而一旦做成位图导入进去和让美工做个效果图还有什么区别呢

实时渲染的有点: 随

实时渲染的有点:
随机性,多变性

预先渲染的好处是:
对CPU的占用很少,对性能提升很有帮助。

具体就是区分使用的场合。

如果觉得预先渲染的过于单调,可以使用随机方式多生成几遍,然后,将生成的这些都保存好,随机调用。
这样可以整合2个的优点。

其实,可以看出,这些方法最后又回到了 在CPU的运算时间和存储空间的交换上了。
你如果需要低CPU占用率,可以通过大量的存储空间来满足,如果要减小最终文件体积,那就是让CPU实时渲染生成效果。

确实是这样

确实是这样,如果特效对实时交互特性要求很强,那么这种方式将不再适用,这里所解决的是相对只是表现一些特效的动画,比如爆炸,我可以用代码写好,播放5遍,然后做成5组图片,这样在客户端调用的时候,随机显示,这样至少达到了一个效果的伪随机,这其实也是在寻求一种平衡,尽量保证效果的同时,均衡一下系统的负载。

帮了大忙了

帮了大忙了

发表新评论

  • 网页地址和电子邮件地址将会被自动转换为链接。
  • 行和段被自动切分。
  • 您可以使用下面的标签来高亮显示您的评论内容: <code>, <blockcode>. 可以使用"[foo]".旁边显示标签样式 "<foo>" PHP代码可以用这样的区块来包含<?php ... ?> or <% ... %>

更多格式化选项信息

验证区域
系统验证:请回答下面的问题