Tag Archive for 'AS3.0'

How to reduce the complie time with Flash IDE

Actionscript 의 덩치가 커지면서 Flash IDE 를 기본 액션에디터로 사용하는 것보다 인텔리젼트 기능이 탑재된 외부 에디터를 이용해 프로그래밍하는 것이 작업의 효율성 측면에서 상당한 개선 얻어올 수 있다.  이 포스팅 내용은 compile 도구로 반드시 Flash IDE 를 사용한다는 것을 전제로 한 내용이다.

작업 환경 조합으로는  Flash IDE + Eclipse(FDT) , Flash IDE  + Flashdevelop 과 같은 경우의 조합으로 많이 사용하는데 이런 외부 에디터를 사용할 경우 자동으로 syntax 를 사전에 체크해줘 compile 타임에 발생할 수 있는 코드의 문제점을 알아차릴 수 있다. 하지만 compile 을 위해 Flash IDE 와 외부에디터의 창을 이러저리 왔다갔다 하거나 compile 을 기다리는 시간 등,  compile 전체에 소모되는 시간이 생각보다 길다라고 느껴질 때가 있을것이다. 특히 수많은 클래스의 사용으로 더욱 그 시간이 길어질 때 더할 것이다. 그래서 이럴경우 compile 시간을 대폭(?) 줄일 수 있는 간단한 tip 하나를 소개할까 한다.

Flash IDE 에서 File -publish Settings… – Flash Tab – Settings…  를 실행하면 위와 같은 화면을 볼 수 있을것이다. 위 radio button 중 Warnings Mode 가 기본적으로는 체크되어있는데 이를 해제하자. Warnings Mode 는 As2.0 코드에서 As3.0 코드로 업데이트할때 발생할 수도 있는 Migration issue 를 리포팅해주는 기능이다.

따라서 체크를 해제하더라도 특별히 문제될건 없다. 이 기능을 해제하게 되면 컴파일 시간이 몰라볼 정도로 빨라지게 된다. 물론 영상이나 폰트를 임베드해서 컴파일이 오래걸리는 경우는 해당사항이 없다.  많은  클래스 파일을 사용하는 컨텐츠일 수록 효과가 크다.

quad core  , ram 4 GB , AS file 60개 정도의 환경으로 테스트 해본 결과 Warnings  Mode 를 체크를 했을 경우 16 sec 정도 걸리던 시간이 해제했을 경우에는 4 sec 정도로 4배이상 시간이 빨라졌다. 특별히 compile 안정성에 문제가 되는것이 아닌것 같으니 Flash IDE 를 사용하면서 class 를 많이 구성하여 사용하는 사람이라면 compile 에 걸리는 시간을 많이 줄일 수 있을 것이다.

Tween Engine Class -AS3.0

flash 를 사용하면서 가장 많이 사용하는 부분은 아마도 트윈 부분일 것이다. 오브젝트의 속성값을 변경하면서 수많은 느낌의 모션을 만들수 있었다.
기존에 포함되어 있는 Tween 클래스는 많은 사용자들이 이런  다양한 트윈을 손쉽게 구현할 수 있게 해준다. 하지만, 생각보다 많은 기능들이 포함되어있어서 덩치도 클뿐더러 구현하는 코드 자체도 길어지게 되었다.
또한 AS3.0에서는 garbage collection 의 동작으로 인해 참조값이 없는 객체에 대해서는 collector 에 의해 메모리 수집의 대상이 되기 때문에 트윈클래스의 인스턴스를 지역변수로 참조하여 사용하게 되면 뜻하지 않게 트윈이 완료되기 이전에 객체가 사라지는 문제가 발생할 수도 있다..
따라서 이런 문제를 해결하기 위해 지역변수보다 좀더 높은 클래스 단계의 scope 의 참조를 사용하게 되는데 이럴경우 불필요하게 많은 참조 변수들을 클래스가 가지게되여 메모리를 소비하게 된다.

그리고 가장 빈번히 사용하게 되는 트윈의 경우 일일이 이벤트 핸들러 함수를 구현하기가 여간 번거로운게 아니다. 코드자체의 길이도 길어질 뿐만 아니라 가독성 측면에서도 떨어지는게 사실이다.

이런 문제를 조금이나마 해결하고자 이전 버전의 Tween 클래스를 기반으로 AS3.0 으로 컨버팅하였다.

기본적은 틀은 이전에 AS2.0 으로 구현한 로직과 큰 차이는 없다.
참조값을 유지하기 위해 전역속성으로 트윈을 적용하였고 객체를 생성하지 않아도 되기 때문에 한결 코드도 간결해졌다.

***** update(2007.10.30) ******

pause 와 resume 기능을 추가
원하는 오브젝트의 트윈에 적용가능함

pause(), pauseAll() 나 resume(), resumeAll() 를 사용하여 전체또는 부분적인 트윈을 제어할 수 있다.

<TweenEngine class>

package com.dstrict.ub.utils.transitions{
 
 import flash.display.DisplayObject;
 import flash.events.*;
 import flash.utils.Dictionary;
 /**
  DisplayObject tween class
  트윈을 적용할 속성의 갯수에 관계없이 일괄적으로 적용가능
  마지막 parameter 로 정해진 형식의 이벤트 오브젝트 적용시 이벤트 시작과 끝을 tracking 할 수 있음. 
 
  @example code
  <code>
 
   function onTweenStart(param):void{
    trace("onTweenStart----&gt;"+param);
   }
 
   function onTweenFinish(param):void{
    trace("onTweenFinish----&gt;"+param);
   }
 
TweenEngine.start(circle,{x:400},Regular.easeOut,30,{onStart:onTweenStart,
onStartParams:["circle"],onFinish:onTweenFinish,onFinishParams:["circle"]});
 </code>
 
 */
 
 public class TweenEngine {
   private static var _referContainer : Dictionary=new Dictionary(true);
  /**
   @param targetObj : DisplayObject , tween 적용할 오브젝트
   @param tweenProperty : Object , 속성오브젝트 ex. {x:100,y:100,alpha:1}
   @param easing : Function , 이징함수
   @param duration : int , 지속프레임
   @param rest : Obejct , [optional]  event object
   ex. {onStart:onTweenStart,onStartParams:[],onFinish:onTweenFinish,onFinishParams:[]}
  */
  public static function start(targetObj:*,tweenProperty:Object,easing:Function,duration:int,...rest):void{
   var time:int=1;
   var beginning:Array=new Array();
   var change:Array=new Array();
   var isCreated : Boolean=false;
   var displayObj : DisplayObject;
 
   TweenEngine.stop(targetObj);
 
   if(!(targetObj is DisplayObject)){
      displayObj = new Shape();
      isCreated=true;
    }else{
      displayObj = targetObj;
     }
 
   for(var i:* in tweenProperty){
       beginning.push(targetObj[i]);
       change.push(tweenProperty[i]-targetObj[i]);
   }
 
   if(rest.length &amp;&amp; rest[0].onStart){
    var eventStartObject:Object=new Object();
    eventStartObject.onStart=rest[0].onStart;
    eventStartObject.onStartParams=rest[0].onStartParams;
 
    //onStart event
    eventStartObject.onStart.apply(eventStartObject,eventStartObject.onStartParams);
   }
 
   //Nested function
   var update:Function=function(){
    var objIdx:int=0;
      for(var i:* in tweenProperty){
       targetObj[i]=easing(time,beginning[objIdx],change[objIdx],duration);
       objIdx++;
      }
      time++;
      if(time&gt;duration){
      delete _referContainer[displayObj];
       displayObj.removeEventListener(Event.ENTER_FRAME,update);
       if(isCreated) displayObj=null;
 
       if(rest.length &amp;&amp; rest[0].onFinish){
        var eventFinishObject:Object=new Object();
        eventFinishObject.onFinish=rest[0].onFinish;
        eventFinishObject.onFinishParams=rest[0].onFinishParams;
 
        //onFinish event
        eventFinishObject.onFinish.apply(eventFinishObject,eventFinishObject.onFinishParams);
       }
     }
   }
     _referContainer[displayObj] = update;
      displayObj.addEventListener(Event.ENTER_FRAME,update);
  }
 
  //Update 2007.10.30
  /**
   * Pause a tweening for a given object.
   */
  public static function  pause(targetObj : *) : void {
   if(targetObj.hasEventListener(Event.ENTER_FRAME)) {
    targetObj.removeEventListener(Event.ENTER_FRAME, _referContainer[targetObj]);
   }
  }
 
  /**
   * Pause all tweenings on the engine.
   */
 public static function pauseAll() : void {
   for(var item:* in _referContainer) {
    if(item.hasEventListener(Event.ENTER_FRAME)) {
     item.removeEventListener(Event.ENTER_FRAME, _referContainer[item]);
    }
   }
  }
 
  /**
   * Resume a tweening from a given object.
   */
  public static function resume(targetObj : *) : void {
   if(_referContainer[targetObj] != null) {
    targetObj.addEventListener(Event.ENTER_FRAME, _referContainer[targetObj]);
   }
  }
 
  /**
   * Resume all tweenings on the engine.
   */
  public static function resumeAll() : void {
   for(var item:* in _referContainer) {
    if(_referContainer[item] != null) {
     item.addEventListener(Event.ENTER_FRAME, _referContainer[item]);
    }
   }
  }
 
  /**
   *  Stop a tweening for a given object
   */
  public static function stop(targetObj : *) : void {
   if(targetObj.hasEventListener(Event.ENTER_FRAME)) {
    targetObj.removeEventListener(Event.ENTER_FRAME, _referContainer[targetObj]);
    delete _referContainer[targetObj];
   }
  }
 
  /**
   * Remove all tweenings from the engine.
   */
  public static function stopAll() : void {
   for(var item:* in _referContainer) {
    if(item.hasEventListener(Event.ENTER_FRAME)) {
     item.removeEventListener(Event.ENTER_FRAME, _referContainer[item]);
     delete _referContainer[item];
    }
   }
  }
 
 }
}
 
import com.dstrict.ub.utils.transitions.*;
import fl.motion.easing.*;
 
TweenEngine.start(circle,{x:400,y:300},Cubic.easeInOut,20,{onStart:onTweenStart,onStartParams:["circle start"],
onFinish:onTweenFinish,onFinishParams:["circle finish"]});
 
//----&gt; 마지막 오브젝트 값은 이벤트 핸들러를 참조하는 값으로 옵션사항이다., 사용시 이벤트 오브젝에서 함수이름을 onStart , onFinish 로
            이벤트 파라미터를 onStartParams,onFinishParams 로 키값을 사용해야만 한다.
 
 function onTweenStart(param):void{
   trace("onTweenStart----&gt;"+param);
}
 
function onTweenFinish(param):void{
  trace("onTweenFinish----&gt;"+param);
}
 
//stop tween
stage.addEventListener(MouseEvent.CLICK,onStop);
function onStop(evt:MouseEvent){
 TweenEngine.stop(circle);
}

download sample

How to access to stage and root (AS3.0)

AS3.0 에서 사용되는 stage 와 root 의 개념은 AS2.0 버전과는 차이가 있다.

우선 stage 를 살펴보면 이전 버전에서는 stage 오브젝트는 static class 로서 주로 movie size 나 onResize 이벤트를 처리하는데 사용하였지만 새롭게 바뀐 AS3.0 에서는 플래시 무비에 존재하는 모든 displayObject 를 담을수 있는 최상위 컨테이너 개념이 첨가되었다.
이는 어떻게 생각하면 기존의 _root 와 같이 생각할 수도 있다. 하지만 바뀐 모델에 있어서 stage 속성은 인스턴스 속성이다. 다시말해, 전역적으로 접근할 수 없고 반드시 displayObject 의 인스턴스 속성으로서만 참조가 가능하다는 이야기이다. 또한 DisplayObject 가  스크린상의 timeline 이나 display list 에 등록하지 않는다면 null 값을 가지게 된다. (Document class 와 screen 상에 보여지는 오브젝트는 제외)
이런 점이 stage 속성을 사용하는데 있어 상당히 제약사항으로 작용하게 된다. 만약 DisplayObject 가 아닌 다른 Object 를 사용할때 stage 속성은 정의된 속성이 아니므로 constructor 에  stage 속성값을 parameter 로 넘겨주는 방식으로 사용할 수 밖에 없다.

<non-display object classes >

package {

import flash.display.Stage;public class CustomObject {

private var _stage:Stage;

public function CustomObject(stage:Stage) {
_stage= stage;
}
}
}

root 는 상황에 따라 다를 수 있지만 일반적으로 현재의 flash movie 에서 main timeline 을 참조할 수 있는 DisplayObject 속성이다. 다시말해 상대적인 최상위 DisplayObject 를 참조한다.
이전의 _root 속성은 전역속성으로서 가장 최상의 컨테이너를 참조하였기 때문에 로더를 통해 불러왔을경우 그 갯수에 따라 _root 의 참조값이 변하였다. 하지만 root 속성은 현재의 flash movie 를 기준으로 참조값을 얻어오기 때문에 각 swf 에 해당하는 main timeline 의 참조값이다. 즉, 이전버전에서 _lockroot 를 적용한 것 같이 root 속성을 상대적으로 참조할 수 있다. 모든 displayObject 가 각각 timeline 의 참조값을 가질 수 있다는 의미이다.
하지만 root 도 stage 속성과 마찬가지로 인스턴스 속성이다. 따라서 stage 의 제한사항을 그대로 가지고 있다.

따라서 이런 문제점들을 해결하기 위해서는 위와같이 각각의 참조값을 parameter 로 넘겨주는 방법과 초기화 함수를 실행하여 addChild 이후에 참조할 수 있도록 처리해야한다.
또다른 방법으로는 Document class 를 활용하여 전역속성으로 만드는 것이다.

Document class 에서는 Stage 에 자동으로 추가되는 main timeline 으로 인해 생성되자마자 stage 속성과 root 속성을 참조할 수 있다.

<static 속성으로 참조할 수 있는 MainStage class>

package {

import flash.display.DisplayObject;
import flash.display.*;

public class MainStage extends MovieClip {
public static var stage:Stage;
public static var root:DisplayObject;

public function MainStage() {
MainStage.stage = this.stage;
MainStage.root = this.root;
}
}
}

<Document class>

package {

public class DocumentClass extends MainStage {

public function DocumentClass() {

}
}
}

위와 같이 document class 에서 MainStage class 을 상속받아 사용하면 어느 오브젝트에서라도  전역적으로 stage를 참조 할 수 있다.
하지만 이는 전역속성으로서 의미가 있는 stage 에만 유용할 뿐 각기 다른 root 속성을 참조하기에는 문제가 있다.
root 속성 참조 대한 문제는 ADD_TO_STAGE 이벤트를  이용하여 오브젝트마다 일일이 체크하는 방법이나 아니면 초기화 함수를 실행하여 처리하는 방법밖에 없는것 같다.(어떤 다른 방법이 있을까?????)

timeline 으로 부터 종속되지 않도록 stage 속성과 root 속성을 추가한것은 참 좋은 방법인것 같다. 하지만 그로 인해 개발자들이 일일이 신경쓰지 않으면 안되는 것들이 정말 많이 생긴것 같다.

timeline 과 class……….플래시의 특성상 종속적일 수 밖에 없는데……
어떤 것이 더 나은 방법일까?….의구심이 든다.

…(rest) parameter (AS3.0)

가변적인 메소드의 parameter 갯수를 이용하려면 AS2.0 버전까지는 arguments 오브젝트를 사용하여 임의의 parameter 에 접근할 수 있었다. 하지만 AS3.0 에서는 컴파일러의 좀더 철저한 데이타 타입의 체크와 parameter 관리에 의해 기존의 방법을 쓸 수가 없게 되었다.

<AS2.0>
function parameterTest():Void{
trace(arguments.length)  //parameter 갯수를 알수 있음
}

parameterTest(1,2,3);
result–> 3

<AS3.0>
function parameterTest():void{
trace(arguments.length)
}

parameterTest(1,2,3);
result–> compiler error  : Incorrect number of arguments.

AS3.0 에서는 메소드 정의시 parameter 갯수와 호출시 parameter 갯수가 일치해야만 한다.
그렇지 않으면 위와 같이 arguments 갯수에 오류가 있다고 에러를 발생시키게 된다.
이를 위해 …(rest) paremeter 구문을 새롭게 제공하였는데 사용법은 단순히 … 뒤에 사용자가 원하는 parameter array 이름을 써주면 된다.

function parameterTest(…param):void{
trace(param.length) // param 은 배열 타입이다.
}

다른 parameter 와 같이 사용하려면
function parameterTest(str1:String,str2:String,…param):void{
//…..statements
}
마지막에 …(rest) parameter 를 써주면 된다.

주의할 점은 위 방법을 사용하면서 arguments 오브젝트를 동시에 사용할 수 없다는 점이다.

Book-Actionscript 3 with Design Patterns

오래전에 사놓고 프로젝트 때문에 읽어보지 못한 책들을 이제서야 한두권씩 찾아서 읽기 시작했다.
1년 전까지만해도 왜 플래시로는 design pattern 책이 나오질 않을까?….우리나라는 그렇다 치더라도 외국에는 충분히 나왔어야할 내용의 책인데…하고 생각했던 적이 있다. 물론 이전에도 패턴에 대해 언급했던 책은 있었지만 전문적으로 플래시를 이용하여 적용한 패턴 책은 찾아 볼 수 없었다.

이제 AS3.0 나 발표된지도 어느정도 지나서인지 관련책들이 많이 보이는것 같다. 안타깝게도 해외에서만 말이다. 처음 이책을 발견하고 그자리에서 구매해버렸다. 자그마치 $50 달러….

1036283543아직 자세히 살펴보지는 못했지만 내가 기대하고 있던 내용의 책이였다. AS3.0 으로 바뀌면서 문법자체가 자바랑 상당부분 비슷하게 바뀌었기 때문에 문법적으로 자바 디자인 패턴책과 엄청난 차이가 있는것은 아니다. 하지만 플래시만의 고유의 영역에 있어서 자바나 다른 언어와는 다른 구조적인 이유로 인해 발생하는 패턴 적용의 이슈들을 어느정도 다뤄줬기 때문에 상당히 유용할것 같다.

많은 플래시 개발자들이 아직까지 플래시로 무슨 디자인패턴까지 쓰냐고 …. 아직까지 인터페이스의 개념조차도 상당수의 플래시 개발자들에게 생소한 마당에 디자인 패턴이라니…. 하면서 효용성에 있어 의문을 제기한다.

물론 나도 이점에 있어서 어느정도 동의한다. 아직까지 플래시 개발에 있어서 기존 응용프로그램 개발만큼의 큰 규모의 프로젝트가 적었기도 했고 대부분 소규모 웹사이트 개발이 전부였을 것이다.
그래서 그런지 플래시 개발을 여러사람이 공동으로 진행했다라는 소리는 좀처럼 들어보지 못한것 같다. 또한 플래시 툴의 특성상 디자인 베이스의 사용자들이 개발자로 전향했던 경우가 많아서 정통 개발자들의 관심인 여러가지 문제에 있어 플래시 개발자들에겐 논외의 대상일 수도 있다.

그렇지만 앞으로의 actionscript 는 그런 문제에 있어 먼저 개발자들이 인지하고 좀더 구조적인 프로그래밍 스킬을 쌓아가지 않으면 안되는 모양새인것 같다.
해외에서는 이미 상당수의 개발자들이 플래시 오픈소스 프로젝트를 진행하고 있다.
혼자서 하는것이 아닌 여러사람이 공동으로 개발에 참여하고 결과물을 내놓는 것이다. 이들이 이렇게 까지 할수 있는 이유 중에 하나는 바로 의사소통을 할수 있는 도구…..그들 나름대로의 프레임워크가  존재하기 때문이다. 이런 프레임워크 정의는 어느정도 구조적인 개발의 전제하에 진행되어야할 것이다.

플래시….참 어떻게 보면 쉬운 툴이고 어떻게 보면 너무 어려운 툴이다.
요즘들어 적어도 Interaction Designer 에게는 플래시 그 이외의 배워야 할것이 너무 많다는걸 느낀다. 뭔가 새로운걸 만들어야한다는 생각과….계속 발전하는 기술…..새로운 기술을 익혀 적용하기에도 바쁜데 남들과 다른 그 어떤 새로운 것을 만들어야 한다는 생각이 들때면 가끔 슬퍼질때가 있다….

예술은 아는 만큼 보이고 아는만큼 느낄수 있다고 한다.
플래시도 알면 알수록 내가 가야할 길이 너무 멀다라는걸 새삼 느낀다.

Table of Contents:

Part I – Successful Projects
1. How to Design Applications
2. Programming to Interfaces

Part II – Patterns
3. MVC
4. Singleton
5. Factory (Abstract Factory and Factory Method)
6. Proxy
7. Iterator
8. Composite
9. Decorator
10. Command
11. Memento
12. State

Part III – Advanced ActionScript Topics
13. Working with Events
14. Sending and Loading Data
15. E4X (XML)
16. Regular Expressions

책정보보기

Bound methods in AS3.0

<These quotes are from the Actionscript 3.0 language reference>

A bound method, sometimes called a method closure, is simply a method that is extracted from its instance. Examples of bound methods include methods that are passed as arguments to a function or returned as values from a function. New in ActionScript 3.0, a bound method is similar to a function closure in that it retains its lexical environment even when extracted from its instance. The key difference, however, between a bound method and a function closure is that the this reference for a bound method remains linked, or bound, to the instance that implements the method. In other words, the this reference in a bound method always points to the original object that implemented the method. For function closures, the this reference is generic, which means that it points to whatever object the function is associated with at the time it is invoked.
Understanding bound methods is important if you use the this keyword. Recall that the this keyword provides a reference to a method’s parent object. Most ActionScript programmers expect that the this keyword always refers to the object or class that contains the definition of a method. Without method binding, however, this would not always be true.
In previous versions of ActionScript, for example, the this reference did not always refer to the instance that implemented the method. When methods are extracted from an instance in ActionScript 2.0, not only is the this reference not bound to the original instance, but also the member variables and methods of the instance’s class are not available. This is not a problem in ActionScript 3.0 because bound methods are automatically created when you pass a method as a parameter. Bound methods ensure that the this keyword always references the object or class in which a method is defined.

The following code defines a class named ThisTest, which contains a method named foo() that defines the bound method, and a method named bar() that returns the bound method. Code external to the class creates an instance of the ThisTest class, calls the bar() method, and stores the return value in a variable named myFunc.

class ThisTest {
private var num:Number = 3;
function foo () { // bound method defined
trace ("foo's this: " + this);
trace ("num: " + num);
}
function bar () {
return foo; // bound method returned
}
}
var myTest:ThisTest = new ThisTest();
var myFunc:Function = myTest.bar();
trace(this); // output: [object global]
myFunc();
/* output:
foo's this: [object ThisTest]
output: num: 3 */

The last two lines of code show that the this reference in the bound method foo() still
points to an instance of ThisTest class, even though the this reference in the line just before
it points to the global object. Moreover, the bound method stored in the myFunc variable still
has access to the member variables of the ThisTest class. If this same code is run in
ActionScript 2.0, the this references would match and the num variable would be undefined.
<These quotes are from the Actionscript 3.0 language reference>

도큐먼트 문서에서 개인적으로 AS3.0 이 새롭게 지원하는 기능중에 가장 좋았던 것 중에 하나다.
더이상 중첩된 메서드 안에서 클래스 안에 선언된 메서드의 참조값을 알아내기 위해 지역변수로 참조를 하지 않아도 된다.
코드 가독성 측면에 있어서 좋지 않았었는데 이젠 끝까지 메서드 선언된 참조 위치를 가지고 있으니 파라미터나 리턴 값에 의해 참조값이 바뀔 염려는 없어진 셈이다.

Mouse Event in AS3.0

기존에 AS2.0 까지는 MovieClip 안에 버튼을 넣고 MovieClip 에 마우스 이벤트를 걸면 작동이 되질 않았다. 즉 버튼안에 버튼이 있는 상태는 마우스 이벤트가 발생하지 않아 네비게이션 같은 작업을 할때 정말 쉽지 않았다.

편법으로 hitTest 를 통해 이벤트를 체크했지만 리소스 측면에서 별로 바람직하지 못한 방법이다.

<AS2.0>

clip.onRollOver=function()

{

trace(“rollOver “+ this);

}

clip 이라는 무비클립안에 버튼이 들어가 있는 상태. 무비클립에 마우스 이벤트를 설정해도 작동하지 않는다.

<AS3.0>

function onRollOver(objEvent:Event)

{

trace(“RollOver “, objEvent.target, objEvent.target.name);

}

clip.addEventListener(MouseEvent.MOUSE_OVER, this.onRollOver);

버튼으로 작동하는 clip 무비클립 안에 버튼이 있어도 이벤트를 발생시킨다.

download sample

Label Statements

ActionScript 3 introcuduces labels, new identifiers that can be associated with loop blocks. Why would you want to identify a loop block? Because you can use that identifier as a target for break and continue commands. Consider two loops where one is nested in the other. If at some point you want to exit both loops while in the nested loop, you can’t. The break command only exits the current block. A common workaround is to use a flag variable to be able to check that, when in the first loop, if that should be exited as well

중첩된 loop의 경우 기존에는 한번에 loop를 벗어나는것은 할수 없었다.

다만 flag를 이용해 벗어나는 경우가 유일한 방법이다. 이젠 그럴필요 없다.

As3.0 에서는 Label Statements 를 이용해 전체 루프를 빠져나올수가 있다.

As 2.0 ActionScript Code:

var i:Number;
var j:Number;
var exit:Boolean = false;
 
for (i=0; i<10; i++) {
	for (j=0; j<10; j++) {
          if (i >3 && j> 3) {
		  exit = true;
		  break;
          }
     }
	if (exit) {
	   break;
	}
 
}

—–> exit 라는 flag 변수를 이용해 체크한다.

As 3.0 ActionScript Code:

var i:Number;
var j:Number;
 
mainLoop: for (i=0; i<10; i++) {
	for (j=0; j<;10; j++) {
		if (i > 3 && j > 3) {
          break mainLoop;
		}
    }
}

——> mainLoop 의 label 을 지정해 한번에 loop 탈출…..지저분하게 변수를 사용하지 않는 명확한 방법이다.

Changing the frame rate in movie

Using ActionScript 3, you can dynamically change the frame rate of your movie using the Stage class.

The Stage class (flash.display.Stage) is the class assigned to the stage object which is accessible from your main movie sprite/movie clip (or others within the same security sandbox) using the stage property. The stage object has a frameRate property which can contain any value between 0.01 and 1000 and determines the frame rate at which the Flash player plays back your movie. Changing this value lets you change the frame rate at runtime.

// change frame rate to 12 fps:

stage.frameRate = 12;

이전 버전에서는 한번 정한 framerate 는 바뀔수가 없었다. 즉 동적으로 frame 속도를 조절할수 없었음.

근데 과연 frameRate 가 1000까지 지원할까?…. 지원하더라도 눈으로 확인은 불가능 할듯.

다만 각각의 swf 파일의 속도는 조절안되고 전체 stage 의 속도만 조절되는것 같다.

Detecting When the Mouse Leaves

One thing about previous versions of ActionScript was that you could never tell when the user no longer had his or her mouse over the Flash movie. This made it hard for people to know whether or not the user is still interacting with their movie or if they’ve given up and moved on to something more interesting. This was especially a problem for custom cursors where, if the user moved the cursor off the Flash movie, the custom cursor would still remain in the Flash movie not moving while the real cursor could be seen moving around every where else. ActionScript 3 now allows you to detect when the mouse has left the flash movie using the stage’s mouseLeave event. This event happens whenever the mouse exits the Flash movie. There is no mouseEnter event, but you can use mouseMove for that since mouseMove only occurs in Flash (for the stage, or really any, object) when the mouse is within the bounds of the movie.

html에서의 플래시 영역 밖으로 마우스 커서를 옮겼을경우 이전에는 정확히 그것을 알아낼 방법이 없었다. 마우스 커서가 안보인다 하더라도 엄연히 플래시 오브젝트 안에 남아서 실행되고 있었는데

이것을 as3.0 에서는 체크할수 있게 되었다.

package {
 
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.ui.Mouse;
 
    public class Test extends Sprite {
 
        private var cursor:Sprite = new Sprite();
 
        public function Test() {
 
            cursor.graphics.beginFill(0xFF);
            cursor.graphics.drawRect(0, 0, 25, 25);
 
            addChild(cursor);
 
            stage.addEventListener(Event.MOUSE_LEAVE, cursorHide);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, cursorFollow);
 
            Mouse.hide();
        }
 
        public function cursorHide(evt:Event):void {
            cursor.visible = false;
        }
 
        public function cursorFollow(evt:MouseEvent):void {
 
            if (!cursor.visible) cursor.visible = true;
            cursor.x = stage.mouseX;
            cursor.y = stage.mouseY;
 
            evt.updateAfterEvent();
        }
    }
}