2016-03-02 48 views
2

我有一個行軍的聲音文件,我一旦發生特定事件時播放,但問題歸結爲讓文件在指定的時間內淡出,然後在音量達到0時停止。此項目用於桌面。Libgdx如何讓SFX淡出?

Sound marching = Gdx.audio.newSound(Gdx.files.internal("sounds/test.wav")); 

我在這第一次嘗試通過定時調度任務:

final long mId = marching.play(1f, 1f, 0); 
for (float i = 1; i > 0; i -= 0.01) { 
    Timer.schedule(new Task() { 
      @Override 
      public void run() { 
       marching.setVolume(mId, i); 
      } 
    }, 0.3f); 
} 
marching.stop(); 

然而這似乎是踏着#setVolume

,我決定採取之前調用行軍#停止另一個應用:

float volume = 1; 
final long mId = marching.play(volume, 1f, 0), startTime = TimeUtils      .millis(); 
while (volume > 0) { 
    if (TimeUtils.millis() - startTime % 300 == 0) marching.setVolume(mId, volume -= 0.1); 
} 
marching.stop(); 

我認爲這會減少體積梅根據分配的時間量,但它只是使程序凍結。

是否有一種簡單的方式來衰減SFX音頻或設置頻繁睡眠的方式,以便可以反覆降低音量?

謝謝。

回答

1

我認爲最簡單的方法就是把這個在render方法:

float FACTOR = 10; // The bigger the factor, the faster the fade-out will be 
float mVolume = 1; 
boolean mIsPlaying = true; 

public void render(float delta) { 
    // ... 
    if (mIsPlaying) { 
     mVolume -= delta * FACTOR; 
     if (mVolume > 0) { 
      marching.setVolume(mId, mVolume); 
     } 
     else { 
      marching.stop(mId); 
      mIsPlaying = false; 
     } 
    } 
    // ... 
} 
1

首先解決方法是錯誤的,我改寫爲你:

final long mId = marching.play(1f, 1f, 0); 

    Timer.schedule(new Task() { 
      @Override 
      public void run() { 
       for (float i = 1; i > 0; i -= 0.01) 
       { 
         marching.setVolume(mId, i); 
         if(i<=0) 
         marching.stop(); 
       } 
      } 
    }, 0.3f); 

二液凍結您的應用程序,因爲你在主線程中調用它,而不是在異步任務中!

但是使用渲染任務不是一個好主意。您應該從遊戲循環任務中分離渲染任務。閱讀:http://gameprogrammingpatterns.com/game-loop.html。你的遊戲的邏輯應該在所有機器上以相同的速度運行。不能通過渲染問題/緩慢問題來限制。

+0

我試着實現你的解決方案,但似乎它在調用run()內部的內容之前等待整個延遲。這導致它在播放聲音之前持續了0.3秒,然後突然結束。 –

+0

「,它在調用run()的內部之前等待整個延遲」這是正確的。嘗試將步驟因子更改爲0.001。 –

+0

如果延遲爲0.001,那麼這不會破壞run()方法的整個目的嗎? –

1

我覺得這個效果比使用循環好得多。

我將MUSIC_FADE_STEP設置爲0.01f(即每次調整音量1%)。

根據需要調整fadeRate(以秒爲單位)。 0.01f可以作爲一個出發點。

Timer.schedule(new Timer.Task() { 
    @Override 
    public void run() { 
     if (music.getVolume() >= MUSIC_FADE_STEP) 
      music.setVolume(music.getVolume()-MUSIC_FADE_STEP); 
     else { 
      music.stop(); 
      this.cancel(); 
     } 
    } 
}, 0f, fadeRate);