0

やることと同じように、Javaで基本的なゲームを作り始めました。

すべて順調に進んでいます。地図を読み込んだり、描画したりできます。

マップ用の音楽や衝突などの効果音を再生しています。

しかし、MAP A(私が残しているもの)の音楽がMAP B(私が入っている地図)の音楽にフェードインする必要があるように感じますが、これは可能ですか?

音楽の再生に使用するコードは次のとおりです。

    try
    {
        if(clip != null)
        {
            clip.stop();
            clip.close();
        }

        clip = AudioSystem.getClip();

        URL a = this.getClass().getResource("/resource/sound/"+Filename + ".mid");

        ais = AudioSystem.getAudioInputStream(a);

        clip.open(ais);
        clip.loop(999);
        clip.start();
    }
    catch(Exception e)
    {

    }

おそらくお分かりのように、私はJavaがあまり得意ではありませんが、私のゲームは今のところうまくいっていて、そうではありません。完全に制御したいので、「エンジン」の使用を拒否します。

何か案は?

ありがとう

編集:

すべての回答に感謝します。あなたがくれたコードを変更しましたが、機能していません= /

以下のコードを作成しました。これは新しいスレッド(したがってRunnable)で実行されるため、再生中に音楽がフェードします。

コードは以下のとおりです。

private Boolean _SwapMusic = false;
private String _Filename;
Thread soundThread;

    Runnable r1 = new Runnable() {
      public void run() {
        while(true)
        {
            if(_SwapMusic)
            {
                _SwapMusic = false;
                try
                {
                    //Try to lower volume
                    for (int i = 0; i < 80; i ++) {
                        FloatControl gainControlA = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
                           gainControlA.setValue(i * -1f);
                        Thread.sleep(10);
                    }
                }
                catch(Exception e){ System.out.print("Lower volume error: " + e + " ");}


                try{
                    clip.stop();
                    clip.close();
                }
                catch (Exception e) { System.out.print("clip.stop/close error: " + e + " ");}
                try
                {
                    clip = AudioSystem.getClip();

                    URL a = this.getClass().getResource("/resource/sound/"+ _Filename + ".mid");

                    ais = AudioSystem.getAudioInputStream(a);

                    clip.open(ais);

                    FloatControl gainControlB = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
                    gainControlB.setValue(-80f);

                    clip.loop(999);
                    clip.start();
                }
                catch(Exception e){ System.out.print("Play error: " + e + " ");}


                try
                {
                    //Try to higher volume
                    for (int i = -80; i < 0; i ++) {
                        FloatControl gainControlC = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN);
                           gainControlC.setValue(i);
                        Thread.sleep(3);
                    }
                }
                catch(Exception e){ 
                System.out.print("Higher volume error: " + e + " ");
                }
            }         
        }
      }
    };

これを明確にするために、MAP Aの音楽を作成しようとしていることを、MAPBの音楽が始まる前に完全にフェードさせます。

これまでのすべての助けに感謝します。

4

3 に答える 3

1

コントロールを使用してMASTER_GAIN、最初のクリップのサウンドを下げ、2番目のクリップのサウンドを上げることができます。dBとタイミングをいじくり回さなければならない場合がありますが、これは機能するはずです。

Clip clipA = AudioSystem.getClip();
Clip clipB = AudioSystem.getClip();
clipA.open(aisA);
clipB.open(aisB);

for (int i = 0; i < 100; i ++) {
   FloatControl gainControlA = (FloatControl) clipA.getControl(FloatControl.Type.MASTER_GAIN);
   gainControlA.setValue(i * -1f);
   FloatControl gainControlB = (FloatControl) clipB.getControl(FloatControl.Type.MASTER_GAIN);
   gainControlB.setValue(-100f + i);

   Thread.sleep(100);
}
于 2012-07-18T17:14:09.070 に答える
1

これは、コメントに収まらない可能性のある有用な情報を追加するほどの答えを意味するものではありません。

はい、-80から6.0はちょっとファンキーです。船外機のミキサーでデシベルを複製することになっていると思います。しかし、耳への傾斜はほとんど直線的ではありません。-20まで下がるまでに正しく思い出せば、音はすでに聞こえない可能性があります。それと、ボリュームの変更でリアルタイムの精度を実現しようとするパフォーマンスの問題との間で、制御ラインの使用をやめ、PCMデータを直接操作し始めました。ただし、この場合はそうすることをお勧めしません。

コントロールの数値範囲をより均等に段階的にするために、ある種の指数関数または三角関数をマップできます。最適なものはわかりませんが、次の2つの関数で有用な結果が得られました。

PCMデータでは、0から1の範囲に正規化された音量で遊んでいます。これまで使用してきた関数の例をいくつか示します。

newValue = 1 - Math.cos(NormalizedPCMValue * PI/2)

newValue = Math.pow(NormalizedPCMValue, 6) 

newValue = Math.pow(2, NormalizedPCMValue)

これらはすべて、直線よりもうまく機能します。私はルックアップテーブルを使用していますが、おそらくその場で値を計算できます。本当にうまく機能するマッピング関数を手に入れたら、ここでそれについて聞いてみたいです。

ちなみに、実際に制御線の値を範囲の一番下まで下げるのは良いことです。静かなときでも突然音が途切れる、または音量の変化で長距離をジャンプすると、カチッという音として現れる不連続性が生じる可能性があります。

于 2012-07-19T18:21:25.410 に答える
0

リューク、次のクリップの再生を開始し、音量を上げながら、残したレベルからクリップをフェードさせてみませんか。

あなたは私を許さなければなりません、私はあなたがどのライブラリを使用しているかについて100%確信していません、しかし確かにクリップオブジェクトは.adjustVolume()メソッドを持っています。

時間の経過とともに音量を調整するには、次のようになります。(疑似コードは気になります)

clip2.adjustVolume(0*time.deltaTime()+5); //Start the clip at volume 0, and increment it each frame, not second.
clip1.adjustVolume(100*time.deltaTime()-5); //Inverse, adjust volume down to fade out.
于 2012-07-18T16:38:05.820 に答える