Progression FrameworkのForLoopとDoTweenerで、ウッヒョーイエー!ダーイ(Die)!

  • このエントリーをはてなブックマークに追加
  • 80

そんな訳でProgression Frameworkの話。つか、何で俺だけこんなに沢山の問題にぶち当たるのだろうか?やはり開発スタイル間違ってるのか?
さて今回は、ForLoopコマンドでDoTweener実行しようとしたらスタックオーバーフローで死ぬって話。

■問題と原因

この理由は案外簡単で、実はForLoop使わなくても、多分DoTweener再利用しようとしたら発生すると思う。
原因になってる、DoTweenerのコードはこの部分。

ActionScript

  1. /*======================================================================*//**
  2. * @inheritDoc
  3. * @langversion 3.0
  4. * @playerversion Flash 9.0.45.0
  5. *//*=======================================================================*/
  6. protected override function _executeProgress():void {
  7.     // 既存のイベントハンドラメソッドを保存する
  8.     _onCompleteFunction = tweeningParameters.onComplete;//・・・・・・・(1)-1
  9.    
  10.     // イベントハンドラメソッドを登録する
  11.     tweeningParameters.onComplete = _onComplete;//・・・・・・・(1)-2
  12.    
  13.     // アニメーションを開始する
  14.     if ( !Tweener.addTween( _target, _tweeningParameters ) ) {
  15.         // 処理を終了する
  16.         _executeComplete();
  17.     }
  18. }
  19.  
  20. /*======================================================================*//**
  21. *
  22. * @langversion 3.0
  23. * @playerversion Flash 9.0.45.0
  24. *//*=======================================================================*/
  25. private function _onComplete():void {
  26.     // Tweener に設定されていた onComplete() メソッドを実行する
  27.     if ( _onCompleteFunction is Function ) {
  28.         _onCompleteFunction.apply( null );//・・・・・・・(2)
  29.     }
  30.    
  31.     // 処理を終了する
  32.     _executeComplete();
  33. }

(1)と(2)は俺が入れたんだけど、この2箇所のコードがポイント。
処理の流れを追うと、

  1. DoTweenerコマンドが始まると、元々Tweenerに渡す予定だったonComplete関数を_onCompleteFunctionに退避して((1)-1)、
  2. 代わりにDoTweenerの終了処理に入れてる((1)-2)。

こうする事で、Tweenerの処理が終わった後呼ばれるのが、DoTweenerコマンドで定義されてる_onComplete()になる。
で、

  1. DoTweenerの終了処理で、_onComplete関数が呼ばれる。
  2. _onComplete関数の中で元々の終了処理である_onCompleteFunction()を実行する。

でまぁ、DoTweenerの処理は滞りなく終了するわけだけど、ここで大きな異変が。
(1)-2の部分で、Tweener用のパラメータが最初とは違うものになっちゃってる。わけです。
具体的に言うとonComplete。こいつが_onComplete関数になっちゃってるから、次にもう一回このDoTweenerコマンドを使うとどうなるか?
処理の流れを追うと、

  1. DoTweenerコマンドが始まると、元々Tweenerに渡す予定だったonComplete関数を_onCompleteFunctionに退避して((1)-1)、
  2. 代わりにDoTweenerの終了処理に入れてる((1)-2)。
  3. DoTweenerの終了処理で、_onComplete関数が呼ばれる。
  4. _onComplete関数の中で元々の終了処理である_onCompleteFunction()を実行する。
  5. が、2回目の「元々の終了処理」は_onComplete関数であるため、_onComplete関数が実行される。
  6. _onComplete関数の中で元々の終了処理である_onCompleteFunction()を実行する。
  7. _onCompleteFunction関数である、_onComplete関数が実行される。
  8. _onComplete関数の中で元々の終了処理である_onCompleteFunction()を実行する。
  9. _onCompleteFunction関数である、_onComplete関数が実行される。
  10. ・・・

こんな感じで無限に_onComplete()が呼ばれ続け、最終的にはスタックオーバーフローで終了。

■解決策

DoTweener#_onCompleteを以下のように修正。

ActionScript

  1. private function _onComplete():void {
  2.     // Tweener に設定されていた onComplete() メソッドを実行する
  3.     if ( _onCompleteFunction is Function ) {
  4.         _onCompleteFunction.apply( null );
  5.     }
  6.  
  7.     //onCompleteを元に戻す。
  8.     tweeningParameters.onComplete = _onCompleteFunction;
  9.     _onCompleteFunction = null;
  10.    
  11.     // 処理を終了する
  12.     _executeComplete();
  13. }

要するに、「終了時には元に戻しましょう」ということでいいと思う。でも成功確認しかしてないけど。

スポンサーリンク
スポンサーリンク
  • このエントリーをはてなブックマークに追加

フォローする

スポンサーリンク
スポンサーリンク