AS3でリンケージしたシンボルを大量複製(getDefinitionByName)

すっげぇ久しぶりの更新です。
いままでサボってゴメンナサイ・・・。

http://studio-ensyu.com/life-style/2008/09/as3swf.html

上の記事で、リンケージに関してちょろと説明ましたが・・・

例えばAS2.0で

var test_mc:MovieClip = _root.attachMovie("link" + id , "MC" + count++ , _root.getNextHighestDepth());

とか書きたい時ってどうすんの?
って話です。

まぁ手っ取り早くサンプルを。

>>Flaファイルをダウンロード

こんな感じで、画面上に、リンケージ設定させたいくつかのシンボルを、ランダムに配置するためには、文字列からクラス名を設定してやる必要があるんですが、さてさて、AS3.0ではどう書くのか・・・?

こう書きます。

import flash.utils.getDefinitionByName;

var className:String = "link" + id;
var ClassReference:Class = getDefinitionByName(className) as Class;

getDefinitionByName(className) as Class;
のclassNameに文字列で引数を渡すと、文字列をObjectに変換してくれるみたいです。
ただし、Objectのまんまだと、Classにならないんで、as Classでキャスト(の様な事)をします。
as Classを記述しないと「1118: 静的型 Object の値が、関連しない可能性が高い型 Class に暗黙で型変換されています。」というエラーを出すんで、明示的にキャストしてあげた方がいいでしょうねぇ(パブリッシュ設定でStrictモードのチェックを外すと、エラーは出ないんですけどね)。

あとはコレを画面に配置するには

var imgObj = new ClassReference();
stage.addChild (imgObj);

としてあげればOK。

んで、サンプルのソースは

//Tweenエフェクト用
import fl.transitions.Tween;
import fl.transitions.TweenEvent;
import fl.transitions.easing.*;

//文字列からクラスを生成するために必要。
import flash.utils.getDefinitionByName;

//リンケージのシンボルを、50ミリ秒ごとに生成
var ID:int = setInterval(intervalFunction , 50);

//生成のための関数
function intervalFunction(){
    //ステージサイズから、生成位置をランダムに生成。stage.widthとかだと、ステージに何も配置されてないと0になってしまうため即値を入れてます。
    var X:Number = Math.random() * 550;
    var Y:Number = Math.random() * 400;
    
    //2つのリンケージからランダムにどちらかのシンボルを指定。
    var id = Math.round(Math.random() * 1);
    var className:String = "link" + id;//ランダムに「link0」と「link1」が生成される。
    var ClassReference:Class = getDefinitionByName(className) as Class;
    
    //配置する。
    var imgObj = new ClassReference();
    stage.addChild (imgObj);
    
    imgObj.x = X;
    imgObj.y = Y;
}

    //生成したシンボルに、再生が終わった後に消す処理を登録。
    imgObj.addEventListener("testEvent" , Func);
}

//消す処理。
function Func(evt:Event){
    var target:Object = evt.target;
    var myTween:Tween = new Tween(target , "alpha" , Regular.easeOut , 1 , 0.2 , 0.2 , true);
    
    setTimeout(finish , 250 , target);
    function finish(){
        stage.removeChild(DisplayObject(arguments[0]));
    }
}

こうなってます。

ちなみに、生成されるシンボル自体は単なるシェイプトゥイーンするだけですが、最終フレームに

stop();
this.dispatchEvent(new Event("testEvent"));

と、記述し、「testEvent」という名前でイベントを送出してます。
すると、
imgObj.addEventListener("testEvent" , Func);
のように、「testEvent」を受け取ることが出来るわけです。
ただ、この辺は、AS2.0の流用なんで、ちょっと怪しい。 EventDispatcher()に関しては、もちょっと調べたらまたエントリー上げます。

//------------------------------------- 2009/2/26日追記 -------------------------------------//

どうやら、addEventListenerメソッドが受け取る第一引数はString型で、イベントタイプの定数もString型のようなので、これでいいみたい。
http://livedocs.adobe.com/flex/2_jp/langref/flash/events/Event.html
さらに言うと、Eventクラスのコンストラクタの第一引数もString型で、つまりは
dispatchEvent(new Event(MouseEvent.CLICK));とか書けば、強制的にクリックイベント送出できたりします。
AS2.0時代のsample_btn.onRelease();で、コードからマウスイベントを強制的に呼び出したみたいに。

コメント(2)

外部SWFをロードしたものの、終了のイベントが取れずに苦労していました。
this.dispatchEvent(new Event("testEvent"));
は目からウロコで、なんとか実装できました。
ありがとうございました。

ちなみに、私は、
stage.dispatchEvent(new Event("testEvent"));
で大きな花火を上げて、どこかれでも確実に仕留める
手法をとらせていただきました。

>うっくんさん

問題解決に力になれたようでうれしい限りです。

>stage.dispatchEvent(new Event("testEvent"));

そうですね。
その書き方なら、
stage.addEventListener("testEvent" , testEventHandler);
と「どの階層からも」書けますね。

このエントリーを書いた当時、「stage.」でどこの階層からでもstageにアクセスできるって知らなかったんですが、知ってからはさらに楽させてもらってる感じです。

今、読み込まれた側のswfファイルが、stageのリサイズイベントを受け取ってエラスティックレイアウトで動作するってサイトを作ってるんですが、
それも
読み込まれる側にstage.addEventListener(Event.RESIZE , resizeHandler);
stage.dispatchEvent(new Event(Event.RESIZE));

って書けて便利だなぁって思ってみたりしてます。

コメントする

トラックバック(0)

このブログ記事を参照しているブログ一覧: AS3でリンケージしたシンボルを大量複製(getDefinitionByName)

このブログ記事に対するトラックバックURL: http://studio-ensyu.sakura.ne.jp/mt/mt-tb.cgi/17

プロフィール

HN.NoBody

NoBody

市ヶ谷のとあるオフィスでFlashクリエイターとして労役中。
なんとなくチーフ。

twitterでつぶやき中