added the logic to play diffrent Background music during diffrent states

added the a Enum for the Music and the MusicEvent
added a song for the game victory
adjusted the backgroundmusic class to handle the logic of the new song
added the Backgroundmusic to the ClientLogic as a EventListener.
This commit is contained in:
Hanno Fleischer hanno.fleischer@unibw.de
2024-10-04 20:43:37 +02:00
parent 961242bb20
commit b18705f064
11 changed files with 220 additions and 22 deletions

View File

@@ -4,19 +4,37 @@
import com.jme3.audio.AudioData.DataType; import com.jme3.audio.AudioData.DataType;
import com.jme3.audio.AudioNode; import com.jme3.audio.AudioNode;
import com.jme3.audio.AudioSource.Status; 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; import java.util.prefs.Preferences;
public class BackgroundMusic { public class BackgroundMusic implements GameEventListener {
private static final String VOLUME_PREF = "volume"; private static final String VOLUME_PREF = "volume";
private static final String MUSIC_ENABLED_PREF = "musicEnabled"; private static final String MUSIC_ENABLED_PREF = "musicEnabled";
private Preferences prefs = Preferences.userNodeForPackage(BackgroundMusic.class); 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 boolean musicEnabled;
private float volume; private float volume;
private Application app;
/** /**
* Initializes and controls the BackgroundMusic * Initializes and controls the BackgroundMusic
* *
@@ -26,32 +44,64 @@ public class BackgroundMusic {
public BackgroundMusic(Application app, String musicFilePath) { public BackgroundMusic(Application app, String musicFilePath) {
this.volume = prefs.getFloat(VOLUME_PREF, 1.0f); this.volume = prefs.getFloat(VOLUME_PREF, 1.0f);
this.musicEnabled = prefs.getBoolean(MUSIC_ENABLED_PREF, true); this.musicEnabled = prefs.getBoolean(MUSIC_ENABLED_PREF, true);
this.app = app;
backgroundMusic = new AudioNode(app.getAssetManager(), musicFilePath, DataType.Stream); menuMusic = createAudioNode(MENU_MUSIC);
backgroundMusic.setLooping(true); battleMusic = createAudioNode(BATTLE_MUSIC);
backgroundMusic.setPositional(false); gameOverMusicL = createAudioNode(GAME_OVER_MUSIC_L);
backgroundMusic.setVolume(volume); gameOverMusicV = createAudioNode(GAME_OVER_MUSIC_V);
stop(battleMusic);
stop(gameOverMusicL);
stop(gameOverMusicV);
lastNodePlayed = menuMusic.getName();
if(musicEnabled) { 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() { private AudioNode createAudioNode(String musicFilePath) {
if (musicEnabled && (backgroundMusic.getStatus() == Status.Stopped || backgroundMusic.getStatus() == Status.Paused)) { AudioNode audioNode = new AudioNode(app.getAssetManager(), musicFilePath, DataType.Stream);
backgroundMusic.play(); 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(){ public void stop(AudioNode audioNode) {
if (backgroundMusic.getStatus() == Status.Playing) { if (audioNode.getStatus() == Status.Playing) {
backgroundMusic.stop(); audioNode.stop();
}
}
public void pause(AudioNode audioNode) {
if (audioNode.getStatus() == Status.Playing) {
audioNode.pause();
} }
} }
@@ -61,12 +111,27 @@ public void stop(){
public void toogleMusic() { public void toogleMusic() {
this.musicEnabled = !this.musicEnabled; this.musicEnabled = !this.musicEnabled;
if (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 { } 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) { public void setVolume(float volume) {
this.volume = volume; this.volume = volume;
backgroundMusic.setVolume(volume); menuMusic.setVolume(volume);
battleMusic.setVolume(volume);
gameOverMusicL.setVolume(volume);
prefs.putFloat(VOLUME_PREF, volume); prefs.putFloat(VOLUME_PREF, volume);
} }
@@ -98,4 +165,65 @@ public float getVolume() {
public boolean isMusicEnabled() { public boolean isMusicEnabled() {
return musicEnabled; 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;
}
}
} }

View File

@@ -440,6 +440,7 @@ void errorDialog(String errorMessage) {
* @return BackgroundMusic * @return BackgroundMusic
*/ */
public BackgroundMusic getBackgroundMusic(){ public BackgroundMusic getBackgroundMusic(){
logic.addListener(backgroundMusic);
return backgroundMusic; return backgroundMusic;
} }
} }

View File

@@ -27,7 +27,7 @@
* An application state that plays sounds. * An application state that plays sounds.
*/ */
public class GameSound extends AbstractAppState implements GameEventListener { 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 Preferences PREFERENCES = getPreferences(GameSound.class);
private static final String ENABLED_PREF = "enabled"; //NON-NLS private static final String ENABLED_PREF = "enabled"; //NON-NLS

View File

@@ -11,6 +11,7 @@
import pp.battleship.message.server.EffectMessage; import pp.battleship.message.server.EffectMessage;
import pp.battleship.model.IntPoint; import pp.battleship.model.IntPoint;
import pp.battleship.model.ShipMap; import pp.battleship.model.ShipMap;
import pp.battleship.notification.Music;
import pp.battleship.notification.Sound; import pp.battleship.notification.Sound;
import java.lang.System.Logger.Level; import java.lang.System.Logger.Level;
@@ -29,6 +30,7 @@ class BattleState extends ClientState {
*/ */
public BattleState(ClientGameLogic logic, boolean myTurn) { public BattleState(ClientGameLogic logic, boolean myTurn) {
super(logic); super(logic);
logic.playMusic(Music.BATTLE_THEME);
this.myTurn = myTurn; this.myTurn = myTurn;
} }
@@ -62,7 +64,7 @@ public void receivedEffect(EffectMessage msg) {
} }
if (msg.isGameOver()) { if (msg.isGameOver()) {
msg.getRemainingOpponentShips().forEach(logic.getOpponentMap()::add); msg.getRemainingOpponentShips().forEach(logic.getOpponentMap()::add);
logic.setState(new GameOverState(logic)); logic.setState(new GameOverState(logic, msg.isGameLost()));
} }
} }

View File

@@ -20,6 +20,8 @@
import pp.battleship.notification.GameEventBroker; import pp.battleship.notification.GameEventBroker;
import pp.battleship.notification.GameEventListener; import pp.battleship.notification.GameEventListener;
import pp.battleship.notification.InfoTextEvent; import pp.battleship.notification.InfoTextEvent;
import pp.battleship.notification.Music;
import pp.battleship.notification.MusicEvent;
import pp.battleship.notification.Sound; import pp.battleship.notification.Sound;
import pp.battleship.notification.SoundEvent; import pp.battleship.notification.SoundEvent;
@@ -258,6 +260,15 @@ public void playSound(Sound sound) {
notifyListeners(new SoundEvent(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. * Loads a map from the specified file.
* *

View File

@@ -7,6 +7,8 @@
package pp.battleship.game.client; package pp.battleship.game.client;
import pp.battleship.notification.Music;
/** /**
* Represents the state of the client when the game is over. * 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 * @param logic the client game logic
*/ */
GameOverState(ClientGameLogic logic) { GameOverState(ClientGameLogic logic, boolean lost) {
super(logic); super(logic);
if (lost){
logic.playMusic(Music.GAME_OVER_THEME_L);
} else {
logic.playMusic(Music.GAME_OVER_THEME_V);
}
} }
/** /**

View File

@@ -45,4 +45,11 @@ default void receivedEvent(SoundEvent event) { /* do nothing */ }
* @param event the received event * @param event the received event
*/ */
default void receivedEvent(ClientStateEvent event) { /* do nothing */ } 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 */ };
} }

View File

@@ -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,
}

View File

@@ -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);
}
}