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 new file mode 100644 index 00000000..262b9150 --- /dev/null +++ b/Projekte/battleship/client/src/main/java/pp/battleship/client/BackgroundMusic.java @@ -0,0 +1,101 @@ +package pp.battleship.client; + +import com.jme3.app.Application; +import com.jme3.audio.AudioData.DataType; +import com.jme3.audio.AudioNode; +import com.jme3.audio.AudioSource.Status; + +import java.util.prefs.Preferences; + +public class BackgroundMusic { + private static final String VOLUME_PREF = "volume"; + private static final String MUSIC_ENABLED_PREF = "musicEnabled"; + private Preferences prefs = Preferences.userNodeForPackage(BackgroundMusic.class); + + + private final AudioNode backgroundMusic; + private boolean musicEnabled; + private float volume; + + /** + * Initializes and controls the BackgroundMusic + * + * @param app The main Application + * @param musicFilePath The Path for the specific background music + */ + public BackgroundMusic(Application app, String musicFilePath) { + this.volume = prefs.getFloat(VOLUME_PREF, 1.0f); + this.musicEnabled = prefs.getBoolean(MUSIC_ENABLED_PREF, true); + + backgroundMusic = new AudioNode(app.getAssetManager(), musicFilePath, DataType.Stream); + backgroundMusic.setLooping(true); + backgroundMusic.setPositional(false); + backgroundMusic.setVolume(1.0f); + + if(musicEnabled) { + play(); + } + } + + /** + * Plays the music if the music is Stopped or paused + */ + public void play() { + if (musicEnabled && (backgroundMusic.getStatus() == Status.Stopped || backgroundMusic.getStatus() == Status.Paused)) { + backgroundMusic.play(); + } + } + + /** + * Stops the music if it is playing + */ + public void stop(){ + if (backgroundMusic.getStatus() == Status.Playing) { + backgroundMusic.stop(); + } + } + + /** + * Toggle Method to control the music + */ + public void toogleMusic() { + this.musicEnabled = !this.musicEnabled; + if (musicEnabled) { + play(); + } else { + stop(); + } + + prefs.putFloat(VOLUME_PREF, volume); + } + + /** + * Method to set the volume for the music + * + * @param volume float to transfer the new volume + */ + public void setVolume(float volume) { + this.volume = volume; + backgroundMusic.setVolume(volume); + + prefs.putFloat(VOLUME_PREF, volume); + } + + /** + * This method retuns the volume + * + * @return the current volume as a float + */ + public float getVolume() { + return volume; + } + + /** + * Returns if music should be played or not + * + * @return boolean value in music should be played + */ + public boolean isMusicEnabled() { + return musicEnabled; + } +} 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 6ac1c729..471ac20e 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 @@ -122,6 +122,11 @@ public class BattleshipApp extends SimpleApplication implements BattleshipClient */ private final ActionListener escapeListener = (name, isPressed, tpf) -> escape(isPressed); + /** + * The Object which handles the background music + */ + private BackgroundMusic backgroundMusic; + static { // Configure logging LogManager manager = LogManager.getLogManager(); @@ -225,6 +230,8 @@ public void simpleInitApp() { setupStates(); setupGui(); serverConnection.connect(); + + backgroundMusic = new BackgroundMusic(this, "Music/MainMenu/Dark_Intro.ogg"); } /** @@ -426,4 +433,13 @@ void errorDialog(String errorMessage) { .build() .open(); } + + /** + * this method returns the object which handles the background music + * + * @return BackgroundMusic + */ + public BackgroundMusic getBackgroundMusic(){ + return backgroundMusic; + } } diff --git a/Projekte/battleship/client/src/main/java/pp/battleship/client/Menu.java b/Projekte/battleship/client/src/main/java/pp/battleship/client/Menu.java index 0e100e86..77005446 100644 --- a/Projekte/battleship/client/src/main/java/pp/battleship/client/Menu.java +++ b/Projekte/battleship/client/src/main/java/pp/battleship/client/Menu.java @@ -9,7 +9,10 @@ import com.simsilica.lemur.Button; import com.simsilica.lemur.Checkbox; +import com.simsilica.lemur.DefaultRangedValueModel; import com.simsilica.lemur.Label; +import com.simsilica.lemur.Slider; +import com.simsilica.lemur.core.VersionedReference; import com.simsilica.lemur.style.ElementId; import pp.dialog.Dialog; import pp.dialog.StateCheckboxModel; @@ -34,6 +37,8 @@ class Menu extends Dialog { private final Button loadButton = new Button(lookup("menu.map.load")); private final Button saveButton = new Button(lookup("menu.map.save")); + private final VersionedReference volumeRef; + /** * Constructs the Menu dialog for the Battleship application. * @@ -45,6 +50,19 @@ public Menu(BattleshipApp app) { addChild(new Label(lookup("battleship.name"), new ElementId("header"))); //NON-NLS addChild(new Checkbox(lookup("menu.sound-enabled"), new StateCheckboxModel(app, GameSound.class))); + + Checkbox musicToggle = new Checkbox(lookup("menu.music.toggle")); + musicToggle.setChecked(app.getBackgroundMusic().isMusicEnabled()); + musicToggle.addClickCommands(s -> toggleMusic()); + + addChild(musicToggle); + + Slider volumeSlider = new Slider(); + volumeSlider.setModel(new DefaultRangedValueModel(0.0 , 2.0, app.getBackgroundMusic().getVolume())); + addChild(volumeSlider); + + volumeRef = volumeSlider.getModel().createReference(); + addChild(loadButton) .addClickCommands(s -> ifTopDialog(this::loadDialog)); addChild(saveButton) @@ -56,6 +74,34 @@ public Menu(BattleshipApp app) { update(); } + /** + * this method is used update the volume when there is a change in the slider + * @param tpf time per frame + */ + @Override + public void update(float tpf){ + if(volumeRef.update()){ + double newVolume = volumeRef.get(); + adjustVolume(newVolume); + } + } + + /** + * this method adjust the volume for the background music + * + * @param volume is the double value of the volume + */ + private void adjustVolume(double volume) { + app.getBackgroundMusic().setVolume((float) volume); + } + + /** + * this method toggles the background music on and off + */ + private void toggleMusic() { + app.getBackgroundMusic().toogleMusic(); + } + /** * Updates the state of the load and save buttons based on the game logic. */ diff --git a/Projekte/battleship/client/src/main/java/pp/battleship/client/gui/SeaSynchronizer.java b/Projekte/battleship/client/src/main/java/pp/battleship/client/gui/SeaSynchronizer.java index 367976e7..17cebcfd 100644 --- a/Projekte/battleship/client/src/main/java/pp/battleship/client/gui/SeaSynchronizer.java +++ b/Projekte/battleship/client/src/main/java/pp/battleship/client/gui/SeaSynchronizer.java @@ -144,18 +144,13 @@ public Spatial visit(Battleship ship) { * @return the spatial representing the battleship */ private Spatial createShip(Battleship ship) { - switch (ship.getLength()){ - case 1: - return createPatrolBoat(ship); - case 2: - return createModernBattleship(ship); - case 3: - return createUBoat(ship); - case 4: - return createBattleship(ship); - default: - throw new IllegalArgumentException("Ship length must be between 1 and 4 units long"); - } + return switch (ship.getLength()) { + case 1 -> createPatrolBoat(ship); + case 2 -> createModernBattleship(ship); + case 3 -> createUBoat(ship); + case 4 -> createBattleship(ship); + default -> throw new IllegalArgumentException("Ship length must be between 1 and 4 units long"); + }; } /** @@ -210,6 +205,12 @@ private Spatial createBattleship(Battleship ship) { return model; } + /** + * creates a detailed 3D model to represent an UBoat + * + * @param ship the ship to be represented + * @return the spatial representing the Uboat + */ private Spatial createUBoat(Battleship ship) { final Spatial model = app.getAssetManager().loadModel(UBOAT); @@ -221,6 +222,12 @@ private Spatial createUBoat(Battleship ship) { return model; } + /** + * creates a detailed 3D model to represent the modern battleship + * + * @param ship the ship to be represented + * @return the spatial representing the Modern Battleship + */ private Spatial createModernBattleship(Battleship ship) { final Spatial model = app.getAssetManager().loadModel(BATTLE_SHIP_MODERN); @@ -232,6 +239,12 @@ private Spatial createModernBattleship(Battleship ship) { return model; } + /** + * creates a detailed 3D model to represent the patrol boat + * + * @param ship the ship to be represented + * @return the spatial representing the patrol boat + */ private Spatial createPatrolBoat(Battleship ship) { final Spatial model = app.getAssetManager().loadModel(PATROL_BOAT); diff --git a/Projekte/battleship/client/src/main/resources/Music/BattleTheme/boss_battle_#2_metal_loop.wav b/Projekte/battleship/client/src/main/resources/Music/BattleTheme/boss_battle_#2_metal_loop.wav new file mode 100644 index 00000000..20622308 Binary files /dev/null and b/Projekte/battleship/client/src/main/resources/Music/BattleTheme/boss_battle_#2_metal_loop.wav differ diff --git a/Projekte/battleship/client/src/main/resources/Music/BattleTheme/boss_battle_#2_metal_opening.wav b/Projekte/battleship/client/src/main/resources/Music/BattleTheme/boss_battle_#2_metal_opening.wav new file mode 100644 index 00000000..13dafb6b Binary files /dev/null and b/Projekte/battleship/client/src/main/resources/Music/BattleTheme/boss_battle_#2_metal_opening.wav differ diff --git a/Projekte/battleship/client/src/main/resources/Music/MainMenu/Dark_Intro.ogg b/Projekte/battleship/client/src/main/resources/Music/MainMenu/Dark_Intro.ogg new file mode 100644 index 00000000..5493dab4 Binary files /dev/null and b/Projekte/battleship/client/src/main/resources/Music/MainMenu/Dark_Intro.ogg differ diff --git a/Projekte/battleship/model/src/main/resources/battleship.properties b/Projekte/battleship/model/src/main/resources/battleship.properties index 80a5ba92..9e153b7e 100644 --- a/Projekte/battleship/model/src/main/resources/battleship.properties +++ b/Projekte/battleship/model/src/main/resources/battleship.properties @@ -31,6 +31,8 @@ menu.return-to-game=Return to game menu.sound-enabled=Sound switched on menu.map.load=Load map from file... menu.map.save=Save map in file... +menu.music.toggle=Toggle the music +menu.volume=Volume label.file=File: label.connecting=Connecting... dialog.error=Error diff --git a/Projekte/battleship/model/src/main/resources/battleship_de.properties b/Projekte/battleship/model/src/main/resources/battleship_de.properties index 58b5bc59..10ab8ace 100644 --- a/Projekte/battleship/model/src/main/resources/battleship_de.properties +++ b/Projekte/battleship/model/src/main/resources/battleship_de.properties @@ -31,6 +31,8 @@ menu.return-to-game=Zurück zum Spiel menu.sound-enabled=Sound eingeschaltet menu.map.load=Karte von Datei laden... menu.map.save=Karte in Datei speichern... +menu.music.toggle=An/Ausschalten der Musik +menu.volume=Lautstärke label.file=Datei: label.connecting=Verbindung wird aufgebaut... dialog.error=Fehler