我已经开始用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 B的音乐开始之前,为了清楚说明我试图让MAP A音乐完全消失。
到目前为止,感谢您的帮助。
答案 0 :(得分:1)
您可以使用MASTER_GAIN
控件降低第一个剪辑的声音,同时提升第二个声音的声音,您可能需要使用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);
}
答案 1 :(得分:1)
这并不是一个答案,而是要添加一些不太适合评论的可能有用的信息。
是的,-80到6.0有点时髦。我认为应该在外置调音台上复制分贝。但是耳朵的斜率几乎不是线性的。如果我记得正确到达-20时,声音可能已经听不见了。在此之间以及尝试在音量变化中实时精确的性能问题之后,我放弃了控制线的使用并开始直接使用PCM数据。但是我并不建议你在这种情况下这样做。
为了使控件的数字范围更加均匀渐变,您可以映射某种指数或触发函数。我不知道最合适的,但我已经通过以下两个函数获得了有用的结果。
对于PCM数据,我一直在使用标准化为0到1范围的音量。以下是我一直在使用的一些功能示例。
newValue = 1 - Math.cos(NormalizedPCMValue * PI/2)
newValue = Math.pow(NormalizedPCMValue, 6)
newValue = Math.pow(2, NormalizedPCMValue)
这些对我来说比直线性更好。我使用查找表,但您可以动态计算值。如果你得到一个非常好用的映射函数,我很乐意在这里听到它。
顺便说一句,最好将控制线值降低到范围的底部。突然切断声音,即使它很安静,或者在音量变化时跳跃很远的距离也会导致声音点击的不连续性。
答案 2 :(得分:0)
Ryuk,你为什么不从你离开的水平淡出剪辑,同时开始播放下一个剪辑,调高音量。
你必须原谅我,我不是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.