
windows版FlashCS6で、ActionScript3を使用しております。
どうぞ、よろしくお願いいたします。
最初に、前提をご説明します。
埋め込みアセットクラスBoxをライブラリに準備します。
Boxの中には、50px × 50pxのビットマップが、基準点を中央で配置してあります。
埋め込みアセットクラスWallをライブラリに準備します。
Wallの中には、550px×400pxのビットマップが、基準点を中央で配置してあります。
ステージサイズは550px×400pxです。
タイムラインに、下記のActionScript3を書きます。
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]);
}
パブリッシュすると、ステージ上にはmyWallのインスタンスが1個と、myBoxのインスタンスが10個配置されます。
myBoxのインスタンスいずれかをクリックすると、クリックされたmyBoxが削除される(クリックされたmyBoxをremoveChild()し、それの参照を保存していた変数にnullを代入する)ようにするには、どのようにスクリプトを組めば良いでしょうか?
背景のmyWallは、クリックされても削除されないようにしたいです。
ご教示のほど、どうぞ、よろしくお願いいたします。
No.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よりも、もっと効率の良い方法はないのでしょうか?
重ねての質問とはなりますが、お教えいただけませんでしょうか。。。?
何卒、よろしくお願い申し上げます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
【VB.NET】別Formのボタンが押...
-
Flashの画面をJPEG画像にしてメ...
-
「Me」を「Form1」にするとエラ...
-
python ボタンを押すと複数の関...
-
else if文の順序を変えることに...
-
photoshopで書いた四角の枠の中...
-
static関数がmapファイルに載ら...
-
マウス自体の移動量の取得
-
SO-01B(2.3.3)のroot化について
-
フォームのテキストの入力数字...
-
Access2000 実行時エラー '3061':
-
全てのテキストボックスをセル...
-
アセンブリ言語のcasl2について...
-
縦横比率のを変えずに画像のサ...
-
テキストボックスの中身をリセ...
-
VBAユーザーホームテキストボッ...
-
ランダムに4桁の数字を表示する...
-
リッチテキストボックスでの書...
-
VBAで改行の入ったデータの正規...
-
シンボル化解除の方法
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
CreateDialogについて
-
flash MXのスクロールパネルに...
-
3つ以上のインスタンスの移動
-
ペンによる手書きの様に
-
VB6.0で、フォームから、別のフ...
-
CREATESTRUCT と GetWindowLong
-
_widthから数値を導き出したい
-
シューティングゲームの自機の...
-
前の質問が消えてしまいました
-
【ActionScript】コンボボック...
-
【VB.NET】別Formのボタンが押...
-
レイヤー内のすべてのMCのX...
-
C#で、コントロールの受け渡し...
-
フォームの生成と破棄
-
画像を一定時間ごとに切り替え...
-
ムービークリップ内に配置した...
-
外部swfが表示されません
-
Androidで共通のレイアウトを使...
-
Flash ActionScriptで変形点を...
-
チェックボックスの制御(onCli...
おすすめ情報