我在开发的游戏中使用 Java 的 Clip 类时遇到问题。具体来说,我认为问题在于同时多次使用同一个剪辑。我做了一些谷歌搜索,有些人建议在自己的线程中运行该剪辑。我想复制剪辑对象,以便它在每个线程中使用不同的剪辑对象,以避免需要“重置”剪辑,但我仍然遇到问题。事实上,问题在于,当同一个剪辑同时播放多次时,游戏似乎会卡住。
Reddit 上有人建议这个问题可能是因为 Clip 类不是同步的,我每次想使用它时都必须打开它。显然,这是行不通的,因为声音的使用非常频繁。
如果有人能够指出该类的致命缺陷,代码如下:
/**
This file is part of Generic Zombie Shooter.
Generic Zombie Shooter is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Generic Zombie Shooter is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Generic Zombie Shooter. If not, see <http://www.gnu.org/licenses/>.
**/
package genericzombieshooter.misc;
import java.io.IOException;
import java.net.URL;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
/**
* Contains all pre-loaded sounds.
* @author Darin Beaudreau
*/
public enum Sounds {
// Weapon-Related
POPGUN("shoot2.wav", false),
RTPS("shoot1.wav", false),
BOOMSTICK("shotgun1.wav", false),
FLAMETHROWER("flamethrower.wav", true),
THROW("throw2.wav", false),
EXPLOSION("explosion2.wav", false),
LANDMINE_ARMED("landmine_armed.wav", false),
TELEPORT("teleport.wav", false),
// Zombie-Related
MOAN1("zombie_moan_01.wav", false),
MOAN2("zombie_moan_02.wav", false),
MOAN3("zombie_moan_03.wav", false),
MOAN4("zombie_moan_04.wav", false),
MOAN5("zombie_moan_05.wav", false),
MOAN6("zombie_moan_06.wav", false),
MOAN7("zombie_moan_07.wav", false),
MOAN8("zombie_moan_08.wav", false),
POISONCLOUD("poison_cloud.wav", false),
// Game Sounds
POWERUP("powerup.wav", false),
PURCHASEWEAPON("purchase_weapon.wav", false),
BUYAMMO("buy_ammo2.wav", false),
PAUSE("pause.wav", false),
UNPAUSE("unpause.wav", false);
private Clip clip;
private boolean looped;
Sounds(String filename, boolean loop) {
openClip(filename, loop);
}
private synchronized void openClip(String filename, boolean loop) {
try {
URL audioFile = Sounds.class.getResource("/resources/sounds/" + filename);
AudioInputStream audio = AudioSystem.getAudioInputStream(audioFile);
AudioFormat format = audio.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
clip = (Clip) AudioSystem.getLine(info);
clip.open(audio);
} catch (UnsupportedAudioFileException uae) {
System.out.println(uae);
} catch (IOException ioe) {
System.out.println(ioe);
} catch (LineUnavailableException lue) {
System.out.println(lue);
}
looped = loop;
}
public synchronized void play() {
play(1.0);
}
public synchronized void play(final double gain) {
Runnable soundPlay = new Runnable() {
@Override
public void run() {
Clip clipCopy = (Clip)clip;
FloatControl gainControl = (FloatControl)clipCopy.getControl(FloatControl.Type.MASTER_GAIN);
float dB = (float)(Math.log(gain) / Math.log(10.0) * 20.0);
gainControl.setValue(dB);
if(!looped) reset(clipCopy);
clipCopy.loop((looped)?Clip.LOOP_CONTINUOUSLY:0);
}
};
new Thread(soundPlay).start();
}
public synchronized void reset() {
reset(clip);
}
public synchronized void reset(Clip clipCopy) {
synchronized(clipCopy) { clipCopy.stop(); }
clipCopy.setFramePosition(0);
}
public static void init() {
values();
}
}
那么我尝试使用枚举和静态 play() 方法做的事情是否可以实现我想要完成的目标?或者我必须寻找其他方法吗?我可以使用不同的类,甚至在必要时使用库,但我宁愿留在核心 Java 中。
有人能想出一种方法来完成我想做的事情吗?
最佳答案
剪辑不支持并发。您可以随时重新启动剪辑并多次播放。但在任何给定时间,同一时间只能播放一个给定剪辑的一个实例。
TinySound 是一个很好的库,但我不记得他的 Clips 是否允许并发播放。您可以在全力以赴之前检查一下。Java-gaming.org 上有关于这个库的大量帖子。
我不了解 Net Beans,但要在 Eclipse 中使用 Git Hub 源,我按照 Git Hub 提供的有关如何设置帐户和进行克隆的说明进行操作,然后将克隆下载到我的 table 面上(使用 Bash)。这些说明并不简单,但这是该产品 (GitHub) 的一个非常基本的使用,您应该能够在其中找到支持。
项目位于桌面上后,我会在 Eclipse 中创建一个新项目,并将提供的桌面克隆的根目录作为位置。 Eclipse 有用于将外部库链接到项目的附加设置。如果 Net Beans 没有类似的东西,我会感到非常惊讶。
Eclipse 还可以从 zip 文件创建项目或链接库。 Zip 与 Jar 文件的格式完全相同。 Net Beans 应该有一种方法来链接到项目的 zip 或 jar。在 Eclipse 中,他们使用术语“归档”来表示存储在 zip 中的项目。但我不知道您拥有的 zip 是否正是作为外部项目加载所需的一切。我对 GitHub 的使用经验很少。
如果您想重复使用枪声或其他任何内容,您可能必须为您希望支持的每个并发副本制作一个剪辑。
我最终编写了自己的剪辑对象,并向其中提供了多个游标,以及一个用于混合来自并发游标的数据的接口(interface)。效果非常好!我愿意向您发送一份副本来试用。它被设置为使用连续运行的音频混合器(我认为与 TinySound 相同)。但如果我向您发送代码,您也许可以重写 Clip 部分以使其独立。 “PFClip”还允许以不同的速度进行平移、音量设置和播放,因此您可以改变枪声的速度。这样做,听起来像是不同的枪(或者如果你让它们非常慢的话会爆炸)。[在这里插入双关语,以获得最大的性价比。]
该库有一些很酷的附加功能:用于循环剪辑的 PFLoop(允许以平滑的方式重叠末端),我刚刚制作了镶边、立体声合唱和音高可变回声。与 TinySound 不同,除了 44100fps 和 16 位的立体声 wav 格式外,我不支持任何其他格式。我为我正在开发的游戏编写了此内容,可通过浏览器玩:http://hexara.com/game.html风铃效果是使用并发剪辑的效果。
忘记了!我之前有另一个混音器演示,它同时以多种方式使用一次枪声: enter link description here JGO 中列出的代码已经过时,但线程下方有一页包含可用于制作您自己的并发剪辑的基本思想。
第二个链接网站上提供了联系信息。
关于java - 使用 Java 的 Clip 类的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19168231/