• ベストアンサー

ActionScriptで対象外の音まで止まる・・・。

フレームに以下のような記述をしたのですが動作が変です。初期段階で「oto1」が鳴っており、インスタンス「b1」をクリックで止まります。これは想定どおりの動作なのですが、「b2」をクリックしても止まるのです。これは理解できません。 何が誤りなのか教えていただけませんでしょうか? よろしくお願いいたします。 (インスタンス名は正しくつけています) oto1 = new Sound(); oto2 = new Sound(); _root.oto1.attachSound("s1"); _root.oto2.attachSound("s2"); _root.oto1.start(0, 99); this.b1.onRelease = function(){ _root.oto1.stop(); }; this.b2.onRelease = function(){ _root.oto2.stop(); };

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

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

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

同じ階層内で複数の音を扱っている時に特定の音を止めるには、Sound.stop の引数にリンケージ識別子を指定します。 各 onRelease イベントハンドラ内の stop を  _root.oto1.stop( "s1" ); と  _root.oto2.stop( "s2" ); に変更してみてください。 s1 はインスタンス b2 をクリックしても止まりません。 s2 を鳴らしている時は逆に、インスタンス b1 では止められなくなります。 タイムラインに音を挿入する場合は、「プロパティ」パネルにある「同期:」というリストで鳴らし方を指定できます。 この中に「ストップ」という項目があり、指定したサウンドだけを止めることができますが、これと同じ機能です。 ------------------------------------------------------------------ Sound クラスのオブジェクトは、どのムービークリップの音を制御するかを指定することができます。 Sound オブジェクトを作る時に  snd = new Sound( clip ); というように対象のインスタンス名を指定すると、指定されたムービークリップの音を制御する Sound オブジェクトになります。 省略した時は _root、つまりムービー全体の音を制御する Sound オブジェクトになります。 こんな設計になっている理由はいろいろあるのですが、一言で言うなら、音を多重的に管理できるように・・・でしょうか。 シンセサイザなどのコンピュータで出す音は、出力ポート数というものが決められています。 ポートは楽器を演奏する奏者のようなもので、ポートの数だけ同時に音を発声できます。 ActionScript ではムービークリップがサウンドの出力ポートのような役割を果たし、理論上はムービークリップの数だけ音を細かく制御できるようになっています。 しかし、単に”複数の音を鳴らしたいだけ”でしたら、実は音の数だけムービークリップを作る必要はありません。 ただ、Sound クラスのオブジェクトで同時に鳴らせるのは1種類だけ( attachSound を実行するたびに、鳴らすサウンドシンボルが切り替わる)ので、スクリプトで同時に何種類もの音を鳴らしたい場合は Sound オブジェクトは音の数だけ必要です。 ご質問文のスクリプトでは oto1 でしか音を鳴らしていませんが、oto2.start(); を実行してみるとよく分かります。 ともに _root の音を制御する Sound オブジェクトでありながら、2種類の音が同時に鳴ります。 これが、どちらも同じムービークリップの音を制御する Sound オブジェクトだったとしても同様です。 タイムラインにサウンドを入れる時も、レイヤーを分けると2種類以上の音を同時に出すことができます。 つまり、”音を鳴らすだけ”なら1つのムービークリップ(タイムライン)でも可能なのです。 Flash でのムービークリップは奏者というよりはむしろ楽団のようなもので、レイヤーが1人1人の奏者にあたると言えるかもしれませんね。 ムービークリップに分けて管理しなければならないのは、2種類の音を同時に鳴らし、1つはボリュームを大きくもう1つは小さく・・・というように、ボリュームやパンなどの出力設定を個別に分ける場合です。 1つのムービークリップ内にある音は、ボリュームやパン(スピーカーの出力位置)などは全て同じものに統一されてしまいます。 (レイヤーを使った時は違いますが、話がややこしくなるのでとりあえず置いておきます) 一方がフェードアウトしながら片方はフェードインするとか、ナレーションが再生されている間は BGM のボリュームを控えめにしてナレーションを目立たせたい・・・など、複数の音を違う出力設定で鳴らしたい時には、音の数だけムービークリップを分ける必要があります。 *************************** では、同じタイムライン内で別の音を同時に鳴らすことができるのに、止める時はなぜ2つとも同じように止まってしまうのでしょうか。 Flash では、音もムービークリップと同様に”サウンドシンボルのインスタンスを作る”という発想で考えます。 目に見えないもので想像しにくいのですが、サウンドインスタンスができた数だけ音が鳴り、インスタンスが削除されたら止まるものと思ってください。 Sound.start は、実行するたびにサウンドインスタンスを作成して音を鳴らします。 作成されたインスタンスは、サウンドシンボルの最後に達すると用済みになって削除され、音が止まります。 Sound.stop は逆に、稼動中のサウンドインスタンスを強制的に削除して音を止めるメソッドです。 何も指定しなければ、Sound オブジェクトの管理下にあるタイムラインに存在している、稼動中のサウンドインスタンス全てを削除します。 実はタイムラインを使って鳴らしている音でも、Sound オブジェクトが管理しているタイムライン内にあるものであれば削除の対象になります。 例えば、ムービークリップ clip があり、このタイムラインにサウンド s1 を入れているとします。 それとは別に、clip の音を制御する Sound オブジェクトの snd があって、attachSound と start で s2 という音を鳴らします。 この状態で  snd.stop(); を実行すると、clip 内で稼動しているサウンドインスタンスが全て削除されて、タイムラインで鳴らしていた s1 もスクリプトで鳴らしていた s2 も止まります。 Sound.stop は指定した音だけを止めることもできます。 これが、冒頭でご紹介した使い方です。 止める音はリンケージの識別子で指定します。 例えば先の例で、  snd.stop( "s1" ); とした時は s1 の方だけ止まります。 タイムラインで鳴らしている音でも、リンケージ識別子が設定されていればSound.stop で指定したものだけを止めることができます。 ちなみに、例えばタイムラインとスクリプトの両方で s1 を鳴らしていた場合、s1 のインスタンスは2つ存在していて二重に音が鳴っています。 この時に s1 を止めるように指示すると、どちらのインスタンスも削除されて止まります。 一般的にはこのような使い方はまずしないと思いますが、stop でリンケージ識別子を指定すると、その識別子を持つサウンドインスタンスが全て削除されるということです。 *************************** ところで、Sound オブジェクトは管理するムービークリップを選べると書きましたが。 _root の音を管理する Sound オブジェクトで stop(); を実行すると、どういうことになるでしょうか。 先述の通り、Sound.stop で止める音を指定しなかった場合は、タイムライン内で稼動中のサウンドインスタンス全てが削除されます。 _root の音を管理する Sound オブジェクトでは”タイムライン内”とはムービー内全てが管轄になりますから、ムービークリップ内で鳴らしている音も全て止まります。 音を止めるにはもう1つ、ムービー内の全ての音を止める stopAllSounds というアクションがありますが、_root の音を管理している Sound オブジェクトの stop(); を使った場合はこれと同等の機能になります。 ご提示のスクリプトで b1 と b2 のどちらをクリックしても音が止まってしまう理由も、ここにあります。 oto1 も oto2 もともに _root の音を制御する Sound オブジェクトなので、stop(); はムービー内の全ての音を止める命令として機能します。 そのために、s1 と s2 のどちらが鳴っているかに関係なく、どちらかのボタンが押されると有無を言わさずムービー内の全ての音が停止してしまうのです。 しかし、_root の音を管理する Sound オブジェクトの stop(); でムービークリップ内も含めた全ての音を一括して止めることはできても、リンケージ識別子で止める音を指定した時はムービークリップ内にある音は止まりません。 なぜこんなややこしい設計になっているのかは、よく分かりませんが。 ------------------------------------------------------------------ Sound クラスは意外に複雑ですが、普通に使う分にはあまり細かく考えなくても、充分、多様な鳴らし方や演出ができます。 同時に複数の音を鳴らすのではなく同時に鳴らすのはあくまでも1つだけで、ミュージックプレイヤーのように何かのタイミングで単に鳴らす音を取り替えたいだけなら、取り替えるところで  oto1.attachSound( "s2" ); というように、attachSound で違うサウンドシンボルに差し替えればいいだけです。 すると、次に oto1.start を実行した時は、新しく attachSound で関連付けた s2 が鳴ります。 サウンドの制御はこのサイトでも度々話題になっています。 いろいろな作例がありますので、興味がありましたら探してみてください。

ikataro
質問者

お礼

いつもお世話になっていますm(_ _)m彡 なんと!stop(); の()内に記述とは思いつきませんでした。 今回の現象について「そんなばかな!」と格闘すること4時間、ついにあきらめて質問させていただきましたがこんなに詳細に解説いただき感動です。 本当にどうもありがとうございました。

その他の回答 (1)

noname#35109
noname#35109
回答No.1

oto1 = new Sound(); だと,全ての音を対象としたSoundオブジェクトが作成されてしまうのでうまくできないのです。 なんと言うのですかね… 非常に説明しにくいのですが, 1サウンドに対して1MCが必要なのですよ。 サウンドを「切り替える」のように, 1つの Soundオブジェクト に対して,複数のSoundを切り替えてならす場合は, _root.oto1 = new Sound(this); のようにして,ムービークリップ this を指定すればいいのです。 私が回答したものではありませんが, こちら↓を参考にしてみてください。 「質問:外部ムービーを読み込んだとき音が鳴らなくて困っています.」 http://oshiete1.goo.ne.jp/kotaeru.php3?q=1570737  ↑教えて!goo  ↓OKWave (同じです) http://okwave.jp/kotaeru.php3?q=1570737 そうではなくて, 複数の音を同時に存在させて,その音を同時に制御する場合は, その音を埋め込む数だけムービークリップが必要となります。 ムービークリップを,実際に作成してインスタンス名を付けても良いですが, 面倒なのでスクリプトで,スクリプトで作るとすれば次のようになります。 最初の2行を付け加えて,次の2行を変更しているだけですが,前文書くと次のようになります。 _root.createEmptyMovieClip("soundMC1", 1); _root.createEmptyMovieClip("soundMC2", 2); oto1 = new Sound(_root.soundMC1); oto2 = new Sound(_root.soundMC2); _root.oto1.attachSound("s1"); _root.oto2.attachSound("s2"); _root.oto1.start(0, 99); this.b1.onRelease = function() { _root.oto1.stop(); }; this.b2.onRelease = function() { _root.oto2.stop(); }; 最初の2行で,深度1と2に空のMCを作成しています。 _root に複数のムービークリップがあって, そのムービークリップ内タイムラインに音が挿入されている状態で, それらの音を制御するという感じですね。 全てが目に見えない状態なのでイメージしにくいですが, _root に複数のムービークリップがあって, それらのタイムラインを stop() させたり play() させたりするような感じにとらえてもらうとわかりやすいかもしれません。 正式には上記のようにするのが正解だと思います。 ちょっと実験でしてみましたら,次のようなスクリプトでもできました。 oto1 = new Sound(this.b1); oto2 = new Sound(this.b2); _root.oto1.attachSound("s1"); _root.oto2.attachSound("s2"); _root.oto1.start(0, 99); this.b1.onRelease = function() { _root.oto1.stop(); }; this.b2.onRelease = function() { _root.oto2.stop(); }; 私の場合,「b1」と「b2」はボタンシンボルで作成したのですが, なぜかそのボタンシンボルのインスタンスを指定しても,大丈夫なようです。 普通は, new Sound() の () 内はムービークリップ(ムービークリップのタイムライン)を指定しますから, この方法はやめた方がいいとは思いますが,簡単な方法としての裏技?です。

ikataro
質問者

お礼

いつもお世話になっていますm(__)m彡 いや、ひょっとしたらFLASHのバグでは・・?などと空想していましたが私の勉強不足でしたね! 実験までやっていただき誠にありがとうございます。 これを基礎にステップアップいたします。

関連するQ&A

  • ActionScriptでの繰り返し記述をすっきりまとめたい

    FLASHのActionScriptを勉強中です。 繰り返し同じ様なものを記述する場合、for文か何かを使うと思うのですが、以下の場合はどうすればいいのでしょうか? *プログラムの内容は複数のインスタンスを表示してクリックで順次消えるというものです。インスタンスに記述ではなく、フレームに記述しています。(イベントハンドラメソッド) this.b1.onRelease = function(){ _root.b1._visible = false; }; this.b2.onRelease = function(){ _root.b2._visible = false; }; this.b3.onRelease = function(){ _root.b3._visible = false; };      以下繰り返し… お詳しい方、よろしくお願いいたします。

    • ベストアンサー
    • Flash
  • 当たり判定で一度だけ音をならすには

    当たり判定で、下記の様に書きました。 I_blueは青ボールインスタンス名、I_green 緑ボール インスタンス名です。 緑ボールをドラッグ&ドロップで青ボールに重ねると音がでるというものを作ろうとしています。 // Hsound01 = new Sound(_root.I_blue); Hsound01.attachSound("HS_sound01"); // _root.I_blue.onEnterFrame = function() { if (this.hitTest(_root.I_green)) { _root.Hsound01.start(0, 1); } }; // I_green.onPress = function(){ startDrag(this,false); } I_green.onRelease = function(){ stopDrag(); } ですが、これだと音が繰り返し再生されてしまいます。 当たり判定で一度だけ音をならすには、どのようにすべきでしょうか。 お知恵をお貸しいただけたらと思います。 よろしくお願いします。

    • ベストアンサー
    • Flash
  • ActionScript2.0のイベントについて

    親ムービークリップに配置した子ムービークリップのイベントが実行されなくて困っています。 親ムービークリップ自体には下記のイベントを設定しています。親ムービークリップはattachMovieで動的に配置しています。 onRollOver・・・onEnterFrameを設定 onRollOut・・・onEnterFrameを削除 子ムービークリップを配置して子ムービークリックにイベントを設定しました。onEnterFrameをは実行されますが、onReleaseが実行されず困っています。 function Parent() { this.onRollOver = function() { this.onEnterFrame = function(){・・・} } this.onRollOut = function(){ delete this.onEnterFrame; } this["child_mc"].onRelease = function() { trace('a') // 実行されない } this["child_mc"].onEnterFrame = function() { trace('b') // 実行される } } ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ _root.attachMovie("Parent", "parent_mc", _root.getNextHighestDepth(), new Parent()); 子ムービークリップはオーサリングで静的にParentに配置し、プロパティでchild_mcと設定しています。 onReleaseは実行できず、そこで止まっています。 なんでも良いので教えてください。

    • ベストアンサー
    • Flash
  • actionscript2.0から3.0へ、

    actionscript2.0から3.0へ、 actionscript2.0から3.0へ、 大変申し訳ございませんが、 どなたか書き換えていただけないでしょうか? 情報が足りない場合ご指摘くださいましたら 追記いたします。 flash8にて制作されたFlaをCS4にて修正しています。 3.0がわかるものが出来なくなってしまったので、 こちらに書かせていただきました。 400フレームのものなのですが、1フレームに下記のスクリプトがあります。 btnSkip.onRelease = function() { this._visible = false; gotoAndStop("end"); btnRepeat._visible = true; } 400フレーム目には下記のスクリプトがあります。 stop(); btnRepeat._visible = true; btnSkip._visible = false; btnRepeat.onRelease = function() { gotoAndPlay("start"); this._visible = false; btnSkip._visible = true; } みたところステージには、スキップとリピートのムービークリップがあります。 スキップをクリックすると、400フレーム目に飛んでストップ、リピートを押すと1フレーム目に戻って再生、という動作です。 修正前(2.0)は正常に動作していました。 これを3.0に書き換えていただきたいのです。 大変恐縮なのですが、大至急直さないといけないのです。。 よろしくお願いいたします。

    • ベストアンサー
    • Flash
  • 【複数の音声】スタート&ストップ

    前にも似たような質問してますが 簡潔にソースのどこが悪いか教えてください。 音を複数出せるように 2種類の再生ボタンを用意します。 ストップボタンも同じように用意します。 ストップボタンを押すと 対応した音が消えるようにしたいのですが どうしたらよいでしょうか? 作成したこと。 1フレームに下記のASを挿入。 //サウンド・クラスのインスタンスを生成 _root.a.bgm01 = new Sound(bgm01); _root.b.bgm02 = new Sound(bgm02); MCを2つ作成。 インスタンスは"a"と"b"を用意。 その中にサウンド素材を"a"と"b"に フレーム1に入れる。 イベントはストップの状態。 ボタンに書いたソースはこちら。 ひとつめ↓ on (release) { _root.a.bgm01.attachSound("bgm01"); _root.a.bgm01.start(); } ふたつめ↓ on (release) { _root.b.bgm02.attachSound("bgm02"); _root.b.bgm02.start(); } 停止ボタンには↓ "a" on (release) { _root.a.bgm01.stop(); } "b" on (release) { _root.b.bgm02.stop(); } 作りかけのファイルは 【http://flash-moe.yi.org/bgm/bgm.fla】 質問が終了次第削除します。

    • ベストアンサー
    • Flash
  • 一曲が終わったら次の曲へ

    こんにちわ ただ今フラッシュでmp3プレイヤー的な物を作ってるのですが 一曲は再生できるものの一曲が終わったら次の曲へ とアクションスクリプトを組むにはどうすればいいのでしょうか? 今のプレイヤーにはプレイ、ストップボタンだけの 単純な機能がそなわっています var song_sound:Sound = new Sound(); song_sound.attachSound("曲名"); play_btn.onRelease = function() { song_sound.start(); }; stop_btn.onRelease = function() { song_sound.stop(); }; このようになっております。 どのようなスクリプトを書き足せばよろしいのでしょうか? また、スクリプトを足す以外に簡易的な作り方など あれば教えてください。 説明しているサイトもいろいろ探したのですが なかなかみつかりません(汗 サイトなどでも結構なのでよろしくお願いいたします FLASH8 WINDOWS XP 使用です

    • ベストアンサー
    • Flash
  • スクリプトをまとめて書くには

    Actionscript 2.0で作成しています。 例えばムービークリップaaa1~aaa10までと、bbb1~bbb10があったとして、 aaa1をクリックするとaaa1とbbb1が動く、というようなスクリプトを書きたい場合、 for( i = 1 ; i <= 10 ; i++ ){ eval("aaa"+i).onRelease = function(){ this.gotoAndPlay(2); _root.eval("bbb"+i).gotoAndPlay(2); } } としてもbbbの方が動きません。 iの値がeval("bbb"+i)の時点で11になってしまってます。 なので現状forを使わずに書いているのですが、 このような方法を簡単な記述で実現するにはどうすればいいのでしょう? それと、同じ動作を別のムービークリップにさせたい場合、 まとめて書くことはできますでしょうか? (例えばこれをまとめて書くとか) aaa.onRelease = function(){ _root.stop(); } bbb.onRelease = function(){ _root.stop(); }

    • ベストアンサー
    • Flash
  • FlashCS5 ActionScript2.0で3つのボタンを制御し

    FlashCS5 ActionScript2.0で3つのボタンを制御しています。 それぞれインスタンス名はbt1,bt2,bt3です。 動きはマウスオーバーで120%大きくなり、ロールアウトで100%へと戻るものです。 しかし、ロールアウトの動作中に他のボタンに触ると、ロールアウトの動作が中断してしまいます。 なぜでしょうか? //////////////////////////////////////// stop(); sx = 3; var i; //----------- for( i = 1; i < 4; i++){ Nov = "bt" + i; _root[Nov].onRollOver = function(){ Name = this._name; btOverMotion(Name); } _root[Nov].onRollOut = function(){ Name = this._name; btOutMotion(Name); } } //----------- function btOutMotion(eachNo){ No = eachNo; onEnterFrame = function(){ if(_root[No]._xscale < 100){ delete this.onEnterFrame; }else{ _root[No]._xscale -= sx*2; _root[No]._yscale -= sx*2; } } } //----------- function btOverMotion(eachNo){ No = eachNo; onEnterFrame = function(){ if(_root[No]._xscale > 120){ delete this.onEnterFrame; }else{ _root[No]._xscale += sx; _root[No]._yscale += sx; } } }

    • ベストアンサー
    • Flash
  • 複数のクリックボタンにより再生と停止場所を指定する方法

    複数のボタンを用意し、クリックするボタンにより異なるフレーム数で停止たいと思っております。 停止したいフレームごとにstop();を入れると、そこで毎回止まってしまうのでボタン毎に停止場所を指定しようと、以下のように試してみましたが、出来ませんでした。 停止場所をラベルでも指定してみましたが、出来ませんでした。 stop(); _root.next1.onRelease = function() { gotoAndPlay(5); this.stop(10); } _root.next2.onRelease = function() { gotoAndPlay(5); this.stop(20); } どなたかお考えのあるかたご教授いただけますと幸いです。 当方 Flash8 ActionScript2.0 を使用しています。

  • flashの音再生について

    main.swfにactionscript2.0で音のon/offしているのですが、 offになって欲しくない音までoffになってしまいます。 スクリプトで呼び出している音ならばまだわかるのですが、 flvで外部から読み込み再生しているファイルなので、 訳が分からず困っています。 ちなみに音再生スクリプトはフレーム上に以下 //BGM制御用のダミーのムービークリップを作る this.createEmptyMovieClip( "bgm_clip" , 0 ); //BGMの設定 sndbgm = new Sound( bgm_clip ); sndbgm.attachSound( "BGM01" ); sndbgm.setVolume( 100 ); sndbgm.onSoundComplete = function() { //無限ループ再生 sndbgm.start(); }; //BGMを再生 sndbgm.start(); //BGMのボリュームとフェードの速さを管理する変数 bgm_vol = 100; fade_spd = 5; //SE設定 allse = new Sound(); allse.setVolume( 100 ); S1 = new Sound(this); S1.attachSound("SE01"); S2 = new Sound(this); S2.attachSound("SE02"); S3 = new Sound(this); S3.attachSound("SE03"); on/offにはMCで以下の様にしています。 on (release) { if (this._parent.sndbgm.getVolume()>0) { this._parent.sndbgm.setVolume(0); this._parent.allse.setVolume(0); this._parent.v_on_off.gotoAndStop("soundOFF"); } else if (this._parent.sndbgm.getVolume()<=0) { this._parent.sndbgm.setVolume(100); this._parent.allse.setVolume(100); this._parent.v_on_off.gotoAndStop("soundON"); } } SE再生にはフレーム上に S1.start(); と入れています。 使用バージョンはCS4になります。 どなたか判る方、教えて下さい。

    • ベストアンサー
    • Flash

専門家に質問してみよう