- ベストアンサー
AS3ステージリサイズでムービークリップを削除後再配置
- AS3でステージリサイズするとムービークリップを削除し、一定時間後に再配置する方法について教えてください。
- ステージ横一杯に配置されたムービークリップを2列に並べており、ステージのリサイズ時にすべてのムービークリップを削除して再配置したいですが、一部のムービークリップを削除し忘れる現象が発生します。
- 現在のコーディングは、ステージのリサイズイベントが発生したときにムービークリップをすべて削除してから再配置するようになっていますが、一部のムービークリップが残ってしまうことがあります。どこに問題があるのでしょうか?
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
問題なのは function AddMC(eventObject:Event):void { … } 内の for文, for (var k:uint=0; k<delate; k++) ですね。 Excel の VBA などをしていると頻繁に登場する事項なのですが, 例えば A1セル~A5セル に全て 10 という値が入っていたとします。 A 1 10 2 10 3 10 4 10 5 10 「もしA○セルの値が 10 であればその行を削除」 この プログラム を走らせるとき, A1→A2→A3→A4→A5 と走査処理を進めてはダメなのです。 なぜかというと まず A1 セルの走査で値が 10 のため1行目が削除されます。 そのとき,2行目が自動的に1行目にずれます。 次に A2 セルの走査をするわけですが, そのときの A2 セルの値は元 A3 セルにあるものがズレてきたものです。 ですから A1 セルに 10 という値が残ったまま, その行は削除されずにとり残されます。 つまり A1→A2→A3→A4→A5 と走査処理をすると, A 1 10 (←元A2) 2 10 (←元A4) と残ってしまします。 ですからこの場合,自動繰り下がりをしないように, A5→A4→A3→A2→A1 と走査処理をしなければなりません。 「Excel(エクセル) VBA入門:条件を満たす行を削除する」 http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/vba_row_del.html これと同様 mc 内の下インデックスの 子MC が消されると それより上の 子MC のインデックス順が繰り下がります。 ですから,まず, for (var k:uint=0; k<delate; k++) を次のように変更すべきです。 for (var k:uint=delate-1; k>=0; k--) しかし, ここにはもう1つ uint という大きな罠があります。 uint は 0 以上の整数です。 上の for文 を抜けた後,変数 k は -1 になろうとします。 ところが, 変数 k が uint 宣言してあると -1 にはなれず, 4294967295 という最大値になってしまいます。 0-1 = 4294967295 ≠ -1 すると k>=0 という条件を再び満たしてしまうので, 上の for文 に再突入しようとします。 その結果 mc.removeChildAt(4294967295); を試み, とんでもないエラーが起こって動作が停止します。 以上のことは,ヘルプを見たり trace を繰り返すとわかります。 したがって結局, for (var k:uint=0; k<delate; k++) を for (var k:uint=delate-1; k>=0; k--) に変更するのではなく 次のように変更すべきです。 for (var k:int=delate-1; k>=0; k--) これで k は for文 を抜けた後 -1 になれます。 -1 だと k>=0 の条件を満たさないので for文 に再突入することなくなります。
その他の回答 (1)
- BlurFiltan
- ベストアンサー率91% (1611/1754)
#1です。 > 外部から読込むタイプにして処理が追いつかづ非表示の場合でてくるのでしょうか? そう書かれましても, 状況がさっぱりわかりませんが。 外部画像として SWF や HTML と同じ階層に 「box.jpg」 という 80×100 の JPEG が 1枚だけあったとします。 それを 元のご質問のスクリプトに当てはめてロード表示させる例です。 ------------------- stage.align=StageAlign.TOP_LEFT; stage.scaleMode=StageScaleMode.NO_SCALE; //--- var myLD:Loader = new Loader(); var myRQ:URLRequest=new URLRequest("box.jpg"); myLD.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete); var bmd:BitmapData; function onComplete(evt:Event):void { bmd=new BitmapData(myLD.width,myLD.height); bmd.draw(myLD); Set(); } myLD.load(myRQ); //--- stage.addEventListener(Event.RESIZE,AddMC); function AddMC(eventObject:Event):void { var delate:uint=mc.numChildren; for (var k:int=delate-1; k>=0; k--) { mc.removeChildAt(k); } if (delate<=0) { var SetTimer:Timer=new Timer(500,1); SetTimer.addEventListener(TimerEvent.TIMER,ReAdd); SetTimer.start(); function ReAdd(eventObject:TimerEvent):void { Set(); } } } //--- function Set():void { var yoko:uint=Math.ceil(stage.stageWidth/80); for (var i:uint=0; i<yoko; i++) { for (var j:uint=0; j<2; j++) { var bmp:Bitmap=new Bitmap(bmd); mc.addChild(bmp); bmp.x=40+80*i; bmp.y=50+100*j; } } } ------------------- 別に何の問題も起こりませんが...。 字数制限に引っかかるため注釈行や説明は抜きです。
補足
ちょっと説明が足りなかったみたいで申し訳ありません。 MCにはTweenとかを使ってるんですよ、これが問題なんでしょうね。 http://www.sarashibar.com/flashsample/ ↑これが実際に作ったFlashなんですが、リサイズするとたまに何も再表示されないときがあります。なにが原因なんでしょう?
お礼
どうも丁寧なご説明ありがとうございました。
補足
ああそうかぁ、ムービークリップの階層は0から始まって消す時はだる磨落し形式で消すので下からだと残る場合があるんですね、だから上から消したほうが確実なんですね。 いつもfor(var i:uint=0; i<num; i++)とやっていてもので「i--」もあったことをすっかり忘れていました。 ところで問題なく正常に消して再設置ができるようにはなったのですが、今度はxmlを使って外部フォルダに保存してある画像を読み取ってLoaderを使って表示させるタイプを作ったのですが、たまにリサイズの仕方、例えばちょこちょこと連続してウィンドウサイズを変えたりするとムービークリップがすべて消された後、なにも表示されない時があります。そのあとちょこっとだけウィンドウサイズを変えたりするとまた正常に表示されます。 連続しないで少し程度間を開けてウィンドウサイズを変えてあげれば問題なく正常に表示されるのですが、これって外部から読込むタイプにして処理が追いつかづ非表示の場合でてくるのでしょうか?