• 締切済み

カーソルが特定のオブジェクトに近づいていくと音量がゼロから最大に徐々に変化するAS2.0

カーソルが特定のオブジェクトに近づけば近づくほど指定した音源の音量がゼロから最大に徐々に変化する方法はありませんか。 以下の音量調節コントローラーを透明にして応用しようと考えましたが、 ----------------------- max_val = 100; // 最大音量設定 set_vol = 0; // 現在の音量設定 s_obj = new Sound(); // SoundObjの作成 s_obj.setVolume(set_vol); // ボリュームセット vol_width = vol_mask._width; // マスクwidth初期値取得 vol_mask._width = (vol_mask._width / max_val)*set_vol; // マスクの位置調整 vol_click.onPress = function(){ this.onEnterFrame = function(){ vol_mask._width = this._xmouse; vol_par = Math.round((vol_mask._width / vol_width)*max_val); if(vol_par < 1){ vol_par = 1; }else if(vol_par >= max_val){ vol_par = max_val; } s_obj.setVolume(vol_par); } } vol_click.onRelease = function(){ delete this.onEnterFrame; } vol_click.onReleaseOutside = function(){ delete this.onEnterFrame; } ------------ onPressの代わりにrollOverにするのと、widthだけでなくheightにも両方適用させる方法が解りません。 このような方法でなくとも、目的のものが出来ればいかなる方法でも結構です。 例えば犬のオブジェクトにカーソルを近づければ近づけるほど犬の鳴く音が大きくなり、遠ざけると音が小さくなるようなものです。 お考えのあるかたは是非ともご教授願います。 当方Flash8 AS2.0です。 宜しくお願いします。

みんなの回答

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

#2です。 this.onMouseMove を複数定義すると、先に定義した onMouseMove に後から定義されたものが上書きされてなくなってしまうため、最後に定義したものだけが有効になります。 #2の最後にも少し書きましたように、ムービークリップが複数ある場合は、配列変数で必要な情報を管理すると便利です。 今回は、onMouseMove イベントハンドラに登録する関数の中で、配列変数を見ながら、配列変数に記録されている全てのムービークリップに対しての音量の処理を一括して行う作例をご紹介します。 作り方の一例です。 ステージに、ムービークリップシンボルのインスタンス dog ・ bird1 ・ bird2 という、3つのインスタンスがあるとします。 また、ライブラリにサウンドシンボルが3つあり、それぞれのリンケージ識別子を SE_DOG ・ SE_BIRD1 ・ SE_BIRD2 とします。 これらに対して#2と同様のことを行うスクリプトは、次のようになります。 このスクリプトは、タイムラインのフレームに記述してください。 (↓各行頭に全角のスペースが入っています。コピーする際は、全て半角のスペースかタブに置き換えてください) /**************************************************/  //////////////////////////////////////////////////////////  //初期設定  //////////////////////////////////////////////////////////  /*   情報をまとめて管理する配列変数   フィールドの各内容は次の通り    clip:ムービークリップの参照    max_vol:音源の音量(最大音量)    range:音が届く距離(円の半径、単位はピクセル)    id:サウンドシンボルのリンケージ識別子  */  info = new Array();  info =  [   { clip : this.dog , max_vol : 100 , range : 200 , id : "SE_DOG" } ,   { clip : this.bird1 , max_vol : 80 , range : 100 , id : "SE_BIRD1" } ,   { clip : this.bird2 , max_vol : 40 , range : 80 , id : "SE_BIRD2" }  ];  //////////////////////////////////////////////////////////  //サウンドのセットアップ  //////////////////////////////////////////////////////////  //音を出すムービークリップの数だけSoundオブジェクトを設定  for( i = 0 ; i < info.length ; i++ )  {   //サウンドのセットアップ   //音はそれぞれのムービークリップから出力する   this[ "snd" + i ] = new Sound( info[ i ].clip );   this[ "snd" + i ].attachSound( info[ i ].id );   //無限ループ再生設定   this[ "snd" + i ].onSoundComplete = function()   {    this.start();   };   //サウンドを再生   //最初は音量を絞っておく   this[ "snd" + i ].setVolume( 0 );   this[ "snd" + i ].start();  }  //////////////////////////////////////////////////////////  //マウスカーソルの位置に応じて音量を変化させる処理  //////////////////////////////////////////////////////////  this.onMouseMove = function()  {   var i;   var mc;   var temp_x , temp_y , d;   var range , max_vol , vol;   for( i = 0 ; i < info.length ; i++ )   {    //各ムービークリップとカーソルの距離を求める    mc = info[ i ].clip;    temp_x = this._xmouse - mc._x;    temp_y = this._ymouse - mc._y;    d = Math.sqrt( Math.pow( temp_x , 2 ) + Math.pow( temp_y , 2 ) );    //カーソルが音の届く範囲(rangeを半径とする円の中)にない場合、音量を絞る    range = info[ i ].range;    max_vol = info[ i ].max_vol;    if( d > range )    {     this[ "snd" + i ].setVolume( 0 );    }    //範囲内にカーソルがある時は、距離に応じた音量を設定    else    {     //距離に応じた音量を算出し、この音量を設定する     vol = Math.floor( max_vol - ( d * max_vol / range ) );     this[ "snd" + i ].setVolume( vol );    }   }  }; /**************************************************/ 今回は複数のムービークリップを扱うということで、処理に必要な情報であるムービークリップ・音源の音量・音が届く範囲・リンケージ識別子を配列変数にまとめ、この情報を見ながら一括して処理を行います。 ActionScript の配列変数は、内部に仕切り(”フィールド”といいます)を作り、複数の情報を効率よく管理できるようになっています。 フィールドの名前と内容につきましては、スクリプト中のコメントをご参照の上、作品に合わせて数値や内容を変更してください。 ActionScript では、スクリプトを記述しているフレームにないインスタンスに指示を出したり、そのインスタンスの情報を見ることはできません。 上記の作例では、配列変数にムービークリップの参照という情報を登録しています。そのため、このスクリプトを記述したフレームにないムービークリップを配列変数に登録しても、これは処理の対象に含まれせん。 後で登場するムービークリップについては個別に処理を作るか、配列変数にはとりあえずムービークリップの名前を入れておいて、後で参照に変換する方法の、どちらかになるかと思います。 なお、今回も onMouseMove イベントハンドラを使いましたが。 音量を変化させるスクリプトは”マウスを動かした時”に実行されるため、「ムービークリップが移動していて、マウスを動かさないのにムービークリップの方がカーソルから遠ざかった場合」は音量が変化しません。 onMouseMove の部分を onEnterFrame に変更していただくと、マウスを動かさなくてもムービークリップとの距離から音量が変化するようになります。 ただし、onEnterFrame を利用した場合はフレームレート分の1秒ごとに計算が行われるようになります。数が多かったり、容量の大きなサウンドシンボルを使うと処理が重くなりますので、ご注意ください。

invisist
質問者

お礼

再度ご丁寧なご回答をしていただいてありがとうございました。 教えていただいた方法は完璧でした。やりたかったことがようやくできたので感激しております。 DPEさんの説明は非常に解り易く丁寧で文章が上手なところからも、論理的思考が長けていて頭が良いうえに、このようなところで回答される奉仕の心を持ち合わせている。感心しました。

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

次のように考えてはいかがでしょう。 ムービークリップの基準点から音が出ているとします。 この音はどの方向にも均等に届くとすると、この音が聞こえる範囲は、”音源のある場所を中心とする円”と考えることができます。 例えば、音の届く範囲を仮に 200 ピクセルとすると、音が聞こえる範囲は、”音源の位置(=ムービークリップの基準点)を中心とする半径 200 ピクセルの円の中”となります。 カーソルが円の中心から遠くにあるほど音量が小さくなり、この円から外れている時は音が聞こえないので、音量を 0 にします。 円の中にある場合は、音源(=円の中心)からの距離に応じて音量を調節します。 円の中にカーソルがあるかどうかは、音源の位置であるムービークリップの基準点からカーソルまでの距離を求め、この値と円の半径を比べることで分かります。 2点間の距離は、三平方の定理で求めることができます。 カーソルまでの距離が半径よりも大きい場合、カーソルは円の中にありません。 円の中にある場合は、円の中心からカーソルまでの距離に応じた音量を算出します。 この円は音量を表していますので、半径の長さが音源の音量に相当します。ですから、比を使って  半径:カーソルまでの距離=音源の音量:目的の音量 このように表せます。 とすると、比の特性から、  目的の音量=カーソルまでの距離×音源の音量÷半径 となります。  しかし、今回の件では、円の中心から遠ざかるほど音量が小さくならなければなりません。上記の考え方で音量を算出すると、”音源から遠ざかるほど大きくなる”計算になってしまいます。 音源から遠ざかるほど小さくなるように音量を決める考え方は2つあります。 1つは、先述の比の考え方でとりあえず音量をとりあえず求め、音源の音量から減算することです。 式にすると  目的の音量=音源の音量-(カーソルまでの距離×音源の音量÷半径) です。 これは、例えば「高さが 10cm のコップに水が 6cm ほど入っている。コップの上から水面までは何 cm あるか?」という問題の考え方と似ています。 もう1つは、カーソルの位置が半径をある比率に分割する点になっていることに注目した方法です。 円の半径とは中心から円周までを結ぶ線で、今回はこの線の長さが最大音量を表しています。 ただし、音源から遠くなる、つまり円の外側に近い方が音量は 0 に近付きますから、円周側の端を 0 として考えます。 合わせますと、”半径を円周側から見た時、円周からカーソルまでの長さが、目的の音量を表わしている”ことになります。 まず、中心からカーソルまでの距離を半径から減算し、この差分が半径のどのくらいの割合に相当するかを求めます。 この割合が音量ではどのくらいに当たるのかを求めればいいので、この割合に音源の音量を乗算します。 つまり、式にすると  目的の音量=(半径-カーソルまでの距離)÷半径×音源の音量 となります。 ------------------------------------------------ スクリプトの一例です。 ステージに、ムービークリップシンボルのインスタンス” dog ”があるとします。 ライブラリにサウンドファイルを読み込み、リンケージを設定してください。リンケージの識別子を、仮に” SE1 ”とします。 dog の基準点のあたりにカーソルを近付けるほど音が大きく、遠ざかるほど小さくなるスクリプトは、次のようになります。 このスクリプトは、タイムラインのフレームに記述してください。 (↓各行頭に全角のスペースが入っています。コピーする際は、全て半角のスペースかタブに置き換えてください) /**************************************************/  //////////////////////////////////////////////////////////  //初期設定  //////////////////////////////////////////////////////////  //音源の音(最大音量)と、音が届く範囲(円の半径、単位はピクセル)  max_vol = 100;  range = 200;  //サウンドのセットアップ  //音はムービークリップ自身から出力する  snd = new Sound( dog );  snd.attachSound( "SE1" );  //無限ループ再生設定  snd.onSoundComplete = function()  {   this.start();  };  //サウンドを再生  //最初は音量を絞っておく  snd.setVolume( 0 );  snd.start();  //////////////////////////////////////////////////////////  //マウスカーソルの位置に応じて音量を変化させる処理  //////////////////////////////////////////////////////////  this.onMouseMove = function()  {   var temp_x , temp_y , d;   var vol;   //ムービークリップとカーソルの距離を求める   temp_x = this._xmouse - dog._x;   temp_y = this._ymouse - dog._y;   d = Math.sqrt( Math.pow( temp_x , 2 ) + Math.pow( temp_y , 2 ) );   //カーソルが音の届く範囲(range)にない場合、音量を絞る   if( d > range )   {    snd.setVolume( 0 );   }   //範囲内にカーソルがある時は、距離に応じた音量を設定   else   {    //距離に応じた音量を算出し、この音量を設定する    vol = Math.floor( max_vol - ( d * max_vol / range ) );    snd.setVolume( vol );   }  }; /**************************************************/ 音源の音量(基準点付近の音量)を変数 max_vol 、音が届く範囲である円の半径を変数 range で管理しています。 鳴らす音や作品に合わせて変更し、動作を確認してみてください。 半径が、変数 range に設定した値と同じピクセルの円を描画し、ムービークリップの基準点の位置とこの円の中心を合わせて仮に配置しておくと、音量の変化を確認しやすいと思います。確認用の円は、用が済んだら削除するか、ガイドレイヤーにするなどして、実際の作品に書き出されないようにご注意ください。 なお、上記のスクリプトでは、音源の音量からカーソルの位置までの音量を減算する方法で目的の音量を求めています。 円の応用で、カーソルがある方向にある時だけ音量を調節することもできます。 Math クラスの atan2 メソッドを使うと、2つの座標から方向(角度)が分かります。 これを利用して、例えば犬が向いている方向にカーソルがある場合だけ音量を調節する、といった演出に使えるかと思います。 生き物の鳴き声やメガホンのようなもので叫ぶ声は、通常は、後ろよりも向いている方向に音がよく伝わります。 音が伝わる範囲を単純に円で考えず方向に制限を加えると、面白い作品になるかもしれません。 この作例ではムービークリップが1つしかありませんが、複数のムービークリップで同じ表現をしたい場合は、配列変数を使って音源の音量や音が届く範囲などを管理すると、for ループでまとめて処理できて便利です。 複数のムービークリップを使うと、カーソルと音源の位置によっては複数の音が混ざって再生されることもあります。 ただし、音を鳴らす処理はもともと重い上に、距離を求める計算も累乗や除算が入っていて、数が多くなれば決して軽い処理とは言えません。 複数の音を同時に鳴らす時は、サウンド素材はなるべく短く容量の少ないものを選び、数もほどほどにしましょう。

invisist
質問者

お礼

ご回答いただき誠にありがとうございました。とてもご丁寧にご説明していただいたので、問題なく行うことができました。感謝しております。 お礼ついでに再度質問して恐縮ですが、 複数の音を同じように音量変化させる場合について教えていただけますと幸いです。 ムービークリップシンボルのインスタンス”bird1 ”を新たに追加して以下のようなスクリプトで試してみましたが動きませんでした。 //音源の音(最大音量)と、音が届く範囲(円の半径、単位はピクセル) max_vol = 100; range = 500; //サウンドのセットアップ //音はムービークリップ自身から出力する snd2 = new Sound( bird1 ); snd2.attachSound( "SE2" ); //無限ループ再生設定 snd2.onSoundComplete = function() { this.start(0,1000); }; //サウンドを再生 //最初は音量を絞っておく snd2.setVolume( 0 ); snd2.start(); ////////////////////////////////////////////////////////// //マウスカーソルの位置に応じて音量を変化させる処理 ////////////////////////////////////////////////////////// this.onMouseMove = function() { var temp2_x , temp2_y , b; var vol; //ムービークリップとカーソルの距離を求める temp2_x = this._xmouse - bird1._x; temp2_y = this._ymouse - bird1._y; b = Math.sqrt( Math.pow( temp2_x , 2 ) + Math.pow( temp2_y , 2 ) ); //カーソルが音の届く範囲(range)にない場合、音量を絞る if( b > range ) { snd2.setVolume( 0 ); } //範囲内にカーソルがある時は、距離に応じた音量を設定 else { //距離に応じた音量を算出し、この音量を設定する vol = Math.floor( max_vol - ( b * max_vol / range ) ); snd2.setVolume( vol ); } }; もし可能でしたらご教授いただけますと幸いです。

回答No.1

ボリューム変更部分のベースはこんな感じでしょうか。 (target_mcが、対象のMC, Actionscript2.0) ----------------------- target_mc.onEnterFrame = function(){ //dist:target_mcとマウスとの距離 dx = _root._xmouse - this._x; dy = _root._ymouse - this._y; dist = Math.sqrt(dx * dx + dy * dy); //distでは、係数が大きすぎるので適当に dist = dist / 25; if (dist < 1.0){ //distが1以下ならばボリューム100% dist = 1.0; } //ボリュームの変更 _root.s_obj.setVolume(100 / dist); } ----------------------- MCの原点とマウスの距離で直線的にボリュームを変化させていますので MCの大きさを考慮したり、ボリューム変化を直線的で なくしたりしてみてください。

invisist
質問者

お礼

ご回答いただき誠にありがとうございました。 この方法で試してみましたが、私が未熟なため完全に理解していないためか、うまくいきませんでした。 別に回答いただいた方法で行うことができました。 ありがとうございました。

関連するQ&A