Progression やってみたよ12の解説

前回のエントリー

やってみたよ→ファイル置きっぱ…以上。

というのも乱暴かな…というのと、勉強ブログとしては自分の理解を深めるためにもちょこっとでも解説したほうがいいと思ったので追記エントリー。

それと、コードを全公開してるのはボランティア精神とか、オープンソース精神とかってことではなく、もっとエロガンスな書き方だとか、実装方法だとか、その辺りを教えてーというのが本音だったりするので今後ともよろしくお願いします(笑)

で、今回のサンプルで解説してこうと思うのは、クラス構成と、ウィンドウサイズが変わった際の(要はリサイズ)オブジェクトの再配置なんかを中心に書いてきます。

まず基本は相変わらず Progression 本サイトに公開されている「東京てら子ワークショップキット」をベースに作ってるので、大筋というか、ほとんどクラス構成はこれと同じです。
ただしワークショップキットでは画面に描画されるオブジェクトのレイアウトは Flash 上(.fla)で作られているところを、今回作ったサンプルでは外部クラス(.as)で制御してます。つまりオブジェクト(クラス)単位で ActionScript によりレイアウトしてます。

レイアウトするにあたっての処理の流れとしては、
※たとえば IndexScene を例に取ると…
まず SceneObject を継承した IndexScene から、CastSprite を継承した IndexPage を追加します。
具体的に、コードから一部抜粋したのが下記です。

ACTIONSCRIPT:
  1. public class IndexScene extends SceneObject {
  2.    
  3.     private var _indexpage:IndexPage;
  4.    
  5.     public function IndexScene( name:String ):void {
  6.         _indexpage = new IndexPage();
  7.     }
  8.    
  9.     protected override function _onInit():void {
  10.         addCommand(
  11.             new AddChildAt( progression.container, _indexpage, 0 )
  12.         );
  13.     }
  14.    
  15.     protected override function _onGoto():void {
  16.         addCommand(
  17.             new RemoveChild( progression.container, _indexpage )
  18.         );
  19.     }
  20. }

次に IndexPage で配置したいオブジェクトをそれぞれ追加してきます。
今回は落書きがひとつあるだけなのでこれを追加。具体的には IndexGraphic クラスになってます。そしてこれは fla ファイルの中のライブラリシンボルに入ってるもので、リンケージプロパティで外部 as ファイル(クラス)と関連付けてます。
さらに今回の場合はどのシーン(ページ)でも落書きがひとつ、画面の中心に配置してるだけなので、全部の落書きに個別に同じコードを書くのではなくて、スーパークラス(親クラス)をひとつ用意して、それをそれぞれが継承するようにしてあります。

まず、IndexPage のコード(の一部抜粋)は下記のようになってます。

ACTIONSCRIPT:
  1. public class IndexPage extends CastSprite {
  2.    
  3.     private var _indexgraphic:IndexGraphic;
  4.    
  5.     public function IndexPage():void {
  6.         _indexgraphic = new IndexGraphic();
  7.     }
  8.    
  9.     protected override function _onCastAdded():void {
  10.         addCommand(
  11.             new AddChild( this, _indexgraphic )
  12.         );
  13.     }
  14. }

次に追加された IndexGraphic クラスは下記のように。

ACTIONSCRIPT:
  1. import ssssample.assets.IllustrationBehavior;
  2.  
  3. public class IndexGraphic extends IllustrationBehavior {
  4.  
  5.     public function IndexGraphic():void {
  6.         super();
  7.     }
  8. }

super() というのは書かなくても動くんですが、素人的にはなんとなく書いておくとシャレオツな気分が味わえるのでここはあえて(笑)
何をしてるのかというと、スーパークラス、あるいは親クラスとか呼んだりしますが、それを呼び出してます。
でもわざわざ書かなくても Flash 側で自動的に呼び出してくれるので書かなくても動きます。

で、前述したように、IndexGraphic にはこれ以上何も処理が書いてません。
全ての処理内容はスーパークラスの IllustrationBehavior に書いてあります。
その中身が下記。

ACTIONSCRIPT:
  1. public class IllustrationBehavior extends CastSprite {
  2.  
  3.     public function IllustrationBehavior():void {
  4.         super();
  5.         alpha = 0;
  6.     }
  7.    
  8.     protected override function _onCastAdded():void {
  9.         addCommand(
  10.             new ParallelList( 0,
  11.                 new Prop( this, {
  12.                     x  :stage.stageWidth / 2,
  13.                     y  :stage.stageHeight / 2
  14.                 } ),
  15.                 new DoTweener( this, {
  16.                     alpha  :1,
  17.                     time   :0.7
  18.                 } ),
  19.                 new Func( null, function():void {
  20.                     stage.addEventListener( Event.RESIZE, onResizeHandler );
  21.                 } )
  22.             )
  23.         );
  24.     }
  25.    
  26.     protected override function _onCastRemoved():void {
  27.         addCommand(
  28.             new ParallelList( 0,
  29.                 new Prop( this, {
  30.                     alpha  :0
  31.                 } ),
  32.                 new Func( null, function():void {
  33.                     stage.removeEventListener( Event.RESIZE, onResizeHandler );
  34.                 } )
  35.             )
  36.         );
  37.     }
  38.    
  39.     private function onResizeHandler( e:Event ):void {
  40.         x = stage.stageWidth / 2;
  41.         y = stage.stageHeight / 2;
  42.     }
  43. }

ステージ(stage)を参照する際、コンストラクタで参照しようと思っても(たとえば x、y 位置を設定しようとしても)null になってしまいます。

今回は画面の中央に配置したいので stage を参照する必要があって、ではどうするのかというと _onCastAdded の中からなら参照可能になります。要は表示オブジェクトコンテナに追加されたタイミングではじめて参照出来るようになります。これ、実は結構つまずいた箇所で、最初全然意味がわかんなくて、なんで stage ゲット出来ないんだぜーとか思ってました。でもよくよく考えてみればそうかそうかと。ちなみにこれは Progression の問題ではなく、ActionScript の理解が出来てなかったということですねー。成長成長。精進精進。

そしてさらにウィンドウがリサイズされた際の処理(ここでは中央配置)ですが、これは _onCastAdded の中で Func クラス(Progression コマンド)を利用してます。
Func クラスで stage にイベントを設定。リサイズされたら onResizeHandler を呼び出す、というふうにしてあります。

あ、それとこれもつまずいてたとこなんですが、_onCastRemoved の処理を最初書いてなくて、そのためにページを移動した後リサイズすると stage なんてねーよとエラーが出てて、たとえば IndexScene から Scene1 に移動したとすると、IndexScene の _onGoto で RemoveChild してんのに(ページを消してるのに)なんで?と思ってたんですが、これもよくよく考えてみたら stage 自体にイベントを設定してる訳で、それ自体を消さない限りページが変わったところで呼び出され続けてしまうんですね。なので IllustrationBehavior の _onCastRemoved で removeEventListener により削除してます。これにてウマー。

と、こんな感じでレイアウト&再配置してます。

ただこの方法でいいのか微妙に不安で。
というのは、オブジェクト単位でレイアウトさせるということは、つまりオブジェクトの数が多くなってきた場合に全部こんな感じで処理を個別に書いてたらたいへんだよなぁと思ったんですよね。それに他のオブジェクトからの位置取りというか、CSS なんかだと自分の前にあるものに影響されながらレイアウトしてきますよね。そういう意味でいうと今回みたいな感じで処理してくとたいへんそうーとか思って。

表示オブジェクト個別ではなく、ページ単位で制御したほうがいいのかな?
そのあたりまだまだ経験不足、勉強不足でいわゆるべすとぷらくてぃすな方法がわかってません。
もっと効率の良い実装方法があるような。デザパタとか、そっちのほうの勉強すればいいのかな?違う?うーん。

コメント / トラックバック 7 件

  1. taka:nium より:

    こんにちわー。

    stage.addEventListener() / stage.removeEventListener() ですが、addCommand() 内で設定する必要もないかなという気もするので、addCommand() の直前にふつーに書いてしまっていい気がしましたー。

    addCommand() の中身をパラレルに実行したい場合には、CastSprite.parallelMode = true; すると、コードがスッキリすると思います!

  2. masaya より:

    こんにちわー。
    コメントありがとうございます!

    えーと…、ということは…、
    コンストラクタで parallelMode = true; としておいて、あとは通常通りにイベントを設定したほうがいいってことでしょうか???
    実は Func の使い方が今イチ理解出来てないんですよね(なのにチュートリアル書いてしまうというハタ迷惑っぷり(笑)。すみませんです…)

  3. taka:nium より:

    addCommand() で CastSprite に追加されたコマンドは、内部的に SerialList コマンドに登録されて実行されているので直列で実行されるんですが、それを ParallelList にしたい場合には parallelMode を true にすることで、ParallelList コマンドに登録されるようになるので、わざわざParallelList を作らないで OK ということですね。
    (ちょっとややこしいですね・・・)

    Func コマンドは、特定の関数を特定のタイミングで実行する為のコマンドなので、使い方は自由です!
    ただ、今回のコードの場合にはタイミングはあまり気にする必要がなさそうだったので、コマンドで処理せずにふつーに書いてしまってもいいかなということですー。
    どっちが正解ということはなくて、よりシンプルに書く場合~ですね。
    (こっちもこっちでややこしいですね・・・)

  4. masaya より:

    >addCommand() で CastSprite に追加されたコマンドは、内部的に SerialList コマンドに登録されて実行されているので直列で実行される

    なるほどー。
    と、いうことは ParallelList が別途用意されているのは
    どういった想定でのことなんでしょうか???
    …ってフォーラムで書いたほうがいいですかね(汗)
    ひとつ分かると次にわからないことが出てくるというスパイラル(笑)

    >Func コマンドは、特定の関数を特定のタイミングで実行する為のコマンド

    特定のタイミングで、ってのが旨味なんでしょうかね???
    わかったようなわからないような…汗(手間のかかる子で申し訳ございません 笑)
    でもたしかに今回のサンプルで言えば ParallelList も Func も使わないで書くほうが仰る通りシンプルになりますね!

    ※追って、今回の作例をブラッシュアップしたバージョンを新たにエントリーしてみようと思います。

  5. taka:nium より:

    > と、いうことは ParallelList が別途用意されているのは
    > どういった想定でのことなんでしょうか???

    SerialList / ParallelList は、いくつでもネストすることが出来るので、並列処理の一部を直列にしたり、その逆もできたりします。
    ですので、parallelMode で切り替えるのは、CastHogeHoge で実行するコマンドの起点をどっちのリストで処理するのか?を設定しているだけですねー。

    > …ってフォーラムで書いたほうがいいですかね(汗)

    熱心な Progressioner は、ここもチェックしてると思います!w

    > 特定のタイミングで、ってのが旨味なんでしょうかね???

    そうですね。
    例えば、DoTweener コマンドとかを使ってアニメーションの再生を終了した後に、特定の関数を実行したい・・・場合には、DoTweener コマンドの後に関数を実行するように設定する必要があるので、そこで Func コマンドを使うのが基本ですねー。

    今回のコードをシンプルに書くとこんな感じかなと思いましたー。

    protected override function _onCastAdded():void {
    x = stage.stageWidth / 2;
    y = stage.stageHeight / 2;

    stage.addEventListener( Event.RESIZE, onResizeHandler );

    addCommand(
    new DoTweener( this, {
    alpha :1,
    time :0.7
    } )
    } )
    }

  6. masaya より:

    返信遅くなりましたー!
    すみませんです。

    >SerialList / ParallelList は、いくつでもネストすることが出来るので、並列処理の一部を直列にしたり、その逆もできたりします。

    なんとー
    なるほどなるほど。すごい…。
    激しく納得致しました。
    そういうことなんですねー。

    Func の件も超納得です!
    Progression 奥深し。恐るべし。
    AS3 勉強の手始めに Progression をチョイスした自分偉い(笑)
    珍しく勘が冴えてた模様(笑)

    しかしコードまで書いて頂きありがとうございます!恐縮です。
    いやー、エントリーしてほんとよかったです。
    でもなんだか質問責めになってしまって申し訳ございませんでした…(笑)

    追ってここでの Tips の数々含め、
    別途エントリーしますねー。

    ありがとうございます!

  7. fffflash» ブログアーカイブ » Progression やってみたよ12をブラッシュアップしたよ より:

    […] 以前エントリーした「Progression やってみたよ12の解説」に対し、nium さん直々に超濃厚なお告げ、アドバイスの数々を頂き(ありがとうございます!)、今回はそれらをもとにサンプルをブラッシュアップしましたのであらためて解説してこうと思います。 […]

コメントをどうぞ