重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

電子書籍の厳選無料作品が豊富!

お世話になります。

Flash初心者です。
ActionScript 3.0でカードゲームみたいなものを作成しようとしていますが、addEventListenerの扱いで行き詰りました。

概要としては
(1)絵柄オブジェクトとテキストオブジェクトを組み合わせてカードオブジェクトを作成
(2)カードをaddChildでメインのタイムラインに生成
(3)カードをクリックすると画像が変わる
といったことをしたいです。

そのため、メインのタイムラインの1フレーム目に以下のような記述を入れました。(抜粋)
---
var player01Card:Array = new Array();

//60枚のカードを生成
for(i=0;i<60;i++){
 player01Card[i] = new Card();
 addChild(player01Card[i]);
}

//カードそれぞれに、クリックされたら絵柄が変わるように設定・・・したい
for(var i:int; i<player01Card.length ;i++){
 player01Card[i].addEventListener(MouseEvent.CLICK,
  function(event:MouseEvent):void{
   player01Card[i].gotoAndStop(36);
  }
 );
}
---

・Cardはカードのムービークリップに設定したリンケージです。
・カードのムービークリップは36フレーム以上あり、画像を変えないため1フレーム目で「stop();」しています。
・36フレーム目に飛ぶことで絵柄を変えるつもりです。

が、カードをクリックすると
--
TypeError: Error #1010: 条件は未定義であり、プロパティがありません。
--
が発生します。

・gotoAndStopの代わりにカードのムービークリップ上に[画像を生成するメソッド]を作成してそれをたたこうとした場合にも同じエラーが発生します。
・traceのような関数では問題は発生しないため、ムービークリップを触りにいくことが問題だと思います。
・player01Card[i].gotoAndStop(36);をaddEventListenerの外に配置した場合は正常に動作します。
・addChildでなく、最初からメインのタイムラインにインスタンスを配備してやるとgotoAndStopできます。

addEventListenerの仕様なのかと考えているのですが、どう変えてやれば動くのかがまったくわかりません。

一応検索して似たような質問を発見していますが、私のコードには微妙に合いません。
http://oshiete.goo.ne.jp/qa/4646183.html
>evnet.target.gotoAndStop(36);としてしまうとカードの合成前の絵柄やテキストがgotoAndStopされてしまう

何が問題なのか、そしてどうすれば動かせるのか教えていただけないでしょうか。

A 回答 (1件)

===【本題の回答の前に】============



2つ目の for文 の一部分に間違いがありますね。

for(var i:int; i<player01Card.length ;i++) {
 ↓iの初期値が抜けてます↓
for (var i:int = 0; i<player01Card.length; i++) {

と言うか...
本来 var i は最初の for文 の方などですべきです。

最初の for文↓

for(i=0;i<60;i++){
 ↓変更↓
for (var i:int=0; i<60; i++) {

2つ目の for文↓

for(var i:int; i<player01Card.length ;i++)
 ↓変更↓
for (i = 0; i<player01Card.length; i++) {

 
.
 
===【本題の回答】===============

> 何が問題なのか、

これについては,
2つ目の for文 の後辺りに
trace(i);
と書いてムービープレビューしてみると
その問題の原因がわかると思います。

for文 を抜けた後
変数 i に代入された値は player01Card.length (=60) になって止まっているため
どのボタンをクリックしても
player01Card[60].gotoAndStop(36);
が動作します。

その player01Card[60] は存在しないはずなのでエラーが出るのです。

この件に関しては
書かれていらっしゃる http://oshiete.goo.ne.jp/qa/4646183.html
超スローモーション的な動作説明を入れて詳細に書いています。

 

> >evnet.target.gotoAndStop(36);としてしまうと
> カードの合成前の絵柄やテキストがgotoAndStopされてしまう

こちらに関しては,
まず第一に書かれていらっしゃる日本語の意味が良くわかりません。
「カードの合成前の絵柄やテキストがgotoAndStopされてしまう」とは???


さらに,
私の方で実際に作って検証してみましたが
無事にクリックした Card 内が フレーム36 で停止しましたよ。

ひょっとして Card のムービークリップは
さらにその中に 子ムービークリップ が入っていて
その 子ムービークリップ 内にも複数フレームがあって
その中でも絵柄が変わるとか???

とにかく何だか良くわかりませんが,
これに関しては target ではなくcurrentTarget を使えば解決するかもしれません。

evnet.target.gotoAndStop(36);
 ↓変更↓
event.currentTarget.gotoAndStop(36);

 
.
 
 
===【オマケの回答】==============

target や currentTarget を使わずに
Card クリック時に クロージャ(関数の一種) を実行させる方法もあることはあります。

◎クロージャを使う方法例↓

//-------------------------------------
var player01Card:Array = new Array();

//60枚のカードを生成
for (var i:int=0; i<60; i++) {
player01Card[i] = new Card();
addChild(player01Card[i]);
//(↓※私の個人的な動作検証用の行)
//player01Card[i].x = i * 8;
}

for (i = 0; i<player01Card.length; i++) {
//player01Card[i] クリック時に関数 onCardClick の戻り値を実行
player01Card[i].addEventListener(MouseEvent.CLICK,onCardClick(player01Card[i]));
}

//クロージャ を返す関数 onCardClick の定義
function onCardClick(obj:Card):Function{
//戻り値として クロージャ を返す
return function():void{
obj.gotoAndStop(36);
}
}
//-------------------------------------


※クロージャ は ActionScript 専用用語ではなく
. 多くの言語で使われる一般的プログラム用語です。

 

 
その他,
私が「ただ考えてみた」というだけのことで
全くお薦めできない方法ですが
次のようにしても target や currentTarget を使わなくてもできることはできます。
(カードどうしが重なることがある上で,さらにカードの上下関係が変わる場合などは,このままでは使えません。)

◎カードの親クリックでマウスとヒットしたカードに命令する方法↓

//-------------------------------------
var player01Card:Array = new Array();

//60枚のカードを生成
for (var i:int=0; i<60; i++) {
player01Card[i] = new Card();
addChild(player01Card[i]);
//(↓※私の個人的な動作検証用の行)
//player01Card[i].x = i * 8;
}

//この階層に対してクリック時の関数を定義
this.addEventListener(MouseEvent.CLICK,
function(event:Event){
//配列要素の最後から最初に向けてループ
for(i = player01Card.length-1; i >= 0; i--){
//配列要素にマウスがヒットしていれば
if(player01Card[i].hitTestPoint(player01Card[i].parent.mouseX,player01Card[i].parent.mouseY,true)){
//対象カード内をフレーム36に進める
player01Card[i].gotoAndStop(36);
//この for文 を抜ける
break;
}
}
}
);
//-------------------------------------

 
    • good
    • 0
この回答へのお礼

拙い質問に丁寧なご回答、ありがとうございました。本当に助かりました。

結論から言えば、ご提示の「クロージャ」を用いたやり方で実現できました。キーワードを教えていただいたので自分でも調べてみたいと思います。


以下、蛇足ながら質問に不備があった部分等の補足です。
---
>ひょっとして Card のムービークリップは
>さらにその中に 子ムービークリップ が入っていて
>その 子ムービークリップ 内にも複数フレームがあって
>その中でも絵柄が変わるとか???
まさにそのとおりです。カードなので背景ムービークリップや絵柄ムービークリップなどの集合として作成していました。具体的にはカードをaddChildした上でさらにカード上に背景と絵柄をaddChildするような感じです。
そのためクリックすると背景の色だけ変わってしまったり絵柄だけ変わってしまったりしていたのです。

>これに関しては target ではなくcurrentTarget を使えば解決するかもしれません。
targetのように絵柄の一部が変わってしまうことはありませんでしたが、元のエラーが発生しまいました。

>2つ目の for文 の一部分に間違いがありますね。
コードを抜粋する際にミスしたようです。一度コンパイルしてみてから展開すべきでした・・・余計なお手間をおかけしました。

>その player01Card[60] は存在しないはずなのでエラーが出るのです。
こちらについては、いろいろと配列番号を変更してみてもエラーは発生しますので、原因は他所のようです。(というかこちらも抜粋する際にコードを編集して余計なエラーを作ってしまっているようです・・・)

お礼日時:2013/10/08 23:11

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!