分类 "ActionScript 3" 的存档.

Use custom tooltip instead of default validate error in flex

We may use the validator  default in flex framework to check user’s input in our application . You may notice that you are probably doing something wrong (as indicated by the red borders around the form items that begin to appear) but you have no idea what you’re doing wrong. Such as the demo site as the following image:
Needless to say. Sometimes having the user switch input devices and exert additional effort in order to see validation error does not make for good usability.

A better alternative is to actually display the error message beside the control component.

Like this :Actually , the default error message is created by ToolTipManager . Thus , we can custom the error tooltip message.
User the function :
ToolTipManager.pcreateToolTip(text:String, x:Number, y:Number, errorTipBorderStyle:String,context:IUIComponent):IToolTip
Now see the demo code:

MXML:
<?xml version=”1.0″?>
<!– tooltips/CreatingErrorTips.mxml –>
<mx:Application xmlns:mx=“http://www.adobe.com/2006/mxml”>
<mx:Script><![CDATA[
import mx.core.UIComponent;
import mx.managers.ToolTipManager;
import mx.controls.ToolTip;
private var myTip:ToolTip;
private var myError:String = "This place should not be empty.";
private function createBigTip(event:Event):void {

var point:Point = new Point();
point = Name.localToGlobal(point);
if(Name.text==""){
if(myTip==null){
myTip = ToolTipManager.createToolTip(
myError,
point.x + Name.width,
point.y,
"errorTipRight",this
) as ToolTip;
}
}else{
if(myTip!=null){
try{
ToolTipManager.destroyToolTip(myTip);
myTip = null;
}
catch (error:Error){}
}

}
}
]]></mx:Script>
<mx:Style>
Application {
backgroundColor:white;
themeColor:white;
}
Panel {
paddingLeft: 5;
paddingRight: 5;
paddingTop: 5;
paddingBottom: 5;
}
</mx:Style>
<mx:Panel width=“600″ height=“200″ title=“ToolTips”>
<mx:Form width=“100%”>
<mx:FormItem label=“Your Name”>
<mx:TextInput id=“Name” width=“140″ errorString=“Empty”/>
</mx:FormItem>
<mx:FormItem label=“Your Password”>
<mx:TextInput displayAsPassword=“true” errorString=“Empty” width=“140″/>
</mx:FormItem>
<mx:FormItem label=“Your Address”>
<mx:TextInput width=“140″ errorString=“Empty”/>
</mx:FormItem>
</mx:Form>
</mx:Panel>
</mx:Application>

How to config global style in popup condition in flex

If we have a popup window in flex application , how can we config the style of the application behind. such as the background color?

You can config the global selector in flex with four attributes:
modalTransparencyBlur,  modalTransparency,  modalTransparencyColora and modalTransparencyDuration.

For Example ( build the css code in <Style> tag or css file ):

CSS:
global {
modalTransparencyBlur: 0;
modalTransparency: 0;
modalTransparencyColor: #dce6e7;
modalTransparencyDuration: 0;
}

Example 2:

CSS:
global {
modalTransparencyBlur: 0;
modalTransparency: 0.8;
modalTransparencyColor: black;
modalTransparencyDuration: 500;
}

Graffiti——ActionScript 3 Bitmap Drawing Library

What is it?

The Graffiti AS3 Bitmap Drawing Library is designed for ActionScript developers to easily integrate drawing functionality into a Flash, Flex or Air project. It is free to use and modify for noncommercial projects.

Graffiti 是一个为actionscript开发者设计的,可以方便地整合绘画功能到flash、Flex或者Air中的as类库。它可以免费使用,但限于非商业用途。

官方地址:http://www.nocircleno.com/graffiti/

目前有两个版本:graffiti_library_2.5 (15)graffiti_library_1.1 (14)

附上三个例子作参考:BasicProject (21)SimpleTextProject (18)  、 AdvancedProject (18)

Features

Feature 2.5 1.1
You choose the size of the Drawing Canvas. Feature Supported in version 2.5 Feature Supported in version 1.1
Built in zoom functionality including ability to drag an obscured canvas with the mouse. Feature Supported in version 2.5 Feature Supported in version 1.1
Add a Vector or Bitmap image above or below the drawing area. Feature Supported in version 2.5 Feature Supported in version 1.1
Keep a drawing history allowing undo and redo. Feature Supported in version 2.5 Feature Supported in version 1.1
Brush Tool with 7 different Brush shapes. Feature Supported in version 2.5 Feature Supported in version 1.1
Brush Tool supports blurring. Feature Supported in version 2.5
Drawing Tools have support for transparent colors. Feature Supported in version 2.5
Line Tool with 3 types of lines, SOLID, DASHED and DOTTED Feature Supported in version 2.5 Feature Supported in version 1.1
Shape Tool with RECTANGLE, SQUARE, OVAL and CIRCLE Feature Supported in version 2.5 Feature Supported in version 1.1
Fill Bucket Tool Feature Supported in version 2.5
Text Tool (Beta) Feature Supported in version 2.5
Get color value for a point on the drawing. Feature Supported in version 2.5 Feature Supported in version 1.1
Easily retrieve drawing data to use with your favorite image encoder. Feature Supported in version 2.5 Feature Supported in version 1.1
UI independent code that fits invisibly into any project. Feature Supported in version 2.5 Feature Supported in version 1.1

ItemRenderer在DataGrid中涉及问题解决

一、设若DataGrid中有个ComboBox的ItemRenderer,操作这个ComboBox,影响其它列的值变化。要使Flash的画面Redraw,需要将绑定到DataGrid上的ArrayCollection执行refresh().

二、涉及到需要通过绑定数据来更新显示多个DataGrid中的ItemRenderer,需要使用ArrayCollection而不是Array.

三、要理解Flex ItemRenderer生成及使用的机制,在Flex开发人员中心中有这么一段话,道出了ItemRenderer的真面目:假设您要显示 1,000 条记录。如果您认为列表控制会创建 1,000 个 itemRenderer, 您就错了。如果列表只显示 10 行, 它会创建约 12 个 itemRenderer-这些足以显示各个可见行, 多出的几个则用于缓冲和性能。列表最初显示行 1–10。当用户滚动这个列表时, 它现在可能显示行 3-12。但那 12 个 itemRenderer 仍在那里: 及时滚动列表后, 也不会新建任何 itemRenderer。

LoaderMax – Smart AS3 Loading(聪明的加载器组件)

LoaderMax是一个新的As3加载系统,它不仅能将swf、mp3、css、video、image、text、binary、xml等文件加载到你的flash应用里,而且加载文件还可以简单得像吃晚餐一样,吃完一个菜,点下一个菜,再吃完一个菜,再点下一个菜。它微小的惊人。事实上,只有其他加载系统的一半,但是却实现了一些特殊的功能,有一些你可能用不到,但是却不想在生活没有它。这里有一些值得注意的特点:
http://www.LoaderMax.com

  • 在要加载的swf里面集成加载器
  • LoaderMax中自动解析XML
  • 为任何加载器定义备用URL
  • 为所有的加载器提供统一的属性和方法设置
  • 可以为图片加载器、Swf加载器、视频加载器设置宽高,当其加载完,图片、swf、视频可以自动匹配你所设定的宽高
  • 一个加载者可以拥有多个LoaderMax实例
  • 实时报告加载进度
  • 在一行代码里设置多个事件监听:new LoaderMax({name:”mainQueue”, onComplete:completeHandler, onProgress:progressHandler, onError:errorHandler});
  • 具有暂停加载及恢复加载的功能
  • 对Flex很友好

源码及Demo:LoaderMax (106)

Flash Game 英文教程

  • 1. Flash Game Development with Flex and Actionscript – Getting Started
  • 2. Flash Game Development with Flex and Actionscript – Double Buffer Rendering
  • 3. Flash Game Development with Flex and Actionscript – Embedding Resources and Adding Game Objects
  • 4. Flash Game Development with Flex and Actionscript – User Input and an Animated Background
  • 5. Flash Game Development with Flex and Actionscript – Adding Weapons
  • 6. Flash Game Development with Flex and Actionscript – Collision Detection
  • 7. Flash Game Development with Flex and Actionscript – Bitmap Animations
  • 8. Flash Game Development with Flex and Actionscript – Music and Sound FX
  • 9. Flash Game Development with Flex and Actionscript – Defining a Level
  • 10. Flash Game Development with Flex and Actionscript – Tiled Background Rendering
  • 先看看英文版的吧,有机会的话再翻译成中文!

    Flex 中限制 TextInput 的输入设置方法

    1. 限制某个字符的输入,用符号 ^ 跟上要限制的字符,可跟多个字符

    <!– 限制字符”~”的输入 –>

    <mx:TextInput id=”xxx”  restrict=”^~” />

    <!– 限制字符”ab”的输入 –>

    <mx:TextInput id=”xxx”  restrict=”^ab” />

    2. 设置只能输入某些字符,将允许输入的字符罗列出来即可,也可以用 – 组合表示字符范围

    <!– 只能输入abc –>

    <mx:TextInput id=”xxx”  restrict=”abc” />

    <!– 只能输入小写字母 –>

    <mx:TextInput id=”xxx”  restrict=”a-z” />

    <!– 只能输入小写字母、大写字母和数字 –>

    <mx:TextInput id=”xxx”  restrict=”a-zA-Z0-9″ />

    3. 组合使用

    <!– 只能输入数字和符号”.” –>

    <mx:TextInput id=”xxx”  restrict=”0-9.” />

    <!– 只能输入除ab之外的小写字母 –>

    <mx:TextInput id=”xxx”  restrict=”a-z^ab” />

    [心得] 12个Flex常用功能代码

    1。 复制内容到系统剪贴板

    System.setClipboard(strContent);
    

    2。 复制一个ArrayCollection

    //dummy solution( well, it works )
    var bar:ArrayCollection = new ArrayCollection();
    for each ( var i:Object in ac ){
    bar.addItem( i );
    }
    // fantastic ! //
    var bar:ListCollectionView = new ListCollectionView( ListCollectionView( ac ).list );
    

    3。 打开一个新浏览器窗口

    navigateToURL(new URLRequest('http://ntt.cc'), '_blank');
    

    4。 刷新浏览器

    navigateToURL(new URLRequest("javascript:location.reload();"),"_self")
    

    5。 关闭浏览器

    navigateToURL(new URLRequest("javascript:window.close()"),"_self");
    

    6。 设置Alert 窗口的背景为透明

    Alert
    
    {
    
    modalTransparency:0.0;
    
    modalTransparencyBlur:0;
    
    }
    

    7。 取随机颜色

      lbl.setStyle('color', 0xffffff*Math.random());
    

    8。 清除子串左侧空格

      public function LTrim(s : String):String
    
         {
    var i : Number = 0;
    while(s.charCodeAt(i) == 32 || s.charCodeAt(i) == 13 || s.charCodeAt(i) == 10 || s.charCodeAt(i) == 9)
    {
    i++;
    }
    return s.substring(i,s.length);
          }
    

    9。 清除字串右侧空格

      public function RTrim(s : String):String
    
         {
    
    	var i : Number = s.length - 1;
    	while(s.charCodeAt(i) == 32 || s.charCodeAt(i) == 13 || s.charCodeAt(i) == 10 ||s.charCodeAt(i) == 9)
    {
    	i--;
    }
    	return s.substring(0,i+1);
          }
    

    10。 清除字串左右的空格

      public function Trim(s : String):String
    
          {
    
    return LTrim(RTrim(s));
          }
    

    11。 获取数据类型

      getQualifiedClassName(data)
    

    12。 生成随机字符串。

      private function GenerateCheckCode():String
    
         {
    
    //init
    var ran:Number;
    var number:Number;
    var  code:String;
    var checkCode:String ="";
    //get 4 radom
    for(var i:int=0; i<4; i++)
    {
    ran=Math.random();
    number =Math.round(ran*10000);            //get result like 0.1234
    if(number % 2 == 0)
    code = String.fromCharCode(48+(number % 10));        //0's ASCII code is 48
    else
    code = String.fromCharCode(65+(number % 26)) ;        // A's ASCII code is 65
    checkCode += code;
    }
    return checkCode;
    }
    

    Flash社交游戏开发攻略(转载)

    引言:
    如今SocailGame火爆的如日中天,AS也是热得滚烫,农场、餐厅以及花园类游戏的火爆使得很多人都打起了开发Flash游戏的算盘。作为公司项目主管,我就负责了两个项目的开发,一个是餐厅,另一个是花园。
    这里是游戏的链接(非广告,大家可以只看截图不点连接)
    接下来我会以这两个游戏开发的过程为范例,给大家分享一些在游戏开发方面的经验以及一些比较不错的技术解决方案
    花园游戏:
    餐厅游戏:
    基础控制流1:
    本来有很多想说的,可一旦真的写了,突然发现无从下手,不过这个感觉就和我第一次开发游戏一样,因此,我就从新手最容易碰到的问题上来说吧。
    很多游戏开发新手在这个问题上都会很迷茫,究竟如何去控制整个FLASH游戏?
    比如,我们要做一个横版飞行游戏,那么我们会设想敌机在空中飞,那么这个飞行肯定是有速度的,新手一般会想到使用Timer类来实现每隔几秒就让某个元件按照一个数学函数来移动一下位置。这的确是最直观的方法。
    不过这么做有两个坏处:
    1 每个Timer如果都是独立的,那么则无法从全局上控制流程,比如让所有飞机都停止。如果是使用一个Timer来处理,那么对很多速度不相同的飞机就无法很好的控制。
    2 我们不能保证每次Timer过后,显示出来的结果都是我们预期的,因为FLASH有相对固定的帧数,比如帧数是每秒1帧,如果你Timer设定10毫秒就移动一个像素,那么你看到的仍然是1秒移动了100像素,但是系统却运算了100次。
    因此我们使用在Flash中更为实用的控制流方式,ENTER_FRAME事件作为控制流的入口。这样做的好处如下:
    1 只有在进入下一帧的时候才会做出相应运算,也就是说,所有内容的运算次数是最为优化的,因为你的眼睛只能看到每一帧的内容,因此我们只要在每帧的时候进行相应的改变就可以了
    2 使用恰当的方式,我们可以由上而下的让所有的类都相对独立,但又可以受到上一级的控制,可以随时暂停任何一个你想暂停的内容。
    那么接下来我们就举一个例子看一下实际的代码:
    在文档类的构造函数中书写如下代码:
    stage.addEventListener(Event.ENTER_FRAME, tick);
    lastTickTime = getTimer();
    lastTickTime 是个私有属性。
    新增加一个私有函数tick
    private function tick(e:Event) : void
    {
    var timer:int = getTimer();
    var timespan:int = timer – lastTickTime;
    lastTickTime = timer;
    tickBase(lastTickTime);
    }
    这个tickBase函数的作用是,对需要被控制的对象执行相应的控制代码,具体内容大家可以根据需要自己写。
    我们需要知道的就是,tickBase可以传2帧的时间间隔给你所需要控制的对象。因为虽然FLASH中我们设定了固定的帧数,但实际帧数会根据运算情况而有所改变,所以我们要使用这样的方式计算两帧的间隔时间。
    好了,大家可以尝试一下,或者休息一会,之后我会写如何去更好的实现这个tickBase中的内容,以达到对你想要控制的内容进行控制

    基础控制流2:

    上一次讲了如何使用Enterframe做基础控制流的入口,我们使用了Timer配合,使得我们可以在每次进入下一帧的时候获得两帧之间的时间。
    现在我们讲讲如何通过tickBase方法进而去控制程序中需要控制的每一个类。
    这次我们用《梦想花园》中的花的成长控制作为例子。
    如果每一朵花都需要自动的生长,我们应该怎么做呢?没错,我们要使用tick,在每次进入下一帧的时候调用tick函数,传入时间间隔timeSpan,累加这些时间,并且判断花朵是否应该长大,从而更换花朵的状态。
    为此,我们写了一个新的类BaseObject类,该类继承Sprite类,该类有个方法addObject代替addChild方法(但是我们不重写addChild,因为也有用到的时候),addObject只能用于添加另一个BaseObject类,该方法的作用是,将另一个BaseObject类的实例化对象加入该类中的一个数组里,作为他的“子”,并且在tick方法中调用它所有“子”的tick,而他所有“子”还将调用“子”中“子”数组的tick方法(如果有这么多“子”)的话。
    可以看一下这个类的构造函数和addObject方法以及tick方法
    public function BaseObject(mc:MoviClip) : void
    {
    baseObjects = new Array();   //  baseObjects 是私有属性
    content = mc; //  content 是私有属性
    }
    public function addObject(baseObj:BaseObject)
    {
    objectsToAdd.push(obj); //objectsToAdd 是私有属性    用于存储需要添加的对象(这是一个临时的数组,当执行了addAndRemoveObjects()方法以后,objectsToAdd才会真正被添加到baseObjects数组中)
    }
    public function tickBase(timeSpan:uint) : void
    {
    for each(var i in baseObjects)
    {
    i.tickBase(timeSpan);
    }
    tick(timeSpan);
    addAndRemoveObjects();//这个方法下次会讲到,很重要,功能是在tick的时候处理把对象添加到显示列表中
    return;
    }
    public function tick(timeSpan:uint)
    {
    //该方法没有实现是个抽象方法,子类继承该抽象方法以完成tick中的内容
    }
    虽然这个类没有完整的书写(还不能用),但是现在已经可以对其功能进行了解。任何继承这个类的子类都会有tick方法,一旦使用了addObject方法添加其他继承该类的对象,只要在上一讲中的ENTERFRAME中,调用一个“父”级的BaseObject中的tickBase,就可以自动的传入所有该对象中的所有“子”级对象中的tick。
    一旦这么做,我们可以先建立一个BaseObject对象land,然后使用land.addObject(flowe)方法,不过flowe对象也得是BaseObject的实例,然后在EnterFrame事件中执行land.tickBase()方法,在每次进入下一帧的时候,flower就会执行自己的tick方法,于是在tick中我们可以执行计算时间并选择播放花朵的那段动画的过程函数了。
    这样的好处是,即便对象之间的关系很复杂(比如land中有grass(草地),grass里有pot(花盆),pot中有5个flower),我们仍然能自由的去写每一个类的tick方法,他们可以有自己的处理方式,然后只要通过addObject方法来添加他的子级就可以达到预期的效果了。
    好了,下次我们再说BaseObject中的具体实现方式,现在只要了解我们是如何控制我们的对象的就可以了。

    上一次讲了如何使用Enterframe做基础控制流的入口,我们使用了Timer配合,使得我们可以在每次进入下一帧的时候获得两帧之间的时间。现在我们讲讲如何通过tickBase方法进而去控制程序中需要控制的每一个类。这次我们用《梦想花园》中的花的成长控制作为例子。如果每一朵花都需要自动的生长,我们应该怎么做呢?没错,我们要使用tick,在每次进入下一帧的时候调用tick函数,传入时间间隔timeSpan,累加这些时间,并且判断花朵是否应该长大,从而更换花朵的状态。为此,我们写了一个新的类BaseObject类,该类继承Sprite类,该类有个方法addObject代替addChild方法(但是我们不重写addChild,因为也有用到的时候),addObject只能用于添加另一个BaseObject类,该方法的作用是,将另一个BaseObject类的实例化对象加入该类中的一个数组里,作为他的“子”,并且在tick方法中调用它所有“子”的tick,而他所有“子”还将调用“子”中“子”数组的tick方法(如果有这么多“子”)的话。可以看一下这个类的构造函数和addObject方法以及tick方法 public function BaseObject(mc:MoviClip) : void {        baseObjects = new Array();   //  baseObjects 是私有属性   content = mc; //  content 是私有属性   }
    public function addObject(baseObj:BaseObject){        objectsToAdd.push(obj); //objectsToAdd 是私有属性    用于存储需要添加的对象(这是一个临时的数组,当执行了addAndRemoveObjects()方法以后,objectsToAdd才会真正被添加到baseObjects数组中)        }
    public function tickBase(timeSpan:uint) : void {         for each(var i in baseObjects) {                    i.tickBase(timeSpan); } tick(timeSpan); addAndRemoveObjects();//这个方法下次会讲到,很重要,功能是在tick的时候处理把对象添加到显示列表中        return; }
    public function tick(timeSpan:uint){ //该方法没有实现是个抽象方法,子类继承该抽象方法以完成tick中的内容}
    虽然这个类没有完整的书写(还不能用),但是现在已经可以对其功能进行了解。任何继承这个类的子类都会有tick方法,一旦使用了addObject方法添加其他继承该类的对象,只要在上一讲中的ENTERFRAME中,调用一个“父”级的BaseObject中的tickBase,就可以自动的传入所有该对象中的所有“子”级对象中的tick。
    一旦这么做,我们可以先建立一个BaseObject对象land,然后使用land.addObject(flowe)方法,不过flowe对象也得是BaseObject的实例,然后在EnterFrame事件中执行land.tickBase()方法,在每次进入下一帧的时候,flower就会执行自己的tick方法,于是在tick中我们可以执行计算时间并选择播放花朵的那段动画的过程函数了。
    这样的好处是,即便对象之间的关系很复杂(比如land中有grass(草地),grass里有pot(花盆),pot中有5个flower),我们仍然能自由的去写每一个类的tick方法,他们可以有自己的处理方式,然后只要通过addObject方法来添加他的子级就可以达到预期的效果了。
    好了,下次我们再说BaseObject中的具体实现方式,现在只要了解我们是如何控制我们的对象的就可以了。

    基础控制流3:

    前段时间比较忙,所以一直没有更新,不好意思。废话不多说,继续我们的控制流第三讲

    这次主要讲两个内容:1、完善插入对象以及移出对象功能

    2、在合适的时候更新显示列表,并更新层深

    1插入以及移出对象

    我们设想,因为程序需要,我们要在场景中插入一个对象,但又因为其他因素,这个对象需要立刻被移出,而这之间的间隔非常小,小到在两帧之间,这个时候我们就没有必要将该对象真正插入到显示列表中(这种情况虽然不多,但是也有可能出现)。

    对应public var objectsToAdd:Array(待添加对象数组) ,我们在建一个数组  public var objectsToRemove:Array(待移出对象数组)

    然后我们在addObject方法中判断该对象是否也在objectsToRemove出现,如果有,则从objectsToRemove数组中移出该对象,否则,添加到objectsToAdd数组中,removeObject方法也如法炮制。代码如下:

    public function addObject(obj:BaseObject) : void

    {

    var removeIndex:int;

    if (obj)

    {

    removeIndex = objectsToRemove.indexOf(obj);

    if (removeIndex != -1)

    {

    objectsToRemove.splice(removeIndex, 1);

    }

    else if (objectsToAdd.indexOf(obj) == -1 && baseObjects.indexOf(obj) == -1)

    {

    objectsToAdd.push(obj);

    if (obj.parent != null && obj.parent is BaseObject)

    {

    BaseObject(obj.parent).removeObject(obj);

    }

    }

    }

    return;

    }

    移出代码就不写了,也是一样的。这么一来,最终我们得到的肯定是一组真正要被添加到显示列表中和要从显示列表中移除的对象数组。注意,无论怎么添加和移出,尚未进入下一帧之前,显示列表中的内容都是没有变的,不会对显示性能造成影响,同时baseObjects中的内容也不会发生变化,通常baseObjects中的内容总是与现实列表中的内容保持一致。

    以上两个方法为我们将要在tickBase中的方法addAndRemoveObjects()做了铺垫,那么接下来我就讨论一下addAndRemoveObjects()方法的作用于特点。

    一旦大家开始做AS3游戏了,很快就会发现一个大问题,那就是层深的控制。as2中层深控制看起来可能比较简单,设置层深的深度就可以了,但这在AS3中被ADOBE取消了,可能是因为性能的低下。取而代之的是使用addChildAt方法来替代,这样一来,我们可能不能很直观的去控制我们想要控制的层深。因此我们使用addAndRemoveObjects()方法结合我们自己新建的属性drawPriority(绘画优先级)来控制层次之间的关系。这样的好处就是:无论一个场景内有多少东西的层次要发生变化,我们只会在进入下一帧的时候对这些对象排序一次。

    public function addAndRemoveObjects() : void

    {

    var obj:BaseObject;

    var index:int;

    var isPrio:Boolean;

    if (objectsToRemove.length > 0)

    {

    for each(var i in objectsToRemove)

    {

    obj = i;

    index = baseObjects.indexOf(obj);

    if (index != -1)

    {

    baseObjects.splice(index, 1);

    }

    if (obj.parent != null && obj.parent == this)

    {

    removeChild(obj);

    }

    }

    objectsToRemove.splice(0, objectsToRemove.length);

    }

    if (objectsToAdd.length > 0)

    {

    for each(var k in objectsToAdd)

    {

    isPrio = false;

    for (var j = 0; j < baseObjects.length; j++ )

    {

    if (k.drawPriority < baseObjects[j].drawPriority)

    {

    addChildAt(k, getChildIndex(baseObjects[j]));

    baseObjects.splice(j, 0, k);

    isPrio = true;

    break;

    }

    }

    if (!isPrio)

    {

    baseObjects.push(k);

    addChild(k);

    }

    }

    objectsToAdd.splice(0, objectsToAdd.length);

    }

    return;

    }

    简单的解释一下代码,一共做了两件事:

    1 把放在objectsToRemove数组中的对象从baseObjects中移出,同时从显示列表中移出,清空objectsToRemove

    2 根据objectsToAdd中的每个对象的drawPriority属性,将对象按顺序插入显示列表以及baseObjects数组中,清空objectsToAdd。

    这样,我们就完成对该对象内的所有“子”的排序与显示层深的重置。并且每帧最多只会排序一次。

    好了,现在我们的BaseObject类已经完成了一大半。拥有了添加删除对象的两个方法,并且会将帧间隔时间传入该对象的子对象以及该对象的子对象的子对象以及……(太多了不写了)中,并且拥有属性drawPriority,只要改变该属性,在进入下一帧的时候就会改变显示列表中的层次关系。

    接下来,我们只要继承这个类,就可以轻松的控制每一个对象的行为(只要在类中重写tick的方法即可),以及轻松的控制他们层次关系(由于只在帧间隔的时候做,即不会在肉眼上有延迟,且执行效率也会比较高)。

    大家可以动手写一个这样的类,然后去用用看,记得在文档类中调用最外层的BaseObject对象的tickBase函数,然后尝试着做添加,删除,修改层深以及覆盖tick方法的操作,这样一来,我们的基本控制流的结构就差不多了。

    接下来我们会讲到如何用反射(Reflection)来简化以及模块化开发。

    反射的应用:

    反射(Reflection),是众多面向对象语言都有的功能,不过我在论坛上常常看到有人不理解反射的用途,甚至有人说反射没有任何用处。今天我不讲反射究竟有多少可挖掘的地方,我们就着我们的游戏内容,来讲一下反射的现实应用,很多东西,不用你是不知道的。

    我们来到花园游戏,花园游戏中有许多的花,很多很多,估计有108种,并且一直在不断的增加。大家都知道,花肯定是flash做好的元件,因此我们要去库里面取,从库里面取也有很多种方法。最简单的就是在库里面元件中的属性点导出,然后在程序里就可以去实例化这个类了。比如你导出类的名字是Flower1, 那么在程序里你就可以这么写:var flower=new Flower1();然后就可以将这个类的实例添加到屏幕了。那么,如果真的这么去做游戏,你就会发现很多问题:1、每次新增加一朵花,我就不得不修改程序,重新新增加一个类的实例化过程。2、如果你想要把主程序和这些资源文件分离的话,你甚至都无法正确编译你的程序,因为在主程序中,并没有Flower1这个类。

    所以我们使用了反射,在这种情况下,反射的作用相当于用字符串来取代类名,正因为他是字符串,你可以不顾及这个类当前存不存在。

    好了我们开始做了,我很简单的讲一下我们的做法,我们把花的元件全部放到一个单独的fla中,每个花都有单独的导出,从Flower1到Flower108,然后生成flower_asset.swf,我们在主程序中加载这个swf文件,与此同时我们加载一个XML配置文件(具体如何加载我之后会详细说明),总之我就是加载,并且读取到了每个id的花所对应到的导出类名(比如id为20001的红玫瑰花对应的元件的类是Flower1),现在我要显示出某个用户的所有的花,比如这个用户有个花朵的数组,数组中有如下数据[20001,20002,20001,20003],那么我们就做一个循环,实例化所有的FlowerXXX的类,然后添加到舞台上。

    我们先在文档类中添加一个静态方法:

    public static function getMovieClip(mcname:String) : MovieClip

    {

    try

    {

    var mcClass:* = Class(getDefinitionByName(mcname));

    if (mcClass == null)

    {

    return null;

    }

    return new mcClass;

    }

    catch (e)

    {

    return null;

    }

    return null;

    }

    注意我使用了try,这是为了系统的稳定性,即便因为一些特殊原因,我们取到了一些错误或者过期的数据(比如有一朵花现在已经在我们的库中删除了,但是因为策划疏忽而没有删除),我们也可以良性地处理这个问题而不至于flash报错。

    然后我们在程序中就可以调用这个方法,根据从配置文件中取到的类名的字符串,调用getMovieClip方法去库中取到相应的元件。几乎在我们所有涉及到显示的类中,最后都有调用到该方法。

    反射的好处在于,动态的决定了主程序将要调用的类,比如一个玩家的场景中只有5种花,我们就没必要让程序导入108个花的类(从性能上来说,反射其实是有待考究的,因为动态的东西通常比静态的慢,但是这其中的性能的得失很复杂,大家可以再讨论。)就从开发以及维护的角度来说,尽量减少编译以及版本发布的次数,让程序更容易被“定制”总是比将代码写死在程序中要好得多。

    as3优化总结

    1.用乘法来代替除法(当除数可转化为有限数的时候)。比如var n:Number = value * 0.5;要比var n:Number = value / 2;快。但差别并不是很大。只有在需要大量计算情况下,比如3D引擎中差别才比较明显。

    2.用位运算代替除2或乘2。比如10>>1要比10*2快,而10<<1要比10*2快。从测试来看位运算几乎比乘除快一倍,但是一般情况下,我们不能选择位运算,比如我们就不能用13>>1来代替13/2,尽管前者比后者运算速度更快,但2者的运算结果却不一样。所以还是要看具体情况。

    3.用unit()或int()代替取整运算Math.floor()和Math.ceil()。比如var test:uint = uint(1.5);要比var test:Number = Math.floor(1.5);快;而var test:uint = uint(1.5)+1;要比var test:Number = Math.ceil(1.5);也快。如果是Math.floor(),还可以用位运算(>>0)来代替。比如var test:uint =1.5>>0,比unit()或int()更快。

    4.用乘-1来代替Math.abs()方法。比如var nn:Number = -23;var test:Number= nn < 0 ? nn * -1 : nn;要比var nn:Number = -23;var test:Number = Math.abs(nn);快。

    当然还有更多的优化计算的方法。一般来说,低级运算要比高级运算速度;内部方法比调用其他方法速度快。另外要注意的是,这些方法有的时候可能并一定适用.

    第二章  Actionscript 优化指南
    来源 gotoAndStop.it

    原著 Marco Lapi,alias Lapo, aw译

    在这篇文章中,我们将讨论多种优化 Actionscript 代码的方法.
    此外我们也针对一些典型的游戏代码进行了系列测试,来最大限度的发掘、提高Flash播放器的性能。


    何时进行优化

    对现有程序进行优化的过程,有时十分的冗长与困难,这与原始代码的非优化程度有关,所以在投入大量时间进行代码优化之前,最重要的是要估计出要在什么地方对代码做出修改或替换。

    一个游戏代码的最重要的部分就是主循环体,通常情况下该循环体要在flash的每一帧上执行,并控制游戏中的角色属性和重要的数据参数。而对于主循环体以外的部分,也可能是次要循环部分,同样要注意是给其否分配了过多的资源,而没有分配给那些更需要资源的核心部分。
    通过积累在各处节约出来的时间(可能每处仅仅是几个毫秒),您会明显发现自己的swf运行得更加稳定,并且游戏感也大大加强。


    简洁与高效的代码

    书写出十分简洁、可以再次调用的代码(有时可能是面向对象的)是一项精细的工作,但这需要多年的编程经验。对于OOP(object oriented programming,面向对象的程序设计),有些场合根本利用不到它的优势,这使得它显得十分奢侈。在有限的资源条件下(可能是flash播放器的原因),通过更先进的方法,像刚刚提到的OOP,就可能反而导致令人不满意的结果。

    我们并不是说OOP对游戏编程不好,只是在某些场合它显得过于奢侈和多余。毕竟有时候“传统的方法”却能得到更好的结果。

    大体而言,用OOP是比较好的,因为它让代码维护更加简单。但在后文中,你会看到有时为了充分发挥flashplayer性能,而不采用OOP技术。例如:处理快速滚动或者计算十分复杂的数学问题。


    基本的优化

    一提及代码优化,我们马上会联想到执行速度的改进,而很少去考虑系统资源的分配。这是因为当今,即使是将被淘汰的计算机,都有足够的内存来运行我们大部分的flash游戏(128M的内存足以满足大多数情况的需要,况且,512M的内存是当今新电脑的基本配置)

    变量

    在各种重要的代码优化手段中,有这么一条:在定义局部变量的时候,一定要用关键字var来定义,因为在Flash播放器中,局部变量的运行速度更快,而且在他们的作用域外是不耗占系统资源的。

    aw附:var变量仅仅在花括号对中才有“生命”,个人认为没有系统学过编程的人容易出错的一个地方:

    awMC.onLoad = function(){
    var aw = 1;
    }
    awMC.onEnterFrame = function(){
    //不存在aw这个变量
    }
    一段非优化代码:

    function doSomething()
    {
    mx = 100
    my = 100
    ar = new Array()

    for (y=0; y < my; y++)
    {
    for (x=0; x < mx; x++)
    {
    i = (y * mx) + x
    arr[i] = i
    }
    }

    return arr
    }

    这段代码中,并未声明函数体内的那些变量(那些仅仅在函数内使用的变量)为局部变量,这使得这些变量被播放器调用的速度更慢,并且在函数执行完毕的时候仍然耗占系统资源。

    下面列出的是经过改进的同样功能的代码:

    function doSomething()
    {
    var mx = 100
    var my = 100
    var ar = new Array()

    for (var y=0; y < my; y++)
    {
    for (var x=0; x < mx; x++)
    {
    var i = (y * mx) + x
    arr[i] = i
    }
    }
    return arr
    }
    这样一来所有的变量均被定义为了局部变量,他们能够更快地被播放器调用。这一点在函数大量(10,000次)循环运行时显得尤为重要!当一个函数调用结束的时候,相应的局部变量都会被销毁,并且释放出他们占有的系统资源。

    onEnterFrame 事件

    onEnterFrame事件对于游戏开发者而言是非常有用的,它使得我们能够快速、反复地按照预设帧频(fps)运行一段程序。回想在Flash5的时代,这(onEnterFrame实时监控)是一种非常流行的技术,用这样的事件来控制机器游戏对手的逻辑,又或者我们可以在每一个子弹上设置这样的事件来监测子弹的碰撞。

    实际上,我们并不推荐给过多的MoveClip添加这样的事件,因为这样做会导致“无头绪码(spaghetti code)”的出现,并且容易导致程序效率明显降低。

    大多数情况下,用单独一个onEnterFrame事件就可以解决问题了:用这一个主循环来执行你所需要的操作。

    另一个简单的办法是设置一个合适的帧频:要知道帧频越高,CPU资源就越紧张。

    在帧频为25-35(fps)之间时,onEnterFrame足以很好地执行较复杂代码,哪怕你的计算机配置较低。因此,在没有特殊要求的场合,我们不推荐使用高于60(fps)的帧频。

    矢量图与位图

    在处理图形前,我们一定要做出正确的选择。Flash能对矢量图和位图进行完美的兼容,然而矢量图和位图在播放器中的表现实质却完全不同。

    在用到矢量图的时候,我们要尽可能简化它们的形状,去除多余的端点。这样做将大大降低播放器用于呈现矢量图所要进行的计算量。另一个重要方面在于线条的运用,尽量减少和避免冗陈的线条结构,因为它们会直接影响到flash的播放效率。

    当某个实例透明度小于100时,也会对播放速率造成影响,所以如果你发现自己的Flash播放速率过慢,就去挑出这些透明的实例来吧!

    那么,如果真的需要呈现比较复杂的场景时,你就最好考虑使用位图实现。虽然Flash在对位图的渲染效率上并不是最优越的(比如和Flash的“兄长”Director比起来),但丰富的视觉内容呈现只能靠位图(与位图同复杂度的矢量图形渲染速率非常低)了,这也是很多基于区块的游戏中广泛采用像素图作为背景的原因。顺便要提到的是,Flash虽然对GIF,JPG和PNG都有所支持,但是渲染速度上PNG还是占有绝对优势,所以我们建议flash中的位图都尽可能采用PNG格式。

    影片剪辑(MovieClip)的可视性[下面将MovieClip简称为mc]

    您可能会经常碰到这样一种情况:有大量不可见/屏幕外的mc等待出场(比如游戏中屏幕外的地图、人物等等)。
    要知道,播放器仍然要消耗一定的资源来处理这些不可见/屏幕外的mc,哪怕他们是单帧,非播放的状态。

    最好的解决办法之一是给这些mc一个空白帧,当他们不出现在屏幕上时,你能用gotoAndStop()语句跳转到这一帧,从而减少播放器对资源的需求。

    请务必记住,这种情况下,简单的设置可见度属性为不可见( _visible = false )是无效的,播放器将继续按照这些mc所停留或播放的帧的复杂度来分配资源。
    数组
    数组在各种需要记录数据的应用程序和游戏中都被广泛的使用。

    一个典型的例子就是基于区块的Flash游戏,在这样一类的游戏中,地图有时被存放成形如arr[y][x]的二维数组。虽然这是一种很常见的方法,但是如果用一维数组的话,却能提高程序的运行效率。另一个重要的方法来提高数组效率是在数组遍历的时候使用for in 循环来代替传统的 for 或者while循环语法。
    例如:

    一段代码如下
    for (var i in arr)
    {
    if (arr[i] > 50)
    {
    // 进行某些操作
    }
    }

    它的执行速度明显高于这一段代码:
    for (var i=0; i < 10000; i++)
    {
    if (arr[i] > 50)
    {
    // 进行某些操作
    }
    }
    前者的效率比后者提高了30%,这个数字在你的游戏要逐帧执行这一段代码的时候显得更加宝贵!


    高级优化:
    1) for循环 和 while循环
    用while循环将会得到比for循环更好的效率。然而,从数组中读取数据,用for in循环式最好的选择!

    所以我们不推荐使用:
    for (var i=0; i < 1000; i++)
    {
    //进行某些操作
    }而推荐使用

    var i=-1
    while (++i < 1000)
    {
    //进行某些操作
    }

    2) 从数组中读取数据
    我们通过测试发现,for in循环的效率大大高于其他的循环方式。参看:
    arr = []
    MAX = 5000

    //数组赋值
    for (i=0; i < MAX; i++)
    {
    arr[i] = i
    }
    var item = null

    // For 循环

    for (var i=0; i < MAX; i++)
    {
    item = arr[i]
    }

    // For 循环
    for (var i in arr)
    {
    item = arr[i]
    }

    // While 循环
    i = -1
    while(++i < MAX)
    {
    item = arr[i]
    }

    3) 向数组中写入数据(while , for)
    可以看到while循环稍占优势。

    4) _global(全局)变量同Timeline(时间轴)变量
    我们猜测采用全局变量能提高变量调用速度,然而效果并不像预计的那样明显。

    5) 单行、多行变量赋值
    我们发现单行变量赋值效率大大高于多行。比如:
    a = 0
    b = 0
    c = 0
    d = 100
    e = 100

    效率就不如:
    a = b = c = 0
    d = e = 100

    6) 变量名寻址
    这个测试反映了变量名的预寻址是非常重要的,尤其是在循环的时候,一定要先给丁一个指向。这样大大节约了寻址时间。

    比如:
    var num = null
    t = getTimer()
    for (var i=0; i < MAX; i++)
    {
    num = Math.floor(MAX) – Math.ceil(MAX)
    }
    t1.text = “Always lookup: ” + (getTimer() – t)

    就不如:
    t = getTimer()
    var floor = Math.floor
    var ceil  = Math.ceil
    for (var i=0; i < MAX; i++)
    {
    num = floor(MAX) – ceil(MAX)
    }

    7) 短变量名和长变量名
    变量名越短,效率越高。考虑到长变量名也有它的好处(比如,便于维护等),因此建议在关键部位(比如大量循环出现的时候)使用短变量名,最好就1-2个字符。

    8) 循环前、后声明变量
    在测试前,我们认为循环前声明变量会更加节约时间,不料测试结果并不明显,甚至还恰恰相反!

    // 内部声明
    t = getTimer()
    for (var i=0; i < MAX; i++)
    {
    var test1 = i
    }
    t1.text = “Inside:” + (getTimer() – t)

    // 外部声明
    t = getTimer()
    var test2
    for (var i=0; i < MAX; i++)
    {
    test2 = i
    }

    9) 使用嵌套的if结构
    当用到复杂的条件表达式时。把他们打散成为嵌套的独立判断结构是最佳方案。下面的代码我们进行了测试,发现这种效果改进明显!
    MAX = 20000
    a = 1
    b = 2
    c = -3
    d = 4

    var i=MAX
    while(–i > -1)
    {
    if (a == 1 && b == 2 && c == 3 && d == 4)
    {
    var k = d * c * b * a
    }
    }

    //下面的判断更加节省时间
    var i=MAX
    while(–i > -1)
    {
    if (a == 1)
    {
    if (b == 2)
    {
    if (c == 3)
    {
    if (d == 4)
    {
    var k = d * c * b * a
    }
    }
    }
    }
    }

    10) 寻找局部变量(this方法同with方法比较)
    局部变量的定位方法很多。我们发现用with比用this更加有优势!
    obj = {}
    obj.a = 1
    obj.b = 2
    obj.c = 3
    obj.d = 4
    obj.e = 5
    obj.f = 6
    obj.g = 7
    obj.h = 8
    obj.test1 = useThis
    obj.test2 = useWith
    MAX = 10000
    function useThis()
    {
    var i = MAX
    while(–i > -1)
    {
    this.a = 1
    this.b = 2
    this.c = 3
    this.d = 4
    this.e = 5
    this.f = 6
    this.g = 7
    this.h = 8
    }
    }
    function useWith()
    {
    var i = MAX
    while(–i > -1)
    {
    with(this)
    {
    a = 1
    b = 2
    c = 3
    d = 4
    e = 5
    f = 6
    g = 7
    h = 8
    }
    }
    }

    11) 循环监听键盘事件
    同刚才所提到的寻址一样,我们实现给一个指向会得到更好的效率,比如:
    keyDown = Key.isDown
    keyLeft = Key.LEFT

    //我们再用 if (keyDown(keyLeft))
    附:我们测试了按键代码和键值常量的效率发现并无太大差别。

    12) Math.floor()方法与int()
    这个问题曾在Flashkit的论坛被提出讨论过。测试表明,旧的int方法反而效率更高。我们的测试结果也反映了这一点。

    13)eval表达式与中括号语法
    我们并没有发现明显的差别,并不像刚才所述那样,旧的eval表达式比起中括号方法并没有太大的优势
    var mc = eval_r(“_root.myMc” + i)
    var mc = _root["myMc" + i]
    //两者效率差不多16) 涉及MC的循环:ASBroadcaster 同欢同循环的差别


    结论
    我们从这些测试结果中发现,对于不同的需求,采用不同的代码,我们可以大大提高脚本的执行效率。虽然我们在这里罗列了许多的优化代码的方法,需要大家自己测试、实验的还有很多(考虑到每个人的需求不同).如果你想更加深入地讨论这类问题。可以来我们的论坛。

    aw附:
    终于翻译完了,自己也学到很多好东西,大家又什么问题可以去gotoAndPlay的官方,也可以来我的Blog提出!

    第三章  黑羽AS心得:浅释ActionScript的代码优化
    来源:Kingda blog

    本文既为浅谈代码优化,那么就不深入到OOP设计层面。仅涉及Flash8帮助里面提到的一些代码编写优化原则,并加以解释。
    准则来源于Flash8 帮助,我做了一些解释:

    1.避免从一个循环中多次调用一个函数。
    在循环中包含小函数的内容,可使效果更佳。小函数生命期短,利于资源释放。尤其是在大的循环中时。

    2.尽可能使用本机函数。
    本机函数要比用户定义的函数运行速度更快。本机函数即Flash中内有的一些函数(intrinsic),比如hitTest(),你没必要自己写一个类似的。

    3.不要过多使用 Object 类型。
    数据类型注释应力求精确,这样可以提高性能。只有在没有适当的备选数据类型时,才使用 Object 类型。同时也便于代码管理,时刻知道对象的类型和作用。
    同时也有利于编译器编译时优化。

    4.避免使用 eval_r() 函数或数据访问运算符。
    通常,较为可取且更有效的做法是只设置一次局部引用。不得已时才用eval,比如转换_droptarget为MovieClip时。

    5.在开始循环前将 Array.length 赋予变量,尤其是大的循环。
    在开始循环前将 Array.length 赋予变量(比如var iLength:Number),将其作为条件使用,而不是使用 myArr.length 本身。
    原因,在循环中,iLength是Number变量,会被放入寄存器使用,效率远比访问Array再得到length高。例如,应使用

    var fontArr:Array = TextField.getFontList();
    var arrayLen:Number = fontArr.length;
    for (var i:Number = 0; i < arrayLen; i++) {
    trace(fontArr[i]);
    }

    来代替:
    var fontArr:Array = TextField.getFontList();
    for (var i:Number = 0; i < fontArr.length; i++) {
    trace(fontArr[i]);
    }

    6.注重优化循环及所有重复动作。
    Flash Player 花费许多时间来处理循环(如使用 setInterval() 函数的循环)。

    7.在局部变量够用时,不要使用全局变量。类静态变量也要少用。
    全局变量是开发者的恶梦。实在需要全局变量的话,我建议使用singleton设计模式来进行管理。

    8.声明变量时,添加 var 关键字。
    这是为了编译时让编译器知道你的变量类型,优化编译。

    黑羽补充一点:对关键字的使用要谨慎。
    不赞成使用关键字作为自己的method和属性名,除非你确认后续开发不会用到相同的事件名和属性名。
    但你怎么知道flash使用了多少隐藏关键字?太多了!比如说 className, invalidate, refresh, mouseOver等等不常用的关键词。好的方法是使用SEPY编辑器来写代码,那里面加亮了所有公布的和没有公布的关键词。
    而且因为很有可能和start,load,等这些常用的事件名重复,带来代码不必要的修改和麻烦。

    9.对涉及到调用绘图资源的函数时,尽量先多判断再调用。
    所有渐变,位置变化,创建删除MC,组件等函数都涉及到绘图资源的调用。在很多情况下,尽量先用逻辑判断变量或者对象的属性,必要时再调用这些函数。这样可以节省较多的计算资源。