書き物

技術とか作った物の話とか愚痴文句感想など

Flex SDK で作った外部 swf の中で定義されているクラスを取り出す方法

Flash で外部ファイルを扱う場合、swf へ埋め込む方法と、直接画像ファイル等をロードする方法があります。swf へ埋め込むとコンパイルに時間がかかったり、埋め込んだ swf 自体のサイズが大きくなったりします。外部ファイルをロードする場合、素材自体が丸見えになる他、数が多くなると、サーバーの負荷が上がったりなど。外部ファイルを自作アーカイブ化して、バイナリデータとして読み込んだ場合、音声データの復元に苦労したりします。

外部データをまとめておく方法の 1 つとして、素材用 swf にデータを埋め込んでおき、その swf をロード、swf 内の素材を取得・・・という方法がありますので、方法を書きます。

まずは素材用 swf を作ります。(parts.swf という名前で作ります。) ソース構成は以下。

/
│  Parts.as
│
└─mahoutukai
    │  Crouch.as
    │  Move.as
    │  Standby.as
    │
    ├─crouch
    │      crouch0001.png
    │
    ├─move
    │      move0001.png
    │      move0002.png
    │      move0003.png
    │
    └─standby
            standby0001.png

■素材用 swf のメインクラス(このクラスをコンパイルします。) package
{ import flash.display.Sprite; import mahoutukai.Crouch; import mahoutukai.Move; import mahoutukai.Standby;

/**
 * 素材
 * 
 * @author asahiufo/AM902
 */
public class Parts extends Sprite 
{
    /**
     * コンストラクタ
     */
    public function Parts()
    {
        Crouch;
        Move;
        Standby;
    }
}

}

■「待機」画像埋め込みクラス package mahoutukai { /* * 待機 * * @author asahiufo/AM902 / public class Standby { [Embed(source=“standby/standby0001.png”)] public var Graphic0001:Class; } }

■「移動」画像埋め込みクラス package mahoutukai { /* * 移動 * * @author asahiufo/AM902 / public class Move { [Embed(source=“move/move0001.png”)] public var Graphic0001:Class; [Embed(source=“move/move0002.png”)] private var Graphic0002:Class; [Embed(source=“move/move0003.png”)] public var Graphic0003:Class; } }

■「しゃがみ」画像埋め込みクラス package mahoutukai { /* * しゃがみ * * @author asahiufo/AM902 / public class Crouch { [Embed(source=“crouch/crouch0001.png”)] public var Graphic0001:Class; } }

この素材用 swf からクラス名を取り出すのですが、Flash で作った場合と違って、Flex にはどんな名前で Class が登録されているか分かりません。(Flash だとシンボルのリンケージにクラス名を指定できるらしい。)swf にどんなクラスが含まれているかを調べるには、FlashDevelop のプロジェクトパネルが使えます。

プロジェクトパネルで parts.swf を開いたの図 プロジェクトパネルで parts.swf を開いたの図 どうやら、「<パッケージ名>.<クラス名>_<変数名>」という名前で埋め込んだデータのクラスが定義されているみたいです。

クラス名が分かった所で、メインの swf を作ります。 ■メインクラス(これをコンパイルします。) package src { import flash.display.Bitmap; import flash.display.Loader; import flash.display.LoaderInfo; import flash.display.Sprite; import flash.events.Event; import flash.net.URLRequest;

/**
 * メイン
 * 
 * @author asahiufo/AM902
 */
public class Main extends Sprite 
{
    /**
     * コンストラクタ
     */
    public function Main() 
    {
        super();

        var loader:Loader = new Loader();
        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, _onComplete);
        loader.load(new URLRequest("parts.swf"));
    }

    /**
     * ロード完了イベントハンドラ
     * 
     * @param event イベント
     */
    private function _onComplete(event:Event):void
    {
        var contentLoaderInfo:LoaderInfo = LoaderInfo(event.target);
        contentLoaderInfo.removeEventListener(Event.COMPLETE, _onComplete);

        // 待機
        var Standby0001:Class = Class(contentLoaderInfo.applicationDomain.getDefinition("mahoutukai.Standby_Graphic0001"));
        var standbyGr0001:Bitmap = new Standby0001();
        standbyGr0001.x = 0;
        standbyGr0001.y = 0;
        addChild(standbyGr0001);

        // 移動
        var Move0001:Class = Class(contentLoaderInfo.applicationDomain.getDefinition("mahoutukai.Move_Graphic0001"));
        var Move0002:Class = Class(contentLoaderInfo.applicationDomain.getDefinition("mahoutukai.Move_Graphic0002"));
        var Move0003:Class = Class(contentLoaderInfo.applicationDomain.getDefinition("mahoutukai.Move_Graphic0003"));
        var moveGr0001:Bitmap = new Move0001();
        var moveGr0002:Bitmap = new Move0002();
        var moveGr0003:Bitmap = new Move0003();
        moveGr0001.x = 0;
        moveGr0001.y = standbyGr0001.y + standbyGr0001.height;
        moveGr0002.x = moveGr0001.x + moveGr0001.width;
        moveGr0002.y = moveGr0001.y;
        moveGr0003.x = moveGr0002.x + moveGr0002.width;
        moveGr0003.y = moveGr0002.y;
        addChild(moveGr0001);
        addChild(moveGr0002);
        addChild(moveGr0003);

        // しゃがみ
        var Crouch0001:Class = Class(contentLoaderInfo.applicationDomain.getDefinition("mahoutukai.Crouch_Graphic0001"));
        var crouchGr0001:Bitmap = new Crouch0001();
        crouchGr0001.x = 0;
        crouchGr0001.y = moveGr0001.y + moveGr0001.height;
        addChild(crouchGr0001);
    }
}

} 要約すると、

  1. parts.swf を Loader で読み込む。
  2. Loader.contentLoaderInfo.applicationDomain.getDefinition() メソッドでクラスを取得する。
  3. 取得したクラスを new してインスタンスを作る。
  4. インスタンスをいじり倒す。

ということです。

実行結果 結果

クラスさえ取得できれば、あとは new するだけで同じデータのインスタンスをポンポン作れます。夢のようですね!!

おまけですが、今回のサンプルの Move クラスで、 [Embed(source=“move/move0002.png”)] private var Graphic0002:Class; として private な Class 型の変数を作ったのですが、このクラスも普通に parts.swf から取得できるみたいです。クラス定義は、受け取る変数名のアクセス修飾子には関係ないみたいです。