2008/11/11 火曜日

CS3素材分離作戦 その後

Action Script, Flashテクニック — Samieru @ 22:19:51

samieruどうも、俺ちゃんです。
トウキョウゲームショウ、行ってきました。ビジネス的には非常に有意義な二日間でしたが、ゲームショウ自体はしんどかったです。疲れますねぇーあれは。でも、なんか打ち合わせしてる時に通りすがりの人が「あれ?NIGOROって書いてある」って言うてたり、どうやらご存知の方もいらっしゃったようです。ありがとうございます。
とりあえず、英語で電話するのはしんどいっすねー。こりゃかなりのリハビリが必要やなと思った今日この頃、皆様如何お過ごしでしょうか。

バウンスショットのネタがバリバリと進んでいる状況ですが、まぁちょいと閑話休題と言うか、俺ちゃんラインの案件が後はクライアントさんの繋ぎこみ完了待ちだけなので今回の案件で実装してみた素材分離作戦の結果報告を兼ねたお話をしようかな、と思います。
いやー、一筋縄では行かなかったですよ。

さて、結構間が開いてるので、素材分離作戦の2とか読み返して頂かないと何の話かさっぱりな気もしますが、要は「Flashって音をmp3に変換したりグラフィクスをJpegに変換したりでコンパイル遅いぜー。ちょっとパラメータ変更してテストしようと思ったらコンパイル5分とかやれやれだぜー」って言う状況をなんとか回避しようって話です。
前回俺ちゃんの出した方法は、「素材は素材用swfで別にして、それのドキュメントクラスに素材呼び出しAPIみたいなんくっつけて、そいつを使ってメインプログラム側に素材読み込むってのはどうだ!?」って事ですね。

とりあえず、先に素材側のドキュメントクラスはこんなんなりました。

//——————————-
package
{

import flash.utils.getDefinitionByName;
import flash.display.MovieClip;
import flash.media.Sound;
import flash.display.BitmapData;
import flash.text.Font;

public class NigoroFactoryClass extends MovieClip implements INigoroFactory
{

private var material_cash_array:Object;

public function NigoroFactoryClass(){

material_cash_array = new Object();

}

public function getMovieClip(mc_name:String):MovieClip{

var cls:Class = getClass(mc_name);
var ret_mc:MovieClip = MovieClip(new cls());

return ret_mc;

}

public function getBitmapFile(mc_name:String):BitmapData{

var cls:Class = getClass(mc_name);
var ret_bmp:BitmapData = BitmapData(new cls(0,0));

return ret_bmp;

}

public function getSoundFile(mc_name:String):Sound{

var cls:Class = getClass(mc_name);
var ret_snd:Sound = Sound(new cls());

return ret_snd;

}

public function getFontFile(mc_name:String):Font{

var cls:Class = getClass(mc_name);
var ret_fnt:Font = Font(new cls());

return ret_fnt;

}

private function getClass(cls_name):Class{

if (material_cash_array[cls_name] == undefined)
material_cash_array[cls_name] = getDefinitionByName(cls_name);

return Class( material_cash_array[cls_name] );
//return Class(getDefinitionByName(cls_name));

}

}
}

//—————————

パッケージは今回関係ないので省いて、INigoroFactoryはただ単にゲッターメソッド(頭にgetが付いてる戻り値でなんか変数とかオブジェクトとかを取得するメソッド)の抽象宣言だけしてるインタフェースで、今の段階だとインタフェースでわける意味はほぼゼロなんですが、まぁ今後の事を考えて、です。

こいつのちょっとだけマトモかも知れない所は、メンバ変数の「material_cash_array」です。
これ何の為にあるかと言うと、getClassメソッドを見てもらえるとわかるんですが、最終的にコイツに呼び出されたクラスをぽんぽん放り込んでいるんですね。っで、二回目以降はコイツから取ってくるようにしてます。
何の為に?
答えは簡単、APIメソッドである「getDefinitionByName」って言う「文字列から指定されたClass(クラス定義オブジェクト、とでも言いますか)を取得する」奴がちょいと重いんです。だからあんまり回数を使いたくない。まーそれだけなんですが、今回コイツがあると無いとでどんだけスピードが変わるかは、そういえば実験してないです。忘れてました。
後はもう、どのゲッターもgetClassで名前が示すClassを取ってきて、それぞれの求められた型にキャストして返す、それだけです。この中で一個だけ注意せんとあかんのがBitmapDataの時で、コイツはコンストラクタに生成するBitmapDataのwidthとheightの指定が必要になるため、「new cls(0,0)」となってます。実際には空のBitmapDataを作る時で無い限り読み込む画像のサイズで勝手に修整される値なので、ここの0,0はコンパイルを通すためには仕方なくそうしているだけで、値は気にしなくて良いです。

ほい、これで基本はOKなんですよ。
これを実装してコンパイルしたswfをLoaderで持ってきて、MovieClipオブジェクトとして保持。前回その問題を言うてましたが、ここでINigoroFactory型とかにキャストしちゃうと、何故か素材が取得出来なくなるので注意が必要です。んで、例えば素材MovieClipオブジェクトの名前が「material」ならば、
var main_mc:MovieClip = material.getMovieClip(”title_movie”);
みたいな感じで貰うと。

素材swf自体が複数存在してもOKです。実際、今回は音素材と画像素材、そしてメインプログラム、とswfを3つに分けて扱っていました。

しかし、これを作っている所で一つの疑問がわきました。「外部素材swfにフォント埋め込んで、それを別のswfが呼び出して使えるってのは著作権的に許されない使い方も簡単に出来るって事よな。」と。
っで、やっぱり問題が出ました。フォントだけはダメだったんです。分けた状態で正常にプログラムは動くんですが取得出来ていません。埋め込みフォントが反映されないんですね。
「埋め込みフォントだけは、最初に呼び出されるswfに存在していないとメソッドで呼び出せない。」
これは注意しましょう。ローダがメインのswfを読んで実行する場合、フォントはローダに置くわけです。まーだから結局このgetFontは使えなかったわけですな。

そして、次の問題。
開発時はコンパイルの関係で素材を分離していたんですが、最終的には「ローダ+本体」の二つにする予定でした。
本体ドッキング時は本体が「NigoroFactoryClass」を継承して、「material = this」になるんすが、最終段階でローダを作って本体と素材を合体させたswfを読み込んだ所、素材が読めなくなったんですよ。ローダを外して本体単体起動だと問題ありません。ローダから始めると全部「そんな名前のクラスないぜー」と例外エラーが出ます。
バラバラのままでローダが本体を読んで、本体が素材を読んだ場合は・・・問題なかったりします。

これは多分「getDefinitionByName」の仕様に起因してるんですが、今んとこ「これか!」ってドキュメントにぶつかってないので決定的な原因は「不明」とさせて下さい。原因を知っている方がいましたら、是非教えていただきたい所です。
んーローダが本体を呼ぶ場合だと、ローダに本体をaddChildしていたのが問題なのかな?

とりあえず解決策としてはローダをメインプログラムに組み込んでしまい、素材だけを分離して読み込ませる事で問題なく動作しています。これだとローダがローディング時のアニメとメインプログラムを含めて容量が3Mぐらいにはなるかもしれませんが、それに対して素材は5倍以上あったりするわけで、ローディングの意味は出来ています。・・・んが、気になりますよねぇ。

こんな感じの現状です。
この件に関してはまた何かわかったら報告したいと思うっす。

さーて次にかかるかぁ。




コメント (1) »

  1. 早速なんですが、これ、とんでもない勘違いをしてたんです。
    とりあえず今そこら辺を修正した奴でテストしてるんで、続報を待てってとこでお願いしますぜ。

    勘違いは、getDifinitionByNameがどっからひっぱってきてるのか?ですね。
    なるほどなー。

    コメント by Samieru — 2008/11/12 水曜日 @ 23:27:09

コメント RSS トラックバック URL

コメントをどうぞ


Copyright (C) Nigoro Allright Reserved. Powered by ASTERIZM