ムービークリップのチェックボックス制御がうまくいかない

このQ&Aのポイント
  • ムービークリップに作成したチェックボックスの制御をするためのアクションスクリプトがうまく作動しない問題が発生しています。
  • ボタンをクリックした際に変数clickedが正しく増えず、またフレームの移動もできません。
  • 解決法を探していますので、アドバイスやヒントがあればお願いします。
回答を見る
  • ベストアンサー

チェックボックスの制御(onClipEvent)

ムービークリップにボタンを二つ組み合わせて作ったチェックボックスをクリックした時に変数clickedの数を0または1に変更するようアクションスクリプトを入力しましたが作動しません。 ムービークリップは、 フレーム1に空ボックス→チェックと変化するボタン、フレーム2にチェック→空ボックスと変化するボタンを配置し、 on(press){ gotoAndStop(2); //フレーム2にはgotoAndStop(1) } とアクションスクリプトを入れています。 これでボタン自体は正常に動くのですが、ボタンがクリックされた状態かどうかを確認する為の変数clickedにクリックした際数字が足されません。 onClipEvent(mouseDown){ clicked++; } 確認のために上記のアクションスクリプトにgotoAndStop(10);のようにフレーム番号を入れ、クリックした際に移動するかも試してみましたが移動しません。こういう場合にonClipEventを使うのが間違っているということでしょうか。 ムービークリップの方に on(press){ gotoAndStop(2); clicked++; } として試してみましたがこちらも上手く行きませんでした。 何か解決法などありましたらアドバイスをよろしくお願いいたします。

  • Flash
  • 回答数2
  • ありがとう数3

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

  • ベストアンサー
  • DPE
  • ベストアンサー率85% (666/776)
回答No.2

ActionScript は階層の指定にうるさい言語です。 操作したいインスタンスや変数・関数がどこの階層にあるのかが正しく指定できていないと、エラーにはならないものの、正常に動きません。 階層の指定のことをターゲットパスと言います。 自分が持っているものならば省略も可能ですが、他の階層やムービークリップが持っているものを操作したい場合は、その持ち主を指定するターゲットパスが必要です。 厄介なものにも見えますけれど、この仕組みがあるおかげで、1つのシンボルから作られた複数のインスタンスが全く同じ名前の変数や関数を持っていたとしても、それぞれが別のものとしてきちんと区別され、個別に制御できるのです。 #1でご紹介しましたスクリプトでは、clicked という変数はチェックボックスのインスタンス自身のものになっています。 例えば「自作チェックボックス」という名前のムービークリップシンボルを作り、ステージにインスタンスを配置したとします。 このインスタンスに check_box1 という名前を付け、#1でご紹介した通りのスクリプトを書くと、clicked という変数は check_box1 の持ち物となります。 この変数を check_box1 に設定した on や onClipEvent アクションの中で使う限りは、自分自身の持ち物なのでターゲットパスは省略できます。 _root 階層(通常はステージ、もしくはメインのタイムライン)でこのチェックボックスがチェックされたかどうかを知りたい時は、check_box1 が持っている clicked の値を参照すれば分かります。 しかし、_root からすると clicked は他人( check_box1 )の持ち物ですので、見せてもらうには持ち主の指定が必要になります。 _root からこの変数の値を見るには、  check_box1.clicked もしくは _root からの絶対パスで  _root.check_box1.clicked と書きます。 ターゲットパスを自動で入力してくれる機能があります。 Flash MX 以降では、「アクション」パネルの上部に並んだ7つのアイコンの、中央のアイコンをクリックすると、リストから対象を選ぶだけでターゲットパスを入力してくれます。 ターゲットパスが分からない時は利用してみてください。 「自作チェックボックス」はシンボルですから、インスタンスをいくつでも作ることができます。 例えば、もう1つインスタンスを作って「 check_box2 」という名前を付けたとします。 このインスタンスにも#1のスクリプトを書くと、check_box2 も同じく clicked という変数を持つことができます。 名前は同じですが、check_box1 が持っている clicked とは違う変数になります。ですから、check_box1 が選択された時に、check_box2 にもチェックが入ったりするようなことはありません。 ---------------------------------------- チェックボックスはラジオボタンとは違い、複数のボタンを同時に選択することが可能です。 となると、ボタンごとにチェックあり・なしの情報を管理しなければなりませんから、それぞれ変数を用意して管理する方が簡単です。 (コンポーネントの CheckBox も、このような設計になっています) このうち1つでも選択されている( true )のであればOKで、1つも選択されていない時はNGというのは、必ず何か1つは選んで送信しなければならない登録フォームやアンケートなどでよく見かける機能です。 選択状況を調べるにはいろいろな考え方がありますが、  1)各インスタンスが持っている clicked の値を片っ端から調べ、true のものが1つでもあればOK。  2)管理用の変数を1つ用意し、最初は0にしておく。   clicked の値が true になる度に +1 、false になった時に -1 する。   変数の値が0のままなら、1つも選択されていない。  3)管理用の変数を1つ用意し、最初は0にしておく。   ビット演算を使って、全てのチェックボックスの選択状況をこの変数で管理する。   変数の値が0のままだったら、1つも選択されていない。 といった方法が考えられます。 1) の方法は面倒に見えますが、インスタンス名の付け方を工夫することで簡単にできます。 ActionScript では、文字列から変数やインスタンスを操作することができます。 例えば、_root 階層で  this[ "check_box1" ].clicked とすると、_root にある check_box1 が持っている clicked という変数を参照できます。 各チェックボックスのインスタンス名を、check_box +通し番号(ここでは仮に 1 ~ 5 とします)を付けると、ループを利用して  check_flg = false;  //全チェックボックスの選択状況を調べる  //1つでも選択されていたらチェック終了  for( i = 1 ; ( i <= 5 ) && ( ! check_flg ) ; i++ )  {   check_flg = _root[ "check_box" + i ].clicked;  } このようにして調べることができます。 ループ終了後、check_flg が true であれば、1つは必ず選択されていることになります。 この方法は、例えば登録フォームで送信前に入力データをチェックするなど、最後に選択状況を調べてOKかNGかを決めたい時に向いています。 2) の方法は、1つ1つのチェックボックスに設定するスクリプトが少し増えますが、リアルタイムで選択状況を把握できる利点があります。 管理用の変数を _root に作り、仮にこの変数を check_cnt とすると、各チェックボックスに設定するスクリプトは  on(release)  {   //クリックされる度にチェックのあり/なしを切り替える   //チェックされているボタンの数も更新する   if( ! clicked )   {    clicked = true;    _root.check_cnt++;   }   else   {    clicked = false;    _root.check_cnt--;   }   //表示する絵の切り替え   gotoAndStop( clicked + 1 );  } こんな感じになります。 必要な時に _root にある check_cnt の値を見て、もし0なら1つも選択されていないと見なすことができます。 選択されている数も同時に把握できるので、2つ以上選択しなければならないとか、選択できる数を3つまでなどの制限を設けたい時にも便利です。 check_cnt を0で初期化しておくことと、変数のターゲットパスの誤りなどがないよう、細かいところに注意が必要です。 3) の方法は、玄人好みのちょっと華麗なプログラムになります。 条件判断が少なく、内部ではとても単純な演算だけになり、変数もたった1つで済みますから、メモリの消費が少なく、処理も速くなります。 (まあ、今のパソコンはもともと処理能力が高く、メモリも余裕がありますから、あまりケチくさく考えなくても大丈夫ですが) 1つの変数で全ての選択状況を管理していますから、この変数が0であれば、チェックボックスは1つも選択されていないことになります。 この方法のイメージとしては、1つの配電盤にスイッチがたくさん並んでいて、必要に応じて、ON / OFF を切り替えたい箇所のスイッチを操作するようなものです。 ビット演算には様々な種類があり、それぞれに決まった法則があります。まず、この法則を知っていることが前提になります。 (ちなみに#1で使っているのは、XOR という演算です) 今回は割愛しますが、興味がありましたらプログラムの教本や解説サイトで調べてみてください。 ヒントは OR ・ AND 演算とビットシフトです。 ビット演算をうまく使うと、ループや if 文を使わずにスッキリとスクリプトをまとめたり、変数を3つも4つも使うことなく情報を管理できたりと、味のあるプログラムになります。 ただし、ビット演算を多用したプログラムは、まるで暗号文のようになって分かりにくくなるという欠点がありますので、こまめにコメントを入れておくといいでしょう。 たびたび長くなってすみませんでした。

quizons
質問者

お礼

御礼が遅くなって申し訳ありません。 詳しく説明していただいたお陰でようやく#1も#2も上手く動かすことが出来ました。 やはり階層の問題が一番大きかったようです。 ターゲットパスボタンを使うと確かに楽でした。階層を理解していなかったのでどう使って良いのか分からず避けていました。 プログラミングはちょっとだけかじったことがあるのですが、ビット演算は知りませんでした。教本でも買ってみようと思います。 今回は本当に勉強になりました。 丁寧に答えてくださって有難うございました。

その他の回答 (1)

  • DPE
  • ベストアンサー率85% (666/776)
回答No.1

変数を使った処理が上手くいかない原因はいくつか考えられます。 よくあるのが、変数がある階層を間違えていたり、変数の名前が正しくなかったなどで、そもそも変数が参照できていないというものです。 もう1つよくあるのは、何らかの原因で変数に目的の数値が入っていないといった場合です。 原因の突き止め方は人により様々ですが、変数が怪しいと思った時はまず、変数に何が入っているかを調べることから始めるといいと思います。 変数の値を知るには、trace アクションを使う方法とデバッガという機能を使う方法などがありますが、一般的には trace アクションがよく使われます。 変数 clicked の値を使って何かをしようとする処理の近辺に、  trace( clicked ); というスクリプトを入れてみてください。「ムービープレビュー」では、「出力」ウィンドウが開いて、clicked に入っている値が表示されます。 この時、undefined と表示されるようなら、clicked という変数は存在しないことになっています。階層の指定や変数の名前が正しく指定できているかどうか、確認してみてください。 NaN と表示された場合は、clicked は正しく参照できているのですが、その中身が、数値ではないものと見なされています。 ですから、例えば  if( clicked == 1 ) というようなスクリプトを書いても、if 文の条件は成立しませんし、  clicked++; としても値は加算されません。 変数を使う時はなるべく、初期値を自分の方から入れておく、つまり明示的に変数を初期化する習慣をつけましょう。 ActionScript では、予め”○○という名前の変数を使う”といった宣言をしておかなくても、変数が利用できるようになっています。 変数に入れるものが文字列であれば、あまり問題はないのですが、今回のように計算に利用する場合は、初期値が不明の変数を信用するのは危険です。 変数の初期化にはいろいろな方法がありますが、ムービークリップの load イベントを利用して  onClipEvent(load)  {   clicked = 0;  } (↑各行頭に全角のスペースが入っています。コピーする際はご注意ください) というように初期化しておく方法があります。 他には、例えば clicked に 1 が入っているはずなのに、なぜか 0 のままだったり、2 や 3 など意図しない値が入っている、といったトラブルもあります。 この場合は、変数を操作する処理に何か問題があることになります。 今回の件で言いますと、clicked++; の処理や mouseDown イベントを使っていることが原因ではないか・・・と、アタリをつけて直していくわけです。 ちなみに mouseDown はムービークリップのイベントですが、必ずしもムービークリップの上でマウスのボタンが押される必要はなく、ステージのどこかでマウスのボタンが押されると発生してしまいます。 特定のムービークリップがクリックされたかどうかを調べるには、press または release イベントを利用するか、あるいは、mouseDown イベントが起きた時にマウスカーソルの座標を見て、ムービークリップと重なっていたかで判断する、といった方法があります。 ------------------------------------ チェックボックスは、Flash MX 以降であれば UI コンポーネント、Flash 5 にもスマートクリップとして提供されています。 あえて自作するのであれば、次のように考えてはいかがでしょう。 ムービークリップのフレーム1にチェックなしの状態を、フレーム2にチェックありの状態を描画します。 あとは、このムービークリップがクリックされる度にフレーム1か2かを切り替えるだけです。 また、clicked の値はチェックされたかされないかの情報だけでいいので、加算ではなく true と false というブール値で充分です。 ムービークリップの中に更にムービークリップがあると、変数がある階層が云々とややこしくなりますが、この設計ではムービークリップは入れ子になっていませんから、チェック状態を管理する変数の扱いも簡単です。 スクリプトは次のように書きます。  //初期設定  onClipEvent(load)  {   //チェック状態を保持   //チェックされた時true、それ以外はfalse   clicked = false;   //最初は止めておく   stop();  }  //チェックの処理  on(release)  {   //クリックされる度にチェックのあり/なしを切り替える   if( ! clicked )   {    clicked = true;   }   else   {    clicked = false;   }   //表示する絵の切り替え   gotoAndStop( clicked + 1 );  } true と false は 識別子になっていて、Flash の内部で予め、true = 1 ・ false = 0 と定義されています。 ムービークリップの絵は、フレーム1がチェックなし、フレーム2がチェックありです。 よって、clicked に true か false ( 1 または 0 )しか入らないようにしておけば、clicked の値に +1 した値が、そのまま表示するフレームの番号になります。 ちなみに、ビット演算という演算を使いますと、  on(release)  {   //クリックされる度にチェックのあり/なしを切り替える   clicked ^= true;   //表示する絵の切り替え   gotoAndStop( clicked + 1 );  } このようにスッキリと書くこともできます。 長くなってすみませんでした。 不明な点がありましたら、補足してください。

quizons
質問者

お礼

詳しく解説してくださって有難うございます。 これからじっくり教えていただいたことを試してみようと思います。 clickedの初期値は、別のレイヤーでまとめてほかの変数と一緒に設定したのですが、onClipEvent(load)の際に指定した方がよさそうですね。 ムービークリップに対するアクションスクリプトの書き方や仕組みが全く分かっていなかったのでとても参考になりました。 少し質問とずれますが、もしチェックボックスが複数あり、その中の一つでもクリックされていればclickedにtrueを入れるというようなことは出来るのでしょうか。(複数選択した場合もtrueで、一つも選択されていない場合のみfalseを返すという意味です) ちょっとした疑問ですので、心当たりがあればお答えくださると嬉しいです。 ではこれから教えていただいたことをもとに試してみます。回答有難うございました。

関連するQ&A

  • Flashでボタンをクリックするとフェードイン、フェードアウトする

    アクションスクリプト初心者なのですが、 スクリプトで、ボタンをクリックすると 現在のフレームのムービークリップがフェードアウトしながら、 次のページのムービークリップがフェードインする方法を ご存知でしたら、教えていただけないでしょうか。 ムービークリップがロードしたら、 フェードインするところまでは出来たのですが、 それだと、現在のムービークリップがフェードアウトしないので 困っています。 ムービークリップがロードしたら、 フェードインするスクリプトは、 onClipEvent (load) { _alpha = 0; } onClipEvent (enterFrame) { _alpha += 2; } と記載しております。 どうぞよろしくお願いします。

    • ベストアンサー
    • Flash
  • flash:ムービークリップの制御

    誠に不勉強の段お許しください。 Flashで知人のサイトを製作しているのですが、どうしてもうまくいかず投稿させて頂きました。使用してる環境;ソフトはMacOS10.4.11:Flash8.0です。 (1)動かしたい内容は、-rootにムービークリップのスプレー缶があって、それにロールオーバーすると少し上がり指が現れ、そこで止まる。(ムービークリップ10フレーム目で停止) (2)ロールアウトすると逆戻りで元の位置に戻る。 (3)(1)の止まった状態でプレスすると10フレーム目から進み(スプレーされるアクションが入り)指定アドレスに飛ぶ。(ムービークリップ15フレーム目でgetURL) この様な、動きをさせたいのですが 様々解らないなりに調べて、何とか15フレーム目までいって止まり、その逆戻りまでは出来たんですが、10フレーム目で一旦止める事が出来ません...。 onClipEvent (load) { nMove = 0; } onClipEvent (enterFrame) { if (nMove != 0) { nNextFrame = this._currentframe+nMove; if (1<=nNextFrame && nNextFrame<=this._totalframes) { this.gotoAndStop(nNextFrame); } else { nMove = 0; } } } on (rollOver) { nMove = 1;} on (rollOut) { nMove = -1; } 大変恐縮ですが、 なにとぞご教授いただけましたら幸に存じます。

    • ベストアンサー
    • Flash
  • setTimeoutでの制御に関しまして

    初めて質問をさせて頂きます。よろしくお願い致します。 「mc_Image1」、「mc_Image2」、「mc_Image3」という 各ムービークリップをストップボタンを押した際に時間差で停止させたいのですが 「mc_Image2」、「mc_Image3」がstopがかからない状態が稀に生じたりします。 (ムービークリップは全て、1フレーム目にstop();、10フレーム目にgotoAndPlay(2);と設定) 少し端折っておりますが、スクリプトを記載いたします。 ---------------------------- //何回ルーレットしたかカウントする var count:Number = 0; //スタート/ストップボタンが押された押されていないかのフラグ var flg_StartStop:Boolean = false; // mc_Image停止待機速度変数(ミリ秒) var hensu1 = 2000; var hensu2 = 3000; //スタート/ストップボタンを押した時に呼び出される関数 btn_StartStop.onPress = function() { if(flg_StartStop) { //選ばれたフレームに飛ぶ mc_Image1.gotoAndStop(parseInt(one)+1); // setInterval で hensu(ミリ秒)後に_root.gotoAndStop(); を実行 stopID = setInterval(function () { _root.mc_Image2.gotoAndStop(parseInt(two)+1); clearInterval(stopID); }, hensu); stop2ID = setInterval(function () { _root.mc_Image3.gotoAndStop(parseInt(three)+1); clearInterval(stop2ID); }, hensu2); //押されたかどうかの変数を「偽」に flg_StartStop = false; //カウンタを増やす count++; } else { //ムービークリップを走らせる mc_Image1.play(); mc_Image2.play(); mc_Image3.play(); //押されたかどうかの変数を「真」に flg_StartStop = true; } } ---------------------------- 。 きちんと「gotoAndStop();」させるにはどのように対処すれば よろしいでしょうか。 不足がございましたら申し訳ありません。 何卒よろしくお願い致します。

  • onClipEvent(enterFrame)よりもフレームに書いたほうが良い?

    最近Flashでfunctionの使い方を勉強しています。 そこで思ったのですが、例えばあるキーが押されたときに動作を行なわせたい場合。ムービークリップにonClipEvent(enterFrame)で記述する方法とフレームにfunctionで記述する方法の2通りあります(もしかして他にも方法あったりします?)。 素人考えでは、例えばonClipEvent(enterFrame)にtrace文を書いた場合、ずっとtrace処理が行なわれますが、フレームに書いた場合はそのフレームが読み込まれた瞬間のみtrace処理が行なわれます。一見onClipEvent(load)のようですが読み込み後、たとえフレーム移動がそこでstopになったとしても、イベントハンドラによって処理を行なわせることは可能です。そう考えると、処理の軽さ的にはフレームに記述する方法の方が優れているのでしょうか? ムービークリップにonClipEvent(enterFrame)で記述する場合とフレームにfunctionで記述する場合、両者の長所・短所も合わせて紹介していただけると助かります。 以上になります。よろしくお願いします。

  • ムービークリップ再生後次のフレームへ移動しません

    アクションスクリプトを使って、テキストが下から上へ流れるようにムービークリップを再生し、テキストが流れ終わったところで次のフレームへ移動させたいのですが、フレームが移動せず困っています。 スクリプトは色々なところで調べて、やっとの事で下記のように書きました。 使用しているのはFlash MX 2004 です。 |○  □|○|  ←1.スクリプトレイヤー |●    □|  ←2.ムービークリップレイヤー |○|●→|●|  ←3.ムービークリップ後に再生したいレイヤー 1.のスクリプト(2つのキーフレームいずれとも) stop(); 2.のムービークリップのスクリプト onClipEvent (load) { spd =5; onClipEvent (enterFrame) { this._y = this._y-spd; if (this._y<=-10) { spd = 0; gotoAndPlay(2); } } 知り合いにお見舞いのメッセージをと思って作ったのですが、送ることが出来なくてとてもあせっています。 どうぞよろしくお願いします。

    • ベストアンサー
    • Flash
  • 移動に関するアクションスクリプトがわかりません

    あるムービークリップをクリックした時にX座標を0の位置にもっていきたいのですが、アクションスクリプトをどう書いたら良いのか分かりません。 瞬間的に移動するのではなくスーッという感じで動かしたいのです。 on (release){ this._x = 0} と onClipEvent(enterframe){ this._x += -2 } これを融合させたような感じにしたいのですが、書き方が分かりません。メインのタイムラインに動くフレームをつくりgotoAndPlay()で飛ばしても良いんですが、アクションスクリプトだけで作ることは不可能でしょうか?

    • ベストアンサー
    • Flash
  • チェックボックスについて

    現在チェックボックスを使用した作品を作成しています。 チェックボックスの左隅(ボックスの左辺)に マウスが乗ってるか乗ってないか位の位置でクリックをすると イベント処理は行われるのですが、チェックが消えなかったり 逆にチェックが表示されないままになってしまいます。 何かいい対処法はあるのでしょうか? ご教授頂けたら幸いです。 開発環境:CS3 AS2.0 以下チェックボックスに記述しているスクリプトです。 onClipEvent(mouseUp){ if(this.hitTest(_root._xmouse, _root._ymouse, false)){ if(this.getState()){ //処理 } else{ //処理 } //処理 } } }

    • ベストアンサー
    • Flash
  • Flash MX ActionScriptのEnterFrame

    Flash 初心者です。 クリップアクションの、 onClipEvent (enterFrame) { } がいまいちよくわかりません。 フレームが1フレームだけのルートのタイムラインに、 何の動きもないムービークリップオブジェクト(これも1フレームのみ)を1つ置いたとします。 そのムービークリップに、例えば、 onClipEvent (enterFrame) { _rotation+=20; } とアクションをつけたとします。 これを再生すると、回転し続けますよね。 これはルートのタイムラインが1フレームだけでも、 それがループしていると考えると、納得できるのですが、 1フレーム目に、this.stop();を記述しても、 回転し続けます。 enterframeとはどのように解釈すればいいのですか? ルートのタイムラインが再生される度に呼び出されるということでは ないのでしょうか? よろしくお願い致します。

  • FLASHでの座標取得

    マウスが動くたびに変数としてテキストボックスにいれるにはどのようなアクションスクリプトをかけばいいのでしょうか? 以下のようにしてみましたができませんでした。 シーン上のフレーム1のところのレイヤーが何もない箇所に以下のアクションスクリプト onClipEvent(mouseMove){ Zahyox = _xmouse; hensuu = Zahyox; } でも何も出てきません。 座標取得をやるのは初めてで、どこへかけばいいのかすらわかってないので、よろしくお願いします。 FLASH5です。

    • ベストアンサー
    • Flash
  • チェックボックスをラジオボタンでの選択に変更したい

    タイムライン(1)にA・B・C3枚のデータを作成してあります。 a・b・c3通りのチェックボックスを作成して、「a」をクリックした場合にはb・cのデータが隠れ(false)aが表示される(true)(b・cも同様で、a・b・c全部を選択していない場合には全部が表示される)スクリプトを書きました。 ところが、チェックボックスの場合には、利用者が例えば2つを選択することが可能なために、この場合には2つのデータが表示され混乱します。 そのため、チェックボックスをラジオボタンに変更して、且つ同様な動きをさせたいと思っています。 ラジオボタンの場合は「ムービークリップ」のために同様なことは出来ないのでしょうか? 宜しくお願いします。

専門家に質問してみよう