RIAidea - Focus on Flash/Flex/AIR http://www.riaidea.com/blog Focus on Flash/Flex/AIR Wed, 21 Jul 2010 07:45:28 +0000 http://wordpress.org/?v=2.9.2 en hourly 1 另类Flash程序中PNG图片素材瘦身方法 http://www.riaidea.com/blog/archives/279.html http://www.riaidea.com/blog/archives/279.html#comments Sun, 27 Jun 2010 05:58:58 +0000 flashlizi http://www.riaidea.com/blog/?p=279 在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左右压缩结果。是的,确实如此。当初看了一些植物大战僵尸的素材就随便选了这张简单的图来做演示,并没有考虑那么多。而事实上,明白的人应该知道,此文旨在演示一种方法,而且这种方法在传统游戏中也有使用。如果认为这种方法对你没有实用价值,那非常抱歉。

]]>
http://www.riaidea.com/blog/archives/279.html/feed 6
周期定时器:一个Flash Player10.1中不得不关注的特性 http://www.riaidea.com/blog/archives/273.html http://www.riaidea.com/blog/archives/273.html#comments Tue, 22 Jun 2010 10:26:45 +0000 flashlizi http://www.riaidea.com/blog/?p=273 在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();
}

]]>
http://www.riaidea.com/blog/archives/273.html/feed 0
元标签注入式MVC框架: InjectMVC http://www.riaidea.com/blog/archives/252.html http://www.riaidea.com/blog/archives/252.html#comments Mon, 31 May 2010 15:56:29 +0000 flashlizi http://www.riaidea.com/blog/?p=252 什么是依赖注入(Dependency Injection)?

依赖注入DI在我们编程中其实随处可见,你也可能正在用构造函数注入,setter注入,属性注入等。网上资料随处可以见,在此就不赘述。

什么是元标签(metadata)注入?

有过flex编程经验的可能都知道如[SWF]、[Bindable]、[Event]这样的元标签metadata,flex编译器会根据不同的metadata
会赋予swf特定的属性或者生成特定的as代码来达到我们的目的。 当我们加上-keep-as3-metadata+=MetaName这样编译参数后,编译器会把指定的metadata保存到编译的swf中去。当你再用describeType()方法获取某个有metadata标记的类的XML描述的时候,你会看到你定义的metadata。基于这样的原理,我们便可以利用这一特性实现特殊的注入。

什么是元标签注入式MVC框架?

这是本人根据这种框架的特性命名的。最典型的当属robotlegs (注:可参考eidiot翻译的robotlegs最佳实践)。本框架也是受了它很大的启发,当然InjectMVC有它自己的特点:可注入事件,框架更简单小巧等。(对robotlegs熟悉的朋友可以直接下载demo和源码了解InjectMVC的特别之处)

InjectMVC里Context的作用?

Context是InjectMVC的中枢,有点像puremvc里的Facade,它负责初始化和管理MVC的核心部分Model、View、Controller。 但它跟Facade不一样,它不是单例,可以被实例化。一般来说,一个context定义一个作用域。MVC成员Mediator、Proxy、Command在context范围内的相互通讯和协作。每个context对应一个显示对象application。

Context有一个非常重要的成员Injector,它负责映射和注入属性和事件给Mediator、 Proxy、Command。但你无需直接操作Injector,它已经被封装到context里,你要做的就是注册Mediator、Proxy、Command,并注入你所需要的属性和事件。Context还有一个contextDispatcher,它负责发送和响应context事件。

Context提供以下API供其MVC成员调用来完成彼此的通讯和协作:

* registerMediator
* getMediator
* removeMediator
* hasMediator
* registerProxy
* getProxy
* removeProxy
* hasProxy
* registerEvent
* removeEvent
* dispatchEvent

当你用上面的方法注册一个mediator,proxy或event的时候,InjectMVC会自动注入它们用[Inject]原标签定义的依赖,并保存它们的映射以供其他类注入使用。

比如,我们注册了这么一个mediator:
registerMediator(btn, ButtonMediator);

那么,我们在之的某个Command中便可以注入这个ButtonMediator:
package
{
public class CustomCommand extends Command
{
[Inject]
public var btnMediator:ButtonMediator;
override public function execute()
{
btnMediator.doSomeThing();
}
}
}

更多的文档请到这里参考wiki

InjectMVC相关下载:

* 演示(含源码)
* InjectMVC(源码及SWC)

]]>
http://www.riaidea.com/blog/archives/252.html/feed 0
SWC Maker (update: v0.5) http://www.riaidea.com/blog/archives/232.html http://www.riaidea.com/blog/archives/232.html#comments Sun, 04 Apr 2010 11:16:28 +0000 flashlizi http://www.riaidea.com/blog/?p=232

SWC Maker是我这两天用Flash Builder 4开发的一个AIR 2程序,功能很简单,就是让打包AS3成SWC库变得更简单和更容易控制。使用步骤也很简单:

1. 在编译选项里配置你的Flex SDK路径;
2. 指定一个swc的输出目录和名字;
3. 添加或删除要打包的as3源文件(.as文件);
4. 添加或删除项目引用的swc类库(.swc文件);
5. 编译,查看结果。

目前功能比较简单,下一个版本将添加合并swc文件等功能,如果有什么bug或功能需求,都可以提出来。
目前最新版本0.5,更新日期:2010-5-18。
特别注意:更新程序运行时版本为AIR 2 RC(因最新的AIR 2 RC版上不能运行AIR 2 beta2的应用程序,因此如果你此前安装有SWCMaker0.4以前的版本,请到控制面板里卸载后再安装0.5版)

更新内容:
* 添加swc工程管理功能
* 添加语言支持(中文和英文)
* 界面优化

点击下载 SWCMaker0.5(本程序需要AIR 2 RC以上才能运行)

]]>
http://www.riaidea.com/blog/archives/232.html/feed 8
一个新的Flash Media Server http://www.riaidea.com/blog/archives/227.html http://www.riaidea.com/blog/archives/227.html#comments Wed, 31 Mar 2010 05:34:10 +0000 flashlizi http://www.riaidea.com/blog/?p=227 ProcessOne刚刚发布了他们的一款用erlang编写的Flash媒体服务器OneTeam Media Server。尽管这次发布的版本功能不像FMS或Red5那样全面,但他们2年前就已经开始开发这个项目了,因此据说性能不错。

它的主要特性有:
1. 支持流式播放实时或已录制好的媒体内容
2. 支持录制实时内容
3. 支持AS3 SharedObject 共享对象
4. 支持Clustering集群
5. 支持用Erlang/OTP编写应用程序模块

目前,OMS还不支持RTMPT。OMS是开源程序,不过因为它不支持Windows系统,所以我还没有时间去尝试。有兴趣的朋友可以去下载试试看。

]]>
http://www.riaidea.com/blog/archives/227.html/feed 0
Gumbo Skinning:强大的Flex4组件皮肤自定义功能 http://www.riaidea.com/blog/archives/218.html http://www.riaidea.com/blog/archives/218.html#comments Tue, 09 Jun 2009 13:39:49 +0000 flashlizi http://www.riaidea.com/blog/?p=218 Flex4与flex3相比有着非常大的变化,而全新的组件皮肤自定义(Gumbo Skinning)最能集中体现flex4的优点。组件功能逻辑与显示分离,布局独立于组件,统一的组件皮肤自定义方式,再加上FXG(Flex Graphics)强大的绘图功能,我们甚至可以抛弃PS、CS3等工具,完全用MXML定制出非常漂亮的组件。

下面是我今天做的一套flex4的组件皮肤,无任何外部图形,大家可以看一下flex4 skinning的效果(需要安装flash player10):


点击下载源文件>>>

]]>
http://www.riaidea.com/blog/archives/218.html/feed 0
Flex 4系列:认识flex 4中的命名空间namespace http://www.riaidea.com/blog/archives/210.html http://www.riaidea.com/blog/archives/210.html#comments Thu, 04 Jun 2009 09:17:02 +0000 flashlizi http://www.riaidea.com/blog/?p=210 Flex 4(gumbo)定义了如下3个命名空间:

1、xmlns:fx=”http://ns.adobe.com/mxml/2009″
这是MXML 2009版的命名空间,它包含了AS3的最顶层(top-level)的基本元素,如Object、Array、Boolean、String、Number、Vector、XML等,详细列表可参看Flex SDK下的framwork目录下的mxml-2009-manifest.xml清单文件。另外,它还包括了一些MXML编译器的标签,如<fx:Script>、<fx:Style>、<fx:Binding>、<fx:Metadata>、<fx:Component>、<fx:Declarations>等。

2、xmlns:mx=”library://ns.adobe.com/flex/halo”
这是Helo组件的命名空间,它包含了所有mx包里的组件。详细列表可参看Flex SDK下的framwork目录下的halo-manifest.xml清单文件。

3、xmlns:s=”library://ns.adobe.com/flex/spark”
这是Spark组件的命名空间,它包含了所有spark包和flashx(新的文本布局组件textLayout)包里的组件。另外,为了方便,它还包含了mx包里的RPC相关的类和states、graphics、effect等,当然你仍然可以使用mx命名空间来使用这些类和组件。详细列表可参看Flex SDK下的framwork目录下的spark-manifest.xml清单文件。

如果你用gumbo来开发或编译flex3的项目的时候,你仍然可以使用flex3的MXML命名空间xmlns:mx=http://www.adobe.com/2006/mxml,但是它不能和MXML 2009的fx命名空间混合使用。

想了解更多内容的话,你可以参看MXML 2009说明书

]]>
http://www.riaidea.com/blog/archives/210.html/feed 0
创建高性能AIR程序的几点提示 http://www.riaidea.com/blog/archives/207.html http://www.riaidea.com/blog/archives/207.html#comments Fri, 22 May 2009 03:01:25 +0000 flashlizi http://www.riaidea.com/blog/?p=207 1、尽量降低应用程序的帧频frameRate。如12,7等。
2、动态改变frameRate来适应程序的需要。当需要展示一个动画的时候,可以临时增加帧频来让动画更加平滑顺畅,动画完成后再把帧频降低。另外,当AIR程序在后台运行的时候,可以把帧频调至0.1甚至0,并临时注销一些ENTER_FRAME或Timer事件处理器,这样能有效降低AIR程序的空闲资源的占有。
3、尽量少用ENTER_FRAME事件,或者用Timer代替。合并可能的Timer,减少同时处理Timer的数量。

]]>
http://www.riaidea.com/blog/archives/207.html/feed 0
用Flex的编译参数实现AS3程序的自身预加载(Self Preloading) http://www.riaidea.com/blog/archives/191.html http://www.riaidea.com/blog/archives/191.html#comments Mon, 06 Apr 2009 15:55:45 +0000 flashlizi http://www.riaidea.com/blog/?p=191 记得在很早的时候,我在blueidea上写过一个关于as3自身加载的帖子,基本思想和as2中的原理类似,而且还曾被人批评为帧的概念太根深蒂固,as3中要完全抛弃frame。今天,我的一个flashdevelop的as3项目需要做个loading,我不觉得一个小swf去加载大的swf文件是一种很好的loading解决方案。 因为用的是flex sdk,没法像flash CS3那样创建帧,又不想创建一个fla文件,所以原来的办法似乎没法用了。

于是我翻出以前bit-101上的一片经典的as3自身加载的文章:Preloaders in AS3,仔细看看后,发现原来的想法是正确的,只不过在flex中靠的是元数据标签Frame来增加一个工程关键帧类factoryClass,而这个类在flex项目中默认为mx.managers.SystemManager,并由此控制flex程序的preloading实现。说白了,就是flex程序的其实都是2帧,第一帧默认是SystemManager类的实例,第二帧才是我们的Application文档类mxml。再进一步查看flex的as3 compiler的源程序,也证实了这点。

可是,当我用元数据标签Frame来加入preloading的时候,编译后的swf文件尺寸陡增,原来当用元数据标签Frame加入factoryClass的时候,就会编译很多flex框架类到swf中来,显然这不是我所期望的,这个方法也行不通。但用双帧原理来做preloading是显然的,因此问题的关键便在于如何创建一个双帧的swf。

当我在flex的as3 compiler的源程序中寻找的时候,突然在flex的编译程序mxmlc的编译参数中看到了一个高级可选参数frames.frame,搜索后找到这个参数在flex-config.xml中的具体用法:
<frames>
      <!-- frames.frame: A SWF frame label with a sequence of classnames that will be linked onto the frame.-->
      <!-- frames.frame usage:
      <frame>
         <label>string</label>
         <classname>string</classname>
      </frame>
      -->
</frames>

这个参数用mxmlc的cmd命令行参数模式为:
-frames.frame label classname

于是我在flashdevelop的项目属性的compiler options里的Additional Compiler Options里加入是一个已有但并未编译到文档类里的类FrameTwoClass:
-frames.frame FrameTwoClass FrameTwoClass
果然,在编译后的swf文件的classes里可以看到一个Frame 2: FrameTwoClass的类,因此便很容易知道,这个参数可以帮我们创建帧并链接到一个指定的类。

到这里为止,我想大家应该都差不多已经知道怎么实现self preloading了吧。创建一个Preloading类并设置为文档类,把我们真正的主程序Application类用刚才的参数frames.frame编译到第二帧上。在Preloading类中用enterframe事件监听loaderInfo的bytesLoaded和bytesTotal从而显示加载进度,当加载完后,利用反射方法getDefinitionByName()来创建真正的主程序Application类的实例,大功告成!

点击查看 demo源文件

]]>
http://www.riaidea.com/blog/archives/191.html/feed 5
Debug flash apps with firebug http://www.riaidea.com/blog/archives/183.html http://www.riaidea.com/blog/archives/183.html#comments Thu, 26 Mar 2009 10:08:03 +0000 flashlizi http://www.riaidea.com/blog/?p=183 >> ]]> 大家应该都有用firebug的经验,现在提供2个类Console和Trace,Console可以将指定的debug的内容输出到firebug的控制面板,Trace则可以在firebug的console中trace页面中的flash里的对象和属性等。使用示例如下:
package
{
import flash.display.Sprite;
public class Main extends Sprite
{
public var version:String = "version 1.0";
public var info:Object = { name:"debug_demo", author:"alex", date:"2009-3-26" };
public function Main():void
{
Console.log("This a flash debug demo!");
Console.dump(info);
Trace.bind('main', this);
}
}
}

上面示例在firebug中的输出和trace截图如下:
firebug_screenshot

源文件和Demo下载>>>

]]>
http://www.riaidea.com/blog/archives/183.html/feed 0