Browse > Home > Archive by category 'Flash CS3/AS3'

| Subcribe via RSS

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

六月 27th, 2010 | 6 Comments , 225 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 , 406 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();
}

元标签注入式MVC框架: InjectMVC

五月 31st, 2010 | No Comments , 179 views | Posted by flashlizi in Design Pattern, Flash CS3/AS3

什么是依赖注入(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)

Debug flash apps with firebug

三月 26th, 2009 | No Comments , 613 views | Posted by flashlizi in Flash CS3/AS3

大家应该都有用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下载>>>

用MSNContact Library获取MSN联系人列表

二月 25th, 2009 | 4 Comments , 857 views | Posted by flashlizi in Flash CS3/AS3

这是最近在做的一个项目中的一部分,功能就是根据你的MSN帐户和密码获取MSN好友列表。不过要注意因为此组件需要连接微软的MSN远程服务,所以会有安全沙箱问题,在debug状态或者添加了全局安全设置之后就不会报安全错误,当然最适合在AIR项目中使用了。
点击下载SWC组件>>

使用方法:
import com.riaidea.msn.MSNAccount;
import com.riaidea.msn.MSNContact;
var email:String = "your email address";
var password:String = "your msn password";
var account:MSNAccount = new MSNAccount(email, password);
account.addEventListener(Event.INIT, initHandler);

function initHandler(evt:Event):void
{
account.removeEventListener(Event.INIT, initHandler);
//在MSNAccount发出INIT事件后,即可用getContacts()方法获取Contact数组列表。
//数组的每个元素都是一个MSNContact对象,包含id,email,nickname三个属性。
for each(var c:MSNContact in account.getContacts())
{
trace(c); //或trace(c.id, c.email, c.nickname);
}
}

AS3类: BigInt(大整数)

二月 22nd, 2009 | No Comments , 1,715 views | Posted by flashlizi in Flash CS3/AS3

最近在一个项目中计算一个64bit的密钥key的时候,需要用到超过64位的数字运算。大家应该都知道,在AS3.0中,Number数据类型的范围是最大的,它可以使用52位来存储有效位数,即53位以上的数字只是近似值。因此需要到用到Big Integer(大整数),像目前的很多的RSA加密算法就建立于超过512位甚至更大的大数运算。网上找了一下只有hurlant的crypto加密库里面有com.hurlant.math.BigInteger这个类,可惜遗憾的是,这个类还是有位数限制,不能满足我的需求。因此我改写了一个BigInt的js类库,实现了简单的加减乘除取模等运算。由于时间比较紧,改写的代码比较乱,不过还是很好用的,现在分享给需要的朋友。点击下载>>>

下面是使用示例:
var x:BigInt = new BigInt("1234567890123456789012345678901234567890");
var y:BigInt = new BigInt("0x123456789abcdef0123456789abcdef0");
var z:BigInt = x.clone();//复制
z = x.negative();//取相反数
z = BigInt.plus(x, y);//加法
z = BigInt.minus(x, y);//减法
z = BigInt.multiply(x, y);//乘法
z = BigInt.divide(x, y);//除法
z = BigInt.mod(x, y);//取模
var compare:int = BigInt.compare(x, y); //大数比较 return -1, 0, or 1
var num:Number = x.toNumber(); //转为Number类型

Tags:

DebugLite: Make your debug life more easy!

一月 23rd, 2009 | No Comments , 416 views | Posted by flashlizi in Flash CS3/AS3

An agile actionscript3 debugger, you can play Eval function at first.

How to play Eval?

You can use actionscript code to access instances in this flash file, the available instances are main, main.tf, main.btn, main.check.  So you can try these actionscript codes in Eval box:
trace(main.tf.text,main.btn.label,main.check.selected);
main.btn.label=main.check.selected?"YES":"NO";
main.btn.dispatchEvent(new MouseEvent(MouseEvent.CLICK));

(note: enter these code into eval box in bottom, click eval button to see result.)

Please visit project homepage for more information.

Project homepage: http://code.google.com/p/debuglite/

Tags: , ,

GlowTween:一个发光的效果类

九月 9th, 2008 | 6 Comments , 902 views | Posted by flashlizi in Flash CS3/AS3

源文件(FlashDevelop项目)下载:

点击下载此文件

Camera.getCamera()的Bug

九月 8th, 2008 | No Comments , 575 views | Posted by flashlizi in Flash CS3/AS3

帮助文档上说:“如果 getCamera() 返回 null,则表明摄像头正由另一个应用程序使用,或者系统上没有安装摄像头。 ”而实际上是,只要系统上安装了摄像头,getCamera()都能返回摄像头,而不是返回null。搜索发现已经有人把这个bug报告给了adobe,不过到了flash player 10 依然没有修正。

另外,帮助文档说使用names.length来确定是否安装了任何摄像头,其实这个也是不能完全信任的。一个明显的bug就是不管你用getCamera()或是names.length都无法在Firefox中准确确定是否安装了摄像头,在安装了摄像头驱动但却没有连上摄像头或临时拔掉摄像头的情况下,上面两种方法都会返回已安装摄像头。不过,在IE下是正常的。

还有,如果用户安装了电视捕捉卡之类的,同样有可能被识别为camera对象,但实际上是无效的camera。

这里还有一些在使用camera的时候值得注意的问题:

Tip 1.

When initiating a connection to the Camera it’s best to do this through the Microphone class. Sounds odd I know! The reason for this is when this code is called :

var camera:Camera = Camera.getCamera();
ns.attachCamera(camera);

there’s a hang just after the allow button is selected on the security dialog panel. This is rationalled in the Adobe Flash help as ‘Scanning the hardware for cameras takes time’. So it’s best to trigger the security panel via

var microphone:Microphone = Microphone.getMicrophone();
ns.attachAudio(microphone);

then listen for the Status Event of UnMuted or later in your application call

var camera:Camera = Camera.getCamera();
ns.attachCamera(camera);

There will always be a delay on this code ns.attachCamera(camera); but at least via activating the Microphone first you won’t get a bug like delay of the security panel not disappearing immediately after the allow button is pressed.

Tip 2.

When recording to a Flash Media Server make sure the camera has activity via the Activity Status Event before publishing the stream. Otherwise you may get a static or black frame at the beginning of the recorded stream.

Tip 3.

To disable/turn off the Camera after a recording is complete do so via :

ns.attachCamera(null);

Though this is actually documented for AS3 it wasn’t in AS2. Once this has been done the Camera will need to be reconnected for a new recording and users will experience this delay again as the Camera starts as mentioned above.

Tip 4.

When embedding your Flash do not change the wmode from default. Otherwise you will get problems on specific browser configurations i.e. Firefox PC . These problems include that the allow button on the security dialog box will not hide on click.

Tip 5.

When detecting wether the user has a web camera you can’t rely on Camera.names.length(). This is because there are scenarios whereby devices will appear in the list which may not be webcameras but devices like TV capture cards and can not be used as a camera. The solution for this is when the camera is attached via

var camera:Camera = Camera.getCamera();
ns.attachCamera(camera);

Then add a time out catch which can be cleared via the camera’s activity event, so that if camera activity occurs within the time out of say 5 seconds then clear the timeout. Otherwise if the timeout happens handle the error scenario.

Tip 6.

Further to the above it’s good at the point of displaying the error message to give the user an option to fix this problem. This is because it may simply be a matter of the user changing the default camera selected. This can be done via adding a button and firing the Camera devices security dialog by the following :

Security.showSettings(SecurityPanel.CAMERA);

It’s interesting to know that when the user is selecting options from the Camera devices list it’s possible to detect wether the option selected is actually a Camera. Once again this is done via camera.activityLevel>0 on the Camera’s activity event. Sadly there is not yet a reliable way to detect when the dialog panel close event occurs. So with this in mind when the user has picked a camera, you should make a noticible visual change somewhere behind the dialog box (and overlay screen) so the user will proceed to the close button – happy days.

慎用正则表达式RegExp

八月 7th, 2008 | No Comments , 367 views | Posted by flashlizi in Flash CS3/AS3

AS3中的正则表达式效率并不高,在很多时候如果用其他方法能实现的话尽量不要用正则,所以String的replace、search、match如果有替换方法的话尽量不要用它们,比如用split&join方法代替一般replace。当然在一些用普通方法不好实现的复杂问题中用正则还是很好的。

比如下面的例子:
var str:String="i love flash-123";
test1(); //replace test1: 330 iloveflash
test2(); //strip test2: 67 iloveflash
function test1():void
{
var time=getTimer();
for(var i = 0; i < 1e4; i++)
{
str.replace(/\W|[0-9]|_/g, "");
}
trace("replace test1:", (getTimer()-time), str.replace(/\W|[0-9]|_/g, ""));
}
function test2():void
{
var time=getTimer();
for(var i = 0; i < 1e4; i++)
{
strip(str);
}
trace("strip test2:", (getTimer()-time), strip(str));
}
function strip(str:String):String
{
var newstr:String = "";
for (var i:int = 0, len:int = str.length; i < len; i++)
{
var char:String = str.charAt(i);
if (char >= “a”; && char <= "z") newstr += char;
}
return newstr;
}