- ベストアンサー
クリックしたインスタンスを削除する方法
- Windows版FlashCS6でActionScript3を使用して、ステージ上のインスタンスを削除する方法を教えてください。
- myBoxのインスタンスのうち、クリックされたものを削除するためには、クリックイベントを監視し、クリックされたインスタンスをremoveChild()関数を使って削除し、変数にnullを代入します。
- ただし、背景のインスタンスであるmyWallは削除されないようにします。
- みんなの回答 (1)
- 専門家の回答
質問者が選んだベストアンサー
スクリプトとしてはとりあえず 次のような感じ↓で良いのではないでしょうか。 //==================================== var myWall:Wall = new Wall(); myWall.x = 275; myWall.y = 200; addChild(myWall); var myBox:Array = new Array(10); for (var i:int=0; i<10; i++) { myBox[i] = new Box(); myBox[i].x = Math.random() * 550; myBox[i].y = Math.random() * 400; addChild(myBox[i]); //------↓以降を追加変更↓------ //(各Boxマウスオーバーでハンドカーソルにする(要る?)) myBox[i].buttonMode = true; //各Boxクリック時に関数 removeBox を実行 myBox[i].addEventListener(MouseEvent.CLICK,removeBox); } //関数 removeBox の定義 function removeBox(e:MouseEvent):void { //クリックされたターゲットをこの階層の表示リストから削除 removeChild(DisplayObject(e.currentTarget)); } //==================================== 上記スクリプトの最後の部分↓ですが //クリックされたターゲットをこの階層の表示リストから削除 removeChild(DisplayObject(e.currentTarget)); 以下ではこの行についてのみの説明を書きます。 この最後の行は 次↓のように変更してもかまいません。 removeChild(Box(e.currentTarget)); または Box クラスが MovieClip クラスを継承している場合は 次↓のように変更してもかまいません。 removeChild(MovieClip(e.currentTarget)); もし removeChild(e.currentTarget); のように 引数を「e.currentTarget」だけにした場合, その「e.currentTarget」は 単なる「Object」クラスのインスタンスとして認識されてしまうため removeChild(=表示リストから削除する) という命令を使うことができなくなります。 (「Object」クラスのインスタンスには,例えば「配列」や「関数」や「音」など "表示されないオブジェクト" も含まれるため「表示リストから削除する」という命令が通用しない。) したがって少なくとも クリックされたターゲットを "表示オブジェクト(DisplayObject)" として認識させる必要があります。 そのために DisplayObject(e.currentTarget) のように書いて イベントターゲットを「DisplayObject」に変換しているわけです。 MovieClipクラスも,Boxクラスも, 少なくとも DisplayObjectクラス は継承しているはずですから, Box(e.currentTarget) や MovieClip(e.currentTarget) などにしてもかまわないということになります。 もし Box クラスが MovieClip クラスを継承していれば クラスの継承関係は次のようになります。 Object > EventDispatcher > DisplayObject > InteractiveObject > DisplayObjectContainer > Sprite > MovieClip > Box これらクラスのうち DisplayObject 以下のクラスとして認識させれば removeChild できるという意味です。 認識させるクラスは作者の都合で適当に決めれば良いです。 ちなみに, Array(配列) クラスであれば継承関係は次のようになります。 Object > Array Function(関数/メソッド) クラスであれば継承関係は次のようになります。 Object > Function Sound(音) クラスであれば継承関係は次のようになります。 Object > EventDispatcher > Sound これら3つはどれも DisplayObject を継承していませんよね? したがって これらはどれも元から表示リストに加える(addChild する)ことができないので 表示リストから削除する(removeChild する)こともできないわけです。 (他にも DisplayObject でないオブジェクトはたくさん存在します。) または, 別の書き方として次のように変更しても良いでしょう。 removeChild(e.currentTarget as DisplayObject); removeChild(e.currentTarget as Box); removeChild(e.currentTarget as MovieClip); この「as」は ActionScript の略(=AS)ではなく, 英語の前置詞である「as (…として)」が語源でしょうね。 【英文例】I looked up to him as an engineer. 【和訳文】私は技術者として彼を尊敬している。 【Script】removeChild(e.currentTarget as DisplayObject); 【和訳文】表示オブジェクトとしてのイベントターゲットを表示リストから削除
お礼
ご教示ありがとうございます! とても丁寧なご説明に、感激しました。 質問させていただいた後、少し考えて removeChild(e.currentTarget); と書いてみて、(当然ですが)コンパイルエラーが出て、理由が解からず困っていました。 >少なくとも >クリックされたターゲットを "表示オブジェクト(DisplayObject)" として認識させる必要があります。 お教えいただき、ようやくコンパイルエラーの理由が解かりました。 ありがとうございます。 removeChildすることで、表示リストから「クリックされたBoxのインスタンス」を外すことが出来ました。 さらに「クリックされたBoxのインスタンス」への参照を保存している変数myBox[i]にnullを代入すれば、「クリックされたBoxのインスタンス」はガベージコレクションの対象になると思います(この考えは、間違えていないでしょうか。。。?)。 ガベージコレクションの対象とするために、setNullという関数を追加してみました。 //ここから上のスクリプトは省略しています。 //各Boxクリック時に関数 removeBox を実行 myBox[i].addEventListener(MouseEvent.CLICK,removeBox); myBox[i].addEventListener(MouseEvent.CLICK,setNull); } function setNull(e:MouseEvent):void{ for(var k:int=0 ; k<10 ; k++){ if(myBox[k] != null){ if(myBox[k].root == null){ myBox[k] = null; } } } } Boxのインスタンスをクリックした際に、myBoxの何番に「クリックされたBoxのインスタンスへの参照」が入っているか判らないため、setNullではmyBoxを全てチェックしています。 myBoxを全てチェックせずとも、「クリックされたBoxのインスタンスへの参照」を見つけることは可能でしょうか? ※上記のsetNullよりも、もっと効率の良い方法はないのでしょうか? 重ねての質問とはなりますが、お教えいただけませんでしょうか。。。? 何卒、よろしくお願い申し上げます。
補足
改めてネットで調べたところ、クロージャを利用することでも、必要な情報を受け渡せることが解かりました。 ※恥ずかしながら、クロージャというモノを、初めて知りました。 お陰様で、今回の質問は解決しました。 ありがとうございました!!