除了一些基本的OOP思想之外,我认为一个优秀的ActionScript程序员还应该具备:
- JSFL的编写能力 - 如果要你把300个类元件绑定好相应类文件输出,你难道会一个一个去改Linkage?
- 正则表达式的运用 - 无论是查代码还是实现功能,正则太重要!
- 支持宏的文本编辑器的使用 - ActionScript代码的整齐性非常好,这给宏提供了极大的用武之地
- 熟练使用Flash Authoring Tool - 有些事情用Shape画不如用Flash画。
- 知道Refactor - 命名规范不行的开发者更要善用Refactor
- 知道Reference - 知道你的类或者对象都在哪
- SVN - 一个人做项目用SVN也是有必要的。
- 较好与人沟通的能力 - AS3和AS1、2不同,讲究合作和谐,而不是单兵作战。
最近为CPU和内存占用的细节努力不少,自己也折腾出了一个检测器,用于实时检测FPS(实际上可以算是检测CPU)和内存占用情况。
使用方法,在application的Document Class(或者Application Class)上构建一个检测器实例(MonitorKit)并addChild即可,所含参数比较简单,不再一一赘述:
var monitor:MonitorKit = new MonitorKit(MonitorKit.MKMODE_T); addChild(monitor);
效果图如下:
MonitorKit类如下:
package com.as3blog.utils{
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.Event;
import flash.system.System;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
import flash.utils.getTimer;
public class MonitorKit extends Sprite{
public static const MKMODE_T:String = "MKMODE_T";
public static const MKMODE_B:String = "MKMODE_B";
public static const MKMODE_L:String = "MKMODE_L";
public static const MKMODE_R:String = "MKMODE_R";
public static const MKMODE_TL:String = "MKMODE_TL";
public static const MKMODE_TR:String = "MKMODE_TR";
public static const MKMODE_BL:String = "MKMODE_BL";
public static const MKMODE_BR:String = "MKMODE_BR";
private static var stageInstance:Stage;
private var lastTime:uint = getTimer();
private var frames:Number = 0;
private var monitorKitTextField:TextField;
private var mode:String;
private var textColor:uint;
private var backgroundColor:uint;
private var transparent:Boolean;
public static var delay:Number = 0;
public function MonitorKit(_mode:String = MKMODE_T,
_transparent:Boolean = true,
_textColor:uint=0xffffff,
_backgroundColor:uint=0x000000) {
mode = _mode;
transparent = _transparent;
textColor = _textColor;
backgroundColor = _backgroundColor;
// Initialize it when rendered on the stage.
addEventListener(Event.ADDED_TO_STAGE, initMonitorHandler);
}
private function initMonitorHandler(event:Event):void {
// Unregister the event handler
removeEventListener(Event.ADDED_TO_STAGE, initMonitorHandler);
stageInstance = this.stage;
monitorKitTextField = new TextField();
monitorKitTextField.selectable = false;
monitorKitTextField.background = transparent;
monitorKitTextField.textColor = textColor;
monitorKitTextField.backgroundColor = backgroundColor;
monitorKitTextField.autoSize = TextFieldAutoSize.LEFT;
var format:TextFormat = new TextFormat();
format.font = "Courier New";
format.size = 15;
monitorKitTextField.setTextFormat(format);
monitorKitTextField.defaultTextFormat = format;
monitorKitTextField.text = "[ Loading... ]";
addChild(monitorKitTextField);
stageInstance.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
public function enterFrameHandler(evt:Event):void {
frames++;
var currentTime:uint = getTimer();
var deltaTime:uint = currentTime - lastTime;
var fps:Number = frames / deltaTime * 1000;
monitorKitTextField.text = "FPS: " + fps.toFixed(1);
monitorKitTextField.appendText("\nMem: " + Number(System.totalMemory/1024/1024).toFixed(3)+"(M)");
frames = 0;
lastTime = currentTime;
// Replace the monitor object
switch (mode) {
case MKMODE_T:
monitorKitTextField.x = stageInstance.stageWidth / 2 - monitorKitTextField.width / 2;
monitorKitTextField.y = 0;
break;
case MKMODE_B:
monitorKitTextField.x = stageInstance.stageWidth / 2 - monitorKitTextField.width / 2;
monitorKitTextField.y = stageInstance.stageHeight - monitorKitTextField.height;
break;
case MKMODE_L:
monitorKitTextField.x = 0;
monitorKitTextField.y = stageInstance.stageHeight / 2 - monitorKitTextField.height / 2;
break;
case MKMODE_R:
monitorKitTextField.x = stageInstance.stageWidth - monitorKitTextField.width;
monitorKitTextField.y = stageInstance.stageHeight / 2 - monitorKitTextField.height / 2;
break;
case MKMODE_TL:
monitorKitTextField.x = 0;
monitorKitTextField.y = 0;
break;
case MKMODE_TR:
monitorKitTextField.x = stageInstance.stageWidth - monitorKitTextField.width;
monitorKitTextField.y = 0;
break;
case MKMODE_BL:
monitorKitTextField.x = 0;
monitorKitTextField.y = stageInstance.stageHeight - monitorKitTextField.height;
break;
case MKMODE_BR:
monitorKitTextField.x = stageInstance.stageWidth - monitorKitTextField.width;
monitorKitTextField.y = stageInstance.stageHeight - monitorKitTextField.height;
break;
default:
break;
}
}
}
}
Google Group配合GMail可以十分方便、高效地讨论技术问题,为此,建立了一个AS3的邮件组交流技术问题。欢迎喜欢使用GMail的朋友们加入。
web地址:
邮件列表地址:
需要加入者请联系这个邮箱,目前需要邀请才可以加入:
http://code.google.com/p/facebook-actionscript-api/
消息来自7yue。
我看了一下,这个库最初由Jason Crist创立,之后Adobe参与联手开发。直接看看源码,很靠谱。
- FlashPlayer9内存管理方面比如FlashPlayer10好,尤其是在一些cacheAsBitmap属性为true的复杂图形进行一定幅度的缩放时(即重绘区域足够大)
- FlashPlayer10在性能和内存管理方面均优于FlashPlayer9
- 对于大量复杂的矢量动画,可以采用动态切换stage.quailty的做法让性能缓解(节约CPU占用)
- 看到我这篇博客的读者,如果你认识我一段时间(并认为彼此性格相符)并有兴趣与我合作一个项目,可以看看这篇文章;
Update: 具体项目中,其实可以用扩展Sprite类并建立setter和getter来实现,不再赘述了。
一个头痛了几天的bug终于fixed……我真的是太迟钝了。
最近,遇到这样一个案例,需要以非常缓慢的速度移动某几个物体,而且,这些物体之间还会发生“无损弹性碰撞”(修正主义万恶的高中课本翻译的是“完全弹性碰撞”,我个人觉得Perfect Collision应该为“无损”更易理解吧?)
总之,这些物体的速度(即位移增量)可能灰常灰常小。小到什么程度呢?这么说吧,由于所有的值都是根据动量守恒定律和能量守恒定律(还记得这俩公式的同学你们可以去解放美帝国主义了)算出来的,因为难免出现某一个物体从某一个角度撞击另一个物体之后,两者中某一物体的某一方向(x或者y)上的速度被“中和”掉了。
刚才提到,在计算机语言中,速度即位移增量。ActoinScript的写法则是:
fuckCERNET.x += fuckCERNET.vx; //fuckCERNET is an instance of some dynamic class
当fuckCERNET.vx < 1/20时,Flash则不再渲染。这是根据FlashPlayer万恶的内部机制来实现的。根据我和一些美帝国主义的Flasher讨论,发现,FlashPlayer对物体x、y属性是有保护的:
Implementation public function get x():Number public function set x(value:Number):void
为什么要有这个保护呢,也不难理解:肯定是因为你直接让一个物体移动到0.001的位置上后计算机(FlashPlayer)不知道怎么去显示它:计算机是根据像素组成的,例如我们通常所说的1024×768:即便你的影片再高清再无码,你放到80×60的显示器上还是只能显示4800个点。
虽然“万恶”,但不得不承认FlashPlayer很聪明地回避了这样的问题,甚至,很优雅地通过一个setter来解决了问题,我们可以想象这个setter可能会是:
public function set x(value:Number):void {
if (value < 0.05) value = 0;
// blah .. blah
}
好的,知道这个之后,就好办了。每次速度改变(即碰撞的时候)做一次“最低值判断”:当速度标量(即不考虑方向)不为0(实际上这种情况很小)但小于0.05时,让速度等于0.05就好,可以用我写的这个函数来修正:
private function fixDecimalFractionPosition(value:Number):Number {
if (Math.abs(value) < .05) {
return (value > 0) ? .05 : -.05;
}
return value;
}
根据官方的说明,结合我自己的经验,分享一下:
该用cacheAsBitmap的时候:
- 在一个复杂的矢量化背景图片上存在大量动画;
- 滚动文本区域;
- 基于窗口的应用(你经常会拖拽整块区域)
- 透明遮罩(必须强制使用,否则失效)
不应该用cacheAsBitmap的时候:
- 不要滥用,cacheAsBitamp十分消耗内存,一块250×250像素的矩形进行cache之后可能占掉250kb的内存!
- 目标元素缩放的时候不要使用。
- 目标元素本身最好是静态的,或者不要经常发生翻转、缩放这样的动画
- 不要把矢量图和cache的位图一起混用。
在Flex Builder调试ActoinScript项目时,偶尔会出现这种奇怪错误。原因主要是快速编译造成的:
Severity and Description Path Resource Location Creation Time Id
An internal build error has occurred. Right-click for more information. ****** Unknown
解决方法很简单,按如下步骤:
Help > Product Details. 点击 Configuration Details 按钮, 点击 View Error Log 按钮.
一般地,我们会找到这样的错误:
java.io.FileNotFoundException: D:\projects\google\MyProject.swf (The process cannot access the file because it is being used by another process)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(Unknown Source)
at java.io.FileOutputStream.<init>(Unknown Source)
at com.adobe.flexbuilder.multisdk.compiler.internal.ASApplicationBuilder$MyBuilder.mybuild(ASApplicationBuilder.java:282)
at com.adobe.flexbuilder.multisdk.compiler.internal.ASApplicationBuilder.build(ASApplicationBuilder.java:122)
at com.adobe.flexbuilder.multisdk.compiler.internal.ASBuilder.build(ASBuilder.java:139)
at com.adobe.flexbuilder.multisdk.compiler.internal.ASItemBuilder.build(ASItemBuilder.java:73)
at com.adobe.flexbuilder.project.compiler.internal.FlexProjectBuilder.buildItem(Unknown Source)
at com.adobe.flexbuilder.project.compiler.internal.FlexProjectBuilder.build(Unknown Source)
at com.adobe.flexbuilder.project.compiler.internal.FlexIncrementalBuilder.build(Unknown Source)
at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:624)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:37)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:166)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:197)
at org.eclipse.core.internal.events.BuildManager$1.run(BuildManager.java:246)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:37)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:249)
at org.eclipse.core.internal.events.BuildManager.basicBuildLoop(BuildManager.java:302)
at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:334)
at org.eclipse.core.internal.events.AutoBuildJob.doBuild(AutoBuildJob.java:137)
at org.eclipse.core.internal.events.AutoBuildJob.run(AutoBuildJob.java:235)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)
原因就是表黑的那个文件被FlashPlayer.exe进程打开但没有关闭,因此Flex编译好的新文件无法覆盖这个文件。解决方法非常容易,打开Taskmgr,找到FlashPlayer.exe干掉就好了:)
经过我的多次测试,发现直接引用Flash的SWC包只能获得相应的代码提示,并不能完全解决纯Flex Builder编译的问题。因此,如果你想彻底抛弃FLA,又希望能用Flash CS3的组件,必须先在Flash CS3中导出一个SWC,再将这个SWC引入到Flex的Library Path中。这种解决方案来自大名鼎鼎的moockblog同学:)
As a simple example, let’s assume we want to use the V3 TextArea component in Flex Builder. Here’s the general process we follow:
1) Create a .swc file containing the desired V3 components.
2) Add the .swc file from Step 1 to the Flex Builder project’s Library path.
3) Import and use the component classes.To generate the .swc file in Flash CS3, we follow these steps:
1) Make a new Flash CS3 ActionScript 3.0 .fla file.
2) Drag the desired component(s) to the Library. In this example, we’ll drag the TextArea component to the Library.
3) Choose File > Export > Export Movie.
4) For File name, enter v3components.swf. (We don’t even want the generated .swf, but there’s no other way to get the .swc to compile.)
5) Select a folder in which to save the .swf file.
6) Click Save.
7) In the Export Flash Player dialog, check Export SWC.
Click OK.
The preceding steps generate two files, v3components.swf and v3components.swc, both of which are placed in the folder selected in Step 5.
Now let’s use v3components.swc in a Flex Builder project. Follow these steps:
1) In Flex Builder, select File > New > ActionScript Project.
2) For Project name, enter "V3Test.as".
3) Click Next.
4) For Main source folder, enter "src".
5) For Main application file, enter "V3Test.as".
6) On the Library path tab, click Add SWC.
7) Browse to the v3components.swc file from the preceding procedure.
Click Finish.
9) Update the code in V3Test.as so it looks like this:package { import flash.display.Sprite; import fl.controls.TextArea; public class V3Test extends Sprite { public function V3Test() { var t:TextArea = new TextArea(); t.text = "You're not cookin'"; addChild(t); } } }10) Run the project.
让drawRoundRect抗锯齿的最简单的方法:
让x和y坐标为小数:
this.graphics.lineStyle(0,0,1);
this.graphics.drawRoundRect(10.5,10.5,100,100,20);
今天在FlashSeer的群里面讨论得出的结论,太经典了。平时让我们头痛的小数坐标现在居然能起到这个作用。这样也避免了位图的引入,提高了程序灵活性。