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

ムービークリップにボタンを二つ組み合わせて作ったチェックボックスをクリックした時に変数clickedの数を0または1に変更するようアクションスクリプトを入力しましたが作動しません。

ムービークリップは、
フレーム1に空ボックス→チェックと変化するボタン、フレーム2にチェック→空ボックスと変化するボタンを配置し、
on(press){
gotoAndStop(2); //フレーム2にはgotoAndStop(1)
}
とアクションスクリプトを入れています。

これでボタン自体は正常に動くのですが、ボタンがクリックされた状態かどうかを確認する為の変数clickedにクリックした際数字が足されません。

onClipEvent(mouseDown){
clicked++;
}

確認のために上記のアクションスクリプトにgotoAndStop(10);のようにフレーム番号を入れ、クリックした際に移動するかも試してみましたが移動しません。こういう場合にonClipEventを使うのが間違っているということでしょうか。

ムービークリップの方に
on(press){
gotoAndStop(2);
clicked++;
}
として試してみましたがこちらも上手く行きませんでした。

何か解決法などありましたらアドバイスをよろしくお願いいたします。

A 回答 (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つも使うことなく情報を管理できたりと、味のあるプログラムになります。
ただし、ビット演算を多用したプログラムは、まるで暗号文のようになって分かりにくくなるという欠点がありますので、こまめにコメントを入れておくといいでしょう。


たびたび長くなってすみませんでした。
    • good
    • 0
この回答へのお礼

御礼が遅くなって申し訳ありません。
詳しく説明していただいたお陰でようやく#1も#2も上手く動かすことが出来ました。

やはり階層の問題が一番大きかったようです。
ターゲットパスボタンを使うと確かに楽でした。階層を理解していなかったのでどう使って良いのか分からず避けていました。

プログラミングはちょっとだけかじったことがあるのですが、ビット演算は知りませんでした。教本でも買ってみようと思います。

今回は本当に勉強になりました。
丁寧に答えてくださって有難うございました。

お礼日時:2005/04/09 07:27

変数を使った処理が上手くいかない原因はいくつか考えられます。


よくあるのが、変数がある階層を間違えていたり、変数の名前が正しくなかったなどで、そもそも変数が参照できていないというものです。
もう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 );
 }

このようにスッキリと書くこともできます。


長くなってすみませんでした。
不明な点がありましたら、補足してください。
    • good
    • 0
この回答へのお礼

詳しく解説してくださって有難うございます。
これからじっくり教えていただいたことを試してみようと思います。

clickedの初期値は、別のレイヤーでまとめてほかの変数と一緒に設定したのですが、onClipEvent(load)の際に指定した方がよさそうですね。
ムービークリップに対するアクションスクリプトの書き方や仕組みが全く分かっていなかったのでとても参考になりました。

少し質問とずれますが、もしチェックボックスが複数あり、その中の一つでもクリックされていればclickedにtrueを入れるというようなことは出来るのでしょうか。(複数選択した場合もtrueで、一つも選択されていない場合のみfalseを返すという意味です)
ちょっとした疑問ですので、心当たりがあればお答えくださると嬉しいです。

ではこれから教えていただいたことをもとに試してみます。回答有難うございました。

お礼日時:2005/04/04 14:24

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