開発中のゲームで 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 内に留まりたいと考えています。
誰かが私がやりたいことをする方法を考えることができますか?