AS3のfl.transitions.Tween、その注意点

AS3のfl.transitions.Tweenが途中で止まるんです。
毎回止まるわけじゃなく、気まぐれに止まるんです。
何が原因かしばらくわからんかった。
再現するサンプルを作ったから、
テレビの前のみんなも一緒に考えてみてくれ。

答えはCMの後で!!


以下のスクリプトは、
ドットを100個生成し、フェードインして表示させるものです。
アニメーションにはfl.transitions.Tweenクラスを使用しています。
Tweenの終了時にイベントを受け取って、トレースしています。
100個のTweenが終了し、100回トレースしてほしいのですが、
かなりの確率で100回トレースされないです。
ただしうまく100回トレースされることもあります。

import fl.transitions.*;
import fl.motion.easing.*;
import flash.utils.*;
stage.frameRate = 30;

//Tween終了カウンタ
var c:int = 0;

//100ミリ秒ごとに一つTwennを生成する。100個まで
var myTimer:Timer = new Timer(100, 100);
myTimer.addEventListener("timer", createTween);
myTimer.start();

function createTween(__e:TimerEvent=null) {

    //Tween目視用スプライトを生成
    var spr:Sprite = new Sprite();
    var shape:Shape = new Shape();
    var gra:Graphics = shape.graphics;
    gra.beginFill(0xff0055);
    gra.drawCircle(0,0,5);
    spr.addChild(shape);
    addChild(spr);
    spr.x = Math.random()*500;
    spr.y = Math.random()*500;

    //Tweenを生成
    var twn:Tween = new Tween(spr, "alpha", Quadratic.easeInOut, 0, 1, 10, true);
    twn.addEventListener(TweenEvent.MOTION_FINISH, onFinish);

}

//Tween終了のイベントハンドラ
function onFinish(__e:TweenEvent):void {
    trace("Finish", ++c);
}

正解は、
「生成したTweenインスタンスが、ガベージコレクトの餌食になっている」
でした。

AS2版のTweenでは、この現象は起こっていませんでした。
Tweenクラスは、内部的にはonEnterFrameイベントを受け取って
トゥイーン処理が行われています。
AS2版のTweenでは、onEnterFrameのリスナであるために、
ガベージコレクトを免れていました。

AS3版のTweenでも、内部的にはevent.ENTER_FRAMEのリスナになっていますが、
リスナに追加される際に「弱い参照」で追加されています。
(今回のことで、addEventListenerするときに「弱い参照」が利用できることを知りました!)
「弱い参照」は通常の参照とは違い、参照カウントが加算されない参照みたいです。

このため、上のコードでは、
Tweenインスタンスを参照するのはfunction内のローカル変数のみであるため、
functionを抜けた後、ガベージコレクトされていたというオチでした。

余談ですが、
フレームレートを上げると、トレースされる数も減るため、
ガベージコレクトのタイミングはフレームレートの影響を受けるみたいですね。

カテゴリー: ActionScript3, AS3fromAS2 | コメントをどうぞ

「排他」を表現するコレクションがあれば便利じゃね?

ふと、「排他」を表現するコレクションがあれば便利じゃね?と思いました。

var exclusiveCollection = new Exclusiveness();
exclusiveCollection.push("A");
exclusiveCollection.push("B");
exclusiveCollection.push("C");

こんな感じでコレクションを作って、

trace(exclusiveCollection.get("A"))

とすると、コレクション内の排他的なオブジェクトが返る。

//output
B,C

何が便利かというと、

たとえば、交差点にある信号機を実装するとして、

各ランプは排他的に点灯するとして、

各ランプは点灯するとイベントを配信するとする。

/**
 * ランプが点灯した
*/

private function onLightOn(e:LightEvent)
{
    //イベントを配信したランプ
    var light : Light = e.target as Light;

    //他のランプを消灯する
    switch(light)
    {
        case red:
            green.off();
            yellow.off();
            break;

        case green:
            red.off();
            yellow.off();
            break;

        case yellow:
            red.off();
            yellow.off();
            break;
    }

}




↑こういった長ったらしいコードが、

↓こんな感じに!

/**
 * ランプが点灯した
*/

private function onLightOn(e:LightEvent)
{
    //イベントを配信したランプ
    var light : Light = e.target as Light;

    //他のランプを取得して消灯する
    var other : Array = exclusiveCollection.get(light);
    other.every(
        function(element:*, index:int, arr:Array):void {
                   Light(element).off() ;
               })

}

最初のコードに比べると、コードが短くなるうえ、

排他的に処理していることが明示できて、いけてるのではないかと。

どうだろう?

(Array.every()は使ったことがないので使い方が間違ってるかもしれない。)

カテゴリー: ActionScript3 | コメントをどうぞ

AS3の継承

メソッドのオーバーライド

AS3では、サブクラスでスーパークラスのメソッドをオーバーライドする場合、
明示的にoverrideキーワードを使用しなければならなくなった。
サブクラスを見るだけで、このメソッドはサブクラス独自のものか
スーパークラスのメソッドを上書きしたものかがわかるようになったので便利。

AS2の場合

//スーパークラス
class SuperClass
{
    //スーパークラスのメソッド
    private function method1():void
    {
        trace("method1");
    }
}


//サブクラス
class SubClass extends SuperClass
{
    function SubClass()
    {
        method1();
    }
    
    //サブクラスのメソッド
    private function method1():void
    {
        super.method1();
    }
}


//サブクラスの生成
var sc:SubClass = new SubClass();

//output
//method1

AS3の場合

package
{
    //スーパークラス
    public class SuperClass
    {
        /* スーパークラスのメソッド
         * privateだとAS2と違ってサブクラスからアクセスできない。
         * サブクラスからアクセスできるようにするにはprotectedまたはinternalキーワードを使用する。
         */
        protected function method1():void
        {
            trace("method1");
        }
    }
}


package
{
    //サブクラス
    public class SubClass extends SuperClass
    {
        public function SubClass()
        {
            method1();
        }
        /*サブクラスのメソッド
         * 上書きするメソッドにはoverrideキーワードをつける。
         * また、スーパークラスのメソッドのアクセス修飾子と一致させる必要がある。
         * (privateだとコンパイルエラー)
         */
        protected override function method1():void
        {
            super.method1();
        }
    }
}


//サブクラスの生成
var sc:SubClass = new SubClass();

//output
//method1

カテゴリー: AS3fromAS2 | コメントをどうぞ

AS3のFunction

引数にデフォルト値を持てるようになった

AS3のFunctionは、引数にデフォルト値を持てるようになった。
デフォルトの値を割り当てた引数はオプションになり、
割り当てられなかった引数は必須引数になる。
必須引数が渡されない場合はコンパイルエラーとなる。

書式は以下の通り。


function defaultValues(x : inty : int = 3, z : int = 5) : void
{
    trace(x, y, z);
}
defaultValues(1); // 1 3 5

注意その1

デフォルト値を持つ引数は、引数リストの末尾に記述しなければならない。

function defaultValues(x : int = 3, y : int = 5, z : int) : void
{
    trace(x, y, z);
}
defaultValues(1); 

//    output
//    末尾がデフォルト値を持たない引数なので、コンパイルエラー

注意その2

デフォルト値として割り当てられる値は、コンパイル時定数でなければならない。
(実行時に生成される値は不可)


function defaultValues(a : Array = []) : void
{
    trace(a);
}
defaultValues(["a""b"]); 

//    output
//    デフォルト値が実行時に生成される値なので、コンパイルエラー

カテゴリー: AS3fromAS2 | コメントをどうぞ

CS3でAS3Unitをつかってみる

AS3Unit

[attention!]

Flash CS3用のAS3Unitが公開されているようです。

現在は、このエントリーにあるようなsvnからのソースの取得の必要はありません。

なにはなくともテスト環境
ということで、Sparkprojectのyossyさんという方が公開してくれているAS3UnitをCS3で使ってみることにする。
こういうものを公開してくれる人はすばらしいですね。

ソースをダウンロード

AS3Unitのページに行き、AS3Unitをダウンロードする。
AS3UnitはFrexで使用する前提?のようなので、as3unit-1.01.swcではなく、as3unit-1.01-src.zipをダウンロードする。

テスト実行用のクラスを作成。

ドキュメントクラスになるMain.asを作成
AS3Unitのページのファーストステップを見ながら、テスト実行用のコードを記述する。

ドキュメントクラス:Main.as

package
{
import flash.display.Sprite;
import org.libspark.as3unit.runner.AS3UnitCore;
public class Main extends Sprite
{
public function Main()
{
AS3UnitCore.main(CalculatorTest);
}
}
}

新規Flaファイルを作成し、firstTest.flaという名前で保存。
パブリッシュ設定を開き、以下の項目を設定。

  • ダウンロードしたソースのsrcディレクトリにクラスパスを通す。
  • ドキュメントクラスをMain.asにする。

setDocumentClass.gif

テストクラスを作成

おなじく、ファーストステップのサンプルに従って、テストクラスとテスト対象クラスを作成する。

テストクラス:Calculator.as (ファーストステップより)

package
{
import org.libspark.as3unit.test;
import org.libspark.as3unit.assert.assertEquals;
use namespace test;
public class ClaculatorTest
{
test function add():void
{
var calc:Calculator = new Calculator();
assertEquals(3, calc.add(1, 2));
}
}
}

コンストラクタにタイポがあり、CalculatorTestがClaculatorTestになっているのでコピペ注意。

テスト対象クラス:Calculator.as (ファーストステップより)

package
{
public class Calculator
{
public function add(a:Number, b:Number):Number
{
return 0;
}
}
}

テストの実行

firstTest.flaをプレビューしてみる。
コンパイラに怒られた。
error1.gif

うーむ。
TestListenerがみつからないそうだ。
こいつのフルパスはorg.libspark.asunit.framework.TestListener。
ダウンロードしたAS3Unit1.01ソースコードにはorg.libspark.asunitパッケージが含まれてない様子。

Sparkprojectのページに戻ってみるとASUnitというものがあった。
これかな?

さっそく、asunit-1.01-src.zipをダウンロード。
org.libsparkパッケージ以下にダウンロードしたasunitパッケージを加える。

プレビューしてみる。
… エラーが増えた w
error2.gif

org.libspark.asunit.framework.AS3UnitTestAdapterとかがない様子。
うーん。これ、CS3じゃ使えないんだろうか。。

また、Sparkprojectのページに戻ってうろうろしていると、
おぉ!AS3Unitのリポジトリが公開されているではないですか!
これ、checkoutしていいんだよね?
どきどきしながら、

svn checkout "as3unit.libspark.org/svn/as3/trunk"

ソースがずらずら落ちてきました。
AS3UnitTestAdapterも含まれてるっぽい。

org.libspark.asunit.framework以下の

  • AS3UnitTestAdapter.as
  • AS3UnitTestAdapterCache.as
  • AS3UnitTestCaseFacade.as

を加えて、3度目のプレビュー。

.E
Time: 0.01
There was 1 failure:
1) add(CalculatorTest)
Error: expected:<3> but was:<0>
at global/org.libspark.as3unit.assert::fail()
at global/org.libspark.as3unit.assert::failNotEquals()
at global/org.libspark.as3unit.assert::assertEquals()
at CalculatorTest/http://as3unit.libspark.org/test::add()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at org.libspark.as3unit.inter.runners::Method/invoke()
at org.libspark.as3unit.inter.runners::TestMethodRunner/org.libspark.as3unit.inter.runners:TestMethodRunner::executeMethodBody()
at org.libspark.as3unit.inter.runners::TestMethodRunner/org.libspark.as3unit.inter.runners:TestMethodRunner::runUnprotected()
at org.libspark.as3unit.inter.runners::BeforeAndAfterRunner/runProtected()
at org.libspark.as3unit.inter.runners::TestMethodRunner/::runMethod()
at org.libspark.as3unit.inter.runners::TestMethodRunner/run()
at org.libspark.as3unit.inter.runners::TestClassMethodsRunner/org.libspark.as3unit.inter.runners:TestClassMethodsRunner::invokeTestMethod()
at org.libspark.as3unit.inter.runners::TestClassMethodsRunner/run()
at ::BeforeClassAndAfterClassRunner/TestClassRunner.as$98:BeforeClassAndAfterClassRunner::runUnprotected()
at org.libspark.as3unit.inter.runners::BeforeAndAfterRunner/runProtected()
at org.libspark.as3unit.inter.runners::TestClassRunner/run()
at org.libspark.as3unit.inter.runners::CompositeRunner/run()
at org.libspark.as3unit.runner::AS3UnitCore/runWithRunner()
at org.libspark.as3unit.runner::AS3UnitCore/run()
at org.libspark.as3unit.runner::AS3UnitCore/runClasses()
at Function/http://adobe.com/AS3/2006/builtin::apply()
at org.libspark.as3unit.runner::AS3UnitCore/runMain()
at org.libspark.as3unit.runner::AS3UnitCore$/main()
at Main$iinit()
FAILURES!!!!
Tests run: 1, Failure: 1

できた!
なんか、表示されなくてもいいはずのようなものが表示されているけど、とりあえず動いてるっぽい。

最後にテストが通るようにCalculatorクラスを実装し、再度テスト。

.
Time: 0.008
OK (1 test)

動いてるなぁ。
これでいいのだろうか?
一抹の不安はありますが、どんどん使っていく事にします。
yossyさん、ありがとう。
なにかできたら、sparkProjectに参加したいなぁ。

カテゴリー: ActionScript3 | コメントをどうぞ

AS3fromAS2

ようやくCS3を導入しました。
周回遅れを取り戻さないと。

AS2からAS3への移行についてのカテゴリを増やして、
どんどんメモっていく予定。



/* 未定義のNumber型のデフォルト値が、AS3ではNaNに変わった。
 * AS2ではundefinedを返していた。
 * AS2で初期化の有無を調べるためにundefinedと評価していた人は注意!
*/

//未初期化のNumber
var num:Number;

//AS2ではundefined、AS3ではNaNを返す。
//AS2で初期化の有無を調べるためにundefinedと評価していた人は注意!
trace("Number ---------");
trace("the default value of Number is " + num);
trace("the default value of Number is 'undefined' : " + (num == undefined));
trace("the default value of Number is 'NaN' : " + isNaN(num));

//未初期化のObject
var obj:Object;

//AS2ではundefined、AS3ではnullを返す。
//ただし、undefined == null は true を返すため、
//初期化の有無を調べるためにundefinedと評価することができる。
trace("\nObject ---------");
trace("the default value of Object is " + obj);
trace("the default value of Object == 'undefined' : " + (obj == undefined));
trace("the default value of Object === 'undefined' : " + (obj === undefined));

//未初期化のString
var str:String;

//AS2ではundefined、AS3ではnullを返す。
//Objectと同じ。
trace("\nString ---------");
trace("the default value of String is " + str);
trace("the default value of String == 'undefined' : " + (str == undefined));
trace("the default value of String === 'undefined' : " + (str === undefined));

/* output
 * Number ---------
 * the default value of Number is NaN
 * the default value of Number is 'undefined' : false
 * the default value of Number is 'NaN' : true
 * 
 * Object ---------
 * the default value of Object is null
 * the default value of Object == 'undefined' : true
 * the default value of Object === 'undefined' : false
 * 
 * String ---------
 * the default value of String is null
 * the default value of String == 'undefined' : true
 * the default value of String === 'undefined' : false
 * 
*/

カテゴリー: AS3fromAS2 | コメントをどうぞ

Tools4Layer

このあいだ(といってもだいぶ前になるけど)にエントリーした

‘タイムライン派のためのちょっとだけ便利なJSFLコマンド’のエクステンションが、
Adobe Exchangeで公開されました。

いくつかのバグが修正されているので、興味がある方はこちらの方をダウンロードして下さい。

名前がおかしいから変えろと言われたり、英語のドキュメント用意せいっていわれたりして、結構めんどうでした。

こんなちっちゃなツールでもこんなに大変なのに、よくみんなライブラリレベルのものを公開できるなぁ。

頭が下がります。

Tools4Layer

カテゴリー: flash | コメントをどうぞ

そのオブジェクト、本当に消えていますか?

(このエントリは‘removeMovieClip()の注意点’の続きです。)

MovieCLip.removeMovieClip() を唱えると、
そのMovieClipとMovieClipの持ち物がすべて削除される、、、
そう思っていた時期が僕にもありました。

removeMovieClip()といえども、
その持ち物はガベージコレクションのメモリ管理から逃れられているわけではありません。
ガベージコレクションとはFlashが不要になったメモリ領域を自動的に解放する機能です。
(http://ja.wikipedia.org/wiki/ガベージコレクション)
参照カウントという仕組みで、不要になったオブジェクトを判定します。
不要と判断されたオブジェクトは自動的に破棄されます。
(http://ja.wikipedia.org/wiki/参照カウント)

 

例えば以下のようなコードの場合、次のようなことが起こっています。

function func():Void
{
var o:Object = new Object();
}

3行目でObjectインスタンスを生成し、 ローカル変数oに格納しています。
このとき、Objectインスタンスは変数oから’参照’されているので 参照カウントが1になります。

4行目で関数を抜けると、変数oはローカル変数なので削除されます。
これでObjectインスタンスは誰からも参照されなくなったので、
参照カウントが0になります。

どのくらいの頻度でガベージコレクションがおこなわれているのかは謎ですが、 つぎにガベージコレクションがおこなわれるタイミングで Objectインスタンスは自動的にメモリから破棄されます。
ガベージコレクションのおかげで、 過去に生成したオブジェクトが不必要になったにもかかわらず メモリを占有してしまうことをふせげるわけです。

 

さて、removeMovieClip()に話を戻しますが、 例えば以下のコードの場合、

 //空のムービークリップ'mc'を生成
var m:MovieClip = _root.createEmptyMovieClip("mc", _root.getNextHighestDepth());
//mcの持ち物としてObject'o'を生成
m.o = new Object();
//oのイベントハンドラ
m.o.onMouseDown = function ()
{
trace("I'm alive !!");
}
//oをMouseのリスナに追加
Mouse.addListener(m.o); 

上記のコードはヘルプにもよく登場する、
リスナ用のオブジェクトを生成しイベントを受け取るやつです。
ムービークリップを生成し、その持ち物としてObjectを生成しています。
Objectインスタンスは、Mouseクラスのリスナとして登録されているので、
マウスイベントを受け取ることができます。

このコードを_rootのタイムラインに記述し実行すると、
マウスをクリックするたびに’I'm alive !!’がトレースされます。

 

では、removeMovieClip()でこのムービークリップを消してみます。

//空のムービークリップ'mc'を生成
var m:MovieClip = _root.createEmptyMovieClip("mc", _root.getNextHighestDepth());
//mcの持ち物としてObject'o'を生成
m.o = new Object();
//oのイベントハンドラ
m.o.onMouseDown = function ()
{
trace("I'm alive !!");
}
//oをMouseのリスナに追加
Mouse.addListener(m.o);
//mcを削除
m.removeMovieClip();

このコードを実行し、マウスをクリックすると何が起こるでしょうか?

removeMovieClip()したのだから、その持ち物であるObjectインスタンスも破棄されてほしいところですが、 実はそううまくは行きません。
このコードを実行しても、マウスをクリックするたびに’I'm alive !!’がトレースされます。
何が起こっているのでしょうか?

参照カウントのことを思い出せば答えはわかります。
m.removeMovieClip()の時点で、mの持ち物である変数’o'は削除され、 Objectインスタンスはムービークリップ’m'からは参照されなくなっていますが、 まだ、Mouseクラスからは参照されています。 (addListener()はMouseクラスが保持している配列に、渡されたオブジェクトの参照を格納します。)
つまり、Objectインスタンスの参照カウントがまだ1であるために Objectインスタンスは破棄されず生き残っているわけです。

 

次のコードも間違いやすい例です。

//空のムービークリップ'mc'を生成
var m:MovieClip = _root.createEmptyMovieClip("mc", _root.getNextHighestDepth());
//mcの持ち物としてObject'o'を生成
m.o = new Object();
//oのイベントハンドラ
m.o.onMouseDown = function ()
{
trace("I'm alive !!");
}
//oをMouseのリスナに追加
Mouse.addListener(m.o);
//oを削除!
delete m.o;
//mcを削除
m.removeMovieClip();

Objectインスタンスを削除したいという意気込みは感じますが、
deleteステートメントはあくまでmの持ち物である変数’o'(Objectインスタンスへの参照)を削除しただけであって、Objectインスタンス自体を削除する命令ではありません。
この場合もやはり、Objectインスタンスは破棄されず生き残っています。

 

Objectインスタンスを確実に破棄したい場合は、 参照カウントを0にする必要があります。

//空のムービークリップ'mc'を生成
var m:MovieClip = _root.createEmptyMovieClip("mc", _root.getNextHighestDepth());
//mcの持ち物としてObject'o'を生成
m.o = new Object();
//oのイベントハンドラ
m.o.onMouseDown = function ()
{
trace("I'm alive !!");
}
//oをMouseのリスナに追加
Mouse.addListener(m.o);
//oをMouseのリスナから削除
Mouse.removeListener(m.o);
//mcを削除
m.removeMovieClip();

 

以上、比較的シンプルな例で説明してみましたが、 気をつけないと消えているつもりのオブジェクトがいつまでも存在するはめになります。
特に、クラス主体で開発を進めるときには注意が必要です。
参照の参照で参照されても、参照カウントはちゃんと1増えています(笑

少なくとも以下の点には注意した方がいいです。

  • addListener, addEventListenerした際は、
     必要がなくなった時点でremoveListener, removeEventListenerする

  • 不用意にメンバ変数でよそのクラスを参照しない。
     (なるべくローカル変数にその都度、参照を取り寄せるとか、クラス同士を疎結合にする設計を考える)

  • removeMovieClip()をラップしたdestroyメソッドなどを用意し、
     不必要な参照をクリアする

 

で、最後になりましたが、 エントリ’removeMovieClip()の注意点’の続きです。

var mc:MovieClip = _root.createEmptyMovieClip("emptyMC",1);
mc.removeMovieClip();
trace("*"+mc+"*");

上記のコードでトレースの内容が変だと騒いでいましたが、 考えてみれば当たり前でした。 removeMovieClip()した後も、 変数mcでMovieClipインスタンスが参照されているため、 不完全に破壊されたMovieClipインスタンスが残ってたのでした。 、、、

という理解であっていると思う。。多分。。。

カテゴリー: ActionScript2 | コメントをどうぞ

タイムライン派のためのちょっとだけ便利なJSFLコマンド

ハードディスクをあさっていると、なつかしいツールが出てきたので公開します。
昔、1000フレームオーバーのフレームアニメーションを大量に作る仕事があって、
そのとき作ったものです。
タイムラインを使ってオーサリングすることが多い方におすすめです。

Layer4Tools

layer4tools.jpg

レイヤーのプロパティを操作するJSFLコマンドで、4つの機能があります。
上から順に以下のようになっています。

  • invisibleGuideLayer
  • outlineMaskLayer
  • deleteEmptyLayer
  • renameLayer
invisibleGuideLayer
モーションガイドや、下絵用のガイドレイヤーなどが大量にある場合、
タイムラインが見にくくて作業効率が落ちちゃいますよね。
そんなときは、このボタンをクリックするとすべてのガイドレイヤーを非表示にしてくれます。
(なぜか、ボタンをクリックしたあと画面のどこかを一度クリックしないと反映されません。)
outlineMaskLayer
マスクレイヤーに置いたオブジェクトは、マスクなだけにいろいろなものを覆い隠してしまいます。
そんなときは、このボタンをクリックするとすべてのマスクレイヤーをアウトライン表示にしてくれます。
(なぜか、ボタンをクリックしたあと画面のどこかを一度クリックしないと反映されません。)
deleteEmptyLayer
ボタンをクリックすると未使用のレイヤーを削除します。
ここでいう未使用のレイヤーとは、以下の条件をすべて満たすレイヤーです。

  • レイヤーにキーフレームが存在しない。
  • レイヤーにラベルが記述されているフレームが存在しない。
  • レイヤーにスクリプトが記述されているフレームが存在しない。
  • レイヤーにサウンドがアタッチされているフレームが存在しない。
  • フォルダレイヤーではない。
renameLayer
ボタンをクリックすると、選択しているレイヤーに名前をつけてくれます。オーサリングしているとすぐに「レイヤー55」などの名前のレイヤーで埋め尽くされてしまう人にお勧めです。

たとえば、こんな感じのレーヤーがあって、、
layer4tools_before.jpg

レイヤーを選択後、ボタンをクリックすると
layer4tools_before2.jpg

こんな感じにリネームされます。
layer4tools_after.jpg

名前付けのルールは上の画像から察して下さい。

ダウンロード

Layer4Tools.mxp

インストール

ダウンロードしたLayer4Tools.mxpをダブルクリックすると
Extension Managerが起動します。
あとは指示にそってインストールして下さい。
もし、Extension Managerがない場合は、ここからダウンロードできます。

インストールが終わったら、Flashを再起動し、起動後、メニューの「ウィンドウ」→「その他のパネル」→「Layer4Tools」を選ぶとパネルが出てきます。

参考資料

エクステンションのインストーラの作成

カテゴリー: flash | コメントをどうぞ

AS2とAS3の違い(その2)

Syntacs

const
  • const キーワードが追加され、定数が定義できるようになった。
  • 定数は一度宣言と同時に代入するか、宣言後、コンストラクタで代入できる
  • 以後変更しようとするとランタイムエラーとなる
    class A
    {
    public const MINIMUM:int = 0;
    public const MAXIMUM:int;
    public function A()
    {
    MAXIMUM = 10;
    }
    }
    var a:A = new A();
    a["MAXIMUM"] = 100; // run-time error
    

Looping Statement

for each..in
  • ループステートメントに新しくfor eacn..inステートメントが加わり、コレクションのアイテムを走査できるようになった。
  • 例えばObjectのプロパティの値を走査する場合
    var myObj:Object = {x:20, y:30};
    for each (var num in myObj)
    {
    trace(num);
    }
    // output:
    // 20
    // 30
    
  • XMLを走査する場合
    var myXML:XML = <users>
    <fname>Jane</fname>
    <fname>Susan</fname>
    <fname>John</fname>
    </users>
    for each (var item in myXML.fname)
    {
    trace(item);
    }
    /* output
    Jane
    Susan
    John
    */
    

Function

匿名関数について
  • コンパイラのモードにstrictとstandardが選べるようになった?
  • strictモードでは、匿名関数を使用することはできない。

    class Example
    {
    var methodExpression = function() {}
    function methodStatement() {}
    }
    var myEx:Example = new Example();
    myEx.methodExpression(); // error in strict mode; okay in standard mode
    myEx.methodStatement(); // okay in strict and standard modes
    
  • ただし、strictモードでも配列アクセスを使えば匿名関数にアクセスできる
  • myEx["methodExpression"]();
    
  • もしくは、classをdynamicにすることでも匿名関数を使用できるようになる。
カテゴリー: AS3fromAS2 | 1件のコメント