2011年6月23日 星期四

Flash執行階段錯誤

適用於 Adobe® Flash® Platform 的 ActionScript® 3.0 參考
下列是可能在執行階段發生的錯誤。
無論您在嚴謹模式或警告模式中進行編譯,ActionScript 3.0 都會進行執行階段類型檢查。

執行階段錯誤




2011年6月22日 星期三

載入外部swf__父層子層雙向取用類別定義

LoaderContext()建構函式
public function LoaderContext(checkPolicyFile:Boolean = false, applicationDomain:ApplicationDomain = null, securityDomain:SecurityDomain = null)

getDefinitionByName()全域函數
public function getDefinitionByName(name:String):Object
會傳回 name 參數所指定之類別的類別物件參照。
參數
name:String — 類別的名稱。
傳回值
Object — 會傳回 name 參數所指定之類別的類別物件參照

※ 本例著眼於 main.swf 載入外部 child.swf,透過LoaderContext類別物件予以設定,則child.swf 中所有的ActionScript 3定義,同時將被載入至main.swf所在的目前應用程式網域,並能被main.swf所取用。事實上,child.swf 中的ActionScript 3定義被合併至main.swf所在的目前應用程式網域,導致main.swf與child.swf 彼此擁有對方類別定義的能見度。


※ main.swf 載入child.swf 之後,可調用child.swf 的Child 類別裡的 weicom()方法。
而,child.swf 則可調用 Main 類別裡的 hello()方法,與 Ball 類別裡的 ballFunc()方法。





※ 這個測試,將main.swf及child.swf隔開在兩個不同的套件根目錄中,以避免相同套件內的存取造成誤判。










Main.as
package  {
 
 import flash.display.Loader;
 import flash.display.Sprite;
 import flash.events.*;
 import flash.events.EventDispatcher;
 import flash.net.URLRequest;
 import flash.system.LoaderContext;
 import flash.system.ApplicationDomain;
 import flash.display.MovieClip;
 import flash.display.LoaderInfo;
 import flash.utils.getDefinitionByName;

 public class Main extends Sprite {
  
  public static const LOADED:String = "loaded";
  public var testVar:String;
  private var ldr:Loader;
  
  public function Main() {
   this.testVar = "abc";
   ldr = new Loader();
   var req:URLRequest = new URLRequest("../external/Child.swf");
   
   /*透過LoaderContext 指定 - 將外部Child.swf的公用類別定義載入到目前應用程式網域*/
   /* ***藉由將載入的 SWF 檔置於相同的應用程式網域中,便可以直接存取其類別。*** */
   var ldrContext:LoaderContext = new LoaderContext(false,ApplicationDomain.currentDomain);
   ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
   ldr.load(req,ldrContext);
  }

  private function completeHandler(event:Event=null):void {
   trace("@Main / completeHandler() / event.target.content : " + event.target.content);
   
   /*A法 : 使用ApplicationDomain.currentDomain.getDefinition()方法*/
   /*取得Child的類別參照,調用其建構式*/
   /*var getClass:Class = ApplicationDomain.currentDomain.getDefinition("Child") as Class;
   trace("@Main / completeHandler / getClass : " + getClass);*/
   
   /*B法 : 使用getDefinitionByName(name:String):Object*/ 
   /*public function getDefinitionByName(name:String):Object*/
   /*傳回 name 參數所指定之類別的類別物件參照*/
   /*參數   name:String — 類別的名稱。*/
   /*傳回值   Object — 會傳回 name 參數所指定之類別的類別物件參照。*/
   /*使用getDefinitionByName()函數,取得Child的類別參照,代表子層類別可見度ok*/
   var getClass:Class = getDefinitionByName("Child") as Class;
   trace("@Main / completeHandler / getClass : " + getClass);
   
   /*載入完成後, 建構一個Child類別實體, 指定給childObj - B法*/
   var childObj:* = new getClass();
   this.addChild(childObj);
   
   /*載入完成後發送自訂事件*/
   var loadedEvent:Event = new Event(LOADED);
   childObj.dispatchEvent(loadedEvent);
   trace("@Main / completeHandler() / this.dispatchEvent(loadedEvent) : " + this.dispatchEvent(loadedEvent));
   
   /*調用childObj實體的welcome()方法, */
   var message:String = childObj.welcome("Alice");
   trace("***********************************");
   trace("從Main調用Child的welcome()方法 - 以下這行");
   trace(message);
   trace("***********************************");
   return;
  }
  
  public function hello():String{
   var helloMessage:String = "@Main : Hello!!! Baby!!!";
   return helloMessage;
  }
 }
}



Child.as
package {

 import flash.display.Sprite;
 import flash.events.Event;
 import flash.system.ApplicationDomain;
 import flash.utils.getDefinitionByName;
 
 public class Child extends Sprite {
  
  public var getMainClass:Class;
  
  public function Child() { 
   if(ApplicationDomain.currentDomain.hasDefinition("Main")){
    /*A法 : 使用 ApplicationDomain.currentDomain.getDefinition()方法*/
    /*this.getMainClass = ApplicationDomain.currentDomain.getDefinition("Main") as Class;*/
    
    /*B法 : 使用getDefinitionByName(name:String):Object,取得Main的類別參照,代表父層類別可見度ok*/
    this.getMainClass = getDefinitionByName("Main") as Class;
    
    trace("@Child / Child() / getMainClass : " + this.getMainClass);
    this.monitor();
   }
   return;
  }
  
  public function monitor():void{
   /*偵聽Main.LOADED 之載入完成事件*/
   this.addEventListener(getMainClass.LOADED,loadedHandler);
   this.addEventListener(Event.ADDED_TO_STAGE,addedToStage);
   return;
  }
  
  public function loadedHandler(event:Event):void{
   this.removeEventListener(getMainClass.LOADED,loadedHandler);
   trace("@Child / loadedHandler() / event.type : " + event.type);
   
   /*取得父類別實體*/
   var myParent:* = getMainClass(this.parent);
   trace("@Child / loadedHandler() / myParent : " + myParent);
   
   /*調用Main的hello()方法*/
   trace("***********************************");
   trace("從Child調用Main的hello()方法 - 以下這行");
   var message:String = myParent.hello();
   trace(message);
   trace("***********************************");
   
   /*A法 : 使用 ApplicationDomain.currentDomain.getDefinition()方法*/
   /*取得Ball的類別參照,調用其建構式*/
   /*var getBallClass:Class = ApplicationDomain.currentDomain.getDefinition("Ball") as Class;*/
   
   /*B法 : 使用getDefinitionByName(name:String):Object,取得Ball的類別參照,代表父層類別可見度ok*/
   var getBallClass:Class = getDefinitionByName("Ball") as Class
   
   trace("@Child / loadedHandler() / getBallClass : " + getBallClass);
   var myParentBall:* = new getBallClass(160,200);
   trace("@Child / loadedHandler() / myParentBall : " + myParentBall);
   this.parent.addChild(myParentBall);
   return;
  }
  
  public function addedToStage(event:Event):void{
   this.removeEventListener(Event.ADDED_TO_STAGE,addedToStage);
   this.addEventListener(Event.REMOVED_FROM_STAGE,removedFromStage);
   return;
  }
  
  public function removedFromStage(event:Event):void{
   this.removeEventListener(Event.REMOVED_FROM_STAGE,removedFromStage);
   return;
  }

  public function welcome(_name:String):String {
   return "@Child : Hello, " + _name;
  }
 }
}


Ball.as
package  {
 
 import flash.display.SimpleButton;
 import flash.events.Event;
 
 public class Ball extends SimpleButton {
  
  public var thisX:Number;
  public var thisY:Number;
  
  public function Ball(_x:Number,_y:Number) {
   this.addEventListener(Event.ADDED_TO_STAGE,addedToStage);
   this.thisX = _x;
   this.thisY = _y;
   return;
  }
  
  public function addedToStage(event:Event):void{
   this.removeEventListener(Event.ADDED_TO_STAGE,addedToStage);
   this.addEventListener(Event.REMOVED_FROM_STAGE,removedFromStage);
   this.x = this.thisX;
   this.y = this.thisY;
   return;
  }
  
  public function removedFromStage(event:Event):void{
   this.removeEventListener(Event.REMOVED_FROM_STAGE,removedFromStage);
   return;
  }
  
  /*此例, Ball類別的這個ballFunc()方法,將在child.swf 被Main.swf 載入後,被Child類別實體調用*/
  public function ballFunc():void{
   trace("@Ball / ballFunc : I am from Ball Class");
  }
 }
 
}





值得注意這件事......

若把Main類別的Main建構函數的以下這行刪掉 :
var ldrContext: LoaderContext = new LoaderContext(false,ApplicationDomain.currentDomain);

且把Main類別的Main建構函數的 ldr.load(req,ldrContext); 的 「,ldrContext」刪掉

[Ctrl+enter]測試影片, 將出現錯誤
ReferenceError: Error #1065: 變數 Child 未定義。
at global/flash.utils::getDefinitionByName()
at Main/completeHandler()

可見, 透過LoaderContext類別物件指定ApplicationDomain.currentDomain
將被載入child.swf 的公用類別定義置於目前載入器根swf所處的應用程式網域
就是本實例能夠正確運作的最大關鍵 ─ 父層子層雙向取用類別定義

若有人真的仔細看了code, 將會發現......
在main與Child裡, 由於處於父層子層彼此類別定義的透視度中
所以, 皆採用 [B法] 來取得對象的類別參照
即 getDefinitionByName(name:String):Object

然而, [A法] 的 ApplicationDomain.currentDomain.getDefinition()方法
則是,未取得父層子層彼此類別定義的透視度時的最佳利器.
透過 ApplicationDomain類別的[靜態]屬性currentDomain傳回目前應用程式網域物件(ApplicationDomain物件),
再調用getDefinition()方法取得類別參照.
很大的好處是,因為 ApplicationDomain.currentDomain為靜態屬性,
可在父層或子層直接呼叫, 達到子層取得父層各類別的目的
否則還真難達成.

前此, 那個 [大誤] 的例子, 最大的錯誤在於......
誤以為從相同網域載入的swf, 不需設定LoaderContext, 就立即與載入器根swf擁有相同應用程式網域
因此彼此擁有相互類別可見度. 其實不然啦.
再者, 沒有將main.as和child.as分開在不同套件目錄
則造成測試的混淆. 大誤阿 !!!

2011年6月21日 星期二

ApplicationDomain.currentDomain.getDefinition()

ApplicationDomain.currentDomain.getDefinition()
LoaderConText.applicationDomain屬性

◎◎◎ 從A.swf將B.swf載入
兩種方式調用getDefinition()方法
※ LoaderInfo.applicationDomain[唯讀].getDefinition()
※ ApplicationDomain.currentDomain[靜態] [唯讀].getDefinition()
※ LoaderInfo.applicationDomain[唯讀].getDefinition()

applicationDomain : ApplicationDomain
[唯讀] 當載入外部 SWF 檔時,所有包含在載入類別的 ActionScript 3.0 定義都會儲存在 applicationDomain 屬性中。
※ ApplicationDomain.currentDomain[靜態] [唯讀].getDefinition()
currentDomain : ApplicationDomain
[靜態] [唯讀] 會取得您的程式碼正在其中執行的目前應用程式網域。

getDefinition () 方法
public function getDefinition(name:String):Object
會從指定的應用程式網域取得公用定義。 定義可以是類別、名稱空間或函數的定義。
參數
name:String — 定義的名稱。
傳回值
Object — 與定義相關聯的物件。


不使用applicationDomain.getDefinition()前提下_載入外部swf_父層子層雙向取用類別

※※※ 1000622更新 : 目前發覺這個測試, 是在錯誤條件下得到的結果, 如果搬開child.swf到另一目錄, 就有錯誤發生. 暫時保留這個主題.


(一) 1000621_Main_1.fla 搭配主要類別(文件類別) Main_1_1000621.as,其元件庫中則有Ball元件綁定外部類別Ball.as,以上匯出為1000621_Main_1.swf。透過Main_1_1000621.as裡面的程式碼將載入外部的child.swf

(二) 被載入的外部swf 為child.swf, 由child.fla搭配Child.as所匯出.

(三) 1000621_Main_1.swf 載入child.swf後。

由於, child.swf 與 1000621_Main_1.swf  位於同一網域,且未以LoaderContext類別做其它設定
被載入的child.swf 與載入器所在的1000621_Main_1.swf,完成載入後,預設將位於同一安全性網域與同一應用程式網域
*** 藉由將載入的 SWF 檔置於相同的應用程式網域中,便可以直接存取其類別 *** 
*** 在載入器swf和被載入的swf之間,彼此所定義的類別為彼此可見 ***

(四) 所以,在Main_1_1000621文件類別中,可以直接調用Child類別建構式來建立其實體。
 var childObj:Child = new Child(); 
並調用其welcome()方法 - 
var message:String = childObj.welcome("Alice");

(五) 在Child.as中,可以直接調用Ball類別建構式,建立其實體。
var myParentBall:Ball = new Ball(275,200);
並調用其ballFunc()方法 - 
myParentBall.ballFunc();

(六) 以上, 質疑的是,是因為所解釋之原因,而能彼此擁有類別的可見度 ???
還是,因為命名空間的關係,而可被存取 ???


1000621_ApplicationDomain_1.rar 下載


Main_1_1000621
package  {
 
 import flash.display.Loader;
 import flash.display.Sprite;
 import flash.events.*;
 import flash.events.EventDispatcher;
 import flash.net.URLRequest;

 public class Main_1_1000621 extends Sprite {
  
  public static const LOADED:String = "loaded";
  public var testVar:String;
  private var ldr:Loader;
  
  public function Main_1_1000621() {
   this.testVar = "abc";
   ldr = new Loader();
   var req:URLRequest = new URLRequest("Child.swf");
   /*將外部Child.swf載入到目前應用程式網域*/
   /* ***藉由將載入的 SWF 檔置於相同的應用程式網域中,便可以直接存取其類別。*** */
   /*var ldrContext:LoaderContext = new LoaderContext(false,ApplicationDomain.currentDomain);*/
   ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
   ldr.load(req);
  }

  private function completeHandler(event:Event=null):void {
   trace("@Main_1_1000621 / completeHandler() / event.target.content : " + event.target.content);
   /*取得ldr載入之Child類別實體 - A法*/
   /*var childObj:Child = event.target.content as Child; */
   
   /*載入完成後, 建構一個Child類別實體, 指定給childObj - B法*/
   var childObj:Child = new Child();
   this.addChild(childObj);
   
   /*調用childObj實體的welcome()方法, */
   var message:String = childObj.welcome("Alice");
   trace("@Main_1_1000621 / completeHandler() / message : " + message);// Hello, Alice 
   
   /*載入完成後發送自訂事件*/
   var loadedEvent:Event = new Event(LOADED);
   childObj.dispatchEvent(loadedEvent);
   trace("@Main_1_1000621 / completeHandler() / this.dispatchEvent(loadedEvent) : " + this.dispatchEvent(loadedEvent));
  }
  
  public function hello():void{
   trace("@Main_1_1000621 / hello() : Hello!!! Baby!!!");
  }
 }
}



Child
package {

 import flash.display.Sprite;
 import flash.events.Event;
 import flash.system.ApplicationDomain;
 
 public class Child extends Sprite {
  
  public var childVar:String;

  public function Child() {
   this.childVar = "@Child : I am from ChildClass";
   /*偵聽Main_1_1000621.LOADED 之載入完成事件*/
   this.addEventListener(Main_1_1000621.LOADED,loadedHandler);
   this.addEventListener(Event.ADDED_TO_STAGE,addedToStage);
   return;
  }
  
  public function loadedHandler(event:Event):void{
   trace("@Child / loadedHandler() / event.type : " + event.type);
   
   /*取得父類別實體*/
   var myParent:Main_1_1000621 = this.parent as Main_1_1000621;
   trace("@Child / loadedHandler() / myParent : " + myParent);
   
   /*調用父類實體的hello()方法*/
   myParent.hello();
   /*trace(myParent.testVar);*/
   return;
  }
  
  public function addedToStage(event:Event):void{
   this.removeEventListener(Event.ADDED_TO_STAGE,addedToStage);
   this.addEventListener(Event.REMOVED_FROM_STAGE,removedFromStage);
   
   /*Ball類別為1000621_Main_1.fla元件庫中Ball元件所綁定外部自訂類別*/
   
   /*由於, child.swf 與 1000621_Main_1.swf  位於同一網域, 且未以LoaderContext類別做其它設定*/
   /*被載入的child.swf 與載入器所在的1000621_Main_1.swf, 完成載入後, 預設將位於同一安全性網域與同一應用程式網域*/
   /* ***藉由將載入的 SWF 檔置於相同的應用程式網域中,便可以直接存取其類別。*** */
   
   /*因此,在這裡Child類別中,可以直接調用Ball類別建構式,建立其類別實體, 並調用Ball類別實體方法*/
   var myParentBall:Ball = new Ball(275,200);
   myParentBall.ballFunc();
   this.parent.addChild(myParentBall);
   return;
  }
  
  public function removedFromStage(event:Event):void{
   this.removeEventListener(Event.REMOVED_FROM_STAGE,removedFromStage);
   return;
  }

  public function welcome(_name:String):String {
   return "Hello, " + _name;
  }
 }
}


Ball
package  {
 
 import flash.display.SimpleButton;
 import flash.events.Event;
 
 public class Ball extends SimpleButton {
  
  public var thisX:Number;
  public var thisY:Number;
  
  public function Ball(_x:Number,_y:Number) {
   this.addEventListener(Event.ADDED_TO_STAGE,addedToStage);
   this.thisX = _x;
   this.thisY = _y;
   return;
  }
  
  public function addedToStage(event:Event):void{
   this.removeEventListener(Event.ADDED_TO_STAGE,addedToStage);
   this.addEventListener(Event.REMOVED_FROM_STAGE,removedFromStage);
   this.x = this.thisX;
   this.y = this.thisY;
   return;
  }
  
  public function removedFromStage(event:Event):void{
   this.removeEventListener(Event.REMOVED_FROM_STAGE,removedFromStage);
   return;
  }
  
  /*此例, Ball類別的這個ballFunc()方法,將在child.swf 被1000621_Main_1.swf 載入後,被Child類別實體調用*/
  public function ballFunc():void{
   trace("@Ball / ballFunc : I am from Ball Class");
  }
 }
 
}

2011年6月16日 星期四

flash.utils 套件__getTimer()函數

getTimer()函數
public function getTimer():int
這個方法會傳回自從 ActionScript 3.0 (AVM2) 的 Flash 執行階段虛擬機器啟動後的毫秒數。
getTimer()函數


1000615_getTimer.swf




import flash.display.MovieClip;
import flash.text.TextFormat;
import flash.text.TextField;
import fl.controls.UIScrollBar;
import fl.controls.ScrollBarDirection;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.ui.Mouse;

var vScrollBar:UIScrollBar;
this.createUIScrollBar();
this.setInfoTF();

var startTime1:Number = getTimer();
trace(this.startTime1);

click.buttonMode = true;
click.addEventListener(MouseEvent.CLICK,clickHandler);

function clickHandler(event:MouseEvent):void {
trace(getTimer()-this.startTime1);
this.addInfo(getTimer()-this.startTime1);

/*強制捲軸立即更新其捲動屬性。 - 重要,否則捲軸拖曳Bar會不見*/
this.vScrollBar.scrollPosition = this.vScrollBar.maxScrollPosition;
trace("this.vScrollBar.scrollPosition : " + this.vScrollBar.scrollPosition);
this.vScrollBar.update();
return;
}

/*設置info動態文字欄位屬性*/
function setInfoTF():void {
var format:TextFormat = new TextFormat();
format.color = 0xFFFFFF;
format.size = 24;
this.info.selectable = true;
this.info.wordWrap = true;
/*autoSize屬性不能開, 否則捲軸會不正常*/
/*this.info.autoSize = TextFieldAutoSize.LEFT;*/
this.info.setTextFormat(format);
this.info.defaultTextFormat = format;
return;
}

/*附加字串至TextField 欄位目前字串之後*/
function addInfo(_obj:*):void {
this.info.appendText(_obj.toString() + "\n");
return;
}

/*初始定義UIScrollBar屬性*/
function createUIScrollBar():void {
this.vScrollBar = new UIScrollBar();
this.vScrollBar.direction = ScrollBarDirection.VERTICAL;
this.vScrollBar.scrollTarget = info;
this.vScrollBar.move(info.x + info.width + 10, info.y);
this.vScrollBar.height = info.height;
this.addChild(this.vScrollBar);
return;
}

2011年6月10日 星期五

亂數取值存入陣列_Array.sort()方法排序(Array.NUMERIC常數、Array.DESCENDING常數)

sort(... args):Array
對陣列中的元素進行排序
此例, 亂數產生100個數字, 存入陣列, 採用Array.sort()方法排序.
Array.NUMERIC常數 : 將陣列元素視為數值,且預設為升冪排序.
Array.DESCENDING常數 : 降冪排序.

1000608_Array.sort.swf


package {

 import flash.display.MovieClip;
 import flash.text.TextFormat;
 import flash.text.TextField;
 import fl.controls.UIScrollBar;
 import fl.controls.ScrollBarDirection;
 import flash.events.MouseEvent;
 import flash.events.Event;
 import flash.ui.Mouse;

 public class ArraySort_1000608 extends MovieClip {

  private var figureArr:Array;
  private var vScrollBar:UIScrollBar;

  public function ArraySort_1000608() {
   this.init();
   this.addMouseEvent();
   return;
  }

  private function init():void {
   this.vScrollBar = new UIScrollBar();
   this.createUIScrollBar();
   return;
  }

  private function addMouseEvent():void {
   this.newRandomArrayBtn.buttonMode = true;
   this.newRandomArrayBtn.addEventListener(MouseEvent.CLICK,this.iniRandomArray);
   this.sortArrayNumericBtn.buttonMode = true;
   this.sortArrayNumericBtn.addEventListener(MouseEvent.CLICK,this.sortArrayNumeric);
   this.sortArrayDescendingBtn.buttonMode = true;
   this.sortArrayDescendingBtn.addEventListener(MouseEvent.CLICK,this.sortArrayDescending);
   return;
  }

  /*亂數取值100次*/
  private function iniRandomArray(event:MouseEvent):void {
   this.figureArr = new Array();
   for (var i:uint=0; i<100; i++) {
    this.getRandomValue();
   }
   this.showInfo();
   return;
  }

  /*亂數取值, 存入陣列*/
  private function getRandomValue():void {
   var newFigure:uint = Math.ceil(Math.random() * 1000);
   this.figureArr.push(newFigure);
   return;
  }

  private function sortArrayNumeric(event:MouseEvent):void {
   if(this.figureArr != null){
    /*將元素視為數值, 且升冪排序 - Array.NUMERIC ; 將元素視為數值,且預設升冪排序*/
    this.figureArr.sort(Array.NUMERIC);
    this.showInfo();
   }
   return;
  }

  private function sortArrayDescending(event:MouseEvent):void {
   if(this.figureArr != null){
    /*將元素視為數值, 且降冪排序 - Array.DESCENDING : 降冪排序*/
    this.figureArr.sort(Array.NUMERIC | Array.DESCENDING);
    this.showInfo();
   }
   return;
  }

  private function showInfo():void {
   trace(figureArr + "\n**************************************************");
   addInfo(figureArr + "\n**************************************************");
   /*強制捲軸立即更新其捲動屬性。 - 重要,否則捲軸拖曳Bar會不見*/
   this.vScrollBar.scrollPosition = this.vScrollBar.maxScrollPosition;
   trace("this.vScrollBar.scrollPosition : " + this.vScrollBar.scrollPosition);
   this.vScrollBar.update();
   return;
  }

  /*設置info動態文字欄位屬性*/
  private function setInfoTF():void {
   var format:TextFormat = new TextFormat();
   format.color = 0x000000;
   this.info.selectable = true;
   this.info.wordWrap = true;
   /*autoSize屬性不能開, 否則捲軸會不正常*/
   /*this.info.autoSize = TextFieldAutoSize.LEFT;*/
   this.info.setTextFormat(format);
   this.info.defaultTextFormat = format;
   return;
  }

  /*附加字串至TextField 欄位目前字串之後*/
  private function addInfo(_obj:*):void {
   this.info.appendText(_obj.toString() + "\n");
   return;
  }

  /*初始定義UIScrollBar屬性*/
  private function createUIScrollBar():void {
   this.vScrollBar = new UIScrollBar();
   this.vScrollBar.direction = ScrollBarDirection.VERTICAL;
   this.vScrollBar.scrollTarget = info;
   this.vScrollBar.move(info.x + info.width + 10, info.y);
   this.vScrollBar.height = info.height;
   this.addChild(vScrollBar);
   return;
  }
 }

}



適用於 Adobe® Flash® Platform 的 ActionScript® 3.0 參考
最上層 - Array - sort()方法

2011年6月9日 星期四

AS3中Object的資料類型

Object 資料類型

摘自上述 Adobe HELP 網址(學習 ActionScript 3.0 > ActionScript 語言和語法 > 資料類型 > Object 資料類型)
ActionScript 3.0 版 Object 資料類型的不同之處包含以下三方面:
第一,Object 資料類型不再是指定給沒有類型註釋之變數的預設資料類型;
第二,Object 資料類型不再包含 undefined 值,過去這是 Object 實體的預設值;
第三,在 ActionScript 3.0 中,Object 類別之實體的預設值是 null。

在舊版 ActionScript 中,沒有類型註釋的變數會自動指定為 Object 資料類型;而在 ActionScript 3.0 中已非如此,現在 ActionScript 3.0 包含真正不具類型變數的概念。沒有類型註釋的變數現在會視為不具類型。若要讓程式碼的讀者清清楚楚地知道,您是刻意要讓變數保持為不具類型,則可以使用類型註釋的星號 (*) 符號,這個符號等於省略類型註釋。

只有不具類型的變數可以存放 undefined 值。若嘗試將 undefined 值指定給具有資料類型的變數,執行階段會將 undefined 值轉換為該資料類型的預設值。例如 Object 資料類型 (預設值為 null),表示如果您嘗試將 undefined 指派為 Object 實體,則值會轉換成 null。

*******************************************************************************

以下簡例 :

var obj1:Object;
trace(obj1);//null

var obj2:Object = undefined;
trace(obj2);//null

var any1:*;
trace(any1);//undefined

var any2;
trace(any2);//undefined

2011年6月8日 星期三

深度交換_DisplayObjectContainer.swapChildrenAt()

swapChildrenAt(index1:int, index2:int)
在子清單的兩個指定索引位置,替換子物件的 z 順序 (深度階層,由前至後順序)。
UIScrollBar
UIScrollBar.scrollPosition = UIScrollBar.maxScrollPosition;
scrollPosition : 會取得或設定目前的捲動位置,並更新縮圖的位置。
maxScrollPosition : 會取得或設定代表最高捲動位置的數字。
UIScrollBar.update();
會強制捲軸立即更新其捲動屬性。

※此例, 點擊舞台,透過 swapChildrenAt()方法, 物件bbb與ccc交換深度,右邊TextField文字欄位info會呈現bbb與ccc深度上下順序. (文字欄位中, 先trace低索引, 再trace高索引)
※UIScrollBar捲軸被附加綁定到info文字欄位上,當字串資料超出欄位底部,捲軸將持續捲至捲動最大值位置並更新畫面,以便閱讀最新字串訊息.

1000608_displayObjectContainer.swapChildrenAt.swf


import fl.controls.UIScrollBar;
import fl.controls.ScrollBarDirection;

var vScrollBar:UIScrollBar = new UIScrollBar();
this.setInfoTF();
this.createUIScrollBar();

trace("this.numChildren : " + this.numChildren);
this.addInfo("this.numChildren : " + this.numChildren);
this.getSpriteIndex();

this.stage.addEventListener(MouseEvent.MOUSE_DOWN,swap);
function swap(event:MouseEvent):void {
 /*深度交換*/
 this.swapChildrenAt(this.getChildIndex(bbb),this.getChildIndex(ccc));
 trace("****************");
 this.getSpriteIndex();
}

/*取得為Sprite類別物件且不為UIScrollBar 的實體*/
/*UIScrollBar 繼承自Sprite → UIScrollBar →ScrollBar →UIComponent →Sprite*/
function getSpriteIndex():void {
 for (var i:uint=0; i < this.numChildren; i++) {
  if (this.getChildAt(i) is Sprite && !(this.getChildAt(i) is UIScrollBar)) {
   trace("索引 " + i + " : " + this.getChildAt(i).name);
   addInfo("索引 " + i + " : " + this.getChildAt(i).name);
  }
 }
 addInfo("**************");
 /*強制捲軸立即更新其捲動屬性。 - 重要,否則捲軸拖曳Bar會不見*/
 this.vScrollBar.scrollPosition = this.vScrollBar.maxScrollPosition;
 trace(this.vScrollBar.scrollPosition);
 this.vScrollBar.update();
 return;
}

/*設置info動態文字欄位屬性*/
function setInfoTF():void {
 var format:TextFormat = new TextFormat();
 format.color = 0x000000;
 this.info.selectable = true;
 this.info.wordWrap = true;
 /*autoSize屬性不能開, 否則捲軸會不正常*/
 /*this.info.autoSize = TextFieldAutoSize.LEFT;*/
 this.info.setTextFormat(format);
 this.info.defaultTextFormat = format;
 return;
}

/*附加字串至TextField 欄位目前字串之後*/
function addInfo(_obj:*):void {
 this.info.appendText(_obj.toString() + "\n");
 return;
}

/*初始定義UIScrollBar屬性*/
function createUIScrollBar():void{
 this.vScrollBar = new UIScrollBar();
 this.vScrollBar.direction = ScrollBarDirection.VERTICAL;
 this.vScrollBar.scrollTarget = info;
 this.vScrollBar.move(info.x + info.width + 10, info.y);
 this.vScrollBar.height = info.height;
 this.addChild(vScrollBar);
 return;
}

交換深度_DisplayObjectContainer.swapChildren()

swapChildren(child1:DisplayObject, child2:DisplayObject):void

替換兩個指定子物件的 z 順序 (深度階層,由前至後順序)。

※簡單實例:點擊舞台stage, 舞台上兩物件ccc與bbb交換深度

1000608_displayObjectContainer_1.swf


this.stage.addEventListener(MouseEvent.MOUSE_DOWN,swap);
function swap(event:MouseEvent):void{
this.swapChildren(ccc,bbb);
}



DisplayObjectContainer.getObjectsUnderPoint()方法_取得指定point座標上的物件

getObjectsUnderPoint()方法
public function getObjectsUnderPoint(point:Point):Array
傳回位於指定點底下,且屬於此 DisplayObjectContainer 實體之子系 (或孫系,以下類推) 的物件陣列。

※此例, 以DisplayObjectContainer.getObjectsUnderPoint()方法, 取得與(200,200)座標重疊的物件陣列.
※aaa、bbb、ccc三個Shape物件配置於元件庫中, 並分別與外部extends Sprite的三個類別AAA、BBB、CCC綁定

1000607_getObjectsUnderPoint.swf


※ trace出來的結果 :
[object Shape],[object Shape],[object TextField]
0 : instance3 : [object Shape]
1 : instance9 : [object Shape]
2 : instance10 : [object TextField]

package  {
 
 import flash.display.MovieClip;
 import flash.geom.Point;
 import flash.display.DisplayObjectContainer;
 import flash.display.Sprite;
 
 public class getObjectsUnderPoint_1000607 extends MovieClip {
  
  public var container:Sprite;
  public var aaa:Sprite;
  public var bbb:Sprite;
  public var ccc:Sprite;
  private var point:Point;
  
  public function getObjectsUnderPoint_1000607() {
   this.container = new Sprite();
   this.addChild(this.container);
   this.createObjects();
   this.point = new Point(200,200);
   var objectsArr:Array = this.getInfo(this.point);
   this.showInfo(objectsArr);
   return;
  }
  
  private function showInfo(_objectsArr:Array):void{
   trace(_objectsArr);
   for (var i:String in _objectsArr){
    trace(i + " : " + _objectsArr[i].name + " : " + _objectsArr[i]);
   }
   /*trace結果
    [object Shape],[object Shape],[object TextField]
    0 : instance3 : [object Shape]
    1 : instance9 : [object Shape]
    2 : instance10 : [object TextField]*/
   return;
  }
  
  private function createObjects():void{
   this.aaa = this.setObjects(aaa,AAA,264,226);
   this.bbb = this.setObjects(bbb,BBB,350,158);
   this.ccc = this.setObjects(ccc,CCC,188,154);
   return;
  }
  
  private function setObjects(_instance:*,_class:Class,_xPos:Number,_yPos:Number):Sprite{
   _instance = new _class();
   _instance.x = _xPos;
   _instance.y = _yPos;
   _instance.name = _instance.toString();
   this.container.addChild(_instance);
   /*trace(_instance);*/
   return _instance;
  }
  
  private function getInfo(_point:Point):Array{
   var objectsArr:Array = this.getObjectsUnderPoint(_point);
   return objectsArr;
  }
 }
 
}

2011年6月7日 星期二

利用遞迴函式巡訪容器中所有子物件,並過濾掉特定類型物件

1000606_recursion_1.swf


/*利用遞迴函式巡訪容器中所有子物件,並過濾掉特定類型物件*/

this.setInfoTF();
var indentSpace:String = "    ";
this.callOn(this, indentSpace);

function callOn(_doc:DisplayObjectContainer,_indentSpace:String):void {
if (_doc is DisplayObjectContainer) {
for (var i:uint; i<_doc.numChildren; i++) {
/*過濾掉Shape和TextField*/
if(_doc.getChildAt(i) is Shape != true && _doc.getChildAt(i) is TextField != true){
trace(_indentSpace + _doc.getChildAt(i).name + " : " + _doc.getChildAt(i));
this.addInfo(_indentSpace + _doc.getChildAt(i).name + " : " + _doc.getChildAt(i));
}
/*子物件中若還有容器,則調用本身函式callOn() - 遞迴*/
if (_doc.getChildAt(i) is DisplayObjectContainer) {
var tmpdoc:DisplayObjectContainer = _doc.getChildAt(i) as DisplayObjectContainer;
callOn(tmpdoc,_indentSpace + "    ");
}
}
}
return;
}

function setInfoTF():void {
var format:TextFormat = new TextFormat();
format.color = 0x222299;
this.info.selectable = false;
this.info.wordWrap = true;
this.info.autoSize = TextFieldAutoSize.LEFT;
this.info.setTextFormat(format);
this.info.defaultTextFormat = format;
return;
}

function addInfo(_obj:*):void {
this.info.appendText(_obj.toString() + "\n");
return;
}

2011年6月5日 星期日

InteractiveObject預設無法接收DOUBLE_CLICK事件__※doubleClickEnabled屬性

InteractiveObject 預設無法接收 DOUBLE_CLICK 事件,因為 InteractiveObject.doubleClickEnabled 屬性預設為false。
所以必須將 doubleClickEnabled 屬性設為 true,如此,繼承自 InteractiveObject 的實體,在其實體範圍內的 DOUBLE_CLICK 點擊事件將被接收。




this.setInfoTF();
/**/
this.square.doubleClickEnabled = true;
this.square.buttonMode = true;
this.square.addEventListener(MouseEvent.DOUBLE_CLICK,mouseEventHandler);
/**/
this.stage.addEventListener(MouseEvent.MOUSE_DOWN,mouseEventHandler);

function mouseEventHandler(event:MouseEvent):void {
/*trace("event.type : " + event.type);*/
switch (event.type) {
case "mouseDown" :
trace("event.type : " + event.type);
break;

case "mouseUp" :
break;

case "click" :
trace("event.type : " + event.type);
break;

case "doubleClick" :
trace("event.type : " + event.type);
break;

default :
break;
}

this.addInfo(event.type);
return;
}

function setInfoTF():void {
var format:TextFormat = new TextFormat();
format.color = 0xffff00;
this.info.selectable = false;
this.info.wordWrap = true;
this.info.autoSize = TextFieldAutoSize.LEFT;
this.info.setTextFormat(format);
this.info.defaultTextFormat = format;
return;
}

function addInfo(_obj:*):void {
this.info.appendText(_obj.toString() + "\n");
return;
}



移動模式測試 & 多物件跟隨目標轉向

1000605_collision_1a.swf <--- 緩進





1000605_collision_1b.swf <--- 無緩進