- ベストアンサー
オブジェクトのランダムな位置表示
- Flash8を使用して、ボタンを押す度にオブジェクトをランダムな位置に、ランダムなサイズで表示させるFlashを作成したい。
- 具体的には、指定したボタンを押すとランダムな位置にランダムなサイズのオブジェクトが表示されるようにしたい。
- 参考サイトのReqmtEと同じような動作をするFlashを作成したい。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
まず, オブジェクトを出没させる件からです。 オブジェクト(この場合ムービークリップ)を, ステージ上に突如出すというのは, 次の2つ↓のうちどちらかのメソッドを利用するのが一般的だと思います。 ///////////////////////////////////////////////////////////////// ◎ムービークリップの複製 MovieClip.duplicateMovieClip("インスタンス名", 深度); ◎ムービークリップシンボルを インスタンスとしてステージ上に配置 MovieClip.attachMovie( "シンボルの識別子", "インスタンス名", 深度); ///////////////////////////////////////////////////////////////// ご質問のような場合は,どちらでも可能ですが, 上の duplicateMovieClip の方は, 最初の状態で,見えない場所であるステージ外ワークスペースにムービークリップを作成しておかなければならなかったり, 複製したいムービークリップを別の階層(ムービークリップ内)に複製することができなかったりするので, ここでは,下の attachMovie を使う方法で説明します。 - - - - - - - - - - - - - - - - - - - - - - - - - - 新規ドキュメントでも作成して, ステージ上に小さめの赤い丸を書いてください。 直径1cmとか2cmとかその辺の適当な大きさで良いです。 その丸を選択して,ムービークリップに変換します。 シンボル名はスクリプトなどに関係ないので適当で良いです。 ステージ上に見えている赤丸ムービークリップ(インスタンス)は必要ないので, ステージ上から消してください。 また必要になれば,ライブラリからドラッグしてくれば良いだけです。 今のところ必要ありません。 その赤丸をムービークリップに変換した後,ライブラリを見ると, (ライブラリが表示されていない場合は「ウィンドウ」→「ライブラリ」で表示されます。) 今作った赤い丸のムービークリップシンボルが見えると思います。 そのシンボルを選択して, 「右クリック」→「リンケージ」と選択します。 すると,「リンケージプロパティ」のパネルが出てきますから, そこで, □ ActionScript に書き出し にチェックを入れます。 すると,「識別子」を書く欄が有効になりますので, この欄に何かわかりやすい識別子を付けます。 ここでは,赤い丸なので 「redMaru」 という識別子を付けたとしておきます。 リンケージプロパティ の様子↓ ------------------------------------------------- 識別子(I): [redMaru ] [ OK ] AS 2.0 クラス(C): [ ] [キャンセル] リンケージ(V): ν ActionScript に書き出し □ ランタイム共用に書き出し ν 最初のフレーム に書き出し ■ ランタイム共用に読み込み (↑グレー:非選択) ------------------------------------------------- これで「OK」をクリックします。 ここまでできたら,うまくできているか実験してみます。 ステージ上に適当なボタンでも用意してください。 そのボタンに, --------------------------------------- on (release) { // redMaru を myMC0 というインスタンス名で, // _root の 深度0 に attachMovie _root.attachMovie("redMaru", "myMC0", 0); // その myMC0 の座標を指定 _root.myMC0._x = Stage.width/2; _root.myMC0._y = Stage.height/2; } --------------------------------------- と書けば(コピペ可), 赤丸ムービークリップがステージ中央に出没するはずです。 出没すれば 赤丸ムービークリップ の下準備は完了です。 赤四角なら「redSikaku」,緑丸なら「greenMaru」… など, 識別子を同様に付けて同様に作成して行けば良いです。 ムービークリップを出没させる件はここまでです。 次にやっと本題の, 「ランダムな位置にランダムなサイズで表示」の部分の説明に移ります。 ランダムにはお決まりのように,Mathクラスのrandomメソッド, Math.random() を使います。 例えば, a = Math.random(); とすると,変数 a には, 0 以上 1 未満の数(0 <= a < 1)がランダムに代入されます。 (例: a = 0.279424419626594) 「ランダムな位置にランダムなサイズで」と言っても, 全くランダムでは困るわけで,ランダムの中にも規則があるはずです。 ランダムな位置に → ステージの範囲内でランダムな位置に ランダムなサイズで → ある程度範囲を持ったランダムなサイズ その規則を数値化して,Math.random() に掛け算や足し算をしてやれば, その規則の範囲内でランダムな数が得られます まず,座標は, 散らばる範囲をステージ内としておきます。 そうすると,x座標は, Math.random() * Stage.width y座標は, Math.random() * Stage.height で得られます。 大きさは, 大きくなる限度をオリジナルな状態の 3 倍(300%)としておきましょうか。 横の大きさ _xscale と縦の大きさ _yscale は, 同じ比で拡大されるようですから,両方とも Math.random() * 300 で得られます。 深度ですが, 同じ深度に attachMovie すると, もとにそこにあったムービークリップは消えてしまいますから, attachMovie する度にずらさなくてはなりません。 こちらはランダムというわけには行かないので, 深度の値を加算して行く方法を取ります。 というわけで,実際のスクリプトです。 まずフレームにレイヤーを新規で作成してください。 そのレイヤーを ActionScript 用のレイヤーとします。 そして,そのレイヤーのフレーム1のを選択して, -------------------- // 深度の初期値を設定 var dep = 0; // 大きくなる限度を設定 var mag = 300; -------------------- そして, 赤丸をランダムな位置にランダムなサイズで出没させるボタンには, 次のようなスクリプトを書けば(コピペ可),できあがりです。 --------------------------------------- on (release) { // 深度の値を 1 加算する _root.dep++; // redMaru を myMC? というインスタンス名で, // _root の 深度? に attachMovie _root.attachMovie("redMaru", "myMC"+_root.dep, _root.dep); // その myMC? の座標を指定 _root["myMC"+_root.dep]._x = Math.random()*Stage.width; _root["myMC"+_root.dep]._y = Math.random()*Stage.height; // その myMC? の大きさを指定 var my_scale = Math.random()*_root.mag; _root["myMC"+_root.dep]._xscale = my_scale; _root["myMC"+_root.dep]._yscale = my_scale; } --------------------------------------- 緑丸ムービークリップ(識別子「greenMaru」)を,出没させるボタンであれば, // redMaru を myMC? というインスタンス名で, // _root の 深度? に attachMovie _root.attachMovie("redMaru", "myMC"+_root.dep, _root.dep); の部分を, // greenMaru を myMC? というインスタンス名で, // _root の 深度? に attachMovie _root.attachMovie("greenMaru", "myMC"+_root.dep, _root.dep); とすれば良いだけです。 ちなみに,消したい場合は, MovieClip.removeMovieClip() か, MovieClip._visible = false; を使うのが一般的です。 全く消し去りたいときは, MovieClip.removeMovieClip() を使います。 ムービークリップを全く消し去りたい場合, クリックするボタンには,次のようなスクリプトを書けば良いと思います。 --------------------------------------- on (release) { // myMC1~myMC? までを消す for (var i = 1; i<=_root.dep; i++) { _root["myMC"+i].removeMovieClip(); } // 深度の値を初期状態に戻す _root.dep = 0; } --------------------------------------- 上のスクリプトでは, 出没させたムービークリップが全く消え去ってしまいますから, それでは問題がある場合, つまり,消した後にもう一度復活表示させたい場合は, 次のようになります。 「非表示」ボタン --------------------------------------- on (release) { // myMC1~myMC? の非表示 for (var i = 1; i<=_root.dep; i++) { _root["myMC"+i]._visible = false; } } --------------------------------------- 「表示」ボタン --------------------------------------- on (release) { // myMC1~myMC? の表示 for (var i = 1; i<=_root.dep; i++) { _root["myMC"+i]._visible = true; } } --------------------------------------- ========================================== あと, ご質問で書かれているURLのサンプルでは, 「赤丸」や「緑四角」などを表示させるボタンが, ランダムに出没する「赤丸」や「緑四角」によって隠れてしまいます。 これを防ぐためには, 「赤丸」や「緑四角」を表示させるボタンをまとめて1つのムービークリップの中に入れてしまい, そのムービークリップの深度を _root.dep より1つ上の数字に移動させると, 出没する「赤丸」や「緑四角」によって隠れるという現象がなくなります。 この深度を変えるのには, MovieClip.swapDepths を使います。 「赤丸」や「緑四角」を表示させるボタンをまとめた1つのムービークリップのインスタンス名を, 「buttons」 としておいたとすると, 赤丸をランダムな位置にランダムなサイズで出没させるボタンは, 次のようなスクリプトになります。 --------------------------------------- on (release) { // 深度の値を 1 加算する _root.dep++; // buttons の深度を変える(★↓この行が増える) _root.buttons.swapDepths(_root.dep+1); // redMaru を myMC? というインスタンス名で, // _root の 深度0 に attachMovie _root.attachMovie("redMaru", "myMC"+_root.dep, _root.dep); // その myMC? の座標を指定 _root["myMC"+_root.dep]._x = Math.random()*Stage.width; _root["myMC"+_root.dep]._y = Math.random()*Stage.height; // その myMC? の大きさを指定 var my_scale = Math.random()*_root.mag; _root["myMC"+_root.dep]._xscale = my_scale; _root["myMC"+_root.dep]._yscale = my_scale; } --------------------------------------- (全て,Flash 5 以上で使用可能なスクリプトです。) と言う感じですか。 スクリプト以外の説明部分が大半で, 長くなってしまいましたが,だいたい以上です。
その他の回答 (1)
#1です。 >> この出来上がった.swfを別の.swfに読み込ませると >> 何故だかどうも上手く動きません。 何故だかと言うより, もしそのままで動いたらそっちの方が怪奇現象です。 読み込む読み込まないに限らず, 階層を変える場合はターゲットパスに注意してください。 Aという swf を,別のBという swf に読み込むと, Bが親でAが子になるわけですが, 同時に _root が指す物は B の _root で, B の _root が全体の _root です。 #1で書いたスクリプトの _root の指す物は, 子である A という swf の _root(level0)です。 それで全てのターゲットパスが辻褄が合うようにしてあるのです。 読み込めば パス が変わりますから当然うまくいきません。 全てのパスを理解して書き直せばうまく行きますが, 単独であっても,読み込まれた場合であっても, 簡単に両方動作するようにするには, _lockroot をかけることです。 フレーム1のスクリプトを次のように訂正してください。 --------------------------------- // _root への参照をしない this._lockroot = true; // 深度の初期値を設定 var dep = 0; // 大きくなる限度を設定 var mag = 300; -------------------------------- 訂正と言うより, this._lockroot = true; を入れただけですね。 これで読み込まれた場合もうまく行くと思いますよ。 AはA内だけで _root にロックをかけているのです。 これで,Aを読み込むBの_rootがA内では有効になりません。 _lockroot が使えるのは, Flash MX 2004 (Flash Player 7)からです。
お礼
遅くなりましたが、どうもありがとうございました。 おかげさまで全て上手くいきました。
補足
とても丁寧なご回答どうもありがとうございます。 おかげさまできれいに上手く作ることが出来ました。 ただ恐縮ながらももう一つ質問なのですが、この出来上がった.swfを別の.swfに読み込ませると何故だかどうも上手く動きません。ボタンは押せるのですが、○や□のオブジェクトが表示されず、また上に書かれているスクリプトにしたがって画面のムービークリップを消そうとするとフリーズしてしまいました。この.swf単体で動かすと全く問題は無いのですが、外部に読み込ませて実行したときのみ上手く作動してくれません。 読み込ませるベースの.swfにはシンプルなボタンのみをステージ上部に配置し、そのすぐ下にLoaderと名前をつけた空のMC置いてそこにloadMovieで読み込ませています。ちなみに他にもいくつか外部.swfを取り込んでいるのですが、それらは全て正常に作動しました。 お手数ですが、何か解決策のようなものはありませんでしょうか。