• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:同じMCが連続で再生されないようにランダム再生)

同じムービークリップのランダム再生方法と連続再生確率の下げ方

このQ&Aのポイント
  • Flash CS6でAS3を使用して、同じムービークリップが連続で再生されないようにランダム再生する方法を教えてください。
  • また、同じムービークリップが連続で再生される確率を下げる方法も知りたいです。
  • 具体的には、3つのムービークリップ(A、B、C)があり、ランダムに再生されるようにしたいです。

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

  • ベストアンサー
  • BlurFiltan
  • ベストアンサー率91% (1611/1754)
回答No.1

重複を無くすとか,割合を操作をする時点で, 「厳密な意味でのランダム」ではなくなってしまいますが それはそれとして以下を続けます。 ご質問本題に関してですが ご質問の【前半】と【後半】とでは 全く違う方法について質問されていると思います。 【前半】連続で再生されないようにランダム再生を続ける方法 【後半】再生させるMCの確率を変動させる方法 . ◎【前半】の方法について これについては, 「3つのMC再生を1クール」として その「1クール」を済ませる度に 「3つのMCの再生順をランダムシャッフルする」 という方向で良いのではないかと思います。 ただし 「前の1クール」の最後のMCが 「次の1クール」の最初にならないようにする。 という内容のスクリプトを加えます。 【例】 「mcB,mcA,mcC」←ランダムシャッフルした1クール目 「mcB,mcC,mcA」←mcCが先頭に来ないようにシャッフル 「mcC,mcB,mcA」←mcAが先頭に来ないようにシャッフル 具体例ですが まず,メインのタイムライン の フレーム1 に 内部が複数フレームある,mcA,mcB,mcC という3つの MC があるものとします。 ※参考【添付図】↓ その場合の メインのタイムライン の フレーム1 に書くスクリプト例です。 //------------------------ //MCの参照を登録する配列「mc_arr」を用意 var mc_arr:Array = [mcA,mcB,mcC]; //配列「mc_arr」に登録したMC内の再生停止 for (var i:int = 0; i < mc_arr.length; i++) { mc_arr[i].stop(); } //カウンタを用意 var cnt:int = 0; //配列「mc_arr」の要素数分ループ for (i = 0; i < mc_arr.length; i++) { //配列「mc_arr」の要素をランダムシャッフル mc_arr.push(mc_arr.splice(int(Math.random()*(mc_arr.length-i)),1)[0]); } //最初のMC内を再生開始 mc_arr[cnt].play(); //毎フレーム 関数 watchMC を実行 addEventListener(Event.ENTER_FRAME,watchMC); //関数 watchMC の定義 function watchMC(e:Event):void { //再生中のMC内が最終フレームになれば if (mc_arr[cnt].currentFrame == mc_arr[cnt].totalFrames) { //再生中のMC内をフレーム1で停止 mc_arr[cnt].gotoAndStop(1); //カウンタに 1 を加算するか 0 に戻す cnt = (cnt < mc_arr.length-1)? cnt+1:0; //カウンタが 0 に戻れば if (cnt == 0) { //再生されていたMCを一時記録 var tmp_mc:MovieClip = mc_arr[mc_arr.length - 1]; //配列「mc_arr」の要素数分ループ for (var i:int = 0; i < mc_arr.length; i++) { //配列「mc_arr」の要素をランダムシャッフル mc_arr.push(mc_arr.splice(int(Math.random()*(mc_arr.length-i)),1)[0]); } //mc_arr[0] が 一時記録された MC と同じであれば if (mc_arr[0] == tmp_mc) { //mc_arr[0] を ランダムな後の要素に挿入 mc_arr.splice(int(Math.random()*(mc_arr.length))+1,0,mc_arr.shift()); } } //次のMC内の再生開始 mc_arr[cnt].play(); } } //------------------------ 上記スクリプトの 『配列「mc_arr」の要素をランダムシャッフルする』 の部分については,書き方こそ全く違っていますが 根底の考え方は次のページと全く同じです。 「FN0212003-配列を偏りなくランダムに並替える」 http://www.fumiononaka.com/TechNotes/Flash/FN0212003.html . ◎【後半】の方法について 用意するものや状況は【前半】と同じで 文字数制限もあるためスクリプトのみ書きます↓。 //------------------------ //MCの参照を登録する配列「mc_arr」を用意 var mc_arr:Array = [mcA,mcB,mcC]; //配列「mc_arr」に登録したMC内の再生停止 for (var i:int = 0; i < mc_arr.length; i++) { mc_arr[i].stop(); } //ランダムな 0~「mc_arr」最終要素番号 の数を得る var rnd:int = int(Math.random()*(mc_arr.length)); //その要素を配列の先頭要素に移動 mc_arr.unshift(mc_arr.splice(rnd,1)[0]); //「mc_arr」の最初のMC内の再生開始 mc_arr[0].play(); //毎フレーム 関数 watchMC を実行 addEventListener(Event.ENTER_FRAME,watchMC); //関数 watchMC の定義 function watchMC(e:Event):void { //再生中のMC内が最終フレームになれば if (mc_arr[0].currentFrame == mc_arr[0].totalFrames) { //再生中のMC内をフレーム1で停止 mc_arr[0].gotoAndStop(1); //0~1未満の小数を得る var rnd:Number = Math.random(); //rnd の値が 0.1 未満(確率10%)であれば if (rnd < 0.1) { //「mc_arr」の最初のMC内の再生開始 mc_arr[0].play(); //それ以外は } else { //ランダムな 1~「mc_arr」最終要素番号 の数を得る rnd = 1+int(Math.random()*(mc_arr.length-1)); //その要素を配列の先頭要素に移動 mc_arr.unshift(mc_arr.splice(rnd,1)[0]); //次のMC内の再生開始 mc_arr[0].play(); } } } //------------------------

Fawkes
質問者

お礼

御回答ありがとうございます。以前教えていただいたムービークリップを特定の組み合わせでランダム再生するスクリプトは今も使わせてもらっています。今回のスクリプトも問題なく動きました。ありがとうございました。確かに二番目のスクリプトはランダム再生というより確率変動させて再生する、ですね。 ただスクリプトを見ていてどういう働きをしているのか分からない箇所があったので質問させてください。 最初のスクリプトのシャッフル部分のここと //配列「mc_arr」の要素をランダムシャッフル mc_arr.push(mc_arr.splice(int(Math.random()*(mc_arr.length-i)),1)[0]); 最後のスクリプトのここなんですが //その要素を配列の先頭要素に移動 mc_arr.unshift(mc_arr.splice(rnd,1)[0]); この[0]はどういう働きをしているのでしょうか?push、unshiftに使っているのでしょうか?

その他の回答 (2)

  • BlurFiltan
  • ベストアンサー率91% (1611/1754)
回答No.3

#1&#2です。 > なぜstrinオブジェクトgが > StringとObjectでtureと判定されてしまうのでしょうか? それは単純に, 変数 a が Object であり,なおかつ String だからでしょう。 ◎参考:ヘルプの「String」より  ~引用~ > String > パッケージ トップレベル > クラス public final class String > 継承 String→Object その他の例も参考まで。 ◎参考:ヘルプの「Array」より  ~引用~ > Array > パッケージ トップレベル > クラス public dynamic class Array > 継承 Array→Object ◎参考:ヘルプの「MovieClip」より  ~引用~ > MovieClip > パッケージ flash.display > クラス public dynamic class MovieClip > 継承 MovieClip→Sprite→DisplayObjectContainer→ > InteractiveObject→DisplayObject→EventDispatcher→Object String オブジェクトも Array オブジェクトも MovieClip オブジェクトも これら3種のオブジェクトは 全て Object クラスを継承しているオブジェクトです。 ですから,どれも Object です。 【喩え1】 人間 は ホニュウ類ですか? → Yes.(true) 人間 は 生物ですか? → Yes.(true) 【喩え2】 鉛筆は 筆記用具ですか? → Yes.(true) 鉛筆は 文房具ですか? → Yes.(true) 鉛筆は 物体ですか? → Yes.(true) 次の文↓は間違っていますよね? 「人間は,ホニュウ類であるが,生物ではない。」 「鉛筆は,筆記用具ではないが,物体である。」 これ↓が正解です。 「人間は,ホニュウ類であるし,生物でもある。」 「鉛筆は,筆記用具である上に,物体でもある。」 ついでに ActionScript や JavaScript など普通のオブジェクト指向言語では Function(関数/メソッド) も Object です。 さらに ActionScript の場合は, BlurFilter(ぼかし)やDropShadowFilter(ドロップシャドウ)のようなフィルターも Object ですまた Tween など「プロパティの変化」さえも Object として扱うことができます。 。 さらに さらに ActionScript 3.0 では Event(例:マウスイベントやキーボードイベントなど) までもが Object です。 ◎参考【添付図】↓ 人間は,ホニュウ類であり,セキツイ動物であり,動物であり,物体である。

Fawkes
質問者

お礼

なるほど。詳細な解説ありがとうございました。勉強になりました。

  • BlurFiltan
  • ベストアンサー率91% (1611/1754)
回答No.2

#1です。 > この[0]はどういう働きをしているのでしょうか? その[0]は「配列の 0番 要素」を取り出すという働きをしています。 そもそも,その[0]を削除するとエラーが出ませんか? [お礼]で書かれている2つのスクリプトですが どちらとも Array クラスの splice() メソッドを使用していますよね。 この splice() メソッドの戻り値(=返り値)は「配列」なのです。  ↓これが「配列」 戻り値 = 配列.splice(抜き出す要素の開始番号,抜き出す要素数); ◎参考:ヘルプの「splice () メソッド」より  ~引用~ > AS3 function > splice(startIndex:int, deleteCount:uint, ... values):Array > …中略… > 戻り値 > Array - 元の配列から削除されたエレメントを含む配列です。 今回使った2つのスクリプトの場合, 抜き出す要素数は 1 つで戻り値は 1 つですから, その戻り値は,なんとなくの雰囲気で見れば, mcA または mcB または mcC のうちのいずれかになるように思えます。 しかし実は違っていて mcA または mcB または mcC のうちのいずれかを1つの要素とする「配列」が戻り値として返ってくるのです。 実際に欲しいのは「配列」ではなくて その中身の「要素」である「ムービークリップ」です。 それで その配列の 0番 要素であるムービークリップを取り出すために [0] を付けているわけです。 新規ドキュメントを作成し, メインのタイムラインのフレーム1に 次のようなスクリプトを書いて(コピペして), 「制御」→「ムービープレビュー」→「プレビュー」してみると, 理解が深まるかもしれません。 //--------------------------------------- //配列["あ","い","う"] の 1番 要素を抜き出し //変数 a に代入 var a = ["あ","い","う"].splice(1,1); //変数 a を出力 trace("a は何? →" + a); //変数 a のタイプを出力 trace("a のタイプは? →" + typeof(a)); //配列["あ","い","う"] の 1番 要素の 0番 要素を抜き出し //変数 b に代入 var b = ["あ","い","う"].splice(1,1)[0]; //変数 b を出力 trace("b は何? →" + b); //変数 a のタイプを出力 trace("b のタイプは? →" + typeof(b)); //--------------------------------------- ムービープレビューでの 上記スクリプト実行時の出力結果↓ --------------- a は何? →い a のタイプは? →object b は何? →い b のタイプは? →string --------------- trace() には, 数値 や 配列 などを自動的に文字列に変換するプログラムが内蔵されているため 便利で使いやすいのですが, その反面,単なる trace(変数名) では, 出力されたものが何であるのかわかりにくいことがあります。 そこで typeof 演算子 を使います。 すると,出力される変数のタイプがある程度わかるようになります。 ◎参考:ヘルプの「typeof 演算子」より  ~引用~ > 式の型 結果 > Array object > Boolean boolean > Function function > int number > Number number > Object object > String string > uint number > XML xml > XMLList xml 上記スクリプトの出力結果で 「a のタイプは? →object」 となりますが もっと細かく言えば a は Array(配列) なのです。 つまり var a = ["あ","い","う"].splice(1,1); では, 配列["あ","い","う"]の 1番 要素1つのみのを要素とする配列 ["い"] が, 変数 a に代入されるわけです。 一方 var b = ["あ","い","う"].splice(1,1)[0]; では, 配列["あ","い","う"]の 1番 要素1つのみのを要素とする配列 ["い"] の さらに 0番 要素である "い" が, 変数 b に代入されるわけです。 説明が長くなって 余計にややこしくなったかもしれませんが とにかく そういう意味の(配列の最初の要素を取り出す意味の) [0] です。 . 【重要ではない補足】========= もし最初の mc_arr.push(mc_arr.splice(int(Math.random()*(mc_arr.length-i)),1)[0]); の方で [0] を使いたくない場合は 次のようにしても良いかもしれません。 mc_arr = mc_arr.concat(mc_arr.splice(int(Math.random()*(mc_arr.length-i)),1)); ○.push(△) は, 配列 ○ の末尾に △ という要素を付け足す(押し込む) という意味になります。 □ = ○.concat(△) は 配列 ○ と 配列 △ とを連結して配列 □ を作成する という意味になります。 push() を使った現状でさえややこしいですが, concat() を使うとさらにややこしくなりますよね...。       ◎参考【イメージ図】↓ 「家」を「配列」,「棒人間」を「要素」だと思って見てください。

Fawkes
質問者

お礼

非常にわかりやすい解説でした。ありがとうございます。教えて頂いたスクリプトを分割して調べている時にエラーがでなかったのですが、あのときは配列を配列の中に入れている形になっていたようです。 それと最初の質問とは外れていってしまいますがもう一つだけ質問をさせてください。教えて頂いたtypeofを使ってみたんですが、このスクリプトを実行すると var a:String ="aaaa"; trace(typeof(a)); trace(a is String); trace(a is Object); 結果が string true true となります。なぜstrinオブジェクトgがStringとObjectでtureと判定されてしまうのでしょうか?

関連するQ&A