added background music and improved model code

reduced switch case for creating different ship models
created a new class for background music
added a button to toggle background music
added a slider so adjust volume
added new style for labeling the slider
This commit is contained in:
Timo Brennförder
2024-10-03 22:08:26 +02:00
parent 3bcaca8810
commit 9cfabdb15d
18 changed files with 186 additions and 697582 deletions

View File

@@ -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 final Preferences pref = 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 = pref.getFloat(VOLUME_PREF, 1.0f);
this.musicEnabled = pref.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();
}
pref.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);
pref.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;
}
}

View File

@@ -122,6 +122,11 @@ public class BattleshipApp extends SimpleApplication implements BattleshipClient
*/
private final ActionListener escapeListener = (name, isPressed, tpf) -> escape(isPressed);
/**
* Object handling the background music
*/
private BackgroundMusic backgroundMusic;
static {
// Configure logging
LogManager manager = LogManager.getLogManager();
@@ -225,6 +230,7 @@ public void simpleInitApp() {
setupStates();
setupGui();
serverConnection.connect();
backgroundMusic = new BackgroundMusic(this, "Sound/Background/Aluminum.ogg");
}
/**
@@ -315,6 +321,10 @@ public Draw getDraw() {
return draw;
}
public BackgroundMusic getBackgroundMusic(){
return backgroundMusic;
}
/**
* Handles a request to close the application.
* If the request is initiated by pressing ESC, this parameter is true.

View File

@@ -15,6 +15,7 @@
import com.jme3.audio.AudioData;
import com.jme3.audio.AudioNode;
import pp.battleship.notification.GameEventListener;
import pp.battleship.notification.Sound;
import pp.battleship.notification.SoundEvent;
import java.lang.System.Logger;
@@ -100,6 +101,7 @@ private AudioNode loadSound(Application app, String name) {
return null;
}
/**
* Plays the splash sound effect.
*/

View File

@@ -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;
@@ -33,6 +36,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 VersionedReference<Double> volumeRef;
/**
* Constructs the Menu dialog for the Battleship application.
@@ -45,6 +49,20 @@ 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);
addChild(new Label(lookup("menu.music.volume"), new ElementId("slider_label")));
Slider volumeSlider = new Slider();
volumeSlider.setModel(new DefaultRangedValueModel(0.00 , 1.00, app.getBackgroundMusic().getVolume()));
volumeSlider.setDelta(0.05);
addChild(volumeSlider);
volumeRef = volumeSlider.getModel().createReference();
addChild(loadButton)
.addClickCommands(s -> ifTopDialog(this::loadDialog));
addChild(saveButton)
@@ -53,9 +71,40 @@ public Menu(BattleshipApp app) {
.addClickCommands(s -> ifTopDialog(this::close));
addChild(new Button(lookup("menu.quit")))
.addClickCommands(s -> ifTopDialog(app::closeApp));
update();
}
/**
* this method is used update the volume when the slider is used
* @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.
*/

View File

@@ -37,7 +37,7 @@ class SeaSynchronizer extends ShipMapSynchronizer {
private static final String KING_GEORGE_V_MODEL = "Models/KingGeorgeV/KingGeorgeV.j3o";
private static final String UBOAT_MODEL = "Models/UBOAT/14084_WWII_Ship_German_Type_II_U-boat_v2_L1.obj";
private static final String PATROL_BOAT_MODEL = "Models/PATROL_BOAT/12219_boat_v2_L2.obj";
private static final String BATTLESHIP_MODEL = "Models/BATTLESHIP/10619_Battleship.obj";
private static final String BATTLESHIPV2_MODEL = "Models/BATTLESHIP/10619_Battleship.obj";
private static final String COLOR = "Color"; //NON-NLS
private static final String SHIP = "ship"; //NON-NLS
private static final String SHOT = "shot"; //NON-NLS
@@ -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 createBattleshipV2(ship);
case 3:
return createUboat(ship);
case 4:
return createBattleship(ship);
default:
return createBox(ship);
}
return switch (ship.getLength()){
case 1 -> createPatrolBoat(ship);
case 2 -> createBattleshipV2(ship);
case 3 -> createUboat(ship);
case 4 -> createBattleship(ship);
default -> createBox(ship);
};
}
/**
@@ -218,7 +213,7 @@ private Spatial createBattleship(Battleship ship) {
*/
private Spatial createBattleshipV2(Battleship ship) {
final Spatial model = app.getAssetManager().loadModel(BATTLESHIP_MODEL);
final Spatial model = app.getAssetManager().loadModel(BATTLESHIPV2_MODEL);
model.rotate(-HALF_PI, calculateRotationAngle(ship.getRot()) + HALF_PI, 0f);
model.scale(0.000075f);