- 2009年11月 3日 02:06
- ActionScript 3.0 | Flash
前回の EnterFrame の管理に引き続き
便利そうなオレオレライブラリを晒してみる。
便利そうなオレオレライブラリを晒してみる。
今回晒すクラスは ExMovieClip。 ファイルは以下に置きました。
今回は関連ファイルがいくつかあるため package を jp.flair4.lib で切ってあります)
flair4lib.zip
この zip には以下のものが含まれています。
- jp.flair4.lib.display.ExMovieClip
- jp.flair4.lib.display.IExMovieClip
- jp.flair4.lib.events.EnterFrameEventOptimizer
- flash.display.IInteractiveObject
- flash.display.IDisplayObject
- flash.display.IDisplayObjectContainer
- flash.display.ISprite
- flash.display.IMovieClip
前半の3つが今回の自作クラス。
IExMovieClip は単純に interface です。
最後の5つは、おなじみの各クラスの public メンバを
ひたすら列挙した Interface です。
その辺の細かい説明は後ほど。
で、こういう晒す系は落として使ってもらおうというよりも
どういう設計思想なのかとかそういう所のほうがニーズがあると思うので
作ろうと思った背景に焦点をあてて説明していきます。
EnterFrameOptimizer
これの設計思想はいたって単純です。
前回の記事でも述べたとおり、EnterFrameは個々に持つと重いから
一箇所でまわしちゃおうという思想から作られています。
とはいえ、停止・再開したいといった状況や
こいつらは止めたいけど、こいつらは動かし続けるといったような
動作単位があると思ったので、new でインスタンス生成でき
pause(); resume(); といったメソッドを用意してあります。
また、稀に1フレーム後だと参照がとれるんだけど・・・とか
1フレーム待つとうまく行く、みたいな状況に出くわす事があります。
そんな時に簡単に1フレーム後の処理を記述できるように
EnterFrameEventOptimizer.once(); という静的メソッドを用意しています。
ExMovieClip
さて、このクラスが今回のメインです。
このクラスは MovieClip の単なる拡張というだけでなく
けっこうな改造が施してあります。
前提となる設計思想は、動作を軽く出来て、無駄を省く という
夢のような話なのですが、具体的に言うと シンタックスの省略と
EnterFrame イベントの管理が主です。
以下 ExMovieClip インスタンスを eMC と表記します
また、大きく分けて 描画管理系 と イベント管理系 に分けて解説します
描画管理系
描画管理といいつつも、addChild 周りの実装がメインです。
ちょっと書くのが面倒って処理を簡略化しようというもの。
◆ 右端 下端 を取得する
// x + width eMC.right // y + height eMC.bottom;
これの思想は単純明快。並べ替える時に
いちいち x + width とか書くのが面倒だっただけです。
◆ 複数の DisplayObject を一気に 追加/削除 する
// 単純な連続 addChild eMC.addChildren( mcA, mcB, ... ); // 指定の index (今回は 0 ) に連続 addChildAt eMC.addChildrenAt( 0, mcA, mcB, ... ); // 一気に削除系 eMC.removeChildren( mcA, mcB, ... );
これも何度も書くのが面倒だったからつくりました。
◆ 特定の DisplayObject の 手前/後ろ に addChild する
// mcA の手前に mcB を addChild addChildFront( mcA, mcB ); // mcA の後ろに mcB を addChild addChildBehind( mcA, mcB );
これもまたまた、index調べて云々というのが面倒だったので・・・
◆ 自らを removeChild する
eMC.removeOwn();
これも面倒(ry
これは実際には親( parent )がいるか調べ、いれば
parent.removeChild(this); をしています。
いなければ何もしません。
地味だけどif文かかなくて良くなるので便利です。
イベント管理系
こちらの実装が ExMovieClip のメインです。
このクラスを使う利点の大半がここに集約されています。
まず EnterFrame はまとめた方が良いという話は
前回述べましたが、いちいち考えてやるのって面倒ですよね。
加えて、EnterFrame が持つもう一つの問題に
EnterFrame イベントは removeChild しても続行されるため
ゴミとして CPU 等のリソースを食いやすいというのがあります。
で、これらを上手いこと解決しようというのがイベント管理系実装です。
◆ stage から remove されたら外れる addEventListener
eMC.addManagedEventListener( eventType, closure );
この addManagedEventListener を用いると
stage から自分が外された瞬間にイベントリスナを
勝手に removeEventListener してくれます。
また、再度 stage に追加され描画されたタイミングで
addEventListner しなおしてくれます。
ちなみに 明示的に removeEventListener した場合は
完全に削除となるので、復元されることはありません。
でも毎回 Managed 書くのめんどくさいという人には
以下の使い方を提供しています。
◆ [static] 管理するイベント名を追加する
ExMovieClip.addAutoManagedEventType( ...eventTypes ); ExMovieClip.removeAutoManagedEventType( ...eventTypes );
この設定をあらかじめしておくと
そのイベントタイプを addEventListener するときは
勝手に管理され removeChild 時に外すようになります。
まあ使いどころ今のところ Event.ENTER_FRAME しか
無いんですけども・・・
◆ [static] EnterFrameOptimizer を利用する
ExMovieClip.useOptimizer = true;
これをあらかじめ記述しておくと
Event.ENTER_FRAME が勝手に EnterFrameEventOptimizer に
ぶっこまれて管理されるようになります。
EnterFrame まとめると早いのはわかったけど
なんか色々面倒だわって人にオススメです。
まとめ
まあ要するに、いかに EnterFrame 系の処理負荷を減らすか
そしてそれらを楽に行うかに特化した MovieClip です。
flash.display.IXXXX
これに関しては、そもそも作らなくても、元からあるんじゃないの?
と思う人もいるかもしれませんが、実際これビルトインではありません。
どんな時に使うかというと、 MovieClip を拡張したクラスの型を
interface で解決したい場合等が挙げられます。
例えば、多種多様なキャラクターが存在するコンテンツで
それらのキャラクタを強い順に並べるクラス
CharacterLayout.as というものがあったとします。
でも、それらのキャラクター達は本当に多種多様で
実装自体も千差万別、また修正頻度も多いという
聞いていると泣きたくなるような仕様だったとします。
そんな時は以下のような方法で
interface を使って型解決をすることがあります
◆ キャラクタ用 interface
public interface ICharacter{
// キャラクタの強さ.
function get strength():Number;
}
◆ キャラクタレイアウト用クラス
public CharacterLayout extends MovieClip{
public function addCharacter( character:ICharacter ):void{
addChild( character as DisplayObject );
// --- character.strength を用いて並べる処理
character.x = 100 * character.strength;
}
こんな感じで、キャラクタ追加するメソッドの引数を
ICharacter で解決して、strength の値が取れれば何でも
突っ込めるようにしちゃったとします。
一見すると大丈夫そうですが、ここで一つ問題が起こります。
何も考えずに実行すると x を指定する所でエラーになります。
なぜなら ICharacter は x というプロパティを持っていないからです。
で、そうか!DisplayObject の interface を継承すリャいいじゃん!
そう思った瞬間わかります。あ、ねえや・・・と。
関数内で、as MovieClip とかでキャストとかしちゃえばいいじゃん
とかそういう考え方もあるかとおもいますが、だったらはじめから
引数の型を MovieClip にするなり、 Character にするなりすれば良い。
でも、前述のような状況で interface で解決することが
必須になる場合、これらが必要になるわけです。
以上です、気に入った物があればご自由にお使いください。
他にもいろいろあるわけなんだけど、Sparkにコミットした方がいいのかな
教えて、beinteractive! ><