Progression Frameworkのコマンド使ってみよう大会継続中だが、今回はLoaderクラスとFuncコマンドを使ってロード完了待ちをしようと言うテクニックと、発生した問題点について述べたいと思う。
Funcコマンドを使った方法は、
こちらを参考にしてみた。
■Funcコマンドでデータ読み込み
さて、Funcコマンドを使った読み込みだが、このような感じになる。
- var loader:CastLoader = new CastLoader();
- loader.contentLoaderInfo..addEventListener(IOErrorEvent.IO_ERROR, function(e:IOErrorEvent):void {
- trace("読み込み失敗(IO):", sceneId, url, e);
- });
- loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function(e:SecurityErrorEvent):void {
- trace("読み込み失敗(SEC):", sceneId, url,e);
- });
- addCommand(
- new Func(null, loader.load, [new URLRequest("image.jpg")], 0,
- loader.contentLoaderInfo, Event.COMPLETE),
- new AddChild(progression.container , loader , true),
- new Goto(children[0].sceneId)
- );
これで、画像「image.jpg」を読み込み、読み込みが完了したら画面に表示して、最後に次のシーンに移動すると言う処理になっている。この簡単なコードでこの処理。Progression Frameworkは偉大だ。
■うまくいくとは限らない
ただし、これは画像がうまく読み込めたらの話。
じゃあ、例えばURLが間違ってたり、その他の理由で画像が読み込めない状況になったらどうなるか?
こうなる。
簡単に言うと、「何も出来なくなる」。
画像は勿論表示されないし、次のシーンに移動もしない。
それどころか、他のボタンを押しても何も起きない。処理が完全に停止し、どうしようもなくなるようなのだ。
何故か!?
それはこれ。
- new Func(null, loader.load, [new URLRequest("image.jpg")], 0, loader.contentLoaderInfo, Event.COMPLETE),
Funcに指定できる、「あるオブジェクトがあるイベントを送出するまで、処理を停止する」機能のせいだ。
この例の場合だと、loader.contentLoaderInfo
から画像読み込みが完了したことを示すEvent.COMPLETE
が送出されるまで、コマンドは処理を停止し、待ち続ける。
が、読み込み失敗時には、その原因に応じてIOErrorEvent.IO_ERROR
やSecurityErrorEvent.SECURITY_ERROR
などが送出され、Event.COMPLETE
が送出されないままで読み込みは終了する。
で、そのままFuncコマンドはずーっと待ちぼうけし続け、以降のコマンドは全く実行されないと言うわけだ。
さらに、addCommand
で一気にコマンドを追加すると、全部が終了するまで他の処理が行われないらしい。前回のエントリで書いた並列実行と直列実行のサンプルでも、直列実行時に一番上のボタン0を押しても何も起きない。すべてのボタンが出終わってからでないと、ボタンの動作が無視されるようなのだ。
■更なる悲劇が!
さて、ではエラー時はどうすればいいのか?
取り敢えず、エラーイベントを拾ったらおとなしく他のシーンに移ってはどうか?
- var loader:CastLoader = new CastLoader();
- loader.contentLoaderInfo..addEventListener(IOErrorEvent.IO_ERROR, function(e:IOErrorEvent):void {
- trace("読み込み失敗(IO):", sceneId, url, e);
- new Goto(progression.root.sceneId).execute();
- });
- loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function(e:SecurityErrorEvent):void {
- trace("読み込み失敗(SEC):", sceneId, url,e);
- });
- addCommand(
- new Func(null, loader.load, [new URLRequest("image.jpg")], 0,
- loader.contentLoaderInfo, Event.COMPLETE),
- new AddChild(progression.container , loader , true),
- new Goto(children[0].sceneId)
- );
と言うわけで、失敗したらルートシーンに戻ると言う事にしてみた。
さて問題!
ココで注意すべき点があります。このコードを書いてはいけない場所はどこ?
・
・
・
・
答え:_onLoad
メソッド内。
今回のコード例だと、コードがあるシーンはルートの子で、行き先は自分の子、つまりルートの孫になる。
なので、エラー時にルートに移動するとどうなるか?
- 画像読み込み(
Func
)開始 - IOエラー発生。ルートへ移動
- シーンが移動し、画像読み込み用の
Func
コマンド停止 - 画像表示(
AddChild
)開始 - シーン移動(ルートの子の子への
Goto
)開始 - ルート→孫への移動の過程で、画像読み込みシーンの
_onLoad
実行 - 1.に戻る
このように無限ループに陥ってしまう。
ミソは、シーンを移動してもFunc
が終わるだけで、後続のコマンドが実行されると言う点。
なので、画像読み込みは_onInit
に書かないとダメ。
まぁ、この辺りはシーン移動のパズルだな。
ちゃんと理解して上手く考えないと、ヒドイ目に逢いますよと言う話。プログラムの世界じゃよくある事だ。
と言うわけで、_onInit
にaddCommandを移したバージョンはこちら。
画像読み込み失敗でも、ちゃんとシーン移動が出来る。
最新コメント