Add music

This commit is contained in:
Felix Koppe
2024-10-08 12:41:24 +02:00
parent 9dbac0b226
commit f96c63e76e
7 changed files with 231 additions and 4 deletions

View File

@@ -122,6 +122,11 @@ public class BattleshipApp extends SimpleApplication implements BattleshipClient
*/
private final ActionListener escapeListener = (name, isPressed, tpf) -> escape(isPressed);
/**
* Listener for handling actions triggered by the Escape key.
*/
private GameMusic music;
static {
// Configure logging
LogManager manager = LogManager.getLogManager();
@@ -193,6 +198,15 @@ DialogManager getDialogManager() {
return dialogManager;
}
/**
* Returns the GameMusic responsible for playing music.
*
* @return The {@link GameMusic} instance.
*/
GameMusic getGameMusic() {
return music;
}
/**
* Returns the game logic handler for the client.
*
@@ -225,6 +239,8 @@ public void simpleInitApp() {
setupStates();
setupGui();
serverConnection.connect();
music = new GameMusic(this, "Sound/Music/battleship.ogg");
}
/**

View File

@@ -0,0 +1,170 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
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 com.jme3.audio.AudioSource;
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 implements GameEventListener {
private static final Logger LOGGER = System.getLogger(GameMusic.class.getName());
private static final Preferences PREFERENCES = getPreferences(GameMusic.class);
private static final String ENABLED_PREF = "toggle"; //NON-NLS
private static final String SLIDER_PREF = "slider"; //NON-NLS
private AudioNode music;
private boolean enabled;
private float volume;
public GameMusic(Application app, String musicFilePath) {
this.enabled = PREFERENCES.getBoolean(ENABLED_PREF, true);
this.volume = PREFERENCES.getFloat(SLIDER_PREF, 2.0f);
music = new AudioNode(app.getAssetManager(), musicFilePath, AudioData.DataType.Stream);
music.setLooping(true);
music.setPositional(false);
music.setVolume(1.0f);
if(enabled) {
start();
}
}
/**
* Checks if music is enabled in the preferences.
*
* @return {@code true} if music is enabled, {@code false} otherwise.
*/
public static boolean enabledInPreferences() {
return PREFERENCES.getBoolean(ENABLED_PREF, true);
}
/**
* Returns the volume value that is set in the preferences.
*
* @return {@code true} if sound is enabled, {@code false} otherwise.
*/
public static float volumeInPreferences() {
return PREFERENCES.getFloat(SLIDER_PREF, 2.0f);
}
/**
* Toggles the game music on or off.
*/
public void toggleMusic() {
setEnabled(!isEnabled());
}
/**
* Sets the enabled state of this AppState.
* Overrides {@link AbstractAppState#setEnabled(boolean)}
*
* @param enabled {@code true} to enable the AppState, {@code false} to disable it.
*/
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
if(enabled) {
start();
} else {
stop();
}
LOGGER.log(Level.INFO, "Music enabled: {0}", enabled); //NON-NLS
PREFERENCES.putBoolean(ENABLED_PREF, enabled);
}
/**
* Sets the volume for the music
*
* @param volume the new volume to be set
*/
public void setVolume(float volume) {
this.volume = volume;
music.setVolume(volume);
LOGGER.log(Level.INFO, "Volume set to: {0}", volume); //NON-NLS
PREFERENCES.putFloat(SLIDER_PREF, volume);
}
/**
* Loads a 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;
}
/**
* Starts the music.
*/
public void start() {
if (enabled && (music.getStatus() == AudioSource.Status.Stopped || music.getStatus() == AudioSource.Status.Paused)) {
music.play();
}
}
/**
* Stops the music.
*/
public void stop() {
if (music.getStatus() == AudioSource.Status.Playing) {
music.stop();
}
}
/**
* This method returns the volume
*
* @return float the current volume
*/
public float getVolume() {
return volume;
}
/**
* Returns if music should be played or not
*
* @return boolean value if music is enabled
*/
public boolean isMusicEnabled() {
return enabled;
}
}

View File

@@ -7,9 +7,8 @@
package pp.battleship.client;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Checkbox;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.*;
import com.simsilica.lemur.core.VersionedReference;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.dialog.StateCheckboxModel;
@@ -34,6 +33,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<Double> volumeRef;
/**
* Constructs the Menu dialog for the Battleship application.
*
@@ -49,6 +50,20 @@ public Menu(BattleshipApp app) {
.addClickCommands(s -> ifTopDialog(this::loadDialog));
addChild(saveButton)
.addClickCommands(s -> ifTopDialog(this::saveDialog));
Checkbox musicToggle = new Checkbox(lookup("menu.music.toggle"));
musicToggle.setChecked(app.getGameMusic().isMusicEnabled());
musicToggle.addClickCommands(s -> toggleMusic());
addChild(musicToggle);
Slider volumeSlider = new Slider(lookup("menu.music.slider"));
volumeSlider.setModel(new DefaultRangedValueModel(0.0 , 4.0, app.getGameMusic().getVolume()));
volumeSlider.setDelta(0.4);
addChild(volumeSlider);
volumeRef = volumeSlider.getModel().createReference();
addChild(new Button(lookup("menu.return-to-game")))
.addClickCommands(s -> ifTopDialog(this::close));
addChild(new Button(lookup("menu.quit")))
@@ -57,12 +72,33 @@ public Menu(BattleshipApp app) {
}
/**
* Updates the state of the load and save buttons based on the game logic.
* Updates the state of the load/save buttons and volume based on the game logic.
*/
@Override
public void update() {
loadButton.setEnabled(app.getGameLogic().mayLoadMap());
saveButton.setEnabled(app.getGameLogic().maySaveMap());
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.getGameMusic().setVolume((float) volume);
}
/**
* this method toggles the background music on and off
*/
private void toggleMusic() {
app.getGameMusic().toggleMusic();
}
/**

View File

@@ -0,0 +1 @@
credit to patrickdearteaga.com

View File

@@ -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 music on/off
menu.music.slider=Volumeslider
label.file=File:
label.connecting=Connecting...
dialog.error=Error

View File

@@ -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=Musik an/ausschalten
menu.music.slider=Lautstärkeregler
label.file=Datei:
label.connecting=Verbindung wird aufgebaut...
dialog.error=Fehler