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を探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
【VB.NET】別Formのボタンが押...
-
Win32 API ウィンドウ
-
プログラミング、アーキテクチ...
-
ハンドルからインスタンス?を取...
-
カーソルを手に変更
-
ActionScript3.0で画面を揺らす...
-
外部テキストが読み込めません
-
BitmapをIDで指定したい
-
別のアプリケーションのテキス...
-
photoshopで書いた四角の枠の中...
-
変数に256文字以上のテキストを...
-
VB6.0 でメニューを作りたいん...
-
FLashでメモ帳などから文字を読...
-
ダブルクリックと2回クリックの...
-
VBAユーザーホームテキストボッ...
-
ダイナミックテキストの表示値...
-
IP Address 入力フォームについて
-
static関数がmapファイルに載ら...
-
VBAで改行の入ったデータの正規...
-
テキストボックスにセルの値を...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
【VB.NET】別Formのボタンが押...
-
VB6.0で、フォームから、別のフ...
-
DataTableの件数を取得したい
-
VB6.0のHideのバグ?
-
ActionScript2.0で画面スクロール
-
ダミーウインドウ
-
オブジェクトの重なり順の変更
-
プログラミング、アーキテクチ...
-
インスタンスとポインタ
-
画像を一定時間ごとに切り替え...
-
【FLASH】インスタンス名の一覧...
-
クリックしたインスタンスを削...
-
Python でシャットダウンのコマ...
-
フォームの生成と破棄
-
ウインドウハンドルとインスタ...
-
【ActionScript】コンボボック...
-
外部swfが表示されません
-
Flashの画面をJPEG画像にしてメ...
-
AS3.0でボタンで指定したフレー...
-
unityの教科書を読んでいて出て...
おすすめ情報