diff --git a/src/de/teamteamteam/spacescooter/screen/GameScreen.java b/src/de/teamteamteam/spacescooter/screen/GameScreen.java index 9bfb091..c5050db 100644 --- a/src/de/teamteamteam/spacescooter/screen/GameScreen.java +++ b/src/de/teamteamteam/spacescooter/screen/GameScreen.java @@ -10,6 +10,7 @@ import de.teamteamteam.spacescooter.gui.InterfaceBar; import de.teamteamteam.spacescooter.gui.ScoreBar; import de.teamteamteam.spacescooter.gui.ShieldBar; import de.teamteamteam.spacescooter.level.Level; +import de.teamteamteam.spacescooter.sound.SoundSystem; import de.teamteamteam.spacescooter.utility.CollisionHandler; /** @@ -32,6 +33,11 @@ public class GameScreen extends Screen { */ private long gameClockTrigger; + /** + * Internal Thread handle for the background music. + */ + private Thread backgroundMusic; + /** * GameScreen Constructor. * Takes the level as its second parameter. @@ -48,6 +54,8 @@ public class GameScreen extends Screen { new HealthBar(10, 5); new ShieldBar(10, 27); new ScoreBar(575, 33); + + this.backgroundMusic = SoundSystem.playSound("music/ScooterFriendsTurbo8Bit.wav"); } @@ -93,6 +101,17 @@ public class GameScreen extends Screen { } } + /** + * Cleanup method for the background music. + */ + @Override + public void cleanup() { + System.out.println("Interrupting Music"); + this.backgroundMusic.interrupt(); + super.cleanup(); + } + + public static Player getPlayer() { return GameScreen.player; } diff --git a/src/de/teamteamteam/spacescooter/screen/MainMenuScreen.java b/src/de/teamteamteam/spacescooter/screen/MainMenuScreen.java index 08c0ea3..587d46c 100644 --- a/src/de/teamteamteam/spacescooter/screen/MainMenuScreen.java +++ b/src/de/teamteamteam/spacescooter/screen/MainMenuScreen.java @@ -10,7 +10,6 @@ import de.teamteamteam.spacescooter.brain.GameConfig; import de.teamteamteam.spacescooter.control.Keyboard; import de.teamteamteam.spacescooter.entity.Player; import de.teamteamteam.spacescooter.gui.Button; -import de.teamteamteam.spacescooter.sound.SoundSystem; /** * This Screen show the games main menu. @@ -36,7 +35,6 @@ public class MainMenuScreen extends Screen { player = new Player(GameConfig.windowWidth/2-170, 209); player.setCanMove(false); player.setCanShoot(false); - SoundSystem.playSound("music/ScooterFriendsTurbo8Bit.wav"); } @Override diff --git a/src/de/teamteamteam/spacescooter/screen/Screen.java b/src/de/teamteamteam/spacescooter/screen/Screen.java index 8cf54ad..09fb977 100644 --- a/src/de/teamteamteam/spacescooter/screen/Screen.java +++ b/src/de/teamteamteam/spacescooter/screen/Screen.java @@ -262,7 +262,7 @@ public abstract class Screen { * When a Screens life ends, this method will take care of existing overlays * and remove all references to existing entities. */ - private void cleanup() { + protected void cleanup() { if(this.overlay != null) { this.overlay.cleanup(); } diff --git a/src/de/teamteamteam/spacescooter/sound/SoundSystem.java b/src/de/teamteamteam/spacescooter/sound/SoundSystem.java index d5b9093..e09c08c 100644 --- a/src/de/teamteamteam/spacescooter/sound/SoundSystem.java +++ b/src/de/teamteamteam/spacescooter/sound/SoundSystem.java @@ -97,35 +97,56 @@ public class SoundSystem { * Create a SourceDataLine and play the BufferedInputStream into it. * Uses the internal audioPlayerRunnable since this operation is blocking. */ - public static void playFromAudioInputStream(URL soundURL) { + public static Thread playFromAudioInputStream(URL soundURL) { final URL fSoundURL = soundURL; Thread soundThread = new Thread(new Runnable() { public void run() { + AudioInputStream sound = null; + SourceDataLine sourceDataLine = null; try { - AudioInputStream sound = SoundSystem.getAudioInputStreamByURL(fSoundURL); + sound = SoundSystem.getAudioInputStreamByURL(fSoundURL); sound.reset(); - SourceDataLine sourceDataLine = AudioSystem.getSourceDataLine(sound.getFormat()); + sourceDataLine = AudioSystem.getSourceDataLine(sound.getFormat()); sourceDataLine.open(sound.getFormat()); sourceDataLine.start(); sound.reset(); - int chunksize = 16384*4; - byte[] b = new byte[chunksize]; - while (sound.available() > 0) { - sound.read(b, 0, chunksize); - sourceDataLine.write(b, 0, chunksize); + int maxChunkSize = 4*4096; + byte[] b = new byte[maxChunkSize]; + int soundCapacity; + while ((soundCapacity = sound.available()) > 0) { + if(Thread.interrupted()) throw new InterruptedException(); + //Make sure we're only writing that many bytes, so we do NOT cause blocking! + //Otherwise, we are unable to interrupt this Thread properly and stop long sounds from playing! + int writeCapacity = sourceDataLine.available(); + if(writeCapacity > soundCapacity) writeCapacity = soundCapacity; + if(writeCapacity > maxChunkSize) writeCapacity = maxChunkSize; + sound.read(b, 0, writeCapacity); + sourceDataLine.write(b, 0, writeCapacity); } sourceDataLine.drain(); - sourceDataLine.close(); - sound.close(); } catch (javax.sound.sampled.LineUnavailableException lue) { System.err.println("Could not play sound: " + fSoundURL); + } catch (InterruptedException ie) { + //Nothing to do here, just falling into finally block, so we can + //close the sourceDataLine without draining it. } catch (Exception e) { e.printStackTrace(); + } finally { + //Clean everything up properly. + if(sourceDataLine != null) sourceDataLine.close(); + if(sound != null) { + try { + sound.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } } } }); soundThread.setName("Sound: " + soundURL.toString()); soundThread.start(); + return soundThread; } /** @@ -151,10 +172,9 @@ public class SoundSystem { /** * Play a sound by passing a relative path to this method. - * TODO: Provide a method to stop existing sounds (aka BackgroundMusic!) */ - public static void playSound(String filename) { - SoundSystem.playFromAudioInputStream(Loader.getSoundURLByFilename(filename)); + public static Thread playSound(String filename) { + return SoundSystem.playFromAudioInputStream(Loader.getSoundURLByFilename(filename)); } /**