- * Note: Attributes of this class should not be marked as {@code final} - * to ensure proper functionality when reading from a properties file. - *
- */ -public class BattleshipAppConfig extends BattleshipClientConfig { - - /** - * Converts a string value found in the properties file into an object of the specified type. - * Extends the superclass method to support conversion to {@link ColorRGBA}. - * - * @param value the string value to be converted - * @param targetType the target type into which the value string is converted - * @return the converted object of the specified type - */ - @Override - protected Object convertToType(String value, Class> targetType) { - if (targetType == ColorRGBA.class) - return makeColorRGBA(value); - return super.convertToType(value, targetType); - } - - /** - * Converts the specified string value to a corresponding {@link ColorRGBA} object. - * - * @param value the color in the format "red, green, blue, alpha" with all values in the range [0..1] - * @return a {@link ColorRGBA} object representing the color - * @throws IllegalArgumentException if the input string is not in the expected format - */ - private static ColorRGBA makeColorRGBA(String value) { - String[] split = value.split(",", -1); - try { - if (split.length == 4) - return new ColorRGBA(Float.parseFloat(split[0]), - Float.parseFloat(split[1]), - Float.parseFloat(split[2]), - Float.parseFloat(split[3])); - } - catch (NumberFormatException e) { - // deliberately left empty - } - throw new IllegalArgumentException(value + " should consist of exactly 4 numbers"); - } - - /** - * The width of the game view resolution in pixels. - */ - @Property("settings.resolution.width") //NON-NLS - private int resolutionWidth = 1200; - - /** - * The height of the game view resolution in pixels. - */ - @Property("settings.resolution.height") //NON-NLS - private int resolutionHeight = 800; - - /** - * Specifies whether the game should start in full-screen mode. - */ - @Property("settings.full-screen") //NON-NLS - private boolean fullScreen = false; - - /** - * Specifies whether gamma correction should be enabled. - * If enabled, the main framebuffer is configured for sRGB colors, - * and sRGB images are linearized. - *- * Requires a GPU that supports GL_ARB_framebuffer_sRGB; otherwise, this setting will be ignored. - *
- */ - @Property("settings.use-gamma-correction") //NON-NLS - private boolean useGammaCorrection = true; - - /** - * Specifies whether full resolution framebuffers should be used on Retina displays. - * This setting is ignored on non-Retina platforms. - */ - @Property("settings.use-retina-framebuffer") //NON-NLS - private boolean useRetinaFrameBuffer = false; - - /** - * Specifies whether the settings window should be shown for configuring the game. - */ - @Property("settings.show") //NON-NLS - private boolean showSettings = false; - - /** - * Specifies whether the JME statistics window should be shown in the lower left corner of the screen. - */ - @Property("statistics.show") //NON-NLS - private boolean showStatistics = false; - - /** - * The color of the top text during gameplay, represented as a {@link ColorRGBA} object. - */ - @Property("overlay.top.color") //NON-NLS - private ColorRGBA topColor = ColorRGBA.White; - - /** - * Creates a default {@code BattleshipAppConfig} with predefined values. - */ - public BattleshipAppConfig() { - // Default constructor - } - - /** - * Returns the width of the game view resolution in pixels. - * - * @return the width of the game view resolution in pixels - */ - public int getResolutionWidth() { - return resolutionWidth; - } - - /** - * Returns the height of the game view resolution in pixels. - * - * @return the height of the game view resolution in pixels - */ - public int getResolutionHeight() { - return resolutionHeight; - } - - /** - * Returns whether the game should start in full-screen mode. - * - * @return {@code true} if the game should start in full-screen mode; {@code false} otherwise - */ - public boolean fullScreen() { - return fullScreen; - } - - /** - * Returns whether gamma correction is enabled. - * If enabled, the main framebuffer is configured for sRGB colors, - * and sRGB images are linearized. - * - * @return {@code true} if gamma correction is enabled; {@code false} otherwise - */ - public boolean useGammaCorrection() { - return useGammaCorrection; - } - - /** - * Returns whether full resolution framebuffers should be used on Retina displays. - * This setting is ignored on non-Retina platforms. - * - * @return {@code true} if full resolution framebuffers should be used on Retina displays; {@code false} otherwise - */ - public boolean useRetinaFrameBuffer() { - return useRetinaFrameBuffer; - } - - /** - * Returns whether the settings window should be shown for configuring the game. - * - * @return {@code true} if the settings window should be shown; {@code false} otherwise - */ - public boolean getShowSettings() { - return showSettings; - } - - /** - * Returns whether the JME statistics window should be shown in the lower left corner of the screen. - * - * @return {@code true} if the statistics window should be shown; {@code false} otherwise - */ - public boolean getShowStatistics() { - return showStatistics; - } - - /** - * Returns the color of the top text during gameplay as a {@link ColorRGBA} object. - * - * @return the color of the top text during gameplay - */ - public ColorRGBA getTopColor() { - return topColor; - } -} diff --git a/Projekte/battleship/client/src/main/java/pp/battleship/client/BattleshipAppState.java b/Projekte/battleship/client/src/main/java/pp/battleship/client/BattleshipAppState.java deleted file mode 100644 index 0094516..0000000 --- a/Projekte/battleship/client/src/main/java/pp/battleship/client/BattleshipAppState.java +++ /dev/null @@ -1,102 +0,0 @@ -//////////////////////////////////////// -// 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 pp.battleship.game.client.ClientGameLogic; - -/** - * Abstract class representing a state in the Battleship game. - * Extends the AbstractAppState from jMonkeyEngine to manage state behavior. - */ -public abstract class BattleshipAppState extends AbstractAppState { - private BattleshipApp app; - - /** - * Creates a new BattleshipAppState that is initially disabled. - * - * @see #setEnabled(boolean) - */ - protected BattleshipAppState() { - setEnabled(false); - } - - /** - * Initializes the state manager and application. - * - * @param stateManager The state manager - * @param application The application instance - */ - @Override - public void initialize(AppStateManager stateManager, Application application) { - super.initialize(stateManager, application); - this.app = (BattleshipApp) application; - if (isEnabled()) enableState(); - } - - /** - * Returns the BattleshipApp instance associated with this BattleshipAppState. - * - * @return The BattleshipApp instance. - */ - public BattleshipApp getApp() { - return app; - } - - /** - * Returns the client game logic handler. - * - * @return the client game logic handler - */ - public ClientGameLogic getGameLogic() { - return app.getGameLogic(); - } - - /** - * Checks if any dialog is currently displayed. - * - * @return true if any dialog is currently shown, false otherwise - */ - public boolean showsDialog() { - return app.getDialogManager().showsDialog(); - } - - /** - * Sets the enabled state of the BattleshipAppState. - * If the new state is the same as the current state, the method returns. - * - * @param enabled The new enabled state. - */ - @Override - public void setEnabled(boolean enabled) { - if (isEnabled() == enabled) return; - super.setEnabled(enabled); - if (app != null) { - if (enabled) - enableState(); - else - disableState(); - } - } - - /** - * This method is called when the state is enabled. - * It is meant to be overridden by subclasses to perform - * specific actions when the state is enabled. - */ - protected abstract void enableState(); - - /** - * This method is called when the state is disabled. - * It is meant to be overridden by subclasses to perform - * specific actions when the state is disabled. - */ - protected abstract void disableState(); -} diff --git a/Projekte/battleship/client/src/main/java/pp/battleship/client/GameSound.java b/Projekte/battleship/client/src/main/java/pp/battleship/client/GameSound.java deleted file mode 100644 index 0fdcef6..0000000 --- a/Projekte/battleship/client/src/main/java/pp/battleship/client/GameSound.java +++ /dev/null @@ -1,135 +0,0 @@ -//////////////////////////////////////// -// 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 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 sounds. - */ -public class GameSound extends AbstractAppState implements GameEventListener { - private static final Logger LOGGER = System.getLogger(GameSound.class.getName()); - private static final Preferences PREFERENCES = getPreferences(GameSound.class); - private static final String ENABLED_PREF = "enabled"; //NON-NLS - - private AudioNode splashSound; - private AudioNode shipDestroyedSound; - private AudioNode explosionSound; - - /** - * 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); - } - - /** - * 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; - super.setEnabled(enabled); - LOGGER.log(Level.INFO, "Sound enabled: {0}", enabled); //NON-NLS - PREFERENCES.putBoolean(ENABLED_PREF, enabled); - } - - /** - * Initializes the sound effects for the game. - * 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); - shipDestroyedSound = loadSound(app, "Sound/Effects/sunken.wav"); //NON-NLS - splashSound = loadSound(app, "Sound/Effects/splash.wav"); //NON-NLS - explosionSound = loadSound(app, "Sound/Effects/explosion.wav"); //NON-NLS - } - - /** - * Loads a sound 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; - } - - /** - * Plays the splash sound effect. - */ - public void splash() { - if (isEnabled() && splashSound != null) - splashSound.playInstance(); - } - - /** - * Plays the explosion sound effect. - */ - public void explosion() { - if (isEnabled() && explosionSound != null) - explosionSound.playInstance(); - } - - /** - * Plays sound effect when a ship has been destroyed. - */ - public void shipDestroyed() { - if (isEnabled() && shipDestroyedSound != null) - shipDestroyedSound.playInstance(); - } - - @Override - public void receivedEvent(SoundEvent event) { - switch (event.sound()) { - case EXPLOSION -> explosion(); - case SPLASH -> splash(); - case DESTROYED_SHIP -> shipDestroyed(); - } - } -} 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 deleted file mode 100644 index 0e100e8..0000000 --- a/Projekte/battleship/client/src/main/java/pp/battleship/client/Menu.java +++ /dev/null @@ -1,143 +0,0 @@ -//////////////////////////////////////// -// 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.simsilica.lemur.Button; -import com.simsilica.lemur.Checkbox; -import com.simsilica.lemur.Label; -import com.simsilica.lemur.style.ElementId; -import pp.dialog.Dialog; -import pp.dialog.StateCheckboxModel; -import pp.dialog.TextInputDialog; - -import java.io.File; -import java.io.IOException; -import java.util.prefs.Preferences; - -import static pp.battleship.Resources.lookup; -import static pp.util.PreferencesUtils.getPreferences; - -/** - * The Menu class represents the main menu in the Battleship game application. - * It extends the Dialog class and provides functionalities for loading, saving, - * returning to the game, and quitting the application. - */ -class Menu extends Dialog { - private static final Preferences PREFERENCES = getPreferences(Menu.class); - private static final String LAST_PATH = "last.file.path"; - private final BattleshipApp app; - private final Button loadButton = new Button(lookup("menu.map.load")); - private final Button saveButton = new Button(lookup("menu.map.save")); - - /** - * Constructs the Menu dialog for the Battleship application. - * - * @param app the BattleshipApp instance - */ - 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(loadButton) - .addClickCommands(s -> ifTopDialog(this::loadDialog)); - addChild(saveButton) - .addClickCommands(s -> ifTopDialog(this::saveDialog)); - addChild(new Button(lookup("menu.return-to-game"))) - .addClickCommands(s -> ifTopDialog(this::close)); - addChild(new Button(lookup("menu.quit"))) - .addClickCommands(s -> ifTopDialog(app::closeApp)); - update(); - } - - /** - * Updates the state of the load and save buttons based on the game logic. - */ - @Override - public void update() { - loadButton.setEnabled(app.getGameLogic().mayLoadMap()); - saveButton.setEnabled(app.getGameLogic().maySaveMap()); - } - - /** - * As an escape action, this method closes the menu if it is the top dialog. - */ - @Override - public void escape() { - close(); - } - - /** - * Functional interface for file actions. - */ - @FunctionalInterface - private interface FileAction { - /** - * Executes a file action. - * - * @param file the file to be processed - * @throws IOException if an I/O error occurs - */ - void run(File file) throws IOException; - } - - /** - * Handles the file action for the provided dialog. - * - * @param fileAction the file action to be executed - * @param dialog the dialog providing the file input - */ - private void handle(FileAction fileAction, TextInputDialog dialog) { - try { - final String path = dialog.getInput().getText(); - PREFERENCES.put(LAST_PATH, path); - fileAction.run(new File(path)); - dialog.close(); - } - catch (IOException e) { - app.errorDialog(e.getLocalizedMessage()); - } - } - - /** - * Shows a file dialog for loading or saving files. - * - * @param fileAction the action to perform with the selected file - * @param label the label for the dialog - */ - private void fileDialog(FileAction fileAction, String label) { - final TextInputDialog dialog = - TextInputDialog.builder(app.getDialogManager()) - .setLabel(lookup("label.file")) - .setFocus(TextInputDialog::getInput) - .setTitle(label) - .setOkButton(lookup("button.ok"), d -> handle(fileAction, d)) - .setNoButton(lookup("button.cancel")) - .setOkClose(false) - .build(); - final String path = PREFERENCES.get(LAST_PATH, null); - if (path != null) - dialog.getInput().setText(path.trim()); - dialog.open(); - } - - /** - * Shows the load dialog for loading maps. - */ - private void loadDialog() { - fileDialog(app.getGameLogic()::loadMap, lookup("menu.map.load")); - } - - /** - * Shows the save dialog for saving maps. - */ - private void saveDialog() { - fileDialog(app.getGameLogic()::saveMap, lookup("menu.map.save")); - } -} diff --git a/Projekte/battleship/client/src/main/java/pp/battleship/client/NetworkDialog.java b/Projekte/battleship/client/src/main/java/pp/battleship/client/NetworkDialog.java deleted file mode 100644 index 3f2f5a6..0000000 --- a/Projekte/battleship/client/src/main/java/pp/battleship/client/NetworkDialog.java +++ /dev/null @@ -1,153 +0,0 @@ -//////////////////////////////////////// -// 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.simsilica.lemur.Container; -import com.simsilica.lemur.Label; -import com.simsilica.lemur.TextField; -import com.simsilica.lemur.component.SpringGridLayout; -import pp.dialog.Dialog; -import pp.dialog.DialogBuilder; -import pp.dialog.SimpleDialog; - -import java.lang.System.Logger; -import java.lang.System.Logger.Level; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; - -import static pp.battleship.Resources.lookup; - -/** - * Represents a dialog for setting up a network connection in the Battleship game. - * Allows users to specify the host and port for connecting to a game server. - */ -class NetworkDialog extends SimpleDialog { - private static final Logger LOGGER = System.getLogger(NetworkDialog.class.getName()); - private static final String LOCALHOST = "localhost"; //NON-NLS - private static final String DEFAULT_PORT = "1234"; //NON-NLS - private final NetworkSupport network; - private final TextField host = new TextField(LOCALHOST); - private final TextField port = new TextField(DEFAULT_PORT); - private String hostname; - private int portNumber; - private Future