I'm making a game, and upon exporting the game to a .jar file, I stumbled upon a problem: I can't make the sound play.
I have made lot of research about this, and I'm starting to think this is some problem with JAVA. I also realized that I'm not the only one with this problem, but there was no answer provided to those people that could help me.
I studied the difference between getClass() and getClassLoader(), and tryed both cases, but still nothing. But The problem is not about loading the resources anyway, it is about the sound not playing, even though it loads.
The game plays nicely, loading all the sprites, but nothing of sound.
During my research about this, I learned the I could execute the game using "java -jar file.jar" on command, and the sound started to work. However this doesn't sound like a good option for me, since I have the intention of distributing the game.
Here is a test I made, that shows exactly what I'm talking about. You can add any image and sound, and test it by your selves.
package testando;
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
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.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class Testando extends JFrame {
private final LineListener myLineListener;
public Testando() {
super();
setLayout( new BorderLayout() );
setBounds( 200, 200, 500, 500 );
myLineListener = new MyLineListener();
MultiSound multiSoundPanel = new MultiSound();
addWindowListener( new WindowAdapter() {
@Override public void windowClosing( WindowEvent e ) {
System.exit( 0 );
}
});
add( multiSoundPanel );
}
private class MultiSound extends JPanel {
final BufferedImage desertImage;
MultiSound(){
super( null, true );
final AudioInfo audioInfos = new AudioInfo( "testando/Iron_Click.wav" );
addMouseListener( new MouseListener() {
final AudioInfo audioInfo = audioInfos;
@Override
public void mousePressed( MouseEvent e ) {
Sound sound = new Sound( audioInfo );
new Thread(sound).start();
}
@Override public void mouseClicked( MouseEvent e ) {}
@Override public void mouseReleased( MouseEvent e ) {}
@Override public void mouseEntered( MouseEvent e ) {}
@Override public void mouseExited( MouseEvent e ) {}
});
java.net.URL streamURL = Thread.currentThread().getContextClassLoader().getResource( "testando/Desert.jpg" );
BufferedImage desertImagebuff = null;
try {
desertImagebuff = ImageIO.read( streamURL );
}
catch ( IOException ex ) {
StringBuilder sb = new StringBuilder(ex.toString());
for (StackTraceElement ste : ex.getStackTrace()) {
sb.append("\n\tat ");
sb.append(ste);
}
String trace = sb.toString();
JOptionPane.showMessageDialog( null, trace, "ERROR", JOptionPane.INFORMATION_MESSAGE);
System.exit( -1 );
}
desertImage = desertImagebuff;
}
@Override
protected void paintComponent( Graphics g ) {
super.paintComponent( g ); //To change body of generated methods, choose Tools | Templates.
Graphics2D g2 = (Graphics2D)g.create();
Rectangle rect = getVisibleRect();
double desSx = ((rect.width*1.0d)/desertImage.getWidth());
double desSy = ((rect.height*1.0d)/desertImage.getHeight());
//To keep the image scalled to the panel;
AffineTransform scale = AffineTransform.getScaleInstance( desSx, desSy );
AffineTransformOp transformer = new AffineTransformOp( scale, null );
g2.drawImage( desertImage, transformer , rect.x, rect.y );
g2.dispose();
}
}
private class AudioInfo {
final AudioFormat audioFormat;
final int size;
final byte[] audio;
final DataLine.Info info;
AudioInfo( String path ){
java.net.URL streamURL = Thread.currentThread().getContextClassLoader().getResource( path );
AudioFormat toAudioFormat = null;
int toSize = -1;
byte[] toByte = null;
DataLine.Info toInfo = null;
try {
InputStream stream = new BufferedInputStream( streamURL.openStream() );
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream( stream );
toAudioFormat = audioInputStream.getFormat();
toSize = (int) ( toAudioFormat.getFrameSize() * audioInputStream.getFrameLength() );
toByte = new byte[toSize];
toInfo = new DataLine.Info(Clip.class, toAudioFormat, toSize);
audioInputStream.read(toByte, 0, toSize);
}
catch ( UnsupportedAudioFileException | IOException ex ) {
StringBuilder sb = new StringBuilder(ex.toString());
for (StackTraceElement ste : ex.getStackTrace()) {
sb.append("\n\tat ");
sb.append(ste);
}
String trace = sb.toString();
JOptionPane.showMessageDialog( null, trace, "ERROR", JOptionPane.INFORMATION_MESSAGE);
System.exit( -1 );
}
audioFormat = toAudioFormat;
size = toSize;
audio = toByte;
info = toInfo;
}
}
private class MyLineListener implements LineListener {
@Override
public void update( LineEvent event ) {
if ( event.getType( ) == LineEvent.Type.STOP )
event.getLine().close();
}
}
private class Sound implements Runnable {
private final Clip sound;
Sound( AudioInfo audioInfo ){
AudioFormat audioFormat = audioInfo.audioFormat;
int size = audioInfo.size;
byte[] audio = audioInfo.audio;
DataLine.Info info = audioInfo.info;
Clip clip = null;
try {
clip = (Clip) AudioSystem.getLine( info );
clip.open( audioFormat, audio, 0, size );
clip.addLineListener( myLineListener );
}
catch ( LineUnavailableException ex ) {
clip = null;
}
sound = clip;
}
@Override
public void run() {
sound.start();
}
}
public static void main( String[] args ) {
Testando testando = new Testando();
testando.setVisible( true );
}
}
I also compiled the executable version with the source code with it if you wish to analize it better. https://www.dropbox.com/s/328dr47i39vbart/testando_dist.zip
I don't know if it is usefull, but I'm using NetBeans 7.4.
Can somebody help me please?
Thank you in advance, saclyr.