Libgdx如何让SFX淡出?

时间:2016-03-02 10:13:53

标签: java audio time libgdx volume

我有一个行进的声音文件,我会在特定事件发生时播放,但问题归结为文件在指定的时间内淡出,然后在音量达到0时停止。此项目适用于桌面。

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

我第一次尝试通过Timer安排任务:

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

之前调用行军#stop

我决定采取另一个计划:

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音频淡出或者设置频繁睡眠的某种方式,以便我可以迭代地降低音量?

感谢。

3 个答案:

答案 0 :(得分: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 :(得分: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。您的游戏逻辑应该在所有机器中以相同的速度运行。不能受渲染问题/慢问题的限制。

答案 2 :(得分: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);