Add music
This commit is contained in:
@@ -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");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
credit to patrickdearteaga.com
|
||||
Binary file not shown.
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user