- ベストアンサー
Flashでランダムな動きのスピード制御をする方法
- スクリーンに配置した小花がランダムに動くムービーを作成する方法について質問です。
- 現在のスクリプトでは移動速度が速すぎてキレイな動きにならないため、スピード制御の方法を知りたいです。
- アクションスクリプトを追加することで、小花の移動速度を制御することができます。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
#1です。 スミマセン…。大きな勘違いをしていました。 > 小花をいくつか配置し、それがスクリーン上をゆらゆらと動く という部分で,「ゆらゆら」だから,勝手に水面上の小花だと思いこんでしまっていました。 その前に「小花」とは「花びら」というイメージがあったんで, 『ゆらゆら動く花びら=水面上の物体』 と勝手にとらえてしまっていたのです。 変なことばっかり書いて申し訳ございませんでした。 #2 の 補足URLを拝見させていただきました。 そういう全く虚構の仮想現実のアニメーションだったのですね。 イメージはだいたいわかりました。 しかし,ランダムに飛び回るようなFlash解説サイトというのは確かにありませんね。 参考URLとは少し違う動きになりましたが,私なりに考えてみました。 説明したいと思いますが,まず, 本体のスクリプトの前に, 説明のためのオブジェクトを用意します。 簡単ですので,本編の前に以下のものを作ってみてください。 新規ドキュメント作成で, そのドキュメントのステージ上に 「kakudo」 という "変数名" のダイナミックテキストをステージ中央付近に用意して, そのダイナミックテキストをムービークリップに変換し, 次のようなスクリプトをそのムービークリップに書いてください(コピペ可)。 --------------------------------------------- onClipEvent (load) { // 変数kakudo と 変数count の初期値を設定 var kakudo = -1/2; var count = 0; } onClipEvent (enterFrame) { // 20で割り切れたら if (count%20 == 0) { // 角度を1/2(=0.5)ずつ加算 if (kakudo>=3/2) { kakudo = 0; } else { kakudo += 1/2; } } // 指定角度方向へ移動 this._x += Math.sin(Math.PI*kakudo)*3; this._y += Math.cos(Math.PI*kakudo)*3; count++; } --------------------------------------------- そしてパブリッシュすると, 変数「kakudo」と動く方向の関係がわかると思います。 つまり,sin cos とその角度との関係が,実感でわかると思います。 これの,説明のためのサンプルの, 角度を徐々に変えた物が,次の本編サンプルということになります。 小花はたくさんあるようなので, 全体的に固定された変数は, フレームのスクリプトとして,まず外にだして置きます。 フレーム1など小花が存在するフレームに, 次のように書いてください(コピペ可)。 -------------------------- // 動くスピードの設定 var speed = 5; // 角度を変えるタイミングの設定 var timing = 20; // 余白の設定 var margin = 15; -------------------------- ここ↑を変えると, 小花ズの全てのスピードやタイミングなどが,一気に変えられるので調節に便利です。 次に,小花のムービークリップに次のようなスクリプトを書いてください(コピペ可)。 -------------------------- onClipEvent (load) { // 各変数の初期値を設定 var count = 0; var ran2 = ran=Math.random()*2; } onClipEvent (enterFrame) { // _root に設定したタイミングで割り切れたとき if (count%_root.timing == 0) { // 変数ran1 と ran2 を動かす ran1 = ran2; ran2 = Math.random()*2; } // 各エリアに達してしまったとき ran を固定 if (this._x<=-_root.margin) { ran = 1/2; } else if (this._x>=Stage.width+_root.margin) { ran = 3/2; } else if (this._y<=-_root.margin) { ran = 0; } else if (this._y>=Stage.height+_root.margin) { ran = 1; // 普通は 徐々に ran を変化させる } else { ran += (ran2-ran1)/_root.timing; } // このMCを上で求められた角度方向に動かす this._x += Math.sin(Math.PI*ran)*_root.speed; this._y += Math.cos(Math.PI*ran)*_root.speed; count++; } -------------------------- 簡単に言うと, #1で,2番目に書いた,動きをスムーズにつなげたスクリプトを 回転するパターンに変更したようなバージョンです。 本当の本体(ランダムに動かすだけ)はもっと短いのです。 しかし本当にランダムに動かすだけの状態では, しばらく動かすと 「そして誰もいなくなった」 状態になってしまうので, 各エリアに達したときは,ステージに呼び戻す部分が入っているため長くなりました。 つまり,長くなってしまったのは2番目のif文のせいです。 _root の 変数margin はステージ外エリアの「動きしろ」(しろ は のりしろ の しろ です)を指定するためのものです。 ステージの縁にぶつかって,その瞬間方向転換したらちょっと格好悪いとおもったので, ステージからはみ出た場合は,そのままはしばらくみださせておいて, その後しばらくして戻ってくるパターンにしました。 そのための 変数margin です。 こんな感じですかね。 参考URLでは,大きい花にマウスを持っていくと, 大きい花の方向に小花が集まりますが, それは,するのかどうかわかりませんし, もしする場合はちょっと,考えてみてください。 さらに場合分けが増えて, 大きい花方向に動かすスクリプトが働くのですよ。 簡単そうでけっこうややこしいですね。
その他の回答 (2)
#1です。 ひょっとしたら,イメージされている動きに近い物ができたかもしれません。スゴイ! (って,単に私がイメージしたものに近いだけのような気もしますが…。) 私が高校生の時に, 「海上のブイ(浮き)は楕円運動をしている」 と確か担当の物理の教諭が言っていたのを,昨日ふと思い出したのですよ。 (専門は理科で,Flashは単なる経験者なのですけどこのことをすっかり忘れていました。) 調べてみると… 啓林館高校理科 ユーザーの広場 より 「第1節 波の伝わり方」 http://www.keirinkan.com/kori/kori_physics/kori_physics_1/contents/ph-1/4-bu/4-1-1.htm#Anchor-55262 なんだかゴチャゴチャ書いていますが,簡単に言うと, 「波のある場所を "横から見たとき" , 水面付近の物ほど円に近い楕円運動をし, 深い物ほど楕円の扁平率が大きくなる。」 というようなことが書いてあります。 横から見たときですから, 上から見たときではありません。 しかし,波のある水面上に浮く物体を斜め上から見れば, やはり超扁平な楕円運動に近い運動をするということになります。 「オブジェクト円運動」の解説とサンプル http://www.esli.co.jp/javascript/dhtml/enn/index.html ココ↑JavaScript を参考に,Flash で作ってみました。 小花ムービークリップに書くスクリプトです(コピペ可)。 ------------------------------- onClipEvent (load) { // ※半径(動く大きさ)の設定 var radius = 30; // ※動くスピードの設定 var speed = 1/10; // ※※ 他の小花とのズレを設定 var angle = 8/10; // 初期位置の保存 var myX0 = this._x; var myY0 = this._y; } onClipEvent (enterFrame) { // 角度を加算 angle += speed; // 楕円の座標に動かす this._x = myX0+Math.sin(angle)*radius; this._y = myY0+Math.cos(angle)*radius/5; } ------------------------------ ※マークの付いた所(3行の値)は, 作成されているものによって変わると思うので, 好きなように変えてください。 ※※ 他の小花とのズレを設定 は例えば一番手前にある小花を 10/10 (1) その少し向こうにある小花を 9/10 さらに向こうにある小花を 5/10 一番遠くにある小花を 0/10 (0) などに変えると,微妙に動く出発点がズレるので, 波が押し寄せてくるような感じなどが表現できると思います。 Math.sin や Math.cos などを使って難しいと思われるかもしれませんが, 上記スクリプトは Flash5 でも作成可能です。 一応,Flash5 と Flash8 にて同じ物を作成し, Flash player 5 ~ Flash player 8 で動作確認済みです。 sin(サイン) cos(コサイン) は, 高校数学 (私の場合は基礎解析) で習った三角関数です。 「コスコス引くシンシン」 とか 「シンコス足すコスシン」 とか, 数学の教諭が公式を覚えさせるために,おまじないのように連発していたのを思い出します。 (どんな公式を覚えるためのおまじないかは忘れました。) この場合 sinθ のθ(シータ) に当たる角度の単位は radian(ラジアン)です。 Flash の基本も radian 単位です。 degree(デグリー:度)に変換しても良かったのですが, キッチリ何度でないとダメとか言うような物ではないので, 計算をシンプルにさせるためにも radian のままでスクリプトを組みました。 360°は 2π radian です。 2π=2×3.14159…=6.28318… です。 だから,var angle = 8/10; の 8/10 は 10分の1(0.1)単位くらいのズレが適当だと思い,分母を10にしています。 深い意味はないのでこの辺も変えてくださってかまいません。 上のものを作ってみて, 「高校時代の物理の先生は正しかったんだ!」 と,今になってやっと実感することができました。 (教わったのはちょうど今から○十年前のことです。)
お礼
本当に細かく色々と有難うございます。 私も小花がランダムに飛び交うところは見た事が有りませんが、このサイト http://www.cacharel.com/_fr/_int/frameset.aspx? の「NOA FLEUR」のページがロードされた後で現れる小花の動きがあまりにもステキだったので、こんな風にランダムに飛ばしてみたいと思ったんです。 それで本で調べて質問内容のようなアクションスクリプトを書いたのですが、動きが早すぎるのでどうしたものかと; 色々ヒントを頂いたので、数値などを変えつつ少し自分で挑戦してみます。 また分らなくなって質問するかもしれませんが、その時はまたご回答いただければ幸いです。
>> 移動速度がものすごく速く、チラチラするだけで >> 全然キレイじゃありません(ToT) >> どう言うスクリプトを書き加えれば、スピード制御できるでしょうか? ということなので,一応, 移動速度を遅くする方法をやってみました↓(コピペ可)。 ----------------------------- // このムービークリップ(MC)が表示されたとき onClipEvent (load) { // 変数count の初期値を 0 に設定 var count = 0; } onClipEvent (enterFrame) { // 変数count を 5 で割った余りが 0 であるとき if (count%5 == 0) { // ランダムな位置へ動かす this._x += Math.floor(Math.random()*101)-50; this._y += Math.floor(Math.random()*101)-50; } // 変数count の値を 1 ずつ加算する count++; } ----------------------------- enterFrame で,1フレーム進む時間ごとに毎回動かすのではなく, 変数の値が 5 で割り切れたときだけ動かしますから,動く頻度は少なくなります。 しかし…, スピードの問題でしょうか? また,質問には書かれていませんが, 実際に作りたいとされる「小花」は, 正確には「小花」ではなく,「小花ズ(複数形)」ではないでしょうか,おそらく…。 複数の小花ズがランダムに動いている様子など, 私は見たことがありませんから想像ができません。 花粉のブラウン運動なら想像出来ますけど。 実際の小花ズがランダムに動くことはあり得ないでしょう。 小花は自分の意志を持って動くのではなく, 水の流れや水面の揺らめきによって動かされているのですから。 ついでに分子の運動でもありません。 人間の目というのはすごくシビアにできていて, 万有引力の法則や波動方程式などを知らなくても, ウソの動きは不自然だと見抜いてしまいます。 動きに限らず,遠近法などもそうです。 ちゃんとした遠近法を使わずに作成した風景画などの絵は, 難しい法則など知らない子どもたちにも,不自然で変だと感じさせてしまいます。 動きに関してですが, スピードの問題ではなく, そもそも,そういう複雑系の自然の動きを, 単なる乱数1つで片付けようとすること自体が, 間違っているような気がしますよ…。 ActionScript というより, 理科のような話ですが,自然を観察してみる方が先だと思います。 自然と言っても,本当の自然ではなく, 単なる理科の実験のような擬似的な自然でもかまいません。 そして, もし,自然のなかで動かしたい動きを見つけることが "できたら", また,そして,それを数学の関数で表すことが "できたら", きっとリアルな ActionScript ができると思いますよ。 "できたら" を強調していますが,私にはできません。 また,仮にできたとしても,質問者さまが表現したい動きとは全く違う動きになると思います。 この回答の最初に書いたスクリプトは 動く頻度は少なくしているだけです。 今度は, 動く頻度を少なくするだけではなく, その上次の地点まで,スムーズに動くようにすると次のようになります。 コピペ可↓。 --------------------------------------- // このムービークリップ(MC)が表示されたとき onClipEvent (load) { // 変数count の初期値を 0 に設定 var count = 0; } onClipEvent (enterFrame) { // 変数count を 10 で割った余りが 0 であるとき if (count%10 == 0) { // 変数randX と randY に乱数をセット var randX = Math.floor(Math.random()*101)-50+this._x; var randY = Math.floor(Math.random()*101)-50+this._y; } // 徐々に乱数座標に近づける this._x += (randX-this._x)/20; this._y += (randY-this._y)/20; // 変数count の値に 1 を加算する count++; } ---------------------------------------- どうです? カクカクに飛ぶのではなく,動きがつながったとは思います。 しかし,どうみても,花が意志を持っているようにしか見えません(私は)。 複数用意した場合だと, 「小花ズ」ではなくて,「アメンボズ」になら見えます。 ====== ここまでの結論 ===== 静止水面上を「小花ズ」は決してそれぞれランダムには動きません。 (流水の水面上であれば,ある程度ランダムに動くこともあるかもしれませんが。) まず 理科的に自然をよく観察してください。 すると「小花」が動くのではなくて,水面が動くので「小花」が動かされるのがわかります。 そして「水面の揺れ」を「小花」で表現する部分を見つけてください。 そして表現したい物が見つかった場合, 数学的 にそれを法則化し,それをスクリプトにしてください。 そうれば ActionScript で可能だと思います。 ===== 全然別の発想 ============= ActionScript でランダムに座標を移動させるのではなく, 座標移動はなしで,モーショントゥイーンで,拡大縮小だけをさせて, その拡大縮小時に,オニオンスキンのような効果を入れる方が まだ,「水面の揺れ」を「小花」で表現出来る気がします。 - - - - - - - - または,小花本体は拡大させず, その周りのオニオンスキンみたいなものだけを,拡大させつつアルファで消す。 などという方法も考えられます。 当然モーショントゥイーンでもできますが, ActionScript ですると次のようになります。 ステージ上に「小花」を1つ描き,ムービークリップに変換します。 その「小花」をコピペで 5つ 任意の位置に配置します。 5つそれぞれに「hana1」「hana2」…「hana5」というインスタンス名を付けます。 そして,その「hana1」~「hana5」までが存在するフレーム(フレーム1)に, 次のような↓スクリプトを書きパブリッシュ。 ------------------------------------------ // 小花の個数の設定(※この場合5個) var hanaNum = 5; // スピードの設定(※正の整数で指定) var speed = 6; // 変数count の初期値を 0 にする var count = 0; _root.onEnterFrame = function() { // 変数count を speed で割った余りが 0 であるとき if (count%speed == 0) { for (var i = 1; i<=hanaNum; i++) { // hana1~hana? を onion1~onion? として複製 duplicateMovieClip("_root.hana"+i, "onion"+i, i); // onion1~onion? の座標とアルファを設定 _root["onion"+i]._x = _root["hana"+i]._x; _root["onion"+i]._y = _root["hana"+i]._y; _root["onion"+i]._alpha = 50; } } for (var i = 1; i<=hanaNum; i++) { // onion1~onion? の大きさとアルファを変更 _root["onion"+i]._xscale *= 106/100; _root["onion"+i]._yscale *= 106/100; _root["onion"+i]._alpha -= 50/speed; } // 変数count の値に 1 を加算する count++; }; ----------------------------------------- いわゆる虚構の偽装現実のようなことですか。 自然では決して起こらない虚構をイメージし, ActionScript で表現する1つの方法例です。 またこんな方法(波紋で表現する方法)もありますね。 「水面に舞う桜の花びら (7KB)」 http://yu-ri.jp/sozai/flash/flash_image01.html (ダウンロードできるのはSWFのみです。)
お礼
長い間お礼も申し上げず失礼しました。 お蔭様で、最初に思い描いたものとかなり近いムービーが出来ました。 有難うございました!