我正在写一个视频游戏,我想在玩家输掉或退出时停止音乐(到主菜单)。
这是我的代码:
public class Music{
private static Clip clip;
private static AudioInputStream stream;
private static void loadMusic(){
if(clip != null) return;
try {
AudioFormat format;
DataLine.Info info;
stream = AudioSystem.getAudioInputStream(Music.class.getResource("/resources/music/music.wav"));
format = stream.getFormat();
info = new DataLine.Info(Clip.class, format);
clip = (Clip) AudioSystem.getLine(info);
clip.open(stream);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void playMusic(boolean loop){
loadMusic();
if(clip == null) return;
if(loop) clip.loop(Clip.LOOP_CONTINUOUSLY);
else clip.start();
}
public static void stopMusic(){
clip.stop();
clip.setMicrosecondPosition(0);
}
}
每当我调用Music.stopMusic()时,游戏会挂起几秒钟然后继续。
答案 0 :(得分:2)
从我收集的描述中,您按下GUI上的停止按钮,然后调用Music.stopMusic()
。结果是音频片段停止播放,但您仍然在GUI响应之前等待3秒钟。
这是因为您在Music.stopMusic()
中进行的调用会对I / O资源进行本机调用,而这不应在EDT中调用。您应该查看运行工作线程来执行此操作:
Thread t = new Thread(new Runnable() {
public void run() {
Music.stop();
}
});
t.start();
或者期待使用SwingWorker。
有趣的是,虽然我不确定返回Clip
的哪个实现,但是快速查看MixerClip
会显示对本机库的调用,然后可能是您的困境中的冒烟 - a 3秒等待回电!
// stop the sample. this invalidates the sample voice id.
nStop(id);
// wait for the callback
synchronized(lock) {
if (id!=0) {
try {
//long time=System.currentTimeMillis();
lock.wait(3000);
//if (System.currentTimeMillis()-time > 2500) {
//System.out.println(" WAITING TIMED OUT!"); System.out.flush();
//id=0;
//}
} catch (InterruptedException e) { }
}
}