我有一个行进的声音文件,我会在特定事件发生时播放,但问题归结为文件在指定的时间内淡出,然后在音量达到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音频淡出或者设置频繁睡眠的某种方式,以便我可以迭代地降低音量?
感谢。
答案 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);