我正在为班级编写游戏,但无法添加声音和图像。我们从 Andrew Davison 的 Killer Game Programming 一书中获得了可以使用的框架,我觉得我正在完全复制它,但我无法播放声音文件。
这是 SDLLoader 类:
package zombieCity;
/* SDLLoader stores a collection of SDLInfo objects
in a HashMap whose keys are their names.
The name and filename for a line is obtained from a sounds
information file which is loaded when SDLLoader is created.
The information file is assumed to be in Sounds/.
SDLLoader allows a specified clip to be played, stopped,
resumed, looped. A SoundsWatcher can be attached to a clip.
All of this functionality is handled in the SDLInfo object;
SDLLoader simply redirects the method call to the right SDLInfo.
It is possible for many lines to play at the same time, since
each SDLInfo object is responsible for playing its clip.
*/
import java.util.*;
import java.io.*;
import javax.print.DocFlavor.URL;
public class SDLLoader
{
private final static String SOUND_DIR = "Sounds/";
private HashMap<String, SDLInfo> sdlMap;
/* The key is the clip 'name', the object (value)
is a SDLInfo object */
public SDLLoader(String soundsFnm)
{ sdlMap = new HashMap<String, SDLInfo>();
loadSoundsFile(soundsFnm);
}
public SDLLoader()
{ sdlMap = new HashMap<String, SDLInfo>(); }
private void loadSoundsFile(String soundsFnm)
/* The file format are lines of:
<name> <filename> // a single sound file
and blank lines and comment lines.
*/
{
String sndsFNm = SOUND_DIR + soundsFnm;
System.out.println("Reading file: " + sndsFNm);
try {
java.net.URL inFile = this.getClass().getResource("/Sounds/SDLInfo.txt");
System.out.println("url " + inFile);
InputStreamReader in = new InputStreamReader(inFile.openStream());
BufferedReader br = new BufferedReader(in);
StringTokenizer tokens;
String line, name, fnm;
while((line = br.readLine()) != null) {
if (line.length() == 0) // blank line
continue;
if (line.startsWith("//")) // comment
continue;
tokens = new StringTokenizer(line);
if (tokens.countTokens() != 2)
System.out.println("Wrong no. of arguments for " + line);
else {
name = tokens.nextToken();
fnm = tokens.nextToken();
load(name, fnm);
}
}
br.close();
}
catch (IOException e)
{ System.out.println("Error reading file: " + sndsFNm);
System.exit(1);
}
} // end of loadSoundsFile()
// ----------- manipulate a particular clip --------
public void load(String name, String fnm)
// create a SDLInfo object for name and store it
{
if (sdlMap.containsKey(name))
System.out.println( "Error: " + name + "already stored");
else {
sdlMap.put(name, new SDLInfo(name, fnm) );
System.out.println("-- " + name + "/" + fnm);
}
} // end of load()
public void close(String name)
// close the specified clip
{ SDLInfo si = (SDLInfo) sdlMap.get(name);
if (si == null)
System.out.println( "Error: " + name + "not stored");
else
si.close();
} // end of close()
public void play(String name, boolean toLoop)
// play (perhaps loop) the specified clip
{ SDLInfo si = (SDLInfo) sdlMap.get(name);
if (si == null)
System.out.println( "Error: " + name + "not stored");
else
si.beginPlayback(toLoop);
} // end of play()
public void stop(String name)
// stop the clip, resetting it to the beginning
{ SDLInfo si = (SDLInfo) sdlMap.get(name);
if (si == null)
System.out.println( "Error: " + name + "not stored");
else
si.stop();
} // end of stop()
// -------------------------------------------------------
public void setWatcher(String name, SoundsWatcher sw)
/* Set up a watcher for the clip. It will be notified when
the clip loops or stops. */
{ SDLInfo si = (SDLInfo) sdlMap.get(name);
if (si == null)
System.out.println( "Error: " + name + "not stored");
else
si.setWatcher(sw);
} // end of setWatcher()
} // end of ClipsLoader class
堆栈跟踪
fps: 100; period: 10 ms
Reading file: Sounds/SDLInfo.txt
url file:/C:/Documents%20and%20Settings/MyName/Desktop/java%20programs/Zombie%20City/bin/Sounds/SDLInfo.txt
Exception in thread "main" java.lang.NullPointerException
at com.sun.media.sound.StandardMidiFileReader.getSequence(Unknown Source)
at javax.sound.midi.MidiSystem.getSequence(Unknown Source)
at com.sun.media.sound.SoftMidiAudioFileReader.getAudioInputStream(Unknown Source)
at javax.sound.sampled.AudioSystem.getAudioInputStream(Unknown Source)
at zombieCity.SDLInfo.loadLine(SDLInfo.java:35)
at zombieCity.SDLInfo.<init>(SDLInfo.java:27)
at zombieCity.SDLLoader.load(SDLLoader.java:95)
at zombieCity.SDLLoader.loadSoundsFile(SDLLoader.java:73)
at zombieCity.SDLLoader.<init>(SDLLoader.java:38)
at zombieCity.FlyingHero.simpleInitialize(FlyingHero.java:144)
at zombieCity.Frame.<init>(Frame.java:68)
at zombieCity.FlyingHero.<init>(FlyingHero.java:80)
at zombieCity.FlyingHero.main(FlyingHero.java:376)
在此类中捕获了错误:
package zombieCity;
/* Load a line, which can be played, stopped, resumed, looped.
An object implementing the SoundsWatcher interface
can be notified when the line loops or stops.
*/
import java.io.*;
import javax.sound.sampled.*;
public class SDLInfo implements LineListener, Runnable
{
private final static String SOUND_DIR = "Sounds/";
private String name, filename;
private SourceDataLine line = null;
private boolean isLooping = false;
private SoundsWatcher watcher = null;
private Thread soundPlayer;
public SDLInfo(String nm, String fnm)
{ name = nm;
filename = SOUND_DIR + fnm;
loadLine(filename);
} // end of SDLInfo()
private void loadLine(String fnm)
{
try {
// link an audio stream to the sound line's file
AudioInputStream stream = AudioSystem.getAudioInputStream(
getClass().getResource(fnm) );
AudioFormat format = stream.getFormat();
// convert ULAW/ALAW formats to PCM format
if ( (format.getEncoding() == AudioFormat.Encoding.ULAW) ||
(format.getEncoding() == AudioFormat.Encoding.ALAW) ) {
AudioFormat newFormat =
new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
format.getSampleRate(),
format.getSampleSizeInBits()*2,
format.getChannels(),
format.getFrameSize()*2,
format.getFrameRate(), true); // big endian
// update stream and format details
stream = AudioSystem.getAudioInputStream(newFormat, stream);
System.out.println("Converted Audio format: " + newFormat);
format = newFormat;
}
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
// make sure sound system supports data line
if (!AudioSystem.isLineSupported(info)) {
System.out.println("Unsupported Line File: " + fnm);
return;
}
// get clip line resource
line = (SourceDataLine) AudioSystem.getLine(info);
// listen to line for events
line.addLineListener(this);
line.open(format); // open the sound file as a line
stream.close(); // we're done with the input stream
} // end of try block
catch (UnsupportedAudioFileException audioException) {
System.out.println("Unsupported audio file: " + fnm);
}
catch (LineUnavailableException noLineException) {
System.out.println("No audio line available for : " + fnm + " " + noLineException);
}
catch (IOException ioException) {
System.out.println("Could not read: " + fnm);
}
// catch (Exception e) {
// System.out.println("Problem with " + fnm);
// }
} // end of loadLine()
public void update(LineEvent lineEvent){}
// update() not used
public void close()
{ if (line != null) {
line.stop();
line.close();
}
}
public void beginPlayback(boolean toLoop)
{
if (line != null){
isLooping = toLoop;
if (soundPlayer == null) {
soundPlayer = new Thread(this);
soundPlayer.start();
}
}
}
public void play()
{
try{
if (line != null) {
int numRead = 0;
byte[] buffer = new byte[line.getBufferSize()];
AudioInputStream stream = AudioSystem.getAudioInputStream(getClass().getResource(filename) );
line.start();
// read and play chunks of the audio
int offset;
while ((numRead = stream.read(buffer,0,buffer.length)) >= 0) {
offset = 0;
while (offset < numRead)
offset += line.write(buffer, offset, numRead-offset);
}
// wait until all data is played, then stop the line
stream.close();
line.drain();
line.stop();
}
}
catch (IOException ioException) {
System.out.println("Could not read: " + filename);
}
catch (UnsupportedAudioFileException audioException) {
System.out.println("Unsupported audio file: " + filename);
}
} //end of play()
public void run()
{
do{ play();}while(isLooping);
}
public void stop()
// stop and reset line to its start
{ if (line != null) {
isLooping = false;
line.drain();
line.stop();
}
}
public void setWatcher(SoundsWatcher sw)
{ watcher = sw; }
// -------------- other access methods -------------------
public String getName()
{ return name; }
} // end of ClipInfo class