diff --git a/Projekte/battleship/client/src/main/java/pp/battleship/client/BackgroundMusic.java b/Projekte/battleship/client/src/main/java/pp/battleship/client/BackgroundMusic.java index 972b6c2c..607669c5 100644 --- a/Projekte/battleship/client/src/main/java/pp/battleship/client/BackgroundMusic.java +++ b/Projekte/battleship/client/src/main/java/pp/battleship/client/BackgroundMusic.java @@ -4,19 +4,37 @@ import com.jme3.audio.AudioData.DataType; import com.jme3.audio.AudioNode; import com.jme3.audio.AudioSource.Status; +import pp.battleship.notification.Music; +import pp.battleship.notification.MusicEvent; +import pp.battleship.notification.GameEventListener; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; import java.util.prefs.Preferences; -public class BackgroundMusic { +public class BackgroundMusic implements GameEventListener { private static final String VOLUME_PREF = "volume"; private static final String MUSIC_ENABLED_PREF = "musicEnabled"; private Preferences prefs = Preferences.userNodeForPackage(BackgroundMusic.class); + static final Logger LOGGER = System.getLogger(BackgroundMusic.class.getName()); + + private static final String MENU_MUSIC = "Music/MainMenu/Dark_Intro.ogg"; + private static final String BATTLE_MUSIC = "Music/BattleTheme/boss_battle_#2_metal_loop.wav"; + private static final String GAME_OVER_MUSIC_L = "Music/GameOver/Lose.ogg"; + private static final String GAME_OVER_MUSIC_V = "Music/GameOver/Victory.wav"; + + private final AudioNode menuMusic; + private final AudioNode battleMusic; + private final AudioNode gameOverMusicL; + private final AudioNode gameOverMusicV; + private String lastNodePlayed; - private final AudioNode backgroundMusic; private boolean musicEnabled; private float volume; + private Application app; + /** * Initializes and controls the BackgroundMusic * @@ -26,32 +44,64 @@ public class BackgroundMusic { public BackgroundMusic(Application app, String musicFilePath) { this.volume = prefs.getFloat(VOLUME_PREF, 1.0f); this.musicEnabled = prefs.getBoolean(MUSIC_ENABLED_PREF, true); + this.app = app; - backgroundMusic = new AudioNode(app.getAssetManager(), musicFilePath, DataType.Stream); - backgroundMusic.setLooping(true); - backgroundMusic.setPositional(false); - backgroundMusic.setVolume(volume); + menuMusic = createAudioNode(MENU_MUSIC); + battleMusic = createAudioNode(BATTLE_MUSIC); + gameOverMusicL = createAudioNode(GAME_OVER_MUSIC_L); + gameOverMusicV = createAudioNode(GAME_OVER_MUSIC_V); + stop(battleMusic); + stop(gameOverMusicL); + stop(gameOverMusicV); + + lastNodePlayed = menuMusic.getName(); if(musicEnabled) { - play(); + play(menuMusic); } } /** - * Plays the music if the music is Stopped or paused + * This method will be used to create the audio node containing the music + * + * @param musicFilePath the file path to the music + * @return the created audio node */ - public void play() { - if (musicEnabled && (backgroundMusic.getStatus() == Status.Stopped || backgroundMusic.getStatus() == Status.Paused)) { - backgroundMusic.play(); + private AudioNode createAudioNode(String musicFilePath) { + AudioNode audioNode = new AudioNode(app.getAssetManager(), musicFilePath, DataType.Stream); + audioNode.setVolume(volume); + audioNode.setPositional(false); + audioNode.setLooping(true); + audioNode.setName(musicFilePath); + return audioNode; + } + + /** + * sets the give audio node to play + * + * @param audioNode the audio node which should start to play + */ + public void play(AudioNode audioNode) { + if (musicEnabled && (audioNode.getStatus() == Status.Stopped || audioNode.getStatus() == Status.Paused)) { + audioNode.play(); + lastNodePlayed = audioNode.getName(); } } /** - * Stops the music if it is playing + * stops the given audio node from playing + * + * @param audioNode the audio node to be stopped */ - public void stop(){ - if (backgroundMusic.getStatus() == Status.Playing) { - backgroundMusic.stop(); + public void stop(AudioNode audioNode) { + if (audioNode.getStatus() == Status.Playing) { + audioNode.stop(); + } + } + + public void pause(AudioNode audioNode) { + if (audioNode.getStatus() == Status.Playing) { + audioNode.pause(); } } @@ -61,12 +111,27 @@ public void stop(){ public void toogleMusic() { this.musicEnabled = !this.musicEnabled; if (musicEnabled) { - play(); + switch (lastNodePlayed){ + case MENU_MUSIC: + play(menuMusic); + break; + case BATTLE_MUSIC: + play(battleMusic); + break; + case GAME_OVER_MUSIC_L: + play(gameOverMusicL); + break; + case GAME_OVER_MUSIC_V: + play(gameOverMusicV); + break; + } } else { - stop(); + pause(menuMusic); + pause(battleMusic); + pause(gameOverMusicL); } - prefs.putBoolean(VOLUME_PREF, musicEnabled); + prefs.putBoolean(MUSIC_ENABLED_PREF, musicEnabled); } /** @@ -76,7 +141,9 @@ public void toogleMusic() { */ public void setVolume(float volume) { this.volume = volume; - backgroundMusic.setVolume(volume); + menuMusic.setVolume(volume); + battleMusic.setVolume(volume); + gameOverMusicL.setVolume(volume); prefs.putFloat(VOLUME_PREF, volume); } @@ -98,4 +165,65 @@ public float getVolume() { public boolean isMusicEnabled() { return musicEnabled; } + + /** + * changes the music to the specified music if it isn't already playing + * + * @param music the music to play + */ + public void changeMusic(Music music) { + if(music == Music.MENU_THEME && !lastNodePlayed.equals(MENU_MUSIC)) { + LOGGER.log(Level.DEBUG, "Received Music change Event {0}", music.toString()); + stop(battleMusic); + stop(gameOverMusicL); + stop(gameOverMusicV); + play(menuMusic); + lastNodePlayed = menuMusic.getName(); + } else if (music == Music.BATTLE_THEME && !lastNodePlayed.equals(BATTLE_MUSIC)) { + LOGGER.log(Level.DEBUG, "Received Music change Event {0}", music.toString()); + stop(menuMusic); + stop(gameOverMusicL); + stop(gameOverMusicV); + play(battleMusic); + lastNodePlayed = battleMusic.getName(); + } else if (music == Music.GAME_OVER_THEME_L && !lastNodePlayed.equals(GAME_OVER_MUSIC_L)) { + LOGGER.log(Level.DEBUG, "Received Music change Event {0}", music.toString()); + stop(menuMusic); + stop(battleMusic); + stop(gameOverMusicV); + play(gameOverMusicL); + lastNodePlayed = gameOverMusicL.getName(); + } else if (music == Music.GAME_OVER_THEME_V && !lastNodePlayed.equals(GAME_OVER_MUSIC_V)){ + LOGGER.log(Level.DEBUG, "Received Music change Event {0}", music.toString()); + stop(menuMusic); + stop(battleMusic); + stop(gameOverMusicL); + play(gameOverMusicV); + lastNodePlayed = gameOverMusicV.getName(); + } + } + + /** + * the method which receives the Event + * + * @param music the received Event + */ + @Override + public void receivedEvent (MusicEvent music){ + LOGGER.log(Level.DEBUG, "Received Music change Event {0}", music.toString()); + switch (music.music()){ + case MENU_THEME: + changeMusic(Music.MENU_THEME); + break; + case BATTLE_THEME: + changeMusic(Music.BATTLE_THEME); + break; + case GAME_OVER_THEME_L: + changeMusic(Music.GAME_OVER_THEME_L); + break; + case GAME_OVER_THEME_V: + changeMusic(Music.GAME_OVER_THEME_V); + break; + } + } } diff --git a/Projekte/battleship/client/src/main/java/pp/battleship/client/BattleshipApp.java b/Projekte/battleship/client/src/main/java/pp/battleship/client/BattleshipApp.java index 471ac20e..e0fb146c 100644 --- a/Projekte/battleship/client/src/main/java/pp/battleship/client/BattleshipApp.java +++ b/Projekte/battleship/client/src/main/java/pp/battleship/client/BattleshipApp.java @@ -440,6 +440,7 @@ void errorDialog(String errorMessage) { * @return BackgroundMusic */ public BackgroundMusic getBackgroundMusic(){ + logic.addListener(backgroundMusic); return backgroundMusic; } } diff --git a/Projekte/battleship/client/src/main/java/pp/battleship/client/GameSound.java b/Projekte/battleship/client/src/main/java/pp/battleship/client/GameSound.java index 0fdcef68..253e0d73 100644 --- a/Projekte/battleship/client/src/main/java/pp/battleship/client/GameSound.java +++ b/Projekte/battleship/client/src/main/java/pp/battleship/client/GameSound.java @@ -27,7 +27,7 @@ * An application state that plays sounds. */ public class GameSound extends AbstractAppState implements GameEventListener { - private static final Logger LOGGER = System.getLogger(GameSound.class.getName()); + static final Logger LOGGER = System.getLogger(GameSound.class.getName()); private static final Preferences PREFERENCES = getPreferences(GameSound.class); private static final String ENABLED_PREF = "enabled"; //NON-NLS diff --git a/Projekte/battleship/client/src/main/resources/Music/GameOver/Lose.ogg b/Projekte/battleship/client/src/main/resources/Music/GameOver/Lose.ogg new file mode 100644 index 00000000..a646117e Binary files /dev/null and b/Projekte/battleship/client/src/main/resources/Music/GameOver/Lose.ogg differ diff --git a/Projekte/battleship/client/src/main/resources/Music/GameOver/Victory.wav b/Projekte/battleship/client/src/main/resources/Music/GameOver/Victory.wav new file mode 100644 index 00000000..1e3069a8 Binary files /dev/null and b/Projekte/battleship/client/src/main/resources/Music/GameOver/Victory.wav differ diff --git a/Projekte/battleship/model/src/main/java/pp/battleship/game/client/BattleState.java b/Projekte/battleship/model/src/main/java/pp/battleship/game/client/BattleState.java index e67c3b88..e0e94b3c 100644 --- a/Projekte/battleship/model/src/main/java/pp/battleship/game/client/BattleState.java +++ b/Projekte/battleship/model/src/main/java/pp/battleship/game/client/BattleState.java @@ -11,6 +11,7 @@ import pp.battleship.message.server.EffectMessage; import pp.battleship.model.IntPoint; import pp.battleship.model.ShipMap; +import pp.battleship.notification.Music; import pp.battleship.notification.Sound; import java.lang.System.Logger.Level; @@ -29,6 +30,7 @@ class BattleState extends ClientState { */ public BattleState(ClientGameLogic logic, boolean myTurn) { super(logic); + logic.playMusic(Music.BATTLE_THEME); this.myTurn = myTurn; } @@ -62,7 +64,7 @@ public void receivedEffect(EffectMessage msg) { } if (msg.isGameOver()) { msg.getRemainingOpponentShips().forEach(logic.getOpponentMap()::add); - logic.setState(new GameOverState(logic)); + logic.setState(new GameOverState(logic, msg.isGameLost())); } } diff --git a/Projekte/battleship/model/src/main/java/pp/battleship/game/client/ClientGameLogic.java b/Projekte/battleship/model/src/main/java/pp/battleship/game/client/ClientGameLogic.java index 3170e8be..4b9ea489 100644 --- a/Projekte/battleship/model/src/main/java/pp/battleship/game/client/ClientGameLogic.java +++ b/Projekte/battleship/model/src/main/java/pp/battleship/game/client/ClientGameLogic.java @@ -20,6 +20,8 @@ import pp.battleship.notification.GameEventBroker; import pp.battleship.notification.GameEventListener; import pp.battleship.notification.InfoTextEvent; +import pp.battleship.notification.Music; +import pp.battleship.notification.MusicEvent; import pp.battleship.notification.Sound; import pp.battleship.notification.SoundEvent; @@ -258,6 +260,15 @@ public void playSound(Sound sound) { notifyListeners(new SoundEvent(sound)); } + /** + * Emits an event to play the specified music + * + * @param music the music to be played + */ + public void playMusic(Music music) { + notifyListeners(new MusicEvent(music)); + } + /** * Loads a map from the specified file. * diff --git a/Projekte/battleship/model/src/main/java/pp/battleship/game/client/GameOverState.java b/Projekte/battleship/model/src/main/java/pp/battleship/game/client/GameOverState.java index 40d2edec..8684f1f3 100644 --- a/Projekte/battleship/model/src/main/java/pp/battleship/game/client/GameOverState.java +++ b/Projekte/battleship/model/src/main/java/pp/battleship/game/client/GameOverState.java @@ -7,6 +7,8 @@ package pp.battleship.game.client; +import pp.battleship.notification.Music; + /** * Represents the state of the client when the game is over. */ @@ -16,8 +18,13 @@ class GameOverState extends ClientState { * * @param logic the client game logic */ - GameOverState(ClientGameLogic logic) { + GameOverState(ClientGameLogic logic, boolean lost) { super(logic); + if (lost){ + logic.playMusic(Music.GAME_OVER_THEME_L); + } else { + logic.playMusic(Music.GAME_OVER_THEME_V); + } } /** diff --git a/Projekte/battleship/model/src/main/java/pp/battleship/notification/GameEventListener.java b/Projekte/battleship/model/src/main/java/pp/battleship/notification/GameEventListener.java index 4b966793..8025476b 100644 --- a/Projekte/battleship/model/src/main/java/pp/battleship/notification/GameEventListener.java +++ b/Projekte/battleship/model/src/main/java/pp/battleship/notification/GameEventListener.java @@ -45,4 +45,11 @@ default void receivedEvent(SoundEvent event) { /* do nothing */ } * @param event the received event */ default void receivedEvent(ClientStateEvent event) { /* do nothing */ } + + /** + * Indicates that the music should be changed + * + * @param event the received Event + */ + default void receivedEvent(MusicEvent event) { /* do nothing */ }; } diff --git a/Projekte/battleship/model/src/main/java/pp/battleship/notification/Music.java b/Projekte/battleship/model/src/main/java/pp/battleship/notification/Music.java new file mode 100644 index 00000000..bc6e50ff --- /dev/null +++ b/Projekte/battleship/model/src/main/java/pp/battleship/notification/Music.java @@ -0,0 +1,23 @@ +package pp.battleship.notification; + +/** + * Enumeration representing different types of sounds used in the game. + */ +public enum Music { + /** + * Menu music + */ + MENU_THEME, + /** + * Battle music + */ + BATTLE_THEME, + /** + * Game over music for a loss + */ + GAME_OVER_THEME_L, + /** + * Game over music for a victory + */ + GAME_OVER_THEME_V, +} diff --git a/Projekte/battleship/model/src/main/java/pp/battleship/notification/MusicEvent.java b/Projekte/battleship/model/src/main/java/pp/battleship/notification/MusicEvent.java new file mode 100644 index 00000000..85565f98 --- /dev/null +++ b/Projekte/battleship/model/src/main/java/pp/battleship/notification/MusicEvent.java @@ -0,0 +1,19 @@ +package pp.battleship.notification; + +/** + * Event when the background music is to be changed + * + * @param music the music to be played + */ +public record MusicEvent(Music music) implements GameEvent { + + /** + * Notifies the game event listener of this event. + * + * @param listener the game event listener + */ + @Override + public void notifyListener(GameEventListener listener) { + listener.receivedEvent(this); + } +}