GenericFlipの機能を利用すると環境レイヤに独自の属性を追加できます。特殊な画像やエフェクトなどをtjsで描画したいときに便利です。初期状態のKAGEXでも動画を再生するGFX_Movie, フラッシュを再生するGFX_Flash, パーティクルを表示するGFX_Particleなどが用意されています。今回は自前でGenericFlipを作成してみます。
GenericFlipの実装例
今回作成するGenericFlipは、指定された画像をインターバルごとに繰り返し表示するものです。以下がそのスクリプトとその使用例です。
/** * 指定された画像を一定時間ごとに切り替えて表示するGenericFlip * layerタグにswitch属性とinterval属性を追加します。 * switch : 表示する画像をコンマで区切って指定します * interval : 画像を切り替える間隔をms単位で指定します * 例) @layer name="テスト" switch="image1,image2" interval=1000 */ // 必ずGenericFlipクラスを継承する class ImageSwitcherGenericFlip extends GenericFlip { var interval; // 画像を切り替える間隔 var files; // 切り替えて表示する画像ファイルが入った配列 var startTick; // 開始時の時間 var currentFileIndex; // 現在読み込んでいるファイルの番号 var targetLayer; // 画像を読み込むレイヤ // コンストラクタにはKAGWindowオブジェクト(kag)が渡される function ImageSwitcherGenericFlip(window) { super.GenericFlip(window); targetLayer = new Layer(window, window.primaryLayer); } // フリップ開始時に呼ばれる // 第1引数には登録属性の属性値、第2引数には全ての属性が入った辞書が渡される function flipStart(files, elm) { // コンマで区切って配列に変換する var files = files.split(","); // 表示を開始する start((int)elm.interval, files); } // フリップ再生中に毎フレーム呼ばれる // 引数には現在のSystem.getTickCount()の返り値が渡される function flipUpdate(currentTick) { // 現在の時間から表示するファイル番号を計算する var elapsedTick = currentTick - startTick; var fileIndex = (elapsedTick \ interval) % files.count; // 現在表示している画像と同じなら何もしない if (currentFileIndex === fileIndex) { return; } currentFileIndex = fileIndex; // targetLayerに現在の画像を読み込み targetLayer.loadImages(files[fileIndex]); targetLayer.setSizeToImageSize(); // flipAssignでtargetLayerを対象のレイヤにコピー flipAssign(targetLayer); } // フリップ停止時に呼ばれる function flipStop() { this.interval = 0; this.files = void; super.flipStop(); // 必ずsuper.flipStopを呼び出す } // セーブする際に呼ばれる // 引数には保存用の辞書が渡される function flipStore(dic) { dic.interval = interval; dic.files = files; } // ロードする際に呼ばれる // 引数にはflipStoreで保存した辞書が渡される function flipRestore(dic) { if (dic.files === void) { return; } // 画像の表示を再開 start(dic.interval, dic.files); } // 画像の表示を開始する関数 // 第1引数に画像を切り替える間隔、第2引数にファイル名が入った配列を渡す function start(interval, files) { this.interval = interval > 0 ? interval : 1000; this.files = files; this.startTick = System.getTickCount(); this.currentFileIndex = void; } } // 定義したクラスをGenericFlipとして登録 GenericFlip.Entry(%[ "class" => ImageSwitcherGenericFlip, // GenericFlipクラス "type" => "switch", // 登録属性 "options" => [ "interval" ], // 使用する属性名 ]);
@linemode mode=vn ; 環境レイヤにimage01, image02, image03を1秒ごとに繰り返し表示する例 @layer name=レイヤ switch="image01,image02,image03" interval=1000 画像を表示しています。 ; レイヤを消したりfile属性などで他のファイルを読み込んだりするとGenericFlipは停止します @layer name=レイヤ hide 画像を消去しました。
実装の詳細はコメントを参照してください。GenericFlipを作る際の一般的な注意点のみ解説します。
GenericFlipとして使うクラスは必ずGenericFlipクラスを継承してください。ここではImageSwitcherGenericFlipクラスをGenericFlipとして使います(10行目)。
クラスを定義したら、GenericFlip.Entryを使って登録する必要があります(88行目)。登録内容は辞書で渡します。classには先ほど定義したクラス、typeにはこのクラスを呼び出すのに使う属性、optionsにはそれ以外に使う属性を配列で渡します。ここでは[layer]タグでswitch属性が使われたときに呼び出されるように登録しています。switch以外にinterval属性を使うのでそれも登録します。
GenericFlipクラスとして機能させるにはいくつかの関数を実装します。ここではflipStart, flipUpdate, flipStop, flipStore, flipStore, flipRestoreを実装しています。それぞれフリップ開始時、フリップ実行中、フリップ停止時、セーブ時、ロード時に呼ばれます。
switch属性が使われるとまずImageSwitcherGenericFlipクラスのオブジェクトが作成され、その後すぐにflipStartが呼び出されます。第1引数には登録属性(ここではswitch属性)の属性値、第2引数にその他の属性が入った辞書が渡されます。
その後は停止されるまでずっとflipUpdateが呼び出され続けます。現在の時間が第1引数に渡されるのでそれに合わせてレイヤに描画すればいいです。ここで重要になるのがflipAssign()です。これはGenericFlipクラスにあらかじめ用意されている関数で、引数に渡したレイヤの内容を環境レイヤにコピーしてくれます。まずは自前のレイヤに描画してからflipAssignを使ってコピーするのが定石です。ここでもtargetLayerに画像を読み込み、それをflipAssignでコピーしています。
環境レイヤが非表示になったりするとGenericFlipは自動的に停止されます。このときに呼ばれるのがflipStopです。ここでは必ずsuper.flipStop()を呼ばなければなりません。忘れないように注意してください。
flipStore, flipRestoreはセーブ・ロードに対応させるために必要です。flipStoreで現在の状態を保存してflipRestoreで実行を再開できるようにしてください。
まとめ
GenericFlipの実装手順は以下のようになります。
・GenericFlipを継承したクラスを定義する
・定義したクラスにflipStart, flipUpdate, flipStop, flipStore, flipRestoreを実装する
・定義したクラスをGenericFlip.Entryで登録する
GenericFlipはtjsを使ってレイヤに描画できます。環境レイヤに機能を追加する形なので、rotateなどの変形やcontrastなどの色調補正、その他のコマンドと組み合わせて使えます。独自のLayerを用意するよりも、可能であればGenericFlipとして描画機能を実装する方が応用がきいて便利だと思います。