Browse > Home > Archive: 六月 2010

| Subcribe via RSS

另类Flash程序中PNG图片素材瘦身方法

六月 27th, 2010 | 10 Comments , 1 views | Posted by flashlizi in Flash CS3/AS3

在Flash游戏开发过程中,我们会用到大量的png图片资源。它的好处大家都知道,具有alpha通道,可以背景透明,因此它也成为flash游戏图片格式的首选。但是它的缺点就是较大的复杂图形的png的尺寸往往比较大,现在提供一个方法来瘦身大尺寸的png图片。

为了方便演示,先看下面一张png图片,这张图片的大小为60k。

然后大家看下面一张jpg图片,它的背景是黑色,上半部分就是我们上面的png图片,而下半部分则是把这个png图片的填充为纯白色的效果,而这张jpg图片因为没有透明图层,因此大小要比上面的png图片小很多,只有30k。(要制作这样的图片很简单:把png导入ps中,修改高度为2倍,增加一个纯黑色的背景层,再选中png图层选区,填充一个纯白色的图层并移动到图片的底部就ok了。)

那么我们怎么把这张jpg图片实现png图片的透明效果呢?这里我们就要用到BitmapData类了。假设我们已经将上面的jpg图片加载到我们的flash中来的BitmapData为jpgBmpData,那么下面的代码就可以实现png透明效果:
var bmp:BitmapData = new BitmapData(jpgBmpData.width, jpgBmpData.height / 2);
//复制图片的真实像素区域
bmp.copyPixels(jpgBmpData, new Rectangle(0, 0, bmp.width, bmp.height), new Point());
//复制图片的下半区域的红色通道到新图的alpha通道里来实现透明
bmp.copyChannel(jpgBmpData, new Rectangle(0, bmp.height, bmp.width, bmp.height), new Point(), BitmapDataChannel.RED, BitmapDataChannel.ALPHA);
//清除原始图片内存
jpgBmpData.dispose();
jpgBmpData = null;
//得到透明图片后就可以任意处理了
var logo:Bitmap = new Bitmap(bmp);
addChild(logo);

至此大功告成了,flash中的效果截图如下:

最后要注意的是,并不是所有png图片都适合这种方式,要在速度和性能之间取得平衡才是最佳方案。

补充说明:一些朋友反映文中的演示png图片如果压缩成png8或者在flash中导出再使用就已经能得到20k左右压缩结果。是的,确实如此。当初看了一些植物大战僵尸的素材就随便选了这张简单的图来做演示,并没有考虑那么多。而事实上,明白的人应该知道,此文旨在演示一种方法,而且这种方法在传统游戏中也有使用。如果认为这种方法对你没有实用价值,那非常抱歉。

周期定时器:一个Flash Player10.1中不得不关注的特性

六月 22nd, 2010 | No Comments , 1 views | Posted by flashlizi in Flash CS3/AS3

在Flash Player 10.1中,Adobe引入了一个全新的Periodic timer定时器概念,它可以改善浏览器中swf内容的CPU使用。在浏览器中的swf文件在不可见状态下(如窗口最小化,隐藏标签tab或页面滚动到swf文件以外的区域)会自动调节以降低资源消耗。(注:之前的Flash Player版本虽然不会渲染图形,但仍然在全速运行AS脚本,音视频编码解码等。)具体改变如下:

可见状态下:
1)SWF的帧频frameRate会被限制和校准为Jiffy时间模式(如最高60fps),但是目前的10.1 beta3仍然保留最高120fps的限制,这在正式版中将会被改变。
2)计时器(AS2中的Interval和AS3中的Timer)也会校准为Jiffy。
3)LocalConnection也同样会被校准。因此消息从一个swf文件到另一个swf文件至少需要33ms(也有说是40ms)。
4)Video不会做改变,他们可以在任何帧频下播放而不受影响。

不可见状态下:
1)SWF的帧频被锁定为2fps,不进行任何渲染。
2)计时器(AS2中的Interval和AS3中的Timer)被锁定为最多2次/秒。
3)LocalConnection也被锁定为最多2次/秒。
4)Video视频解码(不渲染和显示)只占用CPU空闲时间。
5)为了兼容音频,当swf中有音频在播放的时候,swf的帧频会被调整为8fps,同样swf中计时器和LocalConnection也做相应调整。

应该说这个特性非常有利于网络上flash应用的普及,但是也存在着潜在的风险。比如某些情况下,我们的应用程序需要在不可见的时候仍然保持着正常的运转,比如计时器的正确运行,某些事件按时发生,某些下载任务及时进行等等。当swf的帧速下降到2fps的时候,其影响是显而易见的。因此我们需要在swf不可见的时候仍然保持较高或者正常的帧速。目前有两种解决方法:

利用播放一个音频来使swf在不可见状态下维持8fps:
var gs:Sound = new GhostSound();
gs.play(0, int.MAX_VALUE, new SoundTransform(0));

用js的setInterval方法去调用swf的ExternalInterface.addCallback的方法,从而间接实现一些在不可见状态下必须全速运行的一些动作:
setInterval(callSWF, 50);
function callSWF()
{
var swf=document.getElementById("swfID");
if(swf)swf.execSomeMethod();
}