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 6ac1c72..41275ea 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 @@ -23,6 +23,7 @@ import com.simsilica.lemur.style.BaseStyles; import pp.battleship.client.gui.BattleAppState; import pp.battleship.client.gui.EditorAppState; import pp.battleship.client.gui.SeaAppState; +import pp.battleship.client.GameMusic; import pp.battleship.game.client.BattleshipClient; import pp.battleship.game.client.ClientGameLogic; import pp.battleship.game.client.ServerConnection; @@ -267,6 +268,8 @@ public class BattleshipApp extends SimpleApplication implements BattleshipClient stateManager.detach(stateManager.getState(DebugKeysAppState.class)); attachGameSound(); + attachGameMusic(); + stateManager.attachAll(new EditorAppState(), new BattleAppState(), new SeaAppState()); } @@ -280,6 +283,15 @@ public class BattleshipApp extends SimpleApplication implements BattleshipClient stateManager.attach(gameSound); } + /** + * Attaches the music state and sets its initial enabled state. + */ + private void attachGameMusic() { + final GameMusic gameMusic = new GameMusic(); + gameMusic.setEnabled(GameMusic.enabledInPreferences()); + stateManager.attach(gameMusic); + } + /** * Updates the application state every frame. * This method is called once per frame during the game loop. diff --git a/Projekte/battleship/client/src/main/java/pp/battleship/client/GameMusic.java b/Projekte/battleship/client/src/main/java/pp/battleship/client/GameMusic.java new file mode 100644 index 0000000..d1d3e0a --- /dev/null +++ b/Projekte/battleship/client/src/main/java/pp/battleship/client/GameMusic.java @@ -0,0 +1,124 @@ +package pp.battleship.client; + + +import com.jme3.app.Application; +import com.jme3.app.state.AbstractAppState; +import com.jme3.app.state.AppStateManager; +import com.jme3.asset.AssetLoadException; +import com.jme3.asset.AssetNotFoundException; +import com.jme3.audio.AudioData; +import com.jme3.audio.AudioNode; +import pp.battleship.notification.GameEventListener; +import pp.battleship.notification.SoundEvent; + +import java.lang.System.Logger; +import java.lang.System.Logger.Level; +import java.util.prefs.Preferences; + +import static pp.util.PreferencesUtils.getPreferences; + +/** + * An application state that plays music. + */ +public class GameMusic extends AbstractAppState { + private static final Logger LOGGER = System.getLogger(GameMusic.class.getName()); + private static final Preferences PREFERENCES = getPreferences(GameMusic.class); + private static final String ENABLED_PREF = "enabled"; //NON-NLS + private static final String VOLUME_PREF = "volume"; //NON-NLS + + private AudioNode battleMusic; + private AudioNode menuMusicModern; + private AudioNode menuMusicTraditional; + + /** + * Checks if sound is enabled in the preferences. + * + * @return {@code true} if sound is enabled, {@code false} otherwise. + */ + public static boolean enabledInPreferences() { + return PREFERENCES.getBoolean(ENABLED_PREF, true); + } + /** + * Checks enabled volume in preferences. + * + * @return {@code float} if a volumePreference is set, the volume is set to the Value in PREFERENCES, + * {@code 0.25f} if no volumePreference is set in PREFERENCES, the Volume is set to a default of 0.25f + * + */ + + public static float volumePreference() { + return PREFERENCES.getFloat(VOLUME_PREF, 0.25f); + } + + /** + * Toggles the game sound on or off. + */ + public void toggleSound() { + setEnabled(!isEnabled()); + } + + /** + * Sets the enabled state of this AppState. + * Overrides {@link com.jme3.app.state.AbstractAppState#setEnabled(boolean)} + * + * @param enabled {@code true} to enable the AppState, {@code false} to disable it. + */ + @Override + public void setEnabled(boolean enabled) { + if (isEnabled() == enabled) return; + else if (!isEnabled() && enabled) { + if (menuMusicModern != null) menuMusicModern.play(); + } else if (isEnabled() && !enabled) { + if (menuMusicModern != null) menuMusicModern.stop(); + } + + super.setEnabled(enabled); + LOGGER.log(Level.INFO, "Music enabled: {0}", enabled); //NON-NLS + PREFERENCES.putBoolean(ENABLED_PREF, enabled); + } + + /** + * Initializes the music. + * Overrides {@link AbstractAppState#initialize(AppStateManager, Application)} + * + * @param stateManager The state manager + * @param app The application + */ + @Override + public void initialize(AppStateManager stateManager, Application app) { + super.initialize(stateManager, app); + menuMusicModern =loadSound(app, "Sound/BackgroundMusic/menu-music-modern.ogg"); + setVolume(volumePreference()); + menuMusicModern.setLooping(true); + if (isEnabled() && menuMusicModern != null) { + menuMusicModern.play(); + } + + } + + /** + * Loads the music from the specified file. + * + * @param app The application + * @param name The name of the sound file. + * @return The loaded AudioNode. + */ + private AudioNode loadSound(Application app, String name) { + try { + final AudioNode sound = new AudioNode(app.getAssetManager(), name, AudioData.DataType.Buffer); + sound.setLooping(false); + sound.setPositional(false); + return sound; + } + catch (AssetLoadException | AssetNotFoundException ex) { + LOGGER.log(Level.ERROR, ex.getMessage(), ex); + } + return null; + } + + public void setVolume(float vol){ + menuMusicModern.setVolume(vol); + PREFERENCES.putFloat(VOLUME_PREF, vol); + } + +} \ No newline at end of file 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 0e100e8..001013b 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 @@ -11,6 +11,7 @@ import com.simsilica.lemur.Button; import com.simsilica.lemur.Checkbox; import com.simsilica.lemur.Label; import com.simsilica.lemur.style.ElementId; +import pp.battleship.client.gui.VolumeControl; import pp.dialog.Dialog; import pp.dialog.StateCheckboxModel; import pp.dialog.TextInputDialog; @@ -33,6 +34,7 @@ class Menu extends Dialog { private final BattleshipApp app; private final Button loadButton = new Button(lookup("menu.map.load")); private final Button saveButton = new Button(lookup("menu.map.save")); + private final VolumeControl volumeSlider; /** * Constructs the Menu dialog for the Battleship application. @@ -42,9 +44,16 @@ class Menu extends Dialog { public Menu(BattleshipApp app) { super(app.getDialogManager()); this.app = app; - addChild(new Label(lookup("battleship.name"), new ElementId("header"))); //NON-NLS - addChild(new Checkbox(lookup("menu.sound-enabled"), - new StateCheckboxModel(app, GameSound.class))); + addChild(new Label(lookup("battleship.name"), new ElementId("header")));//NON-NLS + + addChild(new Checkbox(lookup("menu.sound-enabled"), new StateCheckboxModel(app, GameSound.class))); + + addChild(new Checkbox(lookup("menu.background-sound-enabled"), new StateCheckboxModel(app, GameMusic.class))); + + volumeSlider = new VolumeControl(app.getStateManager().getState(GameMusic.class)); + + addChild(volumeSlider); + addChild(loadButton) .addClickCommands(s -> ifTopDialog(this::loadDialog)); addChild(saveButton) @@ -65,6 +74,15 @@ class Menu extends Dialog { saveButton.setEnabled(app.getGameLogic().maySaveMap()); } + /** + * Updates the position of the volume control slider. + */ + @Override + public void update(float delta) { + volumeSlider.update(); + } + + /** * As an escape action, this method closes the menu if it is the top dialog. */ diff --git a/Projekte/battleship/client/src/main/java/pp/battleship/client/gui/VolumeControl.java b/Projekte/battleship/client/src/main/java/pp/battleship/client/gui/VolumeControl.java new file mode 100644 index 0000000..5713bbf --- /dev/null +++ b/Projekte/battleship/client/src/main/java/pp/battleship/client/gui/VolumeControl.java @@ -0,0 +1,29 @@ +package pp.battleship.client.gui; + +import com.simsilica.lemur.Slider; +import pp.battleship.client.GameMusic; + +public class VolumeControl extends Slider { + + private final GameMusic menuMusicModern; + + private double vol; + + public VolumeControl(GameMusic music) { + super(); + this.menuMusicModern = music; + vol = GameMusic.volumePreference(); + getModel().setPercent(vol); + } + + public void update() { + if (vol != getModel().getPercent()) { + vol = getModel().getPercent(); + menuMusicModern.setVolume( (float) vol); + } + } + +} + + + diff --git a/Projekte/battleship/client/src/main/resources/Sound/BackgroundMusic/battle-music.ogg b/Projekte/battleship/client/src/main/resources/Sound/BackgroundMusic/battle-music.ogg new file mode 100644 index 0000000..d4dd463 Binary files /dev/null and b/Projekte/battleship/client/src/main/resources/Sound/BackgroundMusic/battle-music.ogg differ diff --git a/Projekte/battleship/client/src/main/resources/Sound/BackgroundMusic/menu-music-modern.ogg b/Projekte/battleship/client/src/main/resources/Sound/BackgroundMusic/menu-music-modern.ogg new file mode 100644 index 0000000..826105e Binary files /dev/null and b/Projekte/battleship/client/src/main/resources/Sound/BackgroundMusic/menu-music-modern.ogg differ diff --git a/Projekte/battleship/client/src/main/resources/Sound/BackgroundMusic/menu-music-traditional.ogg b/Projekte/battleship/client/src/main/resources/Sound/BackgroundMusic/menu-music-traditional.ogg new file mode 100644 index 0000000..06c66e5 Binary files /dev/null and b/Projekte/battleship/client/src/main/resources/Sound/BackgroundMusic/menu-music-traditional.ogg differ diff --git a/Projekte/battleship/model/src/main/resources/battleship.properties b/Projekte/battleship/model/src/main/resources/battleship.properties index 47f1f6c..1aa2991 100644 --- a/Projekte/battleship/model/src/main/resources/battleship.properties +++ b/Projekte/battleship/model/src/main/resources/battleship.properties @@ -29,6 +29,7 @@ wait.its.not.your.turn=Wait, it's not your turn!! menu.quit=Quit game menu.return-to-game=Return to game menu.sound-enabled=Sound switched on +menu.background-sound-enabled=Music switched on menu.map.load=Load map from file... menu.map.save=Save map in file... label.file=File: diff --git a/Projekte/battleship/model/src/main/resources/battleship_de.properties b/Projekte/battleship/model/src/main/resources/battleship_de.properties index 4039420..417991a 100644 --- a/Projekte/battleship/model/src/main/resources/battleship_de.properties +++ b/Projekte/battleship/model/src/main/resources/battleship_de.properties @@ -29,6 +29,7 @@ wait.its.not.your.turn=Warte, Du bist nicht dran!! menu.quit=Spiel beenden menu.return-to-game=Zurück zum Spiel menu.sound-enabled=Sound eingeschaltet +menu.background-sound-enabled=Musik eingeschaltet menu.map.load=Karte von Datei laden... menu.map.save=Karte in Datei speichern... label.file=Datei: