addEventListenerでカードの画像が変わらないエラーが発生する

このQ&Aのポイント
  • Flash初心者がActionScript 3.0でカードゲームの作成を試みています。
  • addEventListenerの扱いで問題が発生しており、カードをクリックしても画像が変わりません。
  • 解決方法についての情報を探しているが、既存の質問とは異なるエラーが発生しているため解決策がわからないとのことです。
回答を見る
  • ベストアンサー

addEventListnerとaddChild

お世話になります。 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://okwave.jp/qa/q4646183.html >evnet.target.gotoAndStop(36);としてしまうとカードの合成前の絵柄やテキストがgotoAndStopされてしまう 何が問題なのか、そしてどうすれば動かせるのか教えていただけないでしょうか。

  • Flash
  • 回答数1
  • ありがとう数11

質問者が選んだベストアンサー

  • ベストアンサー
  • BlurFiltan
  • ベストアンサー率91% (1611/1754)
回答No.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://okwave.jp/qa/q4646183.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; } } } ); //-------------------------------------  

kasumida
質問者

お礼

拙い質問に丁寧なご回答、ありがとうございました。本当に助かりました。 結論から言えば、ご提示の「クロージャ」を用いたやり方で実現できました。キーワードを教えていただいたので自分でも調べてみたいと思います。 以下、蛇足ながら質問に不備があった部分等の補足です。 --- >ひょっとして Card のムービークリップは >さらにその中に 子ムービークリップ が入っていて >その 子ムービークリップ 内にも複数フレームがあって >その中でも絵柄が変わるとか??? まさにそのとおりです。カードなので背景ムービークリップや絵柄ムービークリップなどの集合として作成していました。具体的にはカードをaddChildした上でさらにカード上に背景と絵柄をaddChildするような感じです。 そのためクリックすると背景の色だけ変わってしまったり絵柄だけ変わってしまったりしていたのです。 >これに関しては target ではなくcurrentTarget を使えば解決するかもしれません。 targetのように絵柄の一部が変わってしまうことはありませんでしたが、元のエラーが発生しまいました。 >2つ目の for文 の一部分に間違いがありますね。 コードを抜粋する際にミスしたようです。一度コンパイルしてみてから展開すべきでした・・・余計なお手間をおかけしました。 >その player01Card[60] は存在しないはずなのでエラーが出るのです。 こちらについては、いろいろと配列番号を変更してみてもエラーは発生しますので、原因は他所のようです。(というかこちらも抜粋する際にコードを編集して余計なエラーを作ってしまっているようです・・・)

関連するQ&A

  • ActionScript3.0フレーム移動について

    お世話になります。 Flash ActionScript3.0で、ボタンをクリックしたら、 階層違いのシーンに移動するという 単純なところでつまずいています。 一番上の階層には、 1フレーム目 フレームラベル "a" 2フレーム目 フレームラベル "b" として、それぞれ this.stop();を書いてあります。 "a""b"には、それぞれムービークリップが配置してあって、 今やりたいことは、"a"に配置してあるムービークリップの 2つ下(中?)の階層にあるボタンをクリックしたら、一番上の階層の"b"に移動して、 "b"に配置してあるムービークリップを表示するようにしたいのです。 "a"のムービークリップのボタンのあるフレームには、 this.stop(); button01.addEventListener(MouseEvent.CLICK,jumpB); function jumpB(event:MouseEvent):void { MovieClip(parent.parent).gotoAndStop("b"); } と書いてみましたが、 [TypeError: Error #1009: null のオブジェクト参照のプロパティまたはメソッドにアクセスすることはできません。] と怒られます。 試しに MovieClip(stage).gotoAndStop("b"); とか、"b"に配置してあるムービークリップにインスタンス名"b_mc"を与えて MovieClip(parent.parent).b_mc.play(); などと苦し紛れにやってみましたが、すべて同じように怒られます。 どのようにすれば、下の階層から一番上の階層の別フレームに 移動することができますでしょうか? よろしくお願い致します。

  • AS3.0で、複数のボタンをaddChildを使って配置しマウスイベン

    AS3.0で、複数のボタンをaddChildを使って配置しマウスイベントをfor文でまとめて設定する場合で悩んでおります、現在の以下のようにコーディングしているのですが、 //ボタン数 const Btns:uint=3; //ボタン配置 for (var i:uint=1; i<Btns+1; i++) { var BtnName:String="btn0"+i; ->ボタンにつけたクラスネーム var BtnClass:Class=getDefinitionByName(BtnName) as Class; var btnMC:MovieClip = new BtnClass(); loadmc02.addChild(btnMC); (loadmc2はボタンを配置するMC) btnMC.buttonMode=true; btnMC.x=10*i+140*(i-1); btnMC.y=340; if (i==1) { btnMC.addEventListener(MouseEvent.CLICK, BtnOnClick1); btnMC.addEventListener(MouseEvent.ROLL_OVER, BtnRollOver1); btnMC.addEventListener(MouseEvent.ROLL_OUT, BtnRollOut1); } else if (i==2) { btnMC.addEventListener(MouseEvent.CLICK, BtnOnClick2); btnMC.addEventListener(MouseEvent.ROLL_OVER, BtnRollOver2); btnMC.addEventListener(MouseEvent.ROLL_OUT, BtnRollOut2); } else if (i==3) { btnMC.addEventListener(MouseEvent.CLICK, BtnOnClick3); btnMC.addEventListener(MouseEvent.ROLL_OVER, BtnRollOver3); btnMC.addEventListener(MouseEvent.ROLL_OUT, BtnRollOut3); } } です。BtnOnClick1~3は異なるURLでBtnRollOver1~3、BtnRollOut1~3は function Over(hikisu)、function Out(hikisu)という関数を作って、 function BtnRollOver1(eventObject:MouseEvent):void { Over(1); } function BtnRollOut1(eventObject:MouseEvent):void { Out(1); }てな感じで動かしたい。 2.0とかってが違うので悩んでいます。効率のよいコーディングの仕方を教えてください。 よろしくお願いします。

    • ベストアンサー
    • Flash
  • リンケージを使った表示オブジェクトのコントロールについて教えてください

    FlashCS4でAS3.0を使用してます。 リンケージを使った表示オブジェクトのコントロールについて教えてください。 内容は四角いオブジェクトを作成し、モーショントゥィーンにして、1フレームには小さいオブジェクト(100×100ピクセル)で、そこから10フレームでは最大の大きさ(200×200ピクセル)になるようにし、さらには11フレームからは逆に小さくなって20フレームには元のサイズ(100×100ピクセル)になるムービークリップを作成。あらかじめ10フレームにはアクションスクリプトで「stop();」を記述してムービーが止まるようにしてます。さらにはムービーを最大から最小に再生(11フレーム~20フレームに再生)されるように10フレームには「close_bt」も設置してます。 その後、そのムービークリップのプロパティでリンケージにて「AS用に書き出し」にして「1フレーム目に書き出し」にチェックを入れ、クラスは「Photo1」としました。 その後にメインのタイムラインには先のムービークリップを表示させる為のボタン「p1_bt」を設置して下記のスクリプトを記述しました。 ----------------------------------------------------- p1_bt.buttonMode=true; var newCharacter:MovieClip=new Photo1(); newCharacter.x=60; newCharacter.y=191; p1_bt.addEventListener(MouseEvent.CLICK,p1Click); function p1Click(evt:MouseEvent):void{ addChild(newCharacter); } ----------------------------------------------------- その後に、ムービープレビューをして、ムービークリップを表示させる為のボタン「p1_bt」をクリックすると先のムービークリップが表示されるのですが、いきなり10フレーム目、最大の大きさにて表示されます。小さいサイズからアニメーションせずにいきなり最大のサイズで表示されてしまいます。さらには閉じる為に10フレームには「close_bt」のフレームには下記のスクリプトを記述したのですが、反応がなく表示されたままになってます。 ------------------------------------------------------- var newCharacter:MovieClip=new Photo1(); close_bt.addEventListener(MouseEvent.CLICK,xRemoveClick); function xRemoveClick(evt:MouseEvent):void{ removeChild(newCharacter); } -------------------------------------------------------- このままですと、ムービークリップを表示させる為のボタン「p1_bt」をクリックした場合にはオブジェクトがアニメーションせずにいきなり最大サイズで表示され、その後、閉じる事が出来ないのです。 要は、ムービークリップを表示させる為のボタン「p1_bt」をクリックしたらオブジェクトがアニメーションして最大サイズになり、その最大サイズ時(10フレーム)に設置してある「close_bt」をクリックすれば、最大のサイズから最小のサイズにアニメーションし、その後そのオブジェクトが非表示にさせたいのです。 長々と説明し、説明が上手くないので解り難いかと思いますが、どなたかこの件で解る方がいましたらアドバイス、ご指導のほどをお願い致します。

    • ベストアンサー
    • Flash
  • クラスまたはインタフェイス'MouseEvent'をロードできませんでした。

    「クラスまたはインタフェイス\'MouseEvent\'をロードできませんでした。」 というエラーの解決方法を教えてください。 yes_btn_mcというムービークリップをクリックすると70フレーム目にとばしたいのです。 yes_btn_mc.addEventListener(MouseEvent.CLICK, yesClick); yes_btn_mc.buttonMode=true; function yesClick(evt:MouseEvent):void{ gotoAndstop(70); } 上記のようにアクションパネルに記述しましたが、 「クラスまたはインタフェイス\'MouseEvent\'をロードできませんでした。」 と出て動きませんでした。 どうすれば動くようになるかわかる方、教えてください。

  • actionscript3.0 オブジェクトの動的生成

    actionscript3.0についての質問です。 イラストレーターのテキストツールのように 任意の文字オブジェクトを複数生成し、生成された任意の文字オブジェクト をドラッグで移動する処理をactionScriptで実行したいと考えています。 現在actionscript3.0で行いたいと考えている一連の流れは以下の通りです。 1.ステージに配置したテキストフィールに任意の文字列を入力 2.入力された文字列を参照してムービークリップ内のダイナミックテキストに出力。 3.ステージにボタンを配置し、それを押すことでステージに1.2の手順によって作成されたムービークリップが生成。 4.生成されたムービークリップをドラッグすると動かすことができる。 1から3までの内容を下記のようなスクリプトで行いました。 //ダイナミックテキストを内包するためのムービークリップを定義 //埋め込みアセットクラスmcからインスタンスを生成 var word_mc:MovieClip = new mc( ); //ボタンクリックイベントを登録 create_btn.addEventListener( MouseEvent.Click, creClick ); //ボタンクリック時の処理 function creClick( evt:MouseEvent ):void { //テキストフィールドinputWordに入力されたテキストを変数inputに格納 var input:String = inputWord.text; //word_mc内に配置したダイナミックテキストoutputWordに入力テキスト内容を出力 word_mc.outputword.text = input; //word_mcを画面に表示 addChild( word_mc ); } //word_mcをドラッグで移動させるためのスクリプト word_mc.addEventListener( MouseEvent.MOUSE_OVER, wordMO ); function wordMO( evt:MouseEvent ):void { word_mc.addEventListener( MouseEvent.MOUSE_DOWN, wordMD ); word_mc.addEventListener( MouseEvent.MOUSE_UP, wordMU ); } function wordMD( evt:MouseEvent ):void { word_mc.startDrag( ); } function wordMU( evt:MouseEvent ):void { word_mc.stopDrag( ); } ひとつのオブジェクトを生成するだけならこれで問題ないのですが、 このスクリプトでは、、"車"、"自転車"、"飛行機"という文字列をそれぞれ内包した変数名もしくはクラス名の違うオブジェクトを生成することが できません。 埋め込みアセットクラスをあらかじめ複数作っておいて、クラス名を 連番で名づけ、クラス名から動的にオブジェクトを生成すれば 内容の異なるオブジェクトを生成することは可能ですが、 単語を追加するたびに埋め込みアセットクラスを作成しなければ ならない上、変数名は同じなため、個々のオブジェクトをマウスドラッグすることができません。 イラストレーターのテキストツールのように 任意の文字列を生成した後、個々にマウスドラッグできようにするには どうしたら良いのでしょうか。 どうかご指導のほど、よろしくお願い致します。

    • ベストアンサー
    • Flash
  • AS3.0で子MCから他の子MCのフレームへ移動

    Flash professional CS5を使用してAS3.0で記述しています。 メインのタイムラインにフレームラベルが二つ(main1とmain2)あります。 main1にはステージにムービークリップのmc1が,main2にはmc2が配置してあります。 さらに, こういう書き方でいいのかわかりませんが; mc1内にはフレームラベルsub1,sub2があります。 同様に, mc2内にはフレームラベルpart1,part2があります。 sub1ではボタン(btn1)があり,押すとフレームラベルsub2に進むようになっています。(確認済み) sub2にもボタン(btn2)が用意してあり押したらムービークリップmc2内のpart2に移動させたいと考えています。 フレームラベルsub2で btn2.addEventListener(MouseEvent.CLICK, Click2); function Click2(evt:MouseEvent):void{ MovieClip(parent).gotoAndStop("main2"); } と記述すればメインタイムラインのフレームラベルmain2に移動することは確認しました。 しかしフレームラベルpart2へ移動するにどのように記述したらよいかわかりません。 MovieClip(parent).mc2.gotoAndStop("main2"); としてもやはりmc2が未定義なので無理なのでしょうか? もしそうでしたらmain1の段階で定義しようかと思うのですが,その場合はどのように記述すればよいのでしょうか? つまり,メインタイムライン上における後ろのフレームラベルの子のフレームラベルに移動したいです。 説明がうまくできないので図も載せます。 http://www1.axfc.net/uploader/Img/so/99986 よろしくお願いいたします。

    • ベストアンサー
    • Flash
  • AddChildで配置したインスタンスを動かす

    三角や四角などのブロックを並べて遊ぶアプリを作ろうとしています。 ActionScript3.0のAddChildでライブラリからインスタンスを配置させ それをドラッグできるようにしたいのです。 三角のインスタンスを出現させるために「sankakuBlockBtn」というインスタンス名の ボタンを配置し、それをクリックするとライブラリからインスタンスが配置されるという仕組みを考えています。 //クリックイベント sankakuBlockBtn.addEventListener(MouseEvent.CLICK, sankakuHandler); function sankakuHandler(event:MouseEvent):void { //リンケージでクラス名を「sankakuClass」と設定したものをAddChildでステージに配置 var sankaku:sankakuClass = new sankakuClass this.addChild(sankaku); sankaku.x =400; sankaku.y =400; trace(sankaku.name); } 配置することをまではできるのですが、 これをstartDrag()で動かそうとするのですが、 AddChildで配置するたびにインスタンス名が「instance○○」となるので、 これらをどうやって制御するのか分かりません。 最終的には「三角」「四角」「菱形」「台形」「六角形」をそれぞれステージ上に複数配置して、並べて遊べるようにしたいと思っています。 どなたかお力添えいただけないでしょうか。

  • (AS3)ムービークリップからメインタイムラインにある関数を呼び出したい

    質問はタイトルの通りです。 実は以前同じ質問(http://oshiete1.goo.ne.jp/qa3811855.html)をしましたところ、次のような回答をいただきました。 「 [メインタイムライン] function aaa(){ trace("ok") } [testMC] this.addEventListener(MouseEvent.CLICK , onClick) var rootObj:MovieClip = this.root as MovieClip; function onClic(event:MouseEvent):void{ rootObj.aaa(); } 」 たしかに、この方法はムービークリップ(testMC)をステージに手動で配置したときには有効でしたが、stage.addChild()を使って配置したときには関数を呼び出すことができませんでした。 ちなみに、呼び出そうとすると次のようなエラーがでます。 「 ReferenceError: Error #1069: flash.display.Stage にプロパティ aaa が見つからず、デフォルト値もありません。 」 stage.addChild()で配置したムービークリップから、メインタイムラインの関数を呼び出すにはどうすればよいのでしょうか? 困っています。どうか力を貸してください。

    • ベストアンサー
    • Flash
  • Flash MCのモーショントウィーン

    Flash CS5 ActionScript 3.0にて制作しています。 ムービークリップに動きをつけて色を変更するスクリプトを書いています。 ・ボタン1を押すとムービークリップの色が変わる ・ボタン2を押すと10フレーム目に飛んでモーショントウィーン それぞれ機能は正常に動くのですが、ボタン1を押した後にボタン2を押すとモーショントウィーンが動きません。 ボタン2を押した後にボタン1を押す場合は動きます。 ムービークリップのインスタンス名はtest として下記のようなスクリプトを書いています。 どなたか、お力をお貸し下さい。 よろしくお願い致します。 btn.addEventListener(MouseEvent.CLICK, black); black(event:MouseEvent):void { var color = new flash.geom.ColorTransform(0, 0, 0, 1); test.transform.colorTransform = color; } btn2.addEventListener(MouseEvent.CLICK, btn2); function btn2(event:MouseEvent):void{ gotoAndPlay("10"); }

    • ベストアンサー
    • Flash
  • フラッシュについてcs3とcs4から

    今フラッシュについて勉強しているのですが、CS4のアクションスクリプトをCS3で動かそうとして、1046型が見つからないというエラーが出ました。もしよろしければ直し方を教えていただけませんか。 プログラムは stop(); btn01,addEventListener(MouseEvent.CLICK,jump_10); function jump_10(event:MotionEvent):void { gotoAndStop("10"); }; btn02,addEventListener(MouseEvent.CLICK,jump_20); function jump_20(event:MotionEvent):void { gotoAndStop("20"); }; btn03,addEventListener(MouseEvent.CLICK,jump_30); function jump_30(event:MouseEvent):void { gotoAndStop("30"); }; です。足りないものがありましたらご指摘ください。 よろしくお願いいたします。

    • ベストアンサー
    • Flash