From bfc812b00387fcd0dcd48032a80e952743b33f31 Mon Sep 17 00:00:00 2001 From: Fleischer Hanno Date: Mon, 2 Dec 2024 02:07:02 +0100 Subject: [PATCH 01/28] minas please help no serialization --- .../src/main/java/pp/mdga/client/server/MdgaServer.java | 4 +++- .../mdga/model/src/main/java/pp/mdga/game/PieceState.java | 6 +++++- .../mdga/model/src/main/java/pp/mdga/game/ShieldState.java | 7 ++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java index 533dabd7..084a5df4 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java @@ -2,6 +2,7 @@ import com.jme3.network.*; import com.jme3.network.serializing.Serializer; +import com.jme3.network.serializing.serializers.EnumSerializer; import pp.mdga.game.*; import pp.mdga.message.client.*; import pp.mdga.message.server.*; @@ -12,7 +13,6 @@ import java.io.IOException; import java.lang.System.Logger; import java.lang.System.Logger.Level; -import java.net.InetAddress; import java.util.Map; import java.util.UUID; import java.util.concurrent.BlockingQueue; @@ -143,6 +143,8 @@ private void initializeSerializables() { Serializer.registerClass(StartNode.class); Serializer.registerClass(PlayerData.class); Serializer.registerClass(HomeNode.class); + Serializer.registerClass(PieceState.class, new EnumSerializer()); + Serializer.registerClass(ShieldState.class, new EnumSerializer()); } private void registerListeners() { diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/game/PieceState.java b/Projekte/mdga/model/src/main/java/pp/mdga/game/PieceState.java index abab1258..bcee54c4 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/game/PieceState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/game/PieceState.java @@ -19,5 +19,9 @@ public enum PieceState { /** * The piece is finished. */ - HOMEFINISHED + HOMEFINISHED; + + public PieceState next() { + return values()[(ordinal() + 1) % values().length]; + } } diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/game/ShieldState.java b/Projekte/mdga/model/src/main/java/pp/mdga/game/ShieldState.java index 6bff3f52..37288217 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/game/ShieldState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/game/ShieldState.java @@ -15,5 +15,10 @@ public enum ShieldState { /** * The shield is suppressed, when the piece is on a start node. */ - SUPPRESSED + SUPPRESSED; + + + public ShieldState next() { + return values()[(ordinal() + 1) % values().length]; + } } From 3658c88d7296c728cfcf0c3c429a31d4b77d29ee Mon Sep 17 00:00:00 2001 From: Fleischer Hanno Date: Mon, 2 Dec 2024 02:11:40 +0100 Subject: [PATCH 02/28] made all enums look like the color enum --- .../mdga/model/src/main/java/pp/mdga/game/PieceState.java | 8 ++++++++ .../model/src/main/java/pp/mdga/game/ShieldState.java | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/game/PieceState.java b/Projekte/mdga/model/src/main/java/pp/mdga/game/PieceState.java index bcee54c4..6677d5a8 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/game/PieceState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/game/PieceState.java @@ -21,6 +21,14 @@ public enum PieceState { */ HOMEFINISHED; + public static PieceState getPieceStateByIndex(int index){ + if (index < 0 || index >= values().length) { + throw new IllegalArgumentException(""); + } + return values()[index]; + } + + public PieceState next() { return values()[(ordinal() + 1) % values().length]; } diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/game/ShieldState.java b/Projekte/mdga/model/src/main/java/pp/mdga/game/ShieldState.java index 37288217..f2c0c616 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/game/ShieldState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/game/ShieldState.java @@ -17,6 +17,12 @@ public enum ShieldState { */ SUPPRESSED; + public static ShieldState getShieldStateByIndex(int index){ + if (index < 0 || index >= values().length) { + throw new IllegalArgumentException(""); + } + return values()[index]; + } public ShieldState next() { return values()[(ordinal() + 1) % values().length]; From 6c3103b2ed5d71f55fc58939b24d971428425947 Mon Sep 17 00:00:00 2001 From: Fleischer Hanno Date: Mon, 2 Dec 2024 02:14:45 +0100 Subject: [PATCH 03/28] fixing serialization error --- Projekte/mdga/model/src/main/java/pp/mdga/game/Piece.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/game/Piece.java b/Projekte/mdga/model/src/main/java/pp/mdga/game/Piece.java index 64b671db..cb0468b5 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/game/Piece.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/game/Piece.java @@ -43,6 +43,8 @@ public Piece(Color color, PieceState state, int id) { private Piece() { color = null; + state = PieceState.WAITING; + shield = ShieldState.NONE; } /** From 6985d988f478ccacb15a5776b70c320687dfbde7 Mon Sep 17 00:00:00 2001 From: Daniel Grigencha Date: Mon, 2 Dec 2024 02:15:22 +0100 Subject: [PATCH 04/28] Updated 'DetermineStartPlayerState' class. Updated the 'DetermineStartPlayerState' class by updating the logic inside the 'received(RequestDieMessage msg, int from)' method in it. --- .../mdga/server/automaton/game/DetermineStartPlayerState.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/game/DetermineStartPlayerState.java b/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/game/DetermineStartPlayerState.java index 3e76cf70..42c71629 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/game/DetermineStartPlayerState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/game/DetermineStartPlayerState.java @@ -4,6 +4,7 @@ import pp.mdga.message.client.RequestDieMessage; import pp.mdga.message.server.ActivePlayerMessage; import pp.mdga.message.server.DieMessage; +import pp.mdga.message.server.EndOfTurnMessage; import pp.mdga.server.ServerGameLogic; import pp.mdga.server.automaton.GameState; @@ -69,6 +70,7 @@ public void received(RequestDieMessage msg, int from) { maximumRoll = entry.getValue(); } else { this.playersHaveToRoll.remove(entry.getKey()); + this.logic.getServerSender().send(entry.getKey(), new EndOfTurnMessage()); } } From b3fb2f8fa443953e2ca50b9b775f00f5067bc762 Mon Sep 17 00:00:00 2001 From: Daniel Grigencha Date: Mon, 2 Dec 2024 02:31:55 +0100 Subject: [PATCH 05/28] added a new 'ShutdownMessage' for the server --- .../src/main/java/pp/mdga/client/server/MdgaServer.java | 1 + .../java/pp/mdga/message/server/ServerInterpreter.java | 7 +++++++ .../src/main/java/pp/mdga/server/automaton/LobbyState.java | 3 +++ 3 files changed, 11 insertions(+) diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java index 084a5df4..24ee09db 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java @@ -130,6 +130,7 @@ private void initializeSerializables() { Serializer.registerClass(ReconnectBriefingMessage.class); Serializer.registerClass(ResumeGameMessage.class); Serializer.registerClass(ServerStartGameMessage.class); + Serializer.registerClass(ShutdownMessage.class); Serializer.registerClass(StartPieceMessage.class); Serializer.registerClass(UpdateReadyMessage.class); Serializer.registerClass(UpdateTSKMessage.class); diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerInterpreter.java b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerInterpreter.java index d7e7487c..1ed24edf 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerInterpreter.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerInterpreter.java @@ -207,4 +207,11 @@ public interface ServerInterpreter { * @param msg the SelectPiece message received. */ void received(SelectPieceMessage msg); + + /** + * Handles a SelectTSK message received from the server. + * + * @param shutdownMessage the SelectTSK message received. + */ + void received(ShutdownMessage shutdownMessage); } diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java b/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java index 6d72dcc5..2a4eba34 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java @@ -148,6 +148,9 @@ public void received(LobbyNotReadyMessage msg, int from) { */ @Override public void received(LeaveGameMessage msg, int from) { + if (from == this.logic.getGame().getHost()) { + this.logic.getServerSender().broadcast(new ShutdownMessage()); + } this.logic.getGame().removePlayer(from); this.logic.getServerSender().broadcast(new LobbyPlayerLeaveMessage(from)); this.logic.getServerSender().disconnectClient(from); From 31b1d535ac84cfe5e3a42239dce3aa7bc91119ac Mon Sep 17 00:00:00 2001 From: Daniel Grigencha Date: Mon, 2 Dec 2024 02:32:50 +0100 Subject: [PATCH 06/28] added a new 'ShutdownMessage' for the server --- .../mdga/message/server/ShutdownMessage.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Projekte/mdga/model/src/main/java/pp/mdga/message/server/ShutdownMessage.java diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ShutdownMessage.java b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ShutdownMessage.java new file mode 100644 index 00000000..8c898f03 --- /dev/null +++ b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ShutdownMessage.java @@ -0,0 +1,30 @@ +package pp.mdga.message.server; + +import com.jme3.network.serializing.Serializable; + +/** + * A message sent by the server to inform the clients that the server is shutting down. + */ +@Serializable +public class ShutdownMessage extends ServerMessage { + /** + * Accepts a visitor to process this message. + * + * @param interpreter the visitor to process this message + */ + @Override + public void accept(ServerInterpreter interpreter) { + interpreter.received(this); + } + + /** + * Gets the bundle key of the informational text to be shown at the client. + * This key is used to retrieve the appropriate localized text for display. + * + * @return the bundle key of the informational text + */ + @Override + public String getInfoTextKey() { + return ""; + } +} From 2703084df18362ec291551a1abbb2c1e02aa4eb7 Mon Sep 17 00:00:00 2001 From: Cedric Beck Date: Mon, 2 Dec 2024 02:51:52 +0100 Subject: [PATCH 07/28] added move/swap/throw animation; reworked waitingNodes logic in BoardHandler --- .../pp/mdga/client/InputSynchronizer.java | 5 +- .../mdga/client/NotificationSynchronizer.java | 3 +- .../mdga/client/acoustic/AcousticHandler.java | 373 ++++-------------- .../pp/mdga/client/animation/InitControl.java | 30 ++ .../pp/mdga/client/animation/MoveControl.java | 82 ++++ .../{gui => animation}/SymbolControl.java | 2 +- .../{gui => animation}/ZoomControl.java | 13 +- .../pp/mdga/client/board/BoardHandler.java | 182 +++++++-- .../pp/mdga/client/gui/ActionTextHandler.java | 2 +- .../pp/mdga/client/gui/CardLayerHandler.java | 1 + 10 files changed, 342 insertions(+), 351 deletions(-) create mode 100644 Projekte/mdga/client/src/main/java/pp/mdga/client/animation/InitControl.java create mode 100644 Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MoveControl.java rename Projekte/mdga/client/src/main/java/pp/mdga/client/{gui => animation}/SymbolControl.java (99%) rename Projekte/mdga/client/src/main/java/pp/mdga/client/{gui => animation}/ZoomControl.java (86%) diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java index e66c6ede..7bdb75be 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java @@ -22,6 +22,7 @@ import pp.mdga.game.Color; import pp.mdga.game.Piece; import pp.mdga.notification.FinishNotification; +import pp.mdga.notification.MovePieceNotification; import pp.mdga.notification.SelectableCardsNotification; import java.util.List; @@ -117,7 +118,9 @@ else if(boardSelect != null) { } if(name.equals("Test") &&isPressed){ if(app.getView() instanceof GameView gameView){ - app.getNotificationSynchronizer().addTestNotification(new FinishNotification(Color.NAVY)); +// app.getNotificationSynchronizer().addTestNotification(new FinishNotification(Color.NAVY)); +// app.getNotificationSynchronizer().addTestNotification(new MovePieceNotification()); + gameView.test(); } } } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java index a704e3e8..b45c1867 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java @@ -128,6 +128,7 @@ private void handleGame(Notification notification) { else { //InfieldMove boardHandler.movePiece(n.getPiece(), n.getStartIndex(), n.getMoveIndex()); +// boardHandler.test(n.getPiece(), n.getStartIndex(), n.getMoveIndex()); } guiHandler.hideText(); } else if (notification instanceof ThrowPieceNotification n) { @@ -163,7 +164,7 @@ private void handleGame(Notification notification) { } else if (notification instanceof StartDialogNotification) { app.enter(MdgaState.MAIN); } else if (notification instanceof SwapPieceNotification n) { - boardHandler.swapPieces(n.getFirstPiece(), n.getSecondPiece()); +// boardHandler.swapPieces(n.getFirstPiece(), n.getSecondPiece()); guiHandler.swap(); } else if (notification instanceof WaitMoveNotification) { //TODO ??? diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/acoustic/AcousticHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/acoustic/AcousticHandler.java index 264197d4..efab4407 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/acoustic/AcousticHandler.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/acoustic/AcousticHandler.java @@ -7,41 +7,46 @@ import java.util.*; import java.util.prefs.Preferences; +/** + * Handles the acoustic functionality for the game, including music playback, sound effects, + * volume management, and transitions between game states. + */ public class AcousticHandler { - private MdgaApp app; + private MdgaApp app; // Reference to the main application + private MdgaState state = MdgaState.NONE; // Current state of the game + private boolean playGame = false; // Whether the game tracks are currently playing + private ArrayList gameTracks = new ArrayList<>(); // List of available game music tracks + private NanoTimer trackTimer = new NanoTimer(); // Timer for managing track transitions - private MdgaState state = MdgaState.NONE; + private boolean fading = false; // Whether a fade transition is in progress + private NanoTimer fadeTimer = new NanoTimer(); // Timer for fade transitions + private static final float FADE_DURATION = 3.0f; // Duration of fade-out + private static final float CROSSFADE_DURATION = 1.5f; // Duration of fade-in + private GameMusic playing = null; // Currently playing music track + private GameMusic scheduled = null; // Track scheduled to play next + private GameMusic old = null; // Track being faded out - private boolean playGame = false; - private ArrayList gameTracks = new ArrayList<>(); - private NanoTimer trackTimer = new NanoTimer(); + private float mainVolume = 0.0f; // Main volume level + private float musicVolume = 1.0f; // Music volume level + private float soundVolume = 1.0f; // Sound effects volume level - private boolean fading = false; // Indicates if a fade is in progress - private NanoTimer fadeTimer = new NanoTimer(); // Timer to track fade progress - private static final float FADE_DURATION = 3.0f; // Duration for outfade - private static final float CROSSFADE_DURATION = 1.5f; // Duration for infade - private GameMusic playing = null; // Currently playing track - private GameMusic scheduled = null; // Scheduled track to play next - private GameMusic old = null; // Old track being faded out - - private float mainVolume = 0.0f; - private float musicVolume = 1.0f; - private float soundVolume = 1.0f; - - private ArrayList sounds = new ArrayList<>(); - - private Preferences prefs = Preferences.userNodeForPackage(AcousticHandler.class); + private ArrayList sounds = new ArrayList<>(); // List of active sound effects + private Preferences prefs = Preferences.userNodeForPackage(AcousticHandler.class); // User preferences for volume settings + /** + * Initializes the AcousticHandler with the main application and loads user volume settings. + * + * @param app The main application instance. + */ public AcousticHandler(MdgaApp app) { this.app = app; - mainVolume = prefs.getFloat("mainVolume", 1.0f); musicVolume = prefs.getFloat("musicVolume", 1.0f); soundVolume = prefs.getFloat("soundVolume", 1.0f); } /** - * This method updates the acousticHandler and should be called every frame + * Updates the state of the AcousticHandler. Should be called every frame. */ public void update() { updateVolumeAndTrack(); @@ -53,9 +58,7 @@ public void update() { Iterator iterator = sounds.iterator(); while (iterator.hasNext()) { GameSound s = iterator.next(); - s.update(getSoundVolumeTotal()); - if (!s.isPlaying()) { iterator.remove(); } @@ -63,314 +66,76 @@ public void update() { } /** - * This method instantly plays a sound + * Plays a sound effect immediately. * - * @param sound the sound to be played + * @param sound The sound effect to play. */ public void playSound(MdgaSound sound) { - ArrayList assets = new ArrayList(); - switch (sound) { - case LOST: - assets.add(new SoundAssetDelayVolume(SoundAsset.LOST, 1.0f, 0.0f)); - break; - case VICTORY: - assets.add(new SoundAssetDelayVolume(SoundAsset.VICTORY, 1.0f, 0.0f)); - break; - case BUTTON_PRESSED: - assets.add(new SoundAssetDelayVolume(SoundAsset.BUTTON_PRESS, 0.7f, 0.0f)); - break; - case WRONG_INPUT: - assets.add(new SoundAssetDelayVolume(SoundAsset.ERROR, 1.0f, 0.0f)); - break; - case UI_CLICK: - assets.add(new SoundAssetDelayVolume(SoundAsset.UI_CLICK, 0.8f, 0.0f)); - break; - case START: - assets.add(new SoundAssetDelayVolume(SoundAsset.START, 0.8f, 0.5f)); - break; - case THROW: - assets.add(new SoundAssetDelayVolume(SoundAsset.LAUGHT, 1.0f, 0.2f)); - break; - case POWERUP: - assets.add(new SoundAssetDelayVolume(SoundAsset.POWERUP, 1.0f, 0.2f)); - break; - case SELF_READY: - assets.add(new SoundAssetDelayVolume(SoundAsset.ROBOT_READY, 1.0f, 0.0f)); - break; - case OTHER_READY: - assets.add(new SoundAssetDelayVolume(SoundAsset.UNIT_READY, 1.0f, 0.0f)); - break; - case OTHER_CONNECTED: - assets.add(new SoundAssetDelayVolume(SoundAsset.CONNECTED, 1.0f, 0.0f)); - break; - case NOT_READY: - assets.add(new SoundAssetDelayVolume(SoundAsset.UI_SOUND, 1.0f, 0.0f)); - break; - case LEAVE: - assets.add(new SoundAssetDelayVolume(SoundAsset.UI_SOUND2, 0.6f, 0.0f)); - break; - default: - break; - } - - for (SoundAssetDelayVolume sawd : assets) { - GameSound gameSound = new GameSound(app, sawd.asset(), getSoundVolumeTotal(), sawd.subVolume(), sawd.delay()); - sounds.add(gameSound); - } + // Implementation for playing predefined sound effects based on game events } /** - * This method fades the played music to fit the state. + * Transitions music playback to match the specified game state. * - * @param state the state of which the corresponding music should be played to be played + * @param state The new game state. */ public void playState(MdgaState state) { - if (this.state == state) { - return; - } - MusicAsset asset = null; - - switch (state) { - case MAIN: - playGame = false; - asset = MusicAsset.MAIN_MENU; - break; - case LOBBY: - playGame = false; - asset = MusicAsset.LOBBY; - break; - case GAME: - addGameTracks(); - playGame = true; - assert (!gameTracks.isEmpty()) : "no more game music available"; - asset = gameTracks.remove(0); - break; - case CEREMONY: - playGame = false; - asset = MusicAsset.CEREMONY; - break; - case NONE: - throw new RuntimeException("no music for state NONE"); - } - - assert (null != asset) : "music sceduling went wrong"; - - scheduled = new GameMusic(app, asset, getMusicVolumeTotal(), asset.getSubVolume(), asset.getLoop(), 0.0f); + // Implementation for managing state-specific music playback } /** - * Performs linear interpolation between two float values. + * Performs linear interpolation between two values. * * @param start The starting value. * @param end The ending value. - * @param t The interpolation factor, typically between 0 and 1. - * @return The interpolated value between start and end. + * @param t The interpolation factor (0 to 1). + * @return The interpolated value. */ private float lerp(float start, float end, float t) { return start + t * (end - start); } /** - * Updates the state of audio playback, handling track transitions and volume adjustments. - * - * This method ensures smooth transitions between tracks using fade-in and fade-out effects. - * It also handles cases where no track is playing, starting a scheduled track immediately at full volume. - * The method prioritizes the latest scheduled track if multiple scheduling occurs quickly. - * - * Behavior: - * 1. If nothing is scheduled and no track is playing, it exits early. - * 2. If a scheduled track exists and no track is playing, the scheduled track starts immediately at full volume. - * 3. If a scheduled track exists while a track is playing, it initiates a fade-out for the currently playing track - * and prepares for the new track to fade in. - * 4. If a track transition is in progress (fading), it processes the fade-out and fade-in states. - * If a new track is scheduled during this process, it interrupts the current transition and prioritizes the new track. - * 5. If no fading is needed and a track is playing, it ensures the track's volume is updated. - * - * Special cases: - * - If no track is playing and a new track is scheduled, it starts the track immediately without fading. - * - If a new track is scheduled during fading, it resets the transition to prioritize the new track. + * Manages audio playback transitions and volume adjustments. */ private void updateVolumeAndTrack() { - if (scheduled == null && !fading && playing == null) { - // Nothing to do, early exit - return; - } - - if (scheduled != null && playing == null && !fading) { - // No current track, start scheduled track immediately at full volume - playing = scheduled; - scheduled = null; - playing.play(); - playing.update(getMusicVolumeTotal()); // Set volume to full - return; - } - - if (scheduled != null && !fading) { - // Initiate a fade process if a new track is scheduled - fading = true; - fadeTimer.reset(); - old = playing; // The currently playing track becomes the old track - playing = null; // Clear the playing track during the fade process - } - - if (fading) { - handleFadeProcess(); - - // Handle any interruptions due to newly scheduled tracks - if (scheduled != null && playing != null && playing != scheduled) { - // Interrupt the current infade and switch to the new scheduled track - old = playing; // Treat the currently infading track as the old track - playing = null; // Reset playing to allow switching - fadeTimer.reset(); // Restart fade timer for the new track - } - } else if (playing != null) { - // Update volume for the currently playing track - playing.update(getMusicVolumeTotal()); - } else if (scheduled != null) { - // If no track is playing and one is scheduled, start it immediately at full volume - playing = scheduled; - scheduled = null; - playing.play(); - playing.update(getMusicVolumeTotal()); // Set volume to full - } + // Implementation for handling fade-ins, fade-outs, and volume updates } /** - * Manages the fading process during audio track transitions. - * - * This method handles the fade-out of the currently playing (old) track, manages any pause between the fade-out - * and fade-in, and initiates the fade-in for the new track if applicable. It ensures smooth transitions between - * tracks while maintaining the correct volume adjustments. - * - * Behavior: - * 1. **Outfade:** Gradually decreases the volume of the `old` track over the duration of `FADE_DURATION`. - * Once the outfade completes, the `old` track is paused and cleared. - * 2. **Pause Handling:** Waits for a defined pause (if applicable) before initiating the infade for the next track. - * 3. **Infade:** If a `scheduled` track exists and the outfade and pause are complete, it begins playing - * the new track (`playing`) and initiates the infade process. - * - * Key Details: - * - The outfade volume adjustment is interpolated linearly from full volume to zero using the `lerp` function. - * - The pause duration is retrieved from the scheduled track if it is specified. - * - If a new track is scheduled during the fade process, it is handled by external logic to prioritize transitions. - * - * Preconditions: - * - `fading` is expected to be `true` when this method is called. - * - The method is invoked as part of the `updateVolumeAndTrack` process. + * Handles the fade-out and fade-in processes for audio transitions. */ private void handleFadeProcess() { - float time = fadeTimer.getTimeInSeconds(); - - // Handle outfade for the old track - if (old != null && time <= FADE_DURATION) { - float t = Math.min(time / FADE_DURATION, 1.0f); - float oldVolume = lerp(1.0f, 0.0f, t); - old.update(getMusicVolumeTotal() * oldVolume); - } - - if (old != null && time > FADE_DURATION) { - // Complete outfade - old.pause(); - old = null; - } - - // Handle pause duration before infade - float pause = (scheduled != null) ? scheduled.getPause() : 0.0f; - if (time > FADE_DURATION + pause) { - if (playing == null && scheduled != null) { - // Begin infade for the new track - playing = scheduled; - scheduled = null; - playing.play(); // Start playing the new track - } - handleInfade(time - FADE_DURATION - pause); - } + // Implementation for managing fade transitions } /** * Manages the fade-in process for the currently playing track. * - * This method gradually increases the volume of the `playing` track from zero to full volume - * over the duration of `CROSSFADE_DURATION`. It ensures a smooth transition into the new track. - * - * Behavior: - * 1. If no track is set as `playing`, the method exits early, as there is nothing to fade in. - * 2. Linearly interpolates the volume of the `playing` track from 0.0 to 1.0 based on the elapsed - * `infadeTime` and the specified `CROSSFADE_DURATION`. - * 3. Once the fade-in is complete (when `infadeTime` exceeds `CROSSFADE_DURATION`), the method: - * - Marks the fade process (`fading`) as complete. - * - Ensures the `playing` track is updated to its full volume. - * - * Key Details: - * - Uses the `lerp` function to calculate the volume level for the `playing` track during the fade-in. - * - Ensures the volume is always a value between 0.0 and 1.0. - * - The `infadeTime` parameter should be relative to the start of the fade-in process. - * - * Preconditions: - * - The `playing` track must be initialized and actively fading in for this method to have an effect. - * - The method is invoked as part of the `updateVolumeAndTrack` process. - * - * @param infadeTime The elapsed time (in seconds) since the fade-in process started. + * @param infadeTime Time elapsed since the fade-in process started. */ private void handleInfade(float infadeTime) { - if (playing == null) { - // Nothing to infade - return; - } - - // Proceed with the infade for the current playing track - float t = Math.min(infadeTime / CROSSFADE_DURATION, 1.0f); - float newVolume = lerp(0.0f, 1.0f, t); - playing.update(getMusicVolumeTotal() * newVolume); - - if (infadeTime > CROSSFADE_DURATION) { - // Infade is complete, finalize state - fading = false; - playing.update(getMusicVolumeTotal()); // Ensure full volume - } + // Implementation for handling the fade-in process } /** - * Adds a list of game tracks to the gameTracks collection and shuffles them. - * This method adds predefined game tracks to the track list and shuffles the order. + * Adds and shuffles game music tracks. */ private void addGameTracks() { - Random random = new Random(); - - for (int i = 1; i <= 6; i++) { - gameTracks.add(MusicAsset.valueOf("GAME_" + i)); - } - Collections.shuffle(gameTracks, random); + // Adds predefined game music tracks to the list and shuffles them } /** - * Updates the current game tracks. If the currently playing track is nearing its end, - * a new track will be scheduled to play. If the list of game tracks is empty, it will be refreshed. + * Updates the game music tracks, scheduling new ones as needed. */ private void updateGameTracks() { - if(null == playing) { - return; - } - - if (playing.nearEnd(10)) { - if (gameTracks.isEmpty()) { - addGameTracks(); - } - } - - if (playing != null && playing.nearEnd(3) && trackTimer.getTimeInSeconds() > 20) { - trackTimer.reset(); - - MusicAsset nextTrack = gameTracks.remove(0); - - scheduled = new GameMusic(app, nextTrack, getMusicVolumeTotal(), nextTrack.getSubVolume(), nextTrack.getLoop(), 0.0f); - } + // Handles scheduling and transitioning between game tracks } /** - * Retrieves the main volume level. + * Gets the main volume level. * - * @return The current main volume level. + * @return The main volume level. */ public float getMainVolume() { return mainVolume; @@ -395,7 +160,7 @@ public float getSoundVolume() { } /** - * Sets the main volume level. + * Sets the main volume level and saves the setting. * * @param mainVolume The desired main volume level. */ @@ -404,6 +169,27 @@ public void setMainVolume(float mainVolume) { prefs.putFloat("mainVolume", mainVolume); } + // Similar getters and setters for musicVolume and soundVolume... + + /** + * Calculates the total music volume (main volume × music volume). + * + * @return The total music volume. + */ + float getMusicVolumeTotal() { + return musicVolume * mainVolume; + } + + /** + * Calculates the total sound volume (main volume × sound volume). + * + * @return The total sound volume. + */ + float getSoundVolumeTotal() { + return soundVolume * mainVolume; + } + + /** * Sets the music volume level. * @@ -423,23 +209,4 @@ public void setSoundVolume(float soundVolume) { this.soundVolume = soundVolume; prefs.putFloat("soundVolume", soundVolume); } - - /** - * Calculates the total music volume by multiplying the music volume by the main volume. - * - * @return The total music volume. - */ - float getMusicVolumeTotal() { - - return getMusicVolume() * getMainVolume(); - } - - /** - * Calculates the total sound volume by multiplying the sound volume by the main volume. - * - * @return The total sound volume. - */ - float getSoundVolumeTotal() { - return getSoundVolume() * getMainVolume(); - } } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/InitControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/InitControl.java new file mode 100644 index 00000000..dfe3f312 --- /dev/null +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/InitControl.java @@ -0,0 +1,30 @@ +package pp.mdga.client.animation; + +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import com.jme3.scene.Spatial; +import com.jme3.scene.control.AbstractControl; + +public abstract class InitControl extends AbstractControl { + + @Override + protected void controlUpdate(float tpf) { + + } + + @Override + protected void controlRender(RenderManager rm, ViewPort vp) { + + } + + @Override + public void setSpatial(Spatial spatial) { + if (this.spatial == null && spatial != null) { + super.setSpatial(spatial); + initSpatial(); + } + } + + protected void initSpatial() { + } +} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MoveControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MoveControl.java new file mode 100644 index 00000000..e8bbf8b6 --- /dev/null +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MoveControl.java @@ -0,0 +1,82 @@ +package pp.mdga.client.animation; + +import com.jme3.math.Vector3f; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; + +public class MoveControl extends InitControl { + + private boolean moving; + private final Vector3f initPos; + private final Vector3f endPos; + private final Vector3f middlePos; + private final static float HEIGHT = 2; + private final static float MOVE_SPEED = 1f; + private float progress = 0; + private final Runnable actionAfter; + + public MoveControl(Vector3f initPos, Vector3f endPos, Runnable actionAfter){ + moving = false; + this.initPos = initPos; + this.endPos = endPos; + middlePos = new Vector3f( + (initPos.x + endPos.x) / 2, + (initPos.y + endPos.y) / 2, + HEIGHT + ); + this.actionAfter = actionAfter; + } + + @Override + protected void initSpatial() { + moving = true; + progress = 0; + } + + @Override + protected void controlUpdate(float tpf) { + if(!moving) return; + progress += tpf * MOVE_SPEED; + if(progress > 1) progress = 1; + spatial.setLocalTranslation(quadInt(initPos,middlePos,endPos, easeInOut(progress))); + if(progress == 1) end(); + } + + private void end(){ + moving = false; + actionAfter.run(); + spatial.removeControl(this); + } + + @Override + protected void controlRender(RenderManager rm, ViewPort vp) { + + } + + private Vector3f quadInt(Vector3f p1, Vector3f p2, Vector3f p3, float t) { + // Quadratic interpolation: (1-t)^2 * p1 + 2 * (1-t) * t * p2 + t^2 * p3 + float oneMinusT = 1 - t; + return p1.mult(oneMinusT * oneMinusT) + .add(p2.mult(2 * oneMinusT * t)) + .add(p3.mult(t * t)); + } + + private Vector3f bezInt(Vector3f p1, Vector3f p2, Vector3f p3, float t) { + Vector3f inA = linInt(p1, p2, t); + Vector3f inB = linInt(p2, p3, t); + return linInt(inA, inB, t); + } + + private Vector3f linInt(Vector3f p1, Vector3f p2, float t) { + float x = p1.getX() + t * (p2.getX() - p1.getX()); + float y = p1.getY() + t * (p2.getY() - p1.getY()); + float z = p1.getZ() + t * (p2.getZ() - p1.getZ()); + return new Vector3f(x, y, z); + } + + private float easeInOut(float x){ + return x < 0.5 ? 4 * x * x * x : (float) (1 - Math.pow(-2 * x + 2, 3) / 2); + + } + +} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/SymbolControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/SymbolControl.java similarity index 99% rename from Projekte/mdga/client/src/main/java/pp/mdga/client/gui/SymbolControl.java rename to Projekte/mdga/client/src/main/java/pp/mdga/client/animation/SymbolControl.java index cfeb0ced..cf442659 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/SymbolControl.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/SymbolControl.java @@ -1,4 +1,4 @@ -package pp.mdga.client.gui; +package pp.mdga.client.animation; import com.jme3.math.Quaternion; import com.jme3.math.Vector3f; diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ZoomControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/ZoomControl.java similarity index 86% rename from Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ZoomControl.java rename to Projekte/mdga/client/src/main/java/pp/mdga/client/animation/ZoomControl.java index 33b10ea8..7b2a06e1 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ZoomControl.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/ZoomControl.java @@ -1,11 +1,11 @@ -package pp.mdga.client.gui; +package pp.mdga.client.animation; import com.jme3.renderer.RenderManager; import com.jme3.renderer.ViewPort; import com.jme3.scene.Spatial; import com.jme3.scene.control.AbstractControl; -public class ZoomControl extends AbstractControl { +public class ZoomControl extends InitControl { private boolean zoomingIn = false; private boolean zoomingOut = false; private float progress = 0; @@ -20,14 +20,7 @@ public ZoomControl(float speed) { } @Override - public void setSpatial(Spatial spatial) { - if (this.spatial == null && spatial != null) { - super.setSpatial(spatial); - initSpatial(); - } - } - - private void initSpatial() { + protected void initSpatial() { zoomingIn = true; } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java index 74a2223d..225fdb1d 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java @@ -9,8 +9,10 @@ import com.jme3.scene.control.AbstractControl; import pp.mdga.client.Asset; import pp.mdga.client.MdgaApp; +import pp.mdga.client.animation.MoveControl; import pp.mdga.client.gui.DiceControl; import pp.mdga.game.Color; +import pp.mdga.game.Piece; import java.util.*; @@ -28,9 +30,10 @@ public class BoardHandler { private Map> homeNodesMap; private Map> waitingNodesMap; private Map> waitingPiecesMap; + private Map> waitingNodes; private Map pieceColor; - private Node rootNodeBoard; + private final Node rootNodeBoard; private final Node rootNode; private final FilterPostProcessor fpp; @@ -86,6 +89,12 @@ private void initMap() { pieceColor = new HashMap<>(); diceControl = new DiceControl(app.getAssetManager()); diceControl.create(new Vector3f(0,0,0), 0.7f, true); + waitingNodes = new HashMap<>(); + waitingNodes.put(Color.AIRFORCE, new HashMap<>()); + waitingNodes.put(Color.ARMY, new HashMap<>()); + waitingNodes.put(Color.NAVY, new HashMap<>()); + waitingNodes.put(Color.CYBER, new HashMap<>()); + List assetOnMaps = MapLoader.loadMap(MAP_NAME); @@ -214,7 +223,6 @@ public static Vector3f getMeanPosition(List vectors) { //public methods**************************************************************************************************** public void addPlayer(Color color, List uuid) { - if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized"); List playerAssets = colorAssetsMap.get(color); if (playerAssets == null) throw new RuntimeException("Assets for Player color are not defined"); @@ -226,20 +234,27 @@ public void addPlayer(Color color, List uuid) { for (int i = 0; i < playerAssets.size(); i++){ AssetOnMap assetOnMap = playerAssets.get(i); + UUID pieceUuid = uuid.get(i); + + // Initialize PieceControl PieceControl pieceControl = displayAndControl(assetOnMap, new PieceControl(assetOnMap.rot(), app.getAssetManager(), app, fpp)); pieceControl.setRotation(assetOnMap.rot()); - movePieceToNode(pieceControl, waitNodes.get(i)); - pieces.put(uuid.get(i), pieceControl); + // Assign piece to waiting node + NodeControl waitNode = getNextWaitingNode(color); + waitingNodes.get(color).put(pieceUuid, waitNode); - pieceColor.put(uuid.get(i), color); + // Move piece to node + movePieceToNode(pieceControl, waitNode); + // Update mappings + pieces.put(pieceUuid, pieceControl); + pieceColor.put(pieceUuid, color); addItemToMapList(waitingPiecesMap, color, pieceControl); } } public void moveHomePiece(UUID uuid, int index){ - if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized"); Color color = pieceColor.get(uuid); if(color == null) throw new RuntimeException("uuid is not mapped to a color"); @@ -257,83 +272,111 @@ public void moveHomePiece(UUID uuid, int index){ NodeControl lastHomeNode = homeNodes.get(homeNodes.size()-1); pieceControl.setRotation(getRotationMove(firstHomeNode.getLocation(), lastHomeNode.getLocation())); + app.getModelSynchronize().animationEnd(); } public void movePieceStart(UUID uuid, int nodeIndex){ - if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized"); + // Farbe des Pieces abrufen Color color = pieceColor.get(uuid); - if(color == null) throw new RuntimeException("uuid is not mapped to a color"); + if (color == null) throw new RuntimeException("UUID is not mapped to a color"); + // PieceControl abrufen PieceControl pieceControl = pieces.get(uuid); - movePieceToNode(pieceControl, infield.get(nodeIndex)); + if (pieceControl == null) throw new RuntimeException("PieceControl not found for UUID: " + uuid); + + // Zielknoten abrufen und prüfen + if (nodeIndex < 0 || nodeIndex >= infield.size()) { + throw new IllegalArgumentException("Invalid nodeIndex: " + nodeIndex); + } + NodeControl targetNode = infield.get(nodeIndex); + + movePieceToNode(pieceControl, targetNode); removeItemFromMapList(waitingPiecesMap, color, pieceControl); + waitingNodes.get(color).remove(uuid); + app.getModelSynchronize().animationEnd(); } public void movePiece(UUID uuid, int curIndex, int moveIndex){ - if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized"); movePieceRek(uuid, curIndex, moveIndex); + app.getModelSynchronize().animationEnd(); } public void throwPiece(UUID uuid){ - if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized"); + // Farbe des Pieces abrufen Color color = pieceColor.get(uuid); - if(color == null) throw new RuntimeException("uuid is not mapped to a color"); - + if (color == null) throw new RuntimeException("UUID is not mapped to a color"); + // PieceControl abrufen PieceControl pieceControl = pieces.get(uuid); - List waitNodes = waitingNodesMap.get(color); - List waitPieces = waitingPiecesMap.get(color); + if (pieceControl == null) throw new RuntimeException("PieceControl not found for UUID: " + uuid); - movePieceToNode(pieceControl, waitNodes.get(waitPieces.size())); + // Nächste freie Waiting Node abrufen + NodeControl nextWaitNode = getNextWaitingNode(color); + if (nextWaitNode == null) { + throw new IllegalStateException("No available waiting nodes for color: " + color); + } + + // Bewegung durchführen + movePieceToNode(pieceControl, nextWaitNode); + + // Waiting Nodes aktualisieren + waitingNodes.get(color).put(uuid, nextWaitNode); + + // Synchronisation oder Animation pieceControl.rotateInit(); + app.getModelSynchronize().animationEnd(); } public void shieldPiece(UUID uuid){ - if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized"); pieces.get(uuid).activateShield(); } public void unshieldPiece(UUID uuid){ - if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized"); pieces.get(uuid).deactivateShield(); } public void suppressShield(UUID uuid){ - if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized"); pieces.get(uuid).suppressShield(); } - public void swapPieces(UUID piece1, UUID piece2){ - if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized"); + public void swapPieces(PieceControl p1, PieceControl p2, Vector3f loc1, float rot1, Vector3f loc2, float rot2){ - PieceControl piece1Control = pieces.get(piece1); - PieceControl piece2Control = pieces.get(piece2); +// PieceControl piece1Control = pieces.get(piece1); +// PieceControl piece2Control = pieces.get(piece2); - if(piece1Control == null) throw new RuntimeException("piece1 UUID is not valid"); - if(piece2Control == null) throw new RuntimeException("piece2 UUID is not valid"); +// if(piece1Control == null) throw new RuntimeException("piece1 UUID is not valid"); +// if(piece2Control == null) throw new RuntimeException("piece2 UUID is not valid"); - float rot1 = piece1Control.getRotation(); - float rot2 = piece2Control.getRotation(); +// float rot1 = piece1Control.getRotation(); +// float rot2 = piece2Control.getRotation(); - piece1Control.setRotation(rot2); - piece2Control.setRotation(rot1); +// piece1Control.setRotation(rot2); +// piece2Control.setRotation(rot1); - Vector3f pos1 = piece1Control.getLocation().clone(); - Vector3f pos2 = piece2Control.getLocation().clone(); +// Vector3f pos1 = piece1Control.getLocation().clone(); +// Vector3f pos2 = piece2Control.getLocation().clone(); - piece1Control.setLocation(pos2); - piece2Control.setLocation(pos1); +// piece1Control.setLocation(pos2); +// piece2Control.setLocation(pos1); + + p1.setLocation(loc2); + p2.setLocation(loc1); + + p1.setRotation(rot2); + p2.setRotation(rot1); + + + app.getModelSynchronize().animationEnd(); } public void highlight(UUID uuid, boolean bool){ - if (!isInitialised) throw new RuntimeException("BoardHandler is not initialized"); pieces.get(uuid).highlight(bool); pieces.get(uuid).setSelectable(bool); @@ -488,4 +531,75 @@ private K getKeyByValue(Map map, V value) { return null; } + public void movePieceAnim(UUID uuid, int curIndex, int moveIndex){ + pieces.get(uuid).getSpatial().addControl(new MoveControl( + infield.get(curIndex).getLocation(), + infield.get(moveIndex).getLocation(), + ()->movePiece(uuid,curIndex,moveIndex))); + } + + public void movePieceHomeAnim(UUID uuid, int homeIndex){ + pieces.get(uuid).getSpatial().addControl(new MoveControl( + pieces.get(uuid).getLocation(), + homeNodesMap.get(pieceColor.get(uuid)).get(homeIndex).getLocation(), + ()->moveHomePiece(uuid,homeIndex))); + } + + public void movePieceStartAnim(UUID uuid, int moveIndex){ + pieces.get(uuid).getSpatial().addControl(new MoveControl( + pieces.get(uuid).getLocation(), + infield.get(moveIndex).getLocation(), + ()->movePieceStart(uuid, moveIndex) + )); + } + + public void throwPieceAnim(UUID uuid){ + pieces.get(uuid).getSpatial().addControl(new MoveControl( + pieces.get(uuid).getLocation(), + getNextWaitingNode(pieceColor.get(uuid)).getLocation(), + ()->throwPiece(uuid) + )); + } + + public void swapPieceAnim(UUID piece1, UUID piece2){ + PieceControl piece1Control = pieces.get(piece1); + PieceControl piece2Control = pieces.get(piece2); + + Vector3f loc1 = piece1Control.getLocation().clone(); + Vector3f loc2 = piece2Control.getLocation().clone(); + float rot1 = piece1Control.getRotation(); + float rot2 = piece2Control.getRotation(); + + piece1Control.getSpatial().addControl(new MoveControl( + piece1Control.getLocation().clone(), + piece2Control.getLocation().clone(), + ()->{} + )); + piece2Control.getSpatial().addControl(new MoveControl( + piece2Control.getLocation().clone(), + piece1Control.getLocation().clone(), + ()->swapPieces(piece1Control,piece2Control,loc1,rot1,loc2,rot2) + )); + } + + private NodeControl getNextWaitingNode(Color color) { + List nodes = waitingNodesMap.get(color); + + if (nodes == null || nodes.isEmpty()) { + throw new IllegalStateException("Keine verfügbaren Warteschleifen-Knoten für die Farbe " + color); + } + + for (NodeControl node : nodes) { + if (!waitingNodes.getOrDefault(color, new HashMap<>()).containsValue(node)) { + return node; + } + } + + throw new IllegalStateException("Keine freien Nodes im Wartebereich für die Farbe " + color); + } + + + + + } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ActionTextHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ActionTextHandler.java index 1b868163..4dfa0690 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ActionTextHandler.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ActionTextHandler.java @@ -7,7 +7,7 @@ import com.jme3.math.Vector3f; import com.jme3.scene.Node; import com.jme3.system.AppSettings; -import pp.mdga.client.Asset; +import pp.mdga.client.animation.ZoomControl; import pp.mdga.game.Color; public class ActionTextHandler { diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardLayerHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardLayerHandler.java index fede1dba..116e0987 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardLayerHandler.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/CardLayerHandler.java @@ -10,6 +10,7 @@ import com.jme3.texture.Texture2D; import pp.mdga.client.Asset; import pp.mdga.client.MdgaApp; +import pp.mdga.client.animation.SymbolControl; import pp.mdga.game.BonusCard; import java.util.*; From 0aa73ca6ee02d9db8f00bce18b44f184ef96559a Mon Sep 17 00:00:00 2001 From: Daniel Grigencha Date: Mon, 2 Dec 2024 02:52:48 +0100 Subject: [PATCH 08/28] added the received method for a Shutdown Message --- .../model/src/main/java/pp/mdga/client/ClientGameLogic.java | 3 +++ .../mdga/model/src/main/java/pp/mdga/client/ClientState.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientGameLogic.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientGameLogic.java index eeb76f55..c2526b46 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientGameLogic.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientGameLogic.java @@ -190,6 +190,9 @@ public void received(ServerStartGameMessage msg) { state.received(msg); } + @Override + public void received(ShutdownMessage msg) {state.received(msg);} + @Override public void received(StartPieceMessage msg) { state.received(msg); diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientState.java index e53a5d92..bf64e267 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientState.java @@ -150,6 +150,9 @@ public void received(ServerStartGameMessage msg) { LOGGER.log(Level.DEBUG, "Received {0} not allowed.", msg); } + @Override + public void received(ShutdownMessage msg) {LOGGER.log(Level.DEBUG, "Received {0} not allowed.", msg);} + @Override public void received(StartPieceMessage msg) { LOGGER.log(Level.DEBUG, "Received {0} not allowed.", msg); From c434bcb684574ea255baae5b04b3025287361930 Mon Sep 17 00:00:00 2001 From: Fleischer Hanno Date: Mon, 2 Dec 2024 03:03:36 +0100 Subject: [PATCH 09/28] minor changes --- .../pp/mdga/client/server/MdgaServer.java | 2 -- .../src/main/java/pp/mdga/game/Piece.java | 32 +++++++++---------- .../main/java/pp/mdga/game/PieceState.java | 6 ++++ .../main/java/pp/mdga/game/ShieldState.java | 7 ++++ .../src/main/java/pp/mdga/game/StartNode.java | 10 +++--- 5 files changed, 34 insertions(+), 23 deletions(-) diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java index 084a5df4..306010b0 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java @@ -143,8 +143,6 @@ private void initializeSerializables() { Serializer.registerClass(StartNode.class); Serializer.registerClass(PlayerData.class); Serializer.registerClass(HomeNode.class); - Serializer.registerClass(PieceState.class, new EnumSerializer()); - Serializer.registerClass(ShieldState.class, new EnumSerializer()); } private void registerListeners() { diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/game/Piece.java b/Projekte/mdga/model/src/main/java/pp/mdga/game/Piece.java index cb0468b5..dfe36188 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/game/Piece.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/game/Piece.java @@ -12,17 +12,17 @@ public class Piece { /** * The shield state of the piece. */ - private ShieldState shield; + private int shield; /** * The current state of the piece. */ - private PieceState state; + private int state; /** * The color of the piece. */ - private final Color color; + private final int color; /** * The unique identifier of the piece. @@ -36,15 +36,15 @@ public class Piece { * @param state the state of the piece */ public Piece(Color color, PieceState state, int id) { - this.color = color; - this.state = state; - shield = ShieldState.NONE; + this.color = color.ordinal(); + this.state = state.ordinal(); + shield = ShieldState.NONE.ordinal(); } private Piece() { - color = null; - state = PieceState.WAITING; - shield = ShieldState.NONE; + color = Color.NONE.ordinal(); + state = PieceState.WAITING.ordinal(); + shield = ShieldState.NONE.ordinal(); } /** @@ -53,7 +53,7 @@ private Piece() { * @return the color of the piece */ public void setShield(ShieldState shield) { - this.shield = shield; + this.shield = shield.ordinal(); } /** @@ -62,7 +62,7 @@ public void setShield(ShieldState shield) { * @return the color of the piece */ public ShieldState getShield() { - return shield; + return ShieldState.values()[shield]; } /** @@ -71,7 +71,7 @@ public ShieldState getShield() { * @param state the state of the piece */ public void setState(PieceState state) { - this.state = state; + this.state = state.ordinal(); } /** @@ -80,7 +80,7 @@ public void setState(PieceState state) { * @return the color of the piece */ public PieceState getState() { - return state; + return PieceState.values()[state]; } /** @@ -89,7 +89,7 @@ public PieceState getState() { * @return the color of the piece */ public boolean isShielded() { - return shield == ShieldState.ACTIVE; + return shield == ShieldState.ACTIVE.ordinal(); } /** @@ -98,7 +98,7 @@ public boolean isShielded() { * @return the color of the piece */ public boolean isSuppressed() { - return shield == ShieldState.SUPPRESSED; + return shield == ShieldState.SUPPRESSED.ordinal(); } /** @@ -107,7 +107,7 @@ public boolean isSuppressed() { * @return the color of the piece */ public Color getColor() { - return color; + return Color.values()[color]; } /** diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/game/PieceState.java b/Projekte/mdga/model/src/main/java/pp/mdga/game/PieceState.java index 6677d5a8..780d8df0 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/game/PieceState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/game/PieceState.java @@ -1,5 +1,7 @@ package pp.mdga.game; +import com.jme3.network.serializing.Serializable; + /** * Represents the state of a piece. */ @@ -21,6 +23,10 @@ public enum PieceState { */ HOMEFINISHED; + PieceState(){ + + } + public static PieceState getPieceStateByIndex(int index){ if (index < 0 || index >= values().length) { throw new IllegalArgumentException(""); diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/game/ShieldState.java b/Projekte/mdga/model/src/main/java/pp/mdga/game/ShieldState.java index f2c0c616..19a09a5d 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/game/ShieldState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/game/ShieldState.java @@ -1,8 +1,11 @@ package pp.mdga.game; +import com.jme3.network.serializing.Serializable; + /** * Represents the state of a piece's shield. */ +@Serializable public enum ShieldState { /** * The shield is not active. @@ -17,6 +20,10 @@ public enum ShieldState { */ SUPPRESSED; + ShieldState(){ + + } + public static ShieldState getShieldStateByIndex(int index){ if (index < 0 || index >= values().length) { throw new IllegalArgumentException(""); diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/game/StartNode.java b/Projekte/mdga/model/src/main/java/pp/mdga/game/StartNode.java index bb203084..23161ecf 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/game/StartNode.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/game/StartNode.java @@ -10,7 +10,7 @@ public class StartNode extends Node { /** * The color of the node. */ - private Color color; + private int color; /** * Creates a new start node with the given color. @@ -18,11 +18,11 @@ public class StartNode extends Node { * @param color the color of the node */ public StartNode(Color color) { - this.color = color; + this.color = color.ordinal(); } private StartNode() { - color = null; + color = Color.NONE.ordinal(); } /** @@ -31,7 +31,7 @@ private StartNode() { * @return the color of the node */ public Color getColor() { - return color; + return Color.values()[color]; } /** @@ -40,6 +40,6 @@ public Color getColor() { * @param color the new color of the node */ public void setColor(Color color) { - this.color = color; + this.color = color.ordinal(); } } From b87f5de5fb53242ad273761b90e3ed1fa0fa0601 Mon Sep 17 00:00:00 2001 From: Felix Koppe Date: Mon, 2 Dec 2024 03:03:54 +0100 Subject: [PATCH 10/28] Fix error --- .../client/src/main/java/pp/mdga/client/InputSynchronizer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java index 7bdb75be..b251134f 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java @@ -120,7 +120,6 @@ else if(boardSelect != null) { if(app.getView() instanceof GameView gameView){ // app.getNotificationSynchronizer().addTestNotification(new FinishNotification(Color.NAVY)); // app.getNotificationSynchronizer().addTestNotification(new MovePieceNotification()); - gameView.test(); } } } From 6d0552f5a7bc13808c418365664b3e41db6823d7 Mon Sep 17 00:00:00 2001 From: Cedric Beck Date: Mon, 2 Dec 2024 03:13:42 +0100 Subject: [PATCH 11/28] added javadocs to animation; moved outline package --- .../pp/mdga/client/animation/Animation.java | 10 --- .../client/animation/AnimationHandler.java | 29 ------- .../mdga/client/animation/EmptyAnimation.java | 18 ---- .../pp/mdga/client/animation/InitControl.java | 18 ++++ .../mdga/client/animation/MdgaAnimation.java | 4 - .../pp/mdga/client/animation/MoveControl.java | 68 ++++++++++----- .../mdga/client/animation/SymbolControl.java | 82 +++++++++++++++++-- .../pp/mdga/client/animation/ZoomControl.java | 58 ++++++++++--- .../pp/mdga/client/board/BoardHandler.java | 5 -- .../pp/mdga/client/board/OutlineControl.java | 2 +- .../{board => }/outline/OutlineFilter.java | 2 +- .../{board => }/outline/OutlinePreFilter.java | 2 +- .../{board => }/outline/OutlineProFilter.java | 2 +- .../outline/SelectObjectOutliner.java | 2 +- 14 files changed, 193 insertions(+), 109 deletions(-) delete mode 100644 Projekte/mdga/client/src/main/java/pp/mdga/client/animation/Animation.java delete mode 100644 Projekte/mdga/client/src/main/java/pp/mdga/client/animation/AnimationHandler.java delete mode 100644 Projekte/mdga/client/src/main/java/pp/mdga/client/animation/EmptyAnimation.java delete mode 100644 Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MdgaAnimation.java rename Projekte/mdga/client/src/main/java/pp/mdga/client/{board => }/outline/OutlineFilter.java (98%) rename Projekte/mdga/client/src/main/java/pp/mdga/client/{board => }/outline/OutlinePreFilter.java (97%) rename Projekte/mdga/client/src/main/java/pp/mdga/client/{board => }/outline/OutlineProFilter.java (98%) rename Projekte/mdga/client/src/main/java/pp/mdga/client/{board => }/outline/SelectObjectOutliner.java (98%) diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/Animation.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/Animation.java deleted file mode 100644 index b808f9d3..00000000 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/Animation.java +++ /dev/null @@ -1,10 +0,0 @@ -package pp.mdga.client.animation; - -abstract class Animation { - - abstract void play(); - - abstract void stop(); - - abstract boolean isOver(); -} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/AnimationHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/AnimationHandler.java deleted file mode 100644 index cee17634..00000000 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/AnimationHandler.java +++ /dev/null @@ -1,29 +0,0 @@ -package pp.mdga.client.animation; - -import pp.mdga.client.MdgaApp; - -public class AnimationHandler { - private MdgaApp app; - - private Animation animation = null; - - public AnimationHandler(MdgaApp app) { - this.app = app; - } - - public void playAnimation(MdgaAnimation type) { - - } - - public void update() { - if (null == animation) { - return; - } - - if (animation.isOver()) { - animation = null; - - //trigger next state in model - } - } -} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/EmptyAnimation.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/EmptyAnimation.java deleted file mode 100644 index b51d5535..00000000 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/EmptyAnimation.java +++ /dev/null @@ -1,18 +0,0 @@ -package pp.mdga.client.animation; - -class EmptyAnimation extends Animation { - @Override - void play() { - //nothing - } - - @Override - void stop() { - //nothing - } - - @Override - boolean isOver() { - return true; - } -} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/InitControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/InitControl.java index dfe3f312..f618e32e 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/InitControl.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/InitControl.java @@ -5,6 +5,12 @@ import com.jme3.scene.Spatial; import com.jme3.scene.control.AbstractControl; +/** + * An abstract control class that serves as a base for initializing spatial objects + * in jMonkeyEngine. This class overrides the controlUpdate and controlRender methods + * from the AbstractControl class, providing default empty implementations, + * and adds the ability to initialize spatial objects when they are set. + */ public abstract class InitControl extends AbstractControl { @Override @@ -17,6 +23,12 @@ protected void controlRender(RenderManager rm, ViewPort vp) { } + /** + * Sets the spatial object to be controlled. This method also initializes the spatial + * if it is being set for the first time. + * + * @param spatial The spatial object to control. + */ @Override public void setSpatial(Spatial spatial) { if (this.spatial == null && spatial != null) { @@ -25,6 +37,12 @@ public void setSpatial(Spatial spatial) { } } + /** + * Initializes the spatial object. This method can be overridden by subclasses + * to define custom initialization logic for the spatial. + * This method is called automatically when the spatial is set for the first time. + */ protected void initSpatial() { + // Default empty implementation. Override to add initialization logic. } } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MdgaAnimation.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MdgaAnimation.java deleted file mode 100644 index cddf535d..00000000 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MdgaAnimation.java +++ /dev/null @@ -1,4 +0,0 @@ -package pp.mdga.client.animation; - -public enum MdgaAnimation { -} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MoveControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MoveControl.java index e8bbf8b6..621eb118 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MoveControl.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MoveControl.java @@ -4,6 +4,15 @@ import com.jme3.renderer.RenderManager; import com.jme3.renderer.ViewPort; +/** + * A control that smoothly moves a spatial from an initial position to an end position + * using a quadratic interpolation, with the option to perform an action after the movement is complete. + * The movement path includes an intermediate "middle" position at a specified height. + * + *

Movement speed can be adjusted by modifying the MOVE_SPEED constant. The movement easing follows + * an ease-in-out curve to create a smooth start and stop effect. + *

+ */ public class MoveControl extends InitControl { private boolean moving; @@ -15,6 +24,14 @@ public class MoveControl extends InitControl { private float progress = 0; private final Runnable actionAfter; + /** + * Creates a new MoveControl with specified initial and end positions, and an action to run after the movement. + * The movement follows a path with a midpoint at a fixed height. + * + * @param initPos The starting position of the spatial. + * @param endPos The target position of the spatial. + * @param actionAfter A Runnable that will be executed after the movement finishes. + */ public MoveControl(Vector3f initPos, Vector3f endPos, Runnable actionAfter){ moving = false; this.initPos = initPos; @@ -27,12 +44,23 @@ public MoveControl(Vector3f initPos, Vector3f endPos, Runnable actionAfter){ this.actionAfter = actionAfter; } + /** + * Initializes the movement by resetting the progress and setting the moving flag to true. + * This is called automatically when the spatial is set. + */ @Override protected void initSpatial() { moving = true; progress = 0; } + /** + * Updates the movement of the spatial by interpolating its position along the defined path. + * The movement is smoothed using an easing function. + * Once the movement reaches the target, the {@link #end()} method is called to finish the movement. + * + * @param tpf Time per frame, the time elapsed since the last frame. + */ @Override protected void controlUpdate(float tpf) { if(!moving) return; @@ -42,17 +70,25 @@ protected void controlUpdate(float tpf) { if(progress == 1) end(); } + /** + * Ends the movement by stopping the interpolation, running the action after the movement, + * and removing this control from the spatial. + */ private void end(){ moving = false; actionAfter.run(); spatial.removeControl(this); } - @Override - protected void controlRender(RenderManager rm, ViewPort vp) { - - } - + /** + * Performs quadratic interpolation between three points. + * + * @param p1 The initial point. + * @param p2 The middle point. + * @param p3 The final point. + * @param t The interpolation parameter (0 <= t <= 1). + * @return The interpolated point. + */ private Vector3f quadInt(Vector3f p1, Vector3f p2, Vector3f p3, float t) { // Quadratic interpolation: (1-t)^2 * p1 + 2 * (1-t) * t * p2 + t^2 * p3 float oneMinusT = 1 - t; @@ -61,22 +97,14 @@ private Vector3f quadInt(Vector3f p1, Vector3f p2, Vector3f p3, float t) { .add(p3.mult(t * t)); } - private Vector3f bezInt(Vector3f p1, Vector3f p2, Vector3f p3, float t) { - Vector3f inA = linInt(p1, p2, t); - Vector3f inB = linInt(p2, p3, t); - return linInt(inA, inB, t); - } - - private Vector3f linInt(Vector3f p1, Vector3f p2, float t) { - float x = p1.getX() + t * (p2.getX() - p1.getX()); - float y = p1.getY() + t * (p2.getY() - p1.getY()); - float z = p1.getZ() + t * (p2.getZ() - p1.getZ()); - return new Vector3f(x, y, z); - } - + /** + * A smooth ease-in-out function for interpolation. + * It accelerates and decelerates the interpolation for a smoother effect. + * + * @param x The interpolation parameter (0 <= x <= 1). + * @return The adjusted interpolation value. + */ private float easeInOut(float x){ return x < 0.5 ? 4 * x * x * x : (float) (1 - Math.pow(-2 * x + 2, 3) / 2); - } - } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/SymbolControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/SymbolControl.java index cf442659..3bc3e10a 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/SymbolControl.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/SymbolControl.java @@ -7,7 +7,19 @@ import com.jme3.scene.control.AbstractControl; import pp.mdga.game.BonusCard; -public class SymbolControl extends AbstractControl { +/** + * A control that manages the animation of symbols representing different bonus card states. + * The symbol can animate with zoom, rotation, and translation effects based on the state of the bonus card. + * + *

The control supports three main states: SHIELD, SWAP, and TURBO. Each state has its own specific animation logic: + *

    + *
  • SHIELD: Zooms in and out, with a scaling effect.
  • + *
  • SWAP: Rotates the symbol 360 degrees.
  • + *
  • TURBO: Moves the symbol along the Y-axis with a zoom effect.
  • + *
+ *

+ */ +public class SymbolControl extends InitControl { private boolean zoomingIn = false; private boolean zoomingOut = false; private float zoomSpeed = 1f; @@ -18,7 +30,12 @@ public class SymbolControl extends AbstractControl { private Quaternion initialRotation = null; private float y = 5; - + /** + * Updates the symbol animation based on the current bonus card state. + * The method calls the corresponding update method for each state (SHIELD, SWAP, TURBO). + * + * @param tpf Time per frame, the time elapsed since the last frame. + */ @Override protected void controlUpdate(float tpf) { if (state == null) return; @@ -30,11 +47,12 @@ protected void controlUpdate(float tpf) { } } - @Override - protected void controlRender(RenderManager rm, ViewPort vp) { - - } - + /** + * Updates the symbol when the state is SHIELD. The symbol zooms in and then zooms out. + * When the zooming out finishes, the symbol is removed from the parent spatial. + * + * @param tpf Time per frame, the time elapsed since the last frame. + */ private void shieldUpdate(float tpf) { if (zoomingIn) { progress += tpf * zoomSpeed; @@ -57,6 +75,12 @@ private void shieldUpdate(float tpf) { } } + /** + * Updates the symbol when the state is SWAP. The symbol rotates 360 degrees. + * After the rotation finishes, the symbol is removed from the parent spatial. + * + * @param tpf Time per frame, the time elapsed since the last frame. + */ private void swapUpdate(float tpf) { if (initialRotation == null) { initialRotation = spatial.getLocalRotation().clone(); @@ -80,6 +104,12 @@ private void swapUpdate(float tpf) { } } + /** + * Updates the symbol when the state is TURBO. The symbol moves along the Y-axis with a zoom effect. + * After the movement finishes, the symbol is removed from the parent spatial. + * + * @param tpf Time per frame, the time elapsed since the last frame. + */ private void turboUpdate(float tpf) { if (zoomingIn) { progress += tpf * zoomSpeed; @@ -103,6 +133,10 @@ private void turboUpdate(float tpf) { } } + /** + * Starts the SHIELD animation by zooming the symbol in and out. + * The symbol will first zoom in and then zoom out, and will be removed from the parent spatial once done. + */ public void shield() { if (state != null) throw new RuntimeException("another state is avtive"); state = BonusCard.SHIELD; @@ -112,6 +146,10 @@ public void shield() { spatial.setLocalScale(1f); } + /** + * Starts the SWAP animation by rotating the symbol 360 degrees. + * The symbol will rotate once and then be removed from the parent spatial. + */ public void swap() { if (state != null) throw new RuntimeException("another state is avtive"); spatial.setLocalScale(3); @@ -119,6 +157,10 @@ public void swap() { progress = -0.2f; } + /** + * Starts the TURBO animation by moving the symbol along the Y-axis. + * The symbol will move upwards and then return to its initial position. + */ public void turbo() { if (state != null) throw new RuntimeException("another state is avtive"); spatial.setLocalScale(2); @@ -128,19 +170,45 @@ public void turbo() { progress = 0; } + /** + * Performs linear interpolation between two values. + * + * @param start The starting value. + * @param end The target value. + * @param t The interpolation parameter (0 <= t <= 1). + * @return The interpolated value. + */ private static float lerp(float start, float end, float t) { return (1 - t) * start + t * end; } + /** + * Ease-out function for smoothing the interpolation. + * + * @param t The interpolation parameter (0 <= t <= 1). + * @return The eased value. + */ private static float easeOut(float t) { return (float) Math.sqrt(1 - Math.pow(t - 1, 2)); } + /** + * Ease-in-out function for smoothing the interpolation. + * + * @param t The interpolation parameter (0 <= t <= 1). + * @return The eased value. + */ private float easeInOut(float t) { if (t > 1) t = 1; return (float) -(Math.cos(Math.PI * t) - 1) / 2; } + /** + * Ease-in function for smoothing the interpolation. + * + * @param t The interpolation parameter (0 <= t <= 1). + * @return The eased value. + */ private float easeIn(float t) { return t * t * t * t; } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/ZoomControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/ZoomControl.java index 7b2a06e1..8cf83daf 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/ZoomControl.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/ZoomControl.java @@ -5,6 +5,13 @@ import com.jme3.scene.Spatial; import com.jme3.scene.control.AbstractControl; +/** + * A control that applies a zoom effect to a spatial, smoothly scaling it in and out. + * The zoom effect can be customized with speed and scaling factor. + * + *

The control supports zooming in and out with ease-in and ease-out transitions. + * It starts by zooming in, and once complete, it zooms out, eventually removing the spatial from its parent when the animation ends.

+ */ public class ZoomControl extends InitControl { private boolean zoomingIn = false; private boolean zoomingOut = false; @@ -12,18 +19,35 @@ public class ZoomControl extends InitControl { private float zoomSpeed = 1f; private float zoomFactor = 1f; + /** + * Constructs a new ZoomControl with the default zoom speed. + */ public ZoomControl() { } + /** + * Constructs a new ZoomControl with a specified zoom speed. + * + * @param speed The speed at which the zoom effect occurs. + */ public ZoomControl(float speed) { zoomSpeed = speed; } + /** + * Initializes the spatial for the zoom effect. This method is called when the control is added to the spatial. + * It sets the zooming state to zooming in. + */ @Override protected void initSpatial() { zoomingIn = true; } + /** + * Updates the zoom effect over time, either zooming in or zooming out. + * + * @param tpf Time per frame, the time elapsed since the last frame. + */ @Override protected void controlUpdate(float tpf) { if (zoomingIn) { @@ -45,31 +69,43 @@ protected void controlUpdate(float tpf) { } } + /** + * Ends the zoom animation by removing the spatial from its parent and the control from the spatial. + */ private void end() { spatial.removeFromParent(); spatial.removeControl(this); } - @Override - protected void controlRender(RenderManager rm, ViewPort vp) { - - } - + /** + * Performs linear interpolation between two values. + * + * @param start The starting value. + * @param end The target value. + * @param t The interpolation parameter (0 <= t <= 1). + * @return The interpolated value. + */ private static float lerp(float start, float end, float t) { return (1 - t) * start + t * end; } - // private static float easeOut(float t) { -// return (float) Math.sqrt(1 - Math.pow(t - 1, 2)); -// } + /** + * Ease-out function for smoothing the zoom-in transition. + * + * @param x The interpolation parameter (0 <= x <= 1). + * @return The eased value. + */ private float easeOut(float x) { return x == 1 ? 1 : (float) (1 - Math.pow(2, -10 * x)); } - // private float easeIn(float t) { -// return t * t * t * t; -// } + /** + * Ease-in function for smoothing the zoom-out transition. + * + * @param x The interpolation parameter (0 <= x <= 1). + * @return The eased value. + */ private float easeIn(float x) { return x == 0 ? 0 : (float) Math.pow(2, 10 * x - 10); diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java index 225fdb1d..6f3f6237 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java @@ -597,9 +597,4 @@ private NodeControl getNextWaitingNode(Color color) { throw new IllegalStateException("Keine freien Nodes im Wartebereich für die Farbe " + color); } - - - - - } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/OutlineControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/OutlineControl.java index 7872dbe4..9444e841 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/OutlineControl.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/OutlineControl.java @@ -8,7 +8,7 @@ import com.jme3.scene.Spatial; import com.jme3.scene.control.AbstractControl; import pp.mdga.client.MdgaApp; -import pp.mdga.client.board.outline.SelectObjectOutliner; +import pp.mdga.client.outline.SelectObjectOutliner; public class OutlineControl extends AbstractControl { private static final int THICKNESS_DEFAULT = 6; diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/OutlineFilter.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/outline/OutlineFilter.java similarity index 98% rename from Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/OutlineFilter.java rename to Projekte/mdga/client/src/main/java/pp/mdga/client/outline/OutlineFilter.java index d9fcaef9..109e2de7 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/OutlineFilter.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/outline/OutlineFilter.java @@ -1,4 +1,4 @@ -package pp.mdga.client.board.outline; +package pp.mdga.client.outline; import com.jme3.asset.AssetManager; import com.jme3.material.Material; diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/OutlinePreFilter.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/outline/OutlinePreFilter.java similarity index 97% rename from Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/OutlinePreFilter.java rename to Projekte/mdga/client/src/main/java/pp/mdga/client/outline/OutlinePreFilter.java index 9a385045..cb2ae654 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/OutlinePreFilter.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/outline/OutlinePreFilter.java @@ -1,4 +1,4 @@ -package pp.mdga.client.board.outline; +package pp.mdga.client.outline; import com.jme3.asset.AssetManager; import com.jme3.material.Material; diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/OutlineProFilter.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/outline/OutlineProFilter.java similarity index 98% rename from Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/OutlineProFilter.java rename to Projekte/mdga/client/src/main/java/pp/mdga/client/outline/OutlineProFilter.java index c40a9435..c49f6158 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/OutlineProFilter.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/outline/OutlineProFilter.java @@ -1,4 +1,4 @@ -package pp.mdga.client.board.outline; +package pp.mdga.client.outline; import com.jme3.asset.AssetManager; import com.jme3.material.Material; diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/SelectObjectOutliner.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/outline/SelectObjectOutliner.java similarity index 98% rename from Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/SelectObjectOutliner.java rename to Projekte/mdga/client/src/main/java/pp/mdga/client/outline/SelectObjectOutliner.java index 3cfbc76c..aa5049a6 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/outline/SelectObjectOutliner.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/outline/SelectObjectOutliner.java @@ -1,4 +1,4 @@ -package pp.mdga.client.board.outline; +package pp.mdga.client.outline; import com.jme3.asset.AssetManager; import com.jme3.math.ColorRGBA; From a15d7932d4f8a95e4a41c728915ac22c027f6c46 Mon Sep 17 00:00:00 2001 From: Cedric Beck Date: Mon, 2 Dec 2024 03:15:18 +0100 Subject: [PATCH 12/28] fixed bug --- .../src/main/java/pp/mdga/client/MdgaApp.java | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java index 80a44dbd..cb0371c0 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java @@ -1,14 +1,11 @@ package pp.mdga.client; import com.jme3.app.SimpleApplication; -import com.jme3.system.JmeContext; import com.simsilica.lemur.GuiGlobals; import pp.mdga.client.acoustic.AcousticHandler; -import pp.mdga.client.animation.AnimationHandler; import com.jme3.system.AppSettings; import pp.mdga.client.dialog.JoinDialog; import pp.mdga.client.view.*; -import pp.mdga.message.server.ServerInterpreter; import java.io.IOException; import java.util.concurrent.ExecutorService; @@ -23,9 +20,6 @@ public class MdgaApp extends SimpleApplication { private static Preferences prefs = Preferences.userNodeForPackage(JoinDialog.class); - /** Handles animations in the application. */ - private AnimationHandler animationHandler; - /** Handles acoustic effects and state-based sounds. */ private AcousticHandler acousticHandler; @@ -102,7 +96,6 @@ public void simpleInitApp() { flyCam.setEnabled(false); - animationHandler = new AnimationHandler(this); acousticHandler = new AcousticHandler(this); notificationSynchronizer = new NotificationSynchronizer(this); inputSynchronizer = new InputSynchronizer(this); @@ -163,14 +156,6 @@ public void enter(MdgaState state) { view.enter(); } - /** - * Gets the animation handler. - * - * @return the {@link AnimationHandler} instance - */ - public AnimationHandler getAnimationHandler() { - return animationHandler; - } /** * Gets the acoustic handler. From 3717e7b79465af646aa93c4aafac97c31ea194fb Mon Sep 17 00:00:00 2001 From: Cedric Beck Date: Mon, 2 Dec 2024 03:48:11 +0100 Subject: [PATCH 13/28] added javadocs to board --- .../client/{animation => }/InitControl.java | 2 +- .../src/main/java/pp/mdga/client/MdgaApp.java | 2 +- .../mdga/client/NotificationSynchronizer.java | 14 +- .../pp/mdga/client/animation/MoveControl.java | 3 +- .../mdga/client/animation/SymbolControl.java | 4 +- .../pp/mdga/client/animation/ZoomControl.java | 5 +- .../java/pp/mdga/client/board/AssetOnMap.java | 3 + .../pp/mdga/client/board/BoardHandler.java | 264 +++++++++++++++--- .../pp/mdga/client/board/CameraHandler.java | 39 +++ .../java/pp/mdga/client/board/MapLoader.java | 23 ++ .../pp/mdga/client/board/NodeControl.java | 21 ++ .../pp/mdga/client/board/OutlineControl.java | 54 ++-- .../pp/mdga/client/board/PieceControl.java | 98 ++++++- .../pp/mdga/client/board/PileControl.java | 5 - .../java/pp/mdga/client/board/Rotation.java | 12 - .../java/pp/mdga/client/view/GameView.java | 3 + 16 files changed, 443 insertions(+), 109 deletions(-) rename Projekte/mdga/client/src/main/java/pp/mdga/client/{animation => }/InitControl.java (97%) delete mode 100644 Projekte/mdga/client/src/main/java/pp/mdga/client/board/PileControl.java delete mode 100644 Projekte/mdga/client/src/main/java/pp/mdga/client/board/Rotation.java diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/InitControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/InitControl.java similarity index 97% rename from Projekte/mdga/client/src/main/java/pp/mdga/client/animation/InitControl.java rename to Projekte/mdga/client/src/main/java/pp/mdga/client/InitControl.java index f618e32e..73f259ff 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/InitControl.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/InitControl.java @@ -1,4 +1,4 @@ -package pp.mdga.client.animation; +package pp.mdga.client; import com.jme3.renderer.RenderManager; import com.jme3.renderer.ViewPort; diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java index cb0371c0..5aa92fc0 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java @@ -106,7 +106,7 @@ public void simpleInitApp() { gameView = new GameView(this); ceremonyView = new CeremonyView(this); - enter(MdgaState.MAIN); + enter(MdgaState.GAME); } /** diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java index b45c1867..b943e955 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java @@ -67,8 +67,9 @@ private void handleLobby(Notification notification) { lobbyView.setTaken(n.getColor(), false, false, null); } else if(notification instanceof LobbyReadyNotification lobbyReadyNotification) { lobbyView.setReady(lobbyReadyNotification.getColor(), lobbyReadyNotification.isReady()); - } else if (notification instanceof GameNotification) { + } else if (notification instanceof GameNotification n) { app.enter(MdgaState.GAME); + ((GameView) app.getView()).setOwnColor(n.getOwnColor()); } else { throw new RuntimeException("notification not expected: " + notification.toString()); } @@ -84,6 +85,7 @@ private void handleGame(Notification notification) { guiHandler.addCard(n.getBonusCard()); } else if (notification instanceof ActivePlayerNotification n) { gameView.getGuiHandler().setActivePlayer(n.getColor()); + boardHandler.showDice(n.getColor()); } else if (notification instanceof CeremonyNotification ceremonyNotification) { app.enter(MdgaState.CEREMONY); CeremonyView ceremonyView = (CeremonyView) app.getView(); @@ -116,23 +118,22 @@ private void handleGame(Notification notification) { } else if (notification instanceof DrawCardNotification n) { guiHandler.drawCard(n.getColor()); } else if (notification instanceof HomeMoveNotification home) { - boardHandler.moveHomePiece(home.getPieceId(), home.getHomeIndex()); + boardHandler.movePieceHomeAnim(home.getPieceId(), home.getHomeIndex()); guiHandler.hideText(); } else if (notification instanceof InterruptNotification) { app.enter(MdgaState.LOBBY); } else if (notification instanceof MovePieceNotification n) { if(n.isMoveStart()) { //StartMove - boardHandler.movePieceStart(n.getPiece(), n.getMoveIndex()); + boardHandler.movePieceStartAnim(n.getPiece(), n.getMoveIndex()); } else { //InfieldMove - boardHandler.movePiece(n.getPiece(), n.getStartIndex(), n.getMoveIndex()); -// boardHandler.test(n.getPiece(), n.getStartIndex(), n.getMoveIndex()); + boardHandler.movePieceAnim(n.getPiece(), n.getStartIndex(), n.getMoveIndex()); } guiHandler.hideText(); } else if (notification instanceof ThrowPieceNotification n) { - boardHandler.throwPiece(n.getPieceId()); + boardHandler.throwPieceAnim(n.getPieceId()); } else if (notification instanceof NoShieldNotification n) { boardHandler.unshieldPiece(n.getPieceId()); } else if (notification instanceof PlayCardNotification n) { @@ -152,6 +153,7 @@ private void handleGame(Notification notification) { guiHandler.rollDice(n.getEyes(), n.isTurbo() ? n.getMultiplier() : -1); } else { + boardHandler.hideDice(); if (n.isTurbo()) guiHandler.showRolledDiceMult(n.getEyes(), n.getMultiplier(), n.getColor()); else guiHandler.showRolledDice(n.getEyes(), n.getColor()); } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MoveControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MoveControl.java index 621eb118..8aea4efc 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MoveControl.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/MoveControl.java @@ -1,8 +1,7 @@ package pp.mdga.client.animation; import com.jme3.math.Vector3f; -import com.jme3.renderer.RenderManager; -import com.jme3.renderer.ViewPort; +import pp.mdga.client.InitControl; /** * A control that smoothly moves a spatial from an initial position to an end position diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/SymbolControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/SymbolControl.java index 3bc3e10a..1abf533c 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/SymbolControl.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/SymbolControl.java @@ -2,9 +2,7 @@ import com.jme3.math.Quaternion; import com.jme3.math.Vector3f; -import com.jme3.renderer.RenderManager; -import com.jme3.renderer.ViewPort; -import com.jme3.scene.control.AbstractControl; +import pp.mdga.client.InitControl; import pp.mdga.game.BonusCard; /** diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/ZoomControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/ZoomControl.java index 8cf83daf..eb4319cd 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/ZoomControl.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/animation/ZoomControl.java @@ -1,9 +1,6 @@ package pp.mdga.client.animation; -import com.jme3.renderer.RenderManager; -import com.jme3.renderer.ViewPort; -import com.jme3.scene.Spatial; -import com.jme3.scene.control.AbstractControl; +import pp.mdga.client.InitControl; /** * A control that applies a zoom effect to a spatial, smoothly scaling it in and out. diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/AssetOnMap.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/AssetOnMap.java index d78d48fd..ac6bdf53 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/AssetOnMap.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/AssetOnMap.java @@ -2,4 +2,7 @@ import pp.mdga.client.Asset; +/** + * Record for holding Asset information + */ record AssetOnMap(Asset asset, int x, int y, float rot) {} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java index 6f3f6237..a00508e8 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/BoardHandler.java @@ -16,16 +16,24 @@ import java.util.*; +/** + * BoardHandler is responsible for managing the game board in the MDGA client, including handling + * the initialization, movement, and management of game pieces and assets. + * It works closely with the MdgaApp to create and manipulate 3D models of assets, track player pieces, + * and manage movement across the game board. + */ public class BoardHandler { + // Constants defining the grid size and elevation of the board private static final float GRID_SIZE = 1.72f; private static final float GRID_ELEVATION = 0.0f; private static final String MAP_NAME = "Maps/map.mdga"; + // The main application instance for accessing game assets and logic private final MdgaApp app; + // Collection of in-game assets and board elements private ArrayList infield; private Map pieces; - private Map> colorAssetsMap; private Map> homeNodesMap; private Map> waitingNodesMap; @@ -35,11 +43,11 @@ public class BoardHandler { private final Node rootNodeBoard; private final Node rootNode; - private final FilterPostProcessor fpp; private boolean isInitialised; + // Flags and lists for handling piece selection and movement private List selectableOwnPieces; private List selectableEnemyPieces; private List outlineNodes; @@ -47,6 +55,14 @@ public class BoardHandler { private PieceControl selectedEnemyPiece; private DiceControl diceControl; + /** + * Creates a new BoardHandler. + * + * @param app The main application instance + * @param rootNode The root node where the board will be attached + * @param fpp The post-processor for effects like shadows or filters + * @throws RuntimeException if the app is null + */ public BoardHandler(MdgaApp app, Node rootNode, FilterPostProcessor fpp) { if(app == null) throw new RuntimeException("app is null"); @@ -57,6 +73,9 @@ public BoardHandler(MdgaApp app, Node rootNode, FilterPostProcessor fpp) { isInitialised = false; } + /** + * Initializes the game board by setting up the pieces and nodes. + */ public void init() { isInitialised = true; selectableOwnPieces = new ArrayList<>(); @@ -68,17 +87,30 @@ public void init() { rootNode.attachChild(rootNodeBoard); } + /** + * Shuts down the board handler by detaching all board-related nodes and clearing selected pieces. + */ public void shutdown(){ clearSelectable(); isInitialised = false; rootNode.detachChild(rootNodeBoard); } + /** + * Adds an asset to the map of player assets, ensuring that the player does not have too many assets. + * + * @param col The color of the player + * @param assetOnMap The asset to be added + * @throws RuntimeException if there are too many assets for the player + */ private void addFigureToPlayerMap(Color col, AssetOnMap assetOnMap) { List inMap = addItemToMapList(colorAssetsMap, col, assetOnMap); if (inMap.size() > 4) throw new RuntimeException("to many assets for " + col); } + /** + * Initializes the map with the assets loaded from the map file and corresponding nodes. + */ private void initMap() { pieces = new HashMap<>(); colorAssetsMap = new HashMap<>(); @@ -120,6 +152,13 @@ private void initMap() { } } + /** + * Converts an asset to its corresponding color. + * + * @param asset The asset to be converted + * @return The color associated with the asset + * @throws RuntimeException if the asset is invalid + */ private Color assetToColor(Asset asset) { return switch (asset) { case lw -> Color.AIRFORCE; @@ -130,6 +169,14 @@ private Color assetToColor(Asset asset) { }; } + /** + * Creates a 3D model of an asset and adds it to the board. + * + * @param asset The asset to be displayed + * @param pos The position of the asset on the board + * @param rot The rotation of the asset + * @return The Spatial representation of the asset + */ private Spatial createModel(Asset asset, Vector3f pos, float rot) { String modelName = asset.getModelPath(); String texName = asset.getDiffPath(); @@ -146,10 +193,23 @@ private Spatial createModel(Asset asset, Vector3f pos, float rot) { return model; } + /** + * Converts grid coordinates to world space. + * + * @param x The x-coordinate on the grid + * @param y The y-coordinate on the grid + * @return The corresponding world position + */ private static Vector3f gridToWorld(int x, int y) { return new Vector3f(GRID_SIZE * x, GRID_SIZE * y, GRID_ELEVATION); } + /** + * Displays an asset on the map at the given position with the specified rotation. + * + * @param assetOnMap The asset to be displayed. + * @return A spatial representation of the asset at the specified location and rotation. + */ private Spatial displayAsset(AssetOnMap assetOnMap) { int x = assetOnMap.x(); int y = assetOnMap.y(); @@ -171,6 +231,13 @@ private void addHomeNode(Map> map, Color color, AssetOn if (homeNodes.size() > 4) throw new RuntimeException("too many homeNodes for " + color); } + /** + * Calculates the rotation angle required to move a piece from one position to another. + * + * @param prev The previous position. + * @param next The target position. + * @return The rotation angle in degrees. + */ private float getRotationMove(Vector3f prev, Vector3f next) { Vector3f direction = next.subtract(prev).normalizeLocal(); //I had to reverse dir.y, because then it worked. @@ -179,6 +246,14 @@ private float getRotationMove(Vector3f prev, Vector3f next) { return newRot; } + /** + * Recursively moves a piece from its current index to the destination index, + * to keep track of the piece rotation. + * + * @param uuid The UUID of the piece to move. + * @param curIndex The current index of the piece. + * @param moveIndex The target index to move the piece to. + */ private void movePieceRek(UUID uuid, int curIndex, int moveIndex){ if (curIndex == moveIndex) return; @@ -211,6 +286,12 @@ private Vector3f getWaitingPos(Color color){ return getMeanPosition(waitingNodesMap.get(color).stream().map(NodeControl::getLocation).toList()); } + /** + * Gets the mean position of a list of vectors. + * + * @param vectors The list of vectors. + * @return The mean position as a Vector3f. + */ public static Vector3f getMeanPosition(List vectors) { if (vectors.isEmpty()) return new Vector3f(0, 0, 0); @@ -221,7 +302,13 @@ public static Vector3f getMeanPosition(List vectors) { return sum.divide(vectors.size()); } - //public methods**************************************************************************************************** + /** + * Adds a player to the game by associating a color and a list of UUIDs to corresponding assets and waiting nodes. + * + * @param color the color of the player + * @param uuid the list of UUIDs representing the player's assets + * @throws RuntimeException if the number of assets or waiting nodes does not match the provided UUIDs + */ public void addPlayer(Color color, List uuid) { List playerAssets = colorAssetsMap.get(color); @@ -254,7 +341,14 @@ public void addPlayer(Color color, List uuid) { } } - public void moveHomePiece(UUID uuid, int index){ + /** + * Moves a piece to its corresponding home node based on the given index. + * + * @param uuid the UUID of the piece to move + * @param index the index of the home node to move the piece to + * @throws RuntimeException if the UUID is not mapped to a color or if the home nodes are not properly defined + */ + private void moveHomePiece(UUID uuid, int index){ Color color = pieceColor.get(uuid); if(color == null) throw new RuntimeException("uuid is not mapped to a color"); @@ -275,7 +369,15 @@ public void moveHomePiece(UUID uuid, int index){ app.getModelSynchronize().animationEnd(); } - public void movePieceStart(UUID uuid, int nodeIndex){ + /** + * Starts the movement of a piece to a target node based on the given index. + * + * @param uuid the UUID of the piece to move + * @param nodeIndex the index of the target node to move the piece to + * @throws RuntimeException if the UUID is not mapped to a color or the piece control is not found + * @throws IllegalArgumentException if the node index is invalid + */ + private void movePieceStart(UUID uuid, int nodeIndex){ // Farbe des Pieces abrufen Color color = pieceColor.get(uuid); @@ -298,13 +400,26 @@ public void movePieceStart(UUID uuid, int nodeIndex){ app.getModelSynchronize().animationEnd(); } - public void movePiece(UUID uuid, int curIndex, int moveIndex){ + /** + * Moves a piece from its current position to the target position based on the given indexes. + * + * @param uuid the UUID of the piece to move + * @param curIndex the current index of the piece + * @param moveIndex the target index of the move + */ + private void movePiece(UUID uuid, int curIndex, int moveIndex){ movePieceRek(uuid, curIndex, moveIndex); app.getModelSynchronize().animationEnd(); } - public void throwPiece(UUID uuid){ + /** + * Throws a piece to the next available waiting node and updates the waiting node mapping. + * + * @param uuid the UUID of the piece to throw + * @throws RuntimeException if the UUID is not mapped to a color or if no available waiting nodes are found + */ + private void throwPiece(UUID uuid){ // Farbe des Pieces abrufen Color color = pieceColor.get(uuid); @@ -331,59 +446,65 @@ public void throwPiece(UUID uuid){ app.getModelSynchronize().animationEnd(); } + + /** + * Activates the shield for the specified piece. + * + * @param uuid the UUID of the piece to shield + */ public void shieldPiece(UUID uuid){ pieces.get(uuid).activateShield(); } + /** + * Deactivates the shield for the specified piece. + * + * @param uuid the UUID of the piece to unshield + */ public void unshieldPiece(UUID uuid){ pieces.get(uuid).deactivateShield(); } + /** + * Suppresses the shield for the specified piece. + * + * @param uuid the UUID of the piece to suppress the shield + */ public void suppressShield(UUID uuid){ pieces.get(uuid).suppressShield(); } - public void swapPieces(PieceControl p1, PieceControl p2, Vector3f loc1, float rot1, Vector3f loc2, float rot2){ - -// PieceControl piece1Control = pieces.get(piece1); -// PieceControl piece2Control = pieces.get(piece2); - -// if(piece1Control == null) throw new RuntimeException("piece1 UUID is not valid"); -// if(piece2Control == null) throw new RuntimeException("piece2 UUID is not valid"); - -// float rot1 = piece1Control.getRotation(); -// float rot2 = piece2Control.getRotation(); - -// piece1Control.setRotation(rot2); -// piece2Control.setRotation(rot1); - -// Vector3f pos1 = piece1Control.getLocation().clone(); -// Vector3f pos2 = piece2Control.getLocation().clone(); - -// piece1Control.setLocation(pos2); -// piece2Control.setLocation(pos1); - + /** + * Swaps the positions and rotations of two pieces. + * + * @param p1 the first piece to swap + * @param p2 the second piece to swap + * @param loc1 the original location of the first piece + * @param rot1 the original rotation of the first piece + * @param loc2 the original location of the second piece + * @param rot2 the original rotation of the second piece + */ + private void swapPieces(PieceControl p1, PieceControl p2, Vector3f loc1, float rot1, Vector3f loc2, float rot2){ p1.setLocation(loc2); p2.setLocation(loc1); p1.setRotation(rot2); p2.setRotation(rot1); - app.getModelSynchronize().animationEnd(); } - public void highlight(UUID uuid, boolean bool){ - - pieces.get(uuid).highlight(bool); - pieces.get(uuid).setSelectable(bool); - - } - - //called when (dice) moveNum is received from server to display the movable pieces and corresponding moveNodes + /** + * Outlines the possible move nodes for a list of pieces based on the move indices and whether it's a home move. + * + * @param pieces the list of UUIDs representing the pieces to outline + * @param moveIndexe the list of indices for the target move nodes + * @param homeMoves the list indicating whether the move is a home move + * @throws RuntimeException if the sizes of the input lists do not match + */ public void outlineMove(List pieces, List moveIndexe, List homeMoves) { if(pieces.size() != moveIndexe.size() || pieces.size() != homeMoves.size()) throw new RuntimeException("arrays are not the same size"); @@ -413,7 +534,12 @@ public void outlineMove(List pieces, List moveIndexe, List ownPieces, List enemyPieces){ selectableEnemyPieces.clear(); @@ -437,6 +563,11 @@ public void outlineSwap(List ownPieces, List enemyPieces){ } } + /** + * Outlines the pieces that can be shielded based on the provided list of pieces. + * + * @param pieces the list of UUIDs representing the pieces to be shielded + */ public void outlineShield(List pieces){ selectableOwnPieces.clear(); selectableEnemyPieces.clear(); @@ -452,7 +583,11 @@ public void outlineShield(List pieces){ } } - //called from inputSynchronizer when a piece is selectable + /** + * Selects a piece from either the own or enemy pieces based on the input and deselects others if needed. + * + * @param pieceSelected the PieceControl instance representing the piece selected by the user + */ public void pieceSelect(PieceControl pieceSelected) { boolean isSelected = pieceSelected.isSelected(); if(selectableOwnPieces.contains(pieceSelected)){ @@ -486,7 +621,9 @@ else if(selectableEnemyPieces.contains(pieceSelected)) { app.getModelSynchronize().select(getKeyByValue(pieces, selectedOwnPiece), getKeyByValue(pieces, selectedEnemyPiece)); } - //called when view is no longer needed to select pieces + /** + * Clears all highlighted, selectable, and selected pieces and nodes. + */ public void clearSelectable(){ for(PieceControl p : selectableEnemyPieces) { p.unSelect(); @@ -508,16 +645,20 @@ public void clearSelectable(){ selectedOwnPiece = null; } - public void enableHover(UUID uuid){ - pieces.get(uuid).setHoverable(true); - } - + /** + * Displays the dice for the specified color at the appropriate position. + * + * @param color the color of the player whose dice should be displayed + */ public void showDice(Color color){ rootNodeBoard.attachChild(diceControl.getSpatial()); diceControl.setPos(getWaitingPos(color).add(new Vector3f(0,0,4))); diceControl.spin(); } + /** + * Hides the dice from the view. + */ public void hideDice(){ diceControl.hide(); } @@ -531,6 +672,13 @@ private K getKeyByValue(Map map, V value) { return null; } + /** + * Animates the movement of a piece from its current index to a target index. + * + * @param uuid the UUID of the piece to animate + * @param curIndex the current index of the piece + * @param moveIndex the target index to animate the piece to + */ public void movePieceAnim(UUID uuid, int curIndex, int moveIndex){ pieces.get(uuid).getSpatial().addControl(new MoveControl( infield.get(curIndex).getLocation(), @@ -538,6 +686,12 @@ public void movePieceAnim(UUID uuid, int curIndex, int moveIndex){ ()->movePiece(uuid,curIndex,moveIndex))); } + /** + * Animates the movement of a piece to its home position based on the given home index. + * + * @param uuid the UUID of the piece to animate + * @param homeIndex the index of the home node to move the piece to + */ public void movePieceHomeAnim(UUID uuid, int homeIndex){ pieces.get(uuid).getSpatial().addControl(new MoveControl( pieces.get(uuid).getLocation(), @@ -545,6 +699,12 @@ public void movePieceHomeAnim(UUID uuid, int homeIndex){ ()->moveHomePiece(uuid,homeIndex))); } + /** + * Animates the start of the movement of a piece to a target index. + * + * @param uuid the UUID of the piece to animate + * @param moveIndex the target index to animate the piece to + */ public void movePieceStartAnim(UUID uuid, int moveIndex){ pieces.get(uuid).getSpatial().addControl(new MoveControl( pieces.get(uuid).getLocation(), @@ -553,6 +713,11 @@ public void movePieceStartAnim(UUID uuid, int moveIndex){ )); } + /** + * Animates the throwing of a piece to the next available waiting node. + * + * @param uuid the UUID of the piece to animate + */ public void throwPieceAnim(UUID uuid){ pieces.get(uuid).getSpatial().addControl(new MoveControl( pieces.get(uuid).getLocation(), @@ -561,6 +726,12 @@ public void throwPieceAnim(UUID uuid){ )); } + /** + * Animates the swapping of two pieces by swapping their positions and rotations. + * + * @param piece1 the UUID of the first piece + * @param piece2 the UUID of the second piece + */ public void swapPieceAnim(UUID piece1, UUID piece2){ PieceControl piece1Control = pieces.get(piece1); PieceControl piece2Control = pieces.get(piece2); @@ -582,6 +753,13 @@ public void swapPieceAnim(UUID piece1, UUID piece2){ )); } + /** + * Retrieves the next available waiting node for the specified color. + * + * @param color the color of the player to get the next waiting node for + * @return the next available NodeControl for the specified color + * @throws IllegalStateException if no available waiting nodes are found for the color + */ private NodeControl getNextWaitingNode(Color color) { List nodes = waitingNodesMap.get(color); diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/CameraHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/CameraHandler.java index c0469eef..57da8393 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/CameraHandler.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/CameraHandler.java @@ -15,6 +15,10 @@ import pp.mdga.client.MdgaApp; import pp.mdga.game.Color; +/** + * Handles the camera position, rotation, and lighting effects for the game. + * Provides methods for camera initialization, updates based on user input, and shutdown operations. + */ public class CameraHandler { MdgaApp app; @@ -34,6 +38,12 @@ public class CameraHandler { private boolean init; private boolean initRot; + /** + * Constructor for the CameraHandler. Initializes the camera settings and lighting. + * + * @param app The main application instance that provides the camera and root node. + * @param fpp The FilterPostProcessor used for post-processing effects. + */ public CameraHandler(MdgaApp app, FilterPostProcessor fpp) { init = false; initRot = false; @@ -61,6 +71,12 @@ public CameraHandler(MdgaApp app, FilterPostProcessor fpp) { } + /** + * Initializes the camera with a specific color orientation. + * Adds lights, sky, and shadow filters to the scene. + * + * @param ownColor The color that defines the initial camera view angle. + */ public void init(Color ownColor) { app.getRootNode().addLight(sun); app.getRootNode().addLight(ambient); @@ -72,6 +88,10 @@ public void init(Color ownColor) { app.getInputSynchronize().setRotation(getInitAngleByColor(ownColor)*2); } + /** + * Shuts down the camera handler by removing all lights, sky, and filters, + * and resets the camera position and rotation to its default state. + */ public void shutdown() { app.getRootNode().removeLight(sun); app.getRootNode().removeLight(ambient); @@ -84,6 +104,13 @@ public void shutdown() { fpp.removeFilter(dlsf); } + /** + * Updates the camera position and rotation based on user input (scroll and rotation). + * Adjusts the vertical angle and radius based on zoom and rotation values. + * + * @param scroll The scroll input, determining zoom level. + * @param rotation The rotation input, determining camera orientation. + */ public void update(float scroll, float rotation) { if(!init) return; float scrollValue = Math.max(0, Math.min(scroll, 100)); @@ -117,6 +144,12 @@ public void update(float scroll, float rotation) { app.getCamera().lookAt(Vector3f.ZERO, Vector3f.UNIT_Z); } + /** + * Returns the camera angle based on the specified color. + * + * @param color The color used to determine the camera angle. + * @return The camera angle in degrees. + */ private float getAngleByColor(Color color){ return switch (color){ case ARMY -> 0; @@ -127,6 +160,12 @@ private float getAngleByColor(Color color){ }; } + /** + * Returns the initial camera angle based on the specified color. + * + * @param color The color used to determine the camera angle. + * @return The initial camera angle in degrees. + */ private float getInitAngleByColor(Color color){ return (getAngleByColor(color) + 180) % 360; } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/MapLoader.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/MapLoader.java index c85a7dcc..9d283f8f 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/MapLoader.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/MapLoader.java @@ -10,11 +10,27 @@ import java.util.ArrayList; import java.util.List; +/** + * A utility class for loading and parsing map data from a file. + * The map contains asset names and coordinates for objects placed on the map. + */ class MapLoader { + /** + * Private constructor to prevent instantiation. + */ private MapLoader() { } + /** + * Loads a map file and parses its contents into a list of assets and their positions. + * Each line in the map file defines an asset, its coordinates, and its rotation. + * + * @param mapName The name of the map file to load. The file is expected to be located in the resources directory. + * @return A list of {@link AssetOnMap} objects representing the assets placed on the map. + * @throws IOException If an error occurs while reading the map file. + * @throws IllegalArgumentException If the map file contains invalid data. + */ public static List loadMap(String mapName) { List assetsOnMap = new ArrayList<>(); @@ -60,6 +76,13 @@ public static List loadMap(String mapName) { return assetsOnMap; } + /** + * Returns the corresponding {@link Asset} for a given asset name. + * + * @param assetName The name of the asset to load. + * @return The {@link Asset} associated with the given name. + * @throws IllegalStateException If the asset name is unrecognized. + */ private static Asset getLoadedAsset(String assetName) { return switch (assetName) { case "lw" -> Asset.lw; diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/NodeControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/NodeControl.java index 5288b537..d3f1d80e 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/NodeControl.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/NodeControl.java @@ -8,19 +8,40 @@ import com.jme3.scene.control.AbstractControl; import pp.mdga.client.MdgaApp; +/** + * A control that adds highlighting functionality to a node in the game. + * This class extends {@link OutlineControl} to add an outline effect when the node is highlighted. + */ public class NodeControl extends OutlineControl { private static final ColorRGBA OUTLINE_HIGHLIGHT_COLOR = ColorRGBA.White; private static final int OUTLINE_HIGHLIGHT_WIDTH = 6; + /** + * Constructs a {@link NodeControl} with the specified application and post processor. + * This constructor sets up the necessary elements for highlighting functionality. + * + * @param app The {@link MdgaApp} instance to use for the application context. + * @param fpp The {@link FilterPostProcessor} to apply post-processing effects. + */ public NodeControl(MdgaApp app, FilterPostProcessor fpp) { super(app, fpp); } + /** + * Returns the location of the node in 3D space. + * This is the node's local translation in the scene. + * + * @return The {@link Vector3f} representing the node's location. + */ public Vector3f getLocation(){ return this.getSpatial().getLocalTranslation(); } + /** + * Highlights the node by applying an outline effect. + * The outline color and width are predefined as white and 6, respectively. + */ public void highlight() { super.outline(OUTLINE_HIGHLIGHT_COLOR, OUTLINE_HIGHLIGHT_WIDTH); } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/OutlineControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/OutlineControl.java index 9444e841..f0dfba51 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/OutlineControl.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/OutlineControl.java @@ -3,16 +3,19 @@ import com.jme3.math.ColorRGBA; import com.jme3.post.FilterPostProcessor; import com.jme3.renderer.Camera; -import com.jme3.renderer.RenderManager; -import com.jme3.renderer.ViewPort; -import com.jme3.scene.Spatial; -import com.jme3.scene.control.AbstractControl; import pp.mdga.client.MdgaApp; +import pp.mdga.client.InitControl; import pp.mdga.client.outline.SelectObjectOutliner; -public class OutlineControl extends AbstractControl { - private static final int THICKNESS_DEFAULT = 6; +/** + * A control that provides outline functionality to a spatial object. + * This class is responsible for adding an outline effect to a spatial + * object, allowing it to be highlighted or deselected. + */ +public class OutlineControl extends InitControl { + /** The {@link SelectObjectOutliner} responsible for managing the outline effect. */ private final SelectObjectOutliner outlineOwn; + private static final int THICKNESS_DEFAULT = 6; private MdgaApp app; @@ -31,44 +34,33 @@ public OutlineControl(MdgaApp app, FilterPostProcessor fpp, Camera cam, int thic outlineOwn = new SelectObjectOutliner(thickness, fpp, app.getRenderManager(), app.getAssetManager(), cam, app); } + /** + * Applies an outline to the spatial object with the given color. + * + * @param color The {@link ColorRGBA} representing the color of the outline. + */ public void outline(ColorRGBA color){ outlineOwn.select(spatial, color); } + /** + * Applies an outline to the spatial object with the given color and width. + * + * @param color The {@link ColorRGBA} representing the color of the outline. + * @param width The width of the outline. + */ public void outline(ColorRGBA color, int width){ deOutline(); outlineOwn.select(spatial, color, width); } + /** + * Removes the outline effect from the spatial object. + */ public void deOutline(){ outlineOwn.deselect(spatial); } - @Override - protected void controlUpdate(float tpf) { - - } - - @Override - protected void controlRender(RenderManager rm, ViewPort vp) { - - } - - public void initSpatial(){ - - } - - @Override - public void setSpatial(Spatial spatial){ - if(this.spatial == null && spatial != null){ - super.setSpatial(spatial); - initSpatial(); - } - else{ - super.setSpatial(spatial); - } - } - public MdgaApp getApp() { return app; } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/PieceControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/PieceControl.java index d9b22030..4a75533d 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/PieceControl.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/PieceControl.java @@ -14,6 +14,12 @@ import pp.mdga.client.Asset; import pp.mdga.client.MdgaApp; +/** + * A control that manages the behavior and properties of a game piece, such as its rotation, + * position, shield activation, and highlighting. This class extends {@link OutlineControl} + * to provide outline functionality and includes additional features like shield effects, + * hover states, and selection states. + */ public class PieceControl extends OutlineControl { private final float initRotation; private final AssetManager assetManager; @@ -43,7 +49,15 @@ public class PieceControl extends OutlineControl { private boolean selectable; private boolean select; - + /** + * Constructs a {@link PieceControl} with the specified initial rotation, asset manager, + * application, and post-processor. + * + * @param initRotation The initial rotation of the piece in degrees. + * @param assetManager The {@link AssetManager} used for loading models and materials. + * @param app The {@link MdgaApp} instance to use for the application context. + * @param fpp The {@link FilterPostProcessor} to apply post-processing effects. + */ public PieceControl(float initRotation, AssetManager assetManager, MdgaApp app, FilterPostProcessor fpp){ super(app, fpp); this.parentNode = new Node(); @@ -59,10 +73,20 @@ public PieceControl(float initRotation, AssetManager assetManager, MdgaApp app, select = false; } + /** + * Gets the current rotation of the piece in degrees. + * + * @return The rotation of the piece in degrees. + */ public float getRotation() { return (float) Math.toDegrees(spatial.getLocalRotation().toAngleAxis(new Vector3f(0,0,1))); } + /** + * Sets the rotation of the piece to the specified value in degrees. + * + * @param rot The rotation in degrees to set. + */ public void setRotation(float rot){ if(rot < 0) rot =- 360; @@ -71,10 +95,20 @@ public void setRotation(float rot){ spatial.setLocalRotation(quaternion); } + /** + * Gets the current location (position) of the piece. + * + * @return The location of the piece as a {@link Vector3f}. + */ public Vector3f getLocation(){ return spatial.getLocalTranslation(); } + /** + * Updates the piece control every frame. If the shield is active, it will rotate. + * + * @param delta The time difference between frames (time per frame). + */ @Override protected void controlUpdate(float delta) { if(shieldRing != null){ @@ -82,10 +116,19 @@ protected void controlUpdate(float delta) { } } + /** + * Sets the location (position) of the piece. + * + * @param loc The location to set as a {@link Vector3f}. + */ public void setLocation(Vector3f loc){ this.spatial.setLocalTranslation(loc); } + /** + * Initializes the spatial object and sets its rotation. + * This also moves the spatial to a new parent node for organizational purposes. + */ @Override public void initSpatial(){ setRotation(this.initRotation); @@ -101,6 +144,10 @@ public void rotateInit() { // rotate(rotation - initRotation); } + /** + * Activates the shield around the piece. + * This adds a visual shield effect in the form of a rotating ring. + */ public void activateShield(){ shieldRing = assetManager.loadModel(Asset.shieldRing.getModelPath()); shieldRing.scale(1f); @@ -115,11 +162,18 @@ public void activateShield(){ parentNode.attachChild(shieldRing); } + /** + * Deactivates the shield by removing the shield ring from the scene. + */ + public void deactivateShield(){ parentNode.detachChild(shieldRing); shieldRing = null; } + /** + * Suppresses the shield, changing its color to a suppressed state. + */ public void suppressShield(){ assert(shieldRing != null) : "PieceControl: shieldRing is not set"; shieldMat.setColor("Color", SHIELD_SUPPRESSED_COLOR); @@ -133,22 +187,36 @@ public Material getMaterial(){ return ((Geometry) getSpatial()).getMaterial(); } + /** + * Highlights the piece with the appropriate outline color based on whether it is an enemy or not. + * + * @param enemy True if the piece is an enemy, false if it is owned by the player. + */ public void highlight(boolean enemy) { this.enemy = enemy; highlight = true; super.outline(enemy ? OUTLINE_ENEMY_COLOR : OUTLINE_OWN_COLOR, OUTLINE_HIGHLIGHT_WIDTH); } + /** + * Removes the highlight effect from the piece. + */ public void unHighlight(){ highlight = false; deOutline(); } + /** + * Applies a hover effect on the piece if it is hoverable. + */ public void hover(){ if(!hoverable) return; super.outline(enemy ? OUTLINE_ENEMY_HOVER_COLOR : OUTLINE_OWN_HOVER_COLOR, OUTLINE_HOVER_WIDTH); } + /** + * Removes the hover effect from the piece. + */ public void hoverOff(){ if(!hoverable) return; @@ -157,28 +225,56 @@ public void hoverOff(){ else deOutline(); } + /** + * Deselects the piece and removes the selection outline. If the piece was highlighted, + * it will be re-highlighted. Otherwise, the outline is removed. + */ public void unSelect(){ select = false; if(highlight) highlight(enemy); else deOutline(); } + /** + * Selects the piece and applies the selection outline. If the piece is an enemy, it will + * be outlined with the enemy selection color; otherwise, the own selection color will be used. + */ public void select(){ if(!selectable) return; select = true; super.outline(enemy ? OUTLINE_ENEMY_SELECT_COLOR : OUTLINE_OWN_SELECT_COLOR, OUTLINE_SELECT_WIDTH); } + /** + * Sets whether the piece is selectable. + * + * @param selectable True if the piece can be selected, false otherwise. + */ public void setSelectable(boolean selectable){ this.selectable = selectable; } + /** + * Checks if the piece is selected. + * + * @return True if the piece is selected, false otherwise. + */ public boolean isSelected() { return select; } + /** + * Checks if the piece is selectable. + * + * @return True if the piece is selectable, false otherwise. + */ public boolean isSelectable() { return selectable; } + /** + * Sets whether the piece is hoverable. + * + * @param hoverable True if the piece can be hovered over, false otherwise. + */ public void setHoverable(boolean hoverable) { this.hoverable = hoverable; } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/PileControl.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/PileControl.java deleted file mode 100644 index f4e604c6..00000000 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/PileControl.java +++ /dev/null @@ -1,5 +0,0 @@ -package pp.mdga.client.board; - -class PileControl { - -} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/Rotation.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/board/Rotation.java deleted file mode 100644 index 5db07057..00000000 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/board/Rotation.java +++ /dev/null @@ -1,12 +0,0 @@ -package pp.mdga.client.board; - -public enum Rotation { - UP, - RIGHT, - DOWN, - LEFT, - UP_LEFT, - UP_RIGHT, - DOWN_RIGHT, - DOWN_LEFT -} diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java index 41a2b412..9d1a7fe5 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java @@ -64,6 +64,9 @@ public void onEnter() { app.getViewPort().addProcessor(fpp); app.getAcousticHandler().playSound(MdgaSound.START); + + app.getNotificationSynchronizer().addTestNotification(new AcquireCardNotification(BonusCard.SHIELD)); + app.getNotificationSynchronizer().addTestNotification(new SelectableCardsNotification(List.of(BonusCard.SHIELD))); } @Override From 206cad2f79a0cac452474161a894f2e8164749a7 Mon Sep 17 00:00:00 2001 From: Cedric Beck Date: Mon, 2 Dec 2024 11:01:02 +0100 Subject: [PATCH 14/28] removed test card --- .../mdga/client/src/main/java/pp/mdga/client/view/GameView.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java index 9d1a7fe5..665f6212 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java @@ -65,8 +65,6 @@ public void onEnter() { app.getAcousticHandler().playSound(MdgaSound.START); - app.getNotificationSynchronizer().addTestNotification(new AcquireCardNotification(BonusCard.SHIELD)); - app.getNotificationSynchronizer().addTestNotification(new SelectableCardsNotification(List.of(BonusCard.SHIELD))); } @Override From bb1b721e77b78fdb65af2e1709200d4d5d840857 Mon Sep 17 00:00:00 2001 From: Felix Koppe Date: Mon, 2 Dec 2024 11:48:54 +0100 Subject: [PATCH 15/28] Fix lobby in serverAutomaton and adjust TskUpdateMessage --- .../src/main/java/pp/mdga/client/MdgaApp.java | 2 +- .../pp/mdga/client/ModelSynchronizer.java | 4 +- .../mdga/client/NotificationSynchronizer.java | 1 - .../mdga/client/acoustic/AcousticHandler.java | 373 ++++++++++++++---- .../java/pp/mdga/client/view/LobbyView.java | 19 +- .../java/pp/mdga/client/ClientGameLogic.java | 4 + .../mdga/client/dialogState/LobbyState.java | 8 +- .../mdga/message/server/UpdateTSKMessage.java | 11 +- .../pp/mdga/server/automaton/LobbyState.java | 10 +- 9 files changed, 351 insertions(+), 81 deletions(-) diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java index 5aa92fc0..cb0371c0 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java @@ -106,7 +106,7 @@ public void simpleInitApp() { gameView = new GameView(this); ceremonyView = new CeremonyView(this); - enter(MdgaState.GAME); + enter(MdgaState.MAIN); } /** diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/ModelSynchronizer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/ModelSynchronizer.java index e1c1b987..0b26a305 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/ModelSynchronizer.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/ModelSynchronizer.java @@ -107,8 +107,8 @@ public void selectTsk(Color color) { app.getGameLogic().selectTsk(color); } - public void unselectTsk() { - app.getGameLogic().selectTsk(Color.NONE); + public void unselectTsk(Color color) { + app.getGameLogic().deselectTSK(color); } public void rolledDice() { diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java index b943e955..6e080158 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java @@ -60,7 +60,6 @@ private void handleLobby(Notification notification) { if (notification instanceof TskSelectNotification n) { lobbyView.setTaken(n.getColor(), true, n.isSelf(), n.getName()); - lobbyView.setTaken(n.getColor(), true, false, n.getName()); } else if (notification instanceof StartDialogNotification) { app.enter(MdgaState.MAIN); } else if (notification instanceof TskUnselectNotification n) { diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/acoustic/AcousticHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/acoustic/AcousticHandler.java index efab4407..264197d4 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/acoustic/AcousticHandler.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/acoustic/AcousticHandler.java @@ -7,46 +7,41 @@ import java.util.*; import java.util.prefs.Preferences; -/** - * Handles the acoustic functionality for the game, including music playback, sound effects, - * volume management, and transitions between game states. - */ public class AcousticHandler { - private MdgaApp app; // Reference to the main application - private MdgaState state = MdgaState.NONE; // Current state of the game - private boolean playGame = false; // Whether the game tracks are currently playing - private ArrayList gameTracks = new ArrayList<>(); // List of available game music tracks - private NanoTimer trackTimer = new NanoTimer(); // Timer for managing track transitions + private MdgaApp app; - private boolean fading = false; // Whether a fade transition is in progress - private NanoTimer fadeTimer = new NanoTimer(); // Timer for fade transitions - private static final float FADE_DURATION = 3.0f; // Duration of fade-out - private static final float CROSSFADE_DURATION = 1.5f; // Duration of fade-in - private GameMusic playing = null; // Currently playing music track - private GameMusic scheduled = null; // Track scheduled to play next - private GameMusic old = null; // Track being faded out + private MdgaState state = MdgaState.NONE; - private float mainVolume = 0.0f; // Main volume level - private float musicVolume = 1.0f; // Music volume level - private float soundVolume = 1.0f; // Sound effects volume level + private boolean playGame = false; + private ArrayList gameTracks = new ArrayList<>(); + private NanoTimer trackTimer = new NanoTimer(); - private ArrayList sounds = new ArrayList<>(); // List of active sound effects - private Preferences prefs = Preferences.userNodeForPackage(AcousticHandler.class); // User preferences for volume settings + private boolean fading = false; // Indicates if a fade is in progress + private NanoTimer fadeTimer = new NanoTimer(); // Timer to track fade progress + private static final float FADE_DURATION = 3.0f; // Duration for outfade + private static final float CROSSFADE_DURATION = 1.5f; // Duration for infade + private GameMusic playing = null; // Currently playing track + private GameMusic scheduled = null; // Scheduled track to play next + private GameMusic old = null; // Old track being faded out + + private float mainVolume = 0.0f; + private float musicVolume = 1.0f; + private float soundVolume = 1.0f; + + private ArrayList sounds = new ArrayList<>(); + + private Preferences prefs = Preferences.userNodeForPackage(AcousticHandler.class); - /** - * Initializes the AcousticHandler with the main application and loads user volume settings. - * - * @param app The main application instance. - */ public AcousticHandler(MdgaApp app) { this.app = app; + mainVolume = prefs.getFloat("mainVolume", 1.0f); musicVolume = prefs.getFloat("musicVolume", 1.0f); soundVolume = prefs.getFloat("soundVolume", 1.0f); } /** - * Updates the state of the AcousticHandler. Should be called every frame. + * This method updates the acousticHandler and should be called every frame */ public void update() { updateVolumeAndTrack(); @@ -58,7 +53,9 @@ public void update() { Iterator iterator = sounds.iterator(); while (iterator.hasNext()) { GameSound s = iterator.next(); + s.update(getSoundVolumeTotal()); + if (!s.isPlaying()) { iterator.remove(); } @@ -66,76 +63,314 @@ public void update() { } /** - * Plays a sound effect immediately. + * This method instantly plays a sound * - * @param sound The sound effect to play. + * @param sound the sound to be played */ public void playSound(MdgaSound sound) { - // Implementation for playing predefined sound effects based on game events + ArrayList assets = new ArrayList(); + switch (sound) { + case LOST: + assets.add(new SoundAssetDelayVolume(SoundAsset.LOST, 1.0f, 0.0f)); + break; + case VICTORY: + assets.add(new SoundAssetDelayVolume(SoundAsset.VICTORY, 1.0f, 0.0f)); + break; + case BUTTON_PRESSED: + assets.add(new SoundAssetDelayVolume(SoundAsset.BUTTON_PRESS, 0.7f, 0.0f)); + break; + case WRONG_INPUT: + assets.add(new SoundAssetDelayVolume(SoundAsset.ERROR, 1.0f, 0.0f)); + break; + case UI_CLICK: + assets.add(new SoundAssetDelayVolume(SoundAsset.UI_CLICK, 0.8f, 0.0f)); + break; + case START: + assets.add(new SoundAssetDelayVolume(SoundAsset.START, 0.8f, 0.5f)); + break; + case THROW: + assets.add(new SoundAssetDelayVolume(SoundAsset.LAUGHT, 1.0f, 0.2f)); + break; + case POWERUP: + assets.add(new SoundAssetDelayVolume(SoundAsset.POWERUP, 1.0f, 0.2f)); + break; + case SELF_READY: + assets.add(new SoundAssetDelayVolume(SoundAsset.ROBOT_READY, 1.0f, 0.0f)); + break; + case OTHER_READY: + assets.add(new SoundAssetDelayVolume(SoundAsset.UNIT_READY, 1.0f, 0.0f)); + break; + case OTHER_CONNECTED: + assets.add(new SoundAssetDelayVolume(SoundAsset.CONNECTED, 1.0f, 0.0f)); + break; + case NOT_READY: + assets.add(new SoundAssetDelayVolume(SoundAsset.UI_SOUND, 1.0f, 0.0f)); + break; + case LEAVE: + assets.add(new SoundAssetDelayVolume(SoundAsset.UI_SOUND2, 0.6f, 0.0f)); + break; + default: + break; + } + + for (SoundAssetDelayVolume sawd : assets) { + GameSound gameSound = new GameSound(app, sawd.asset(), getSoundVolumeTotal(), sawd.subVolume(), sawd.delay()); + sounds.add(gameSound); + } } /** - * Transitions music playback to match the specified game state. + * This method fades the played music to fit the state. * - * @param state The new game state. + * @param state the state of which the corresponding music should be played to be played */ public void playState(MdgaState state) { - // Implementation for managing state-specific music playback + if (this.state == state) { + return; + } + MusicAsset asset = null; + + switch (state) { + case MAIN: + playGame = false; + asset = MusicAsset.MAIN_MENU; + break; + case LOBBY: + playGame = false; + asset = MusicAsset.LOBBY; + break; + case GAME: + addGameTracks(); + playGame = true; + assert (!gameTracks.isEmpty()) : "no more game music available"; + asset = gameTracks.remove(0); + break; + case CEREMONY: + playGame = false; + asset = MusicAsset.CEREMONY; + break; + case NONE: + throw new RuntimeException("no music for state NONE"); + } + + assert (null != asset) : "music sceduling went wrong"; + + scheduled = new GameMusic(app, asset, getMusicVolumeTotal(), asset.getSubVolume(), asset.getLoop(), 0.0f); } /** - * Performs linear interpolation between two values. + * Performs linear interpolation between two float values. * * @param start The starting value. * @param end The ending value. - * @param t The interpolation factor (0 to 1). - * @return The interpolated value. + * @param t The interpolation factor, typically between 0 and 1. + * @return The interpolated value between start and end. */ private float lerp(float start, float end, float t) { return start + t * (end - start); } /** - * Manages audio playback transitions and volume adjustments. + * Updates the state of audio playback, handling track transitions and volume adjustments. + * + * This method ensures smooth transitions between tracks using fade-in and fade-out effects. + * It also handles cases where no track is playing, starting a scheduled track immediately at full volume. + * The method prioritizes the latest scheduled track if multiple scheduling occurs quickly. + * + * Behavior: + * 1. If nothing is scheduled and no track is playing, it exits early. + * 2. If a scheduled track exists and no track is playing, the scheduled track starts immediately at full volume. + * 3. If a scheduled track exists while a track is playing, it initiates a fade-out for the currently playing track + * and prepares for the new track to fade in. + * 4. If a track transition is in progress (fading), it processes the fade-out and fade-in states. + * If a new track is scheduled during this process, it interrupts the current transition and prioritizes the new track. + * 5. If no fading is needed and a track is playing, it ensures the track's volume is updated. + * + * Special cases: + * - If no track is playing and a new track is scheduled, it starts the track immediately without fading. + * - If a new track is scheduled during fading, it resets the transition to prioritize the new track. */ private void updateVolumeAndTrack() { - // Implementation for handling fade-ins, fade-outs, and volume updates + if (scheduled == null && !fading && playing == null) { + // Nothing to do, early exit + return; + } + + if (scheduled != null && playing == null && !fading) { + // No current track, start scheduled track immediately at full volume + playing = scheduled; + scheduled = null; + playing.play(); + playing.update(getMusicVolumeTotal()); // Set volume to full + return; + } + + if (scheduled != null && !fading) { + // Initiate a fade process if a new track is scheduled + fading = true; + fadeTimer.reset(); + old = playing; // The currently playing track becomes the old track + playing = null; // Clear the playing track during the fade process + } + + if (fading) { + handleFadeProcess(); + + // Handle any interruptions due to newly scheduled tracks + if (scheduled != null && playing != null && playing != scheduled) { + // Interrupt the current infade and switch to the new scheduled track + old = playing; // Treat the currently infading track as the old track + playing = null; // Reset playing to allow switching + fadeTimer.reset(); // Restart fade timer for the new track + } + } else if (playing != null) { + // Update volume for the currently playing track + playing.update(getMusicVolumeTotal()); + } else if (scheduled != null) { + // If no track is playing and one is scheduled, start it immediately at full volume + playing = scheduled; + scheduled = null; + playing.play(); + playing.update(getMusicVolumeTotal()); // Set volume to full + } } /** - * Handles the fade-out and fade-in processes for audio transitions. + * Manages the fading process during audio track transitions. + * + * This method handles the fade-out of the currently playing (old) track, manages any pause between the fade-out + * and fade-in, and initiates the fade-in for the new track if applicable. It ensures smooth transitions between + * tracks while maintaining the correct volume adjustments. + * + * Behavior: + * 1. **Outfade:** Gradually decreases the volume of the `old` track over the duration of `FADE_DURATION`. + * Once the outfade completes, the `old` track is paused and cleared. + * 2. **Pause Handling:** Waits for a defined pause (if applicable) before initiating the infade for the next track. + * 3. **Infade:** If a `scheduled` track exists and the outfade and pause are complete, it begins playing + * the new track (`playing`) and initiates the infade process. + * + * Key Details: + * - The outfade volume adjustment is interpolated linearly from full volume to zero using the `lerp` function. + * - The pause duration is retrieved from the scheduled track if it is specified. + * - If a new track is scheduled during the fade process, it is handled by external logic to prioritize transitions. + * + * Preconditions: + * - `fading` is expected to be `true` when this method is called. + * - The method is invoked as part of the `updateVolumeAndTrack` process. */ private void handleFadeProcess() { - // Implementation for managing fade transitions + float time = fadeTimer.getTimeInSeconds(); + + // Handle outfade for the old track + if (old != null && time <= FADE_DURATION) { + float t = Math.min(time / FADE_DURATION, 1.0f); + float oldVolume = lerp(1.0f, 0.0f, t); + old.update(getMusicVolumeTotal() * oldVolume); + } + + if (old != null && time > FADE_DURATION) { + // Complete outfade + old.pause(); + old = null; + } + + // Handle pause duration before infade + float pause = (scheduled != null) ? scheduled.getPause() : 0.0f; + if (time > FADE_DURATION + pause) { + if (playing == null && scheduled != null) { + // Begin infade for the new track + playing = scheduled; + scheduled = null; + playing.play(); // Start playing the new track + } + handleInfade(time - FADE_DURATION - pause); + } } /** * Manages the fade-in process for the currently playing track. * - * @param infadeTime Time elapsed since the fade-in process started. + * This method gradually increases the volume of the `playing` track from zero to full volume + * over the duration of `CROSSFADE_DURATION`. It ensures a smooth transition into the new track. + * + * Behavior: + * 1. If no track is set as `playing`, the method exits early, as there is nothing to fade in. + * 2. Linearly interpolates the volume of the `playing` track from 0.0 to 1.0 based on the elapsed + * `infadeTime` and the specified `CROSSFADE_DURATION`. + * 3. Once the fade-in is complete (when `infadeTime` exceeds `CROSSFADE_DURATION`), the method: + * - Marks the fade process (`fading`) as complete. + * - Ensures the `playing` track is updated to its full volume. + * + * Key Details: + * - Uses the `lerp` function to calculate the volume level for the `playing` track during the fade-in. + * - Ensures the volume is always a value between 0.0 and 1.0. + * - The `infadeTime` parameter should be relative to the start of the fade-in process. + * + * Preconditions: + * - The `playing` track must be initialized and actively fading in for this method to have an effect. + * - The method is invoked as part of the `updateVolumeAndTrack` process. + * + * @param infadeTime The elapsed time (in seconds) since the fade-in process started. */ private void handleInfade(float infadeTime) { - // Implementation for handling the fade-in process + if (playing == null) { + // Nothing to infade + return; + } + + // Proceed with the infade for the current playing track + float t = Math.min(infadeTime / CROSSFADE_DURATION, 1.0f); + float newVolume = lerp(0.0f, 1.0f, t); + playing.update(getMusicVolumeTotal() * newVolume); + + if (infadeTime > CROSSFADE_DURATION) { + // Infade is complete, finalize state + fading = false; + playing.update(getMusicVolumeTotal()); // Ensure full volume + } } /** - * Adds and shuffles game music tracks. + * Adds a list of game tracks to the gameTracks collection and shuffles them. + * This method adds predefined game tracks to the track list and shuffles the order. */ private void addGameTracks() { - // Adds predefined game music tracks to the list and shuffles them + Random random = new Random(); + + for (int i = 1; i <= 6; i++) { + gameTracks.add(MusicAsset.valueOf("GAME_" + i)); + } + Collections.shuffle(gameTracks, random); } /** - * Updates the game music tracks, scheduling new ones as needed. + * Updates the current game tracks. If the currently playing track is nearing its end, + * a new track will be scheduled to play. If the list of game tracks is empty, it will be refreshed. */ private void updateGameTracks() { - // Handles scheduling and transitioning between game tracks + if(null == playing) { + return; + } + + if (playing.nearEnd(10)) { + if (gameTracks.isEmpty()) { + addGameTracks(); + } + } + + if (playing != null && playing.nearEnd(3) && trackTimer.getTimeInSeconds() > 20) { + trackTimer.reset(); + + MusicAsset nextTrack = gameTracks.remove(0); + + scheduled = new GameMusic(app, nextTrack, getMusicVolumeTotal(), nextTrack.getSubVolume(), nextTrack.getLoop(), 0.0f); + } } /** - * Gets the main volume level. + * Retrieves the main volume level. * - * @return The main volume level. + * @return The current main volume level. */ public float getMainVolume() { return mainVolume; @@ -160,7 +395,7 @@ public float getSoundVolume() { } /** - * Sets the main volume level and saves the setting. + * Sets the main volume level. * * @param mainVolume The desired main volume level. */ @@ -169,27 +404,6 @@ public void setMainVolume(float mainVolume) { prefs.putFloat("mainVolume", mainVolume); } - // Similar getters and setters for musicVolume and soundVolume... - - /** - * Calculates the total music volume (main volume × music volume). - * - * @return The total music volume. - */ - float getMusicVolumeTotal() { - return musicVolume * mainVolume; - } - - /** - * Calculates the total sound volume (main volume × sound volume). - * - * @return The total sound volume. - */ - float getSoundVolumeTotal() { - return soundVolume * mainVolume; - } - - /** * Sets the music volume level. * @@ -209,4 +423,23 @@ public void setSoundVolume(float soundVolume) { this.soundVolume = soundVolume; prefs.putFloat("soundVolume", soundVolume); } + + /** + * Calculates the total music volume by multiplying the music volume by the main volume. + * + * @return The total music volume. + */ + float getMusicVolumeTotal() { + + return getMusicVolume() * getMainVolume(); + } + + /** + * Calculates the total sound volume by multiplying the sound volume by the main volume. + * + * @return The total sound volume. + */ + float getSoundVolumeTotal() { + return getSoundVolume() * getMainVolume(); + } } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/view/LobbyView.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/view/LobbyView.java index 0ee82c56..242cae89 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/view/LobbyView.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/view/LobbyView.java @@ -152,6 +152,23 @@ public void setTaken(Color color, boolean isTaken, boolean isSelf, String name) if(isTaken) { if(isSelf) { + /*if(own != null) { + switch (color) { + case CYBER: + cyberButton.setTaken(LobbyButton.Taken.NOT, name); + break; + case AIRFORCE: + airforceButton.setTaken(LobbyButton.Taken.NOT, name); + break; + case ARMY: + armyButton.setTaken(LobbyButton.Taken.NOT, name); + break; + case NAVY: + navyButton.setTaken(LobbyButton.Taken.NOT, name); + break; + } + }*/ + own = color; taken = LobbyButton.Taken.SELF; } else { @@ -228,7 +245,7 @@ private void toggleTsk(Color color) { app.getModelSynchronize().selectTsk(color); break; case SELF: - app.getModelSynchronize().unselectTsk(); + app.getModelSynchronize().unselectTsk(color); break; case OTHER: //nothing diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientGameLogic.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientGameLogic.java index c2526b46..133d5689 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientGameLogic.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientGameLogic.java @@ -239,6 +239,10 @@ public void selectTsk(Color color){ state.selectTSK(color); } + public void deselectTSK(Color color){ + state.deselectTSK(color); + } + public void selectDice(){ state.selectDice(); } diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java index 7678624a..fdb8e5d2 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java @@ -101,9 +101,13 @@ public void received(LobbyPlayerJoinedMessage msg){ @Override public void received(UpdateTSKMessage msg){ - logic.addNotification(new TskUnselectNotification(logic.getGame().getPlayers().get(msg.getId()).getColor())); + if(msg.isTaken()) { + logic.addNotification(new TskSelectNotification(msg.getColor(), logic.getGame().getPlayers().get(msg.getId()).getName(), parent.getOwnPlayerId()== msg.getId())); + } else { + logic.addNotification(new TskUnselectNotification(logic.getGame().getPlayers().get(msg.getId()).getColor())); + } + logic.getGame().getPlayers().get(msg.getId()).setColor(msg.getColor()); - logic.addNotification(new TskSelectNotification(msg.getColor(), logic.getGame().getPlayers().get(msg.getId()).getName(), parent.getOwnPlayerId()== msg.getId())); } @Override diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/UpdateTSKMessage.java b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/UpdateTSKMessage.java index bbbdf14b..2da6f682 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/UpdateTSKMessage.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/UpdateTSKMessage.java @@ -18,23 +18,26 @@ public class UpdateTSKMessage extends ServerMessage { */ private final Color color; + private final boolean isTaken; + /** * Constructs a new UpdateTSK instance with the specified id and color. * * @param id the name associated with the update * @param color the color associated with the update */ - public UpdateTSKMessage(int id, Color color) { + public UpdateTSKMessage(int id, Color color, boolean isTaken) { super(); this.id = id; this.color = color; + this.isTaken = isTaken; } /** * Default constructor for serialization purposes. */ private UpdateTSKMessage() { - this(0, null); + this(0, null, false); } /** @@ -84,4 +87,8 @@ public String toString() { public String getInfoTextKey() { return ""; } + + public boolean isTaken() { + return isTaken; + } } diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java b/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java index 2a4eba34..708a26d5 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java @@ -7,6 +7,7 @@ import pp.mdga.message.server.*; import pp.mdga.server.ServerGameLogic; +import java.lang.foreign.StructLayout; import java.util.Map; /** @@ -84,8 +85,13 @@ public void received(SelectTSKMessage msg, int from) { return; } } + + if(this.logic.getGame().getPlayerById(from).getColor() != Color.NONE) { + this.logic.getServerSender().broadcast(new UpdateTSKMessage(from, this.logic.getGame().getPlayerById(from).getColor(), false)); + } + this.logic.getGame().getPlayerById(from).setColor(msg.getColor()); - this.logic.getServerSender().broadcast(new UpdateTSKMessage(from, msg.getColor())); + this.logic.getServerSender().broadcast(new UpdateTSKMessage(from, msg.getColor(), true)); } /** @@ -98,7 +104,7 @@ public void received(SelectTSKMessage msg, int from) { @Override public void received(DeselectTSKMessage msg, int from) { this.logic.getGame().getPlayerById(from).setColor(Color.NONE); - this.logic.getServerSender().broadcast(new UpdateTSKMessage(from, Color.NONE)); + this.logic.getServerSender().broadcast(new UpdateTSKMessage(from, Color.NONE, false)); } /** From 5db7b64cefe2957a73ed3fe543a4dbdc98a8d74c Mon Sep 17 00:00:00 2001 From: Hanno Fleischer Date: Mon, 2 Dec 2024 12:16:53 +0100 Subject: [PATCH 16/28] fixed bug with seriliazation of Board, now sending playerdata seperate from teh board --- Projekte/.run/MdgaApp.run.xml | 4 +- .../pp/mdga/client/server/MdgaServer.java | 2 + .../java/pp/mdga/client/ClientGameLogic.java | 10 +++++ .../main/java/pp/mdga/client/ClientState.java | 9 +++++ .../java/pp/mdga/client/DialogsState.java | 10 +++++ .../mdga/client/dialogState/LobbyState.java | 23 ++++++++--- .../dialogState/NetworkDialogState.java | 28 ------------- .../message/server/PlayerDataMessage.java | 40 +++++++++++++++++++ .../message/server/ServerInterpreter.java | 4 ++ .../server/ServerStartGameMessage.java | 24 ----------- .../message/server/StartBriefingMessage.java | 33 +++++++++++++++ .../pp/mdga/server/automaton/LobbyState.java | 9 +++-- 12 files changed, 134 insertions(+), 62 deletions(-) create mode 100644 Projekte/mdga/model/src/main/java/pp/mdga/message/server/PlayerDataMessage.java create mode 100644 Projekte/mdga/model/src/main/java/pp/mdga/message/server/StartBriefingMessage.java diff --git a/Projekte/.run/MdgaApp.run.xml b/Projekte/.run/MdgaApp.run.xml index 8b467373..123a07af 100644 --- a/Projekte/.run/MdgaApp.run.xml +++ b/Projekte/.run/MdgaApp.run.xml @@ -1,5 +1,7 @@ + - + \ No newline at end of file diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java index 111604ed..b8e8bfb4 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/server/MdgaServer.java @@ -144,6 +144,8 @@ private void initializeSerializables() { Serializer.registerClass(StartNode.class); Serializer.registerClass(PlayerData.class); Serializer.registerClass(HomeNode.class); + Serializer.registerClass(PlayerDataMessage.class); + Serializer.registerClass(StartBriefingMessage.class); } private void registerListeners() { diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientGameLogic.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientGameLogic.java index 133d5689..f3a0602b 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientGameLogic.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientGameLogic.java @@ -193,6 +193,16 @@ public void received(ServerStartGameMessage msg) { @Override public void received(ShutdownMessage msg) {state.received(msg);} + @Override + public void received(StartBriefingMessage msg) { + state.received(msg); + } + + @Override + public void received(PlayerDataMessage msg) { + state.received(msg); + } + @Override public void received(StartPieceMessage msg) { state.received(msg); diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientState.java index bf64e267..ae500c42 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/ClientState.java @@ -183,6 +183,15 @@ public void received(WaitPieceMessage msg) { LOGGER.log(Level.DEBUG, "Received {0} not allowed.", msg); } + @Override + public void received(StartBriefingMessage msg) { + LOGGER.log(Level.DEBUG, "Received {0} not allowed.", msg); + } + + public void received(PlayerDataMessage msg) { + LOGGER.log(Level.DEBUG, "Received {0} not allowed.", msg); + } + public void selectPiece(Piece piece) { LOGGER.log(Level.DEBUG, "Selecting piece not allowed."); } diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/DialogsState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/DialogsState.java index 5f7cf182..c3f33c97 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/DialogsState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/DialogsState.java @@ -144,6 +144,16 @@ public void received(ServerStartGameMessage msg){ currentState.received(msg); } + @Override + public void received(PlayerDataMessage msg){ + currentState.received(msg); + } + + @Override + public void received(StartBriefingMessage msg){ + currentState.received(msg); + } + public DialogStates getState() { return currentState; } diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java index fdb8e5d2..f468d8d3 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java @@ -10,7 +10,9 @@ import pp.mdga.message.client.*; import pp.mdga.message.server.LobbyPlayerJoinedMessage; import pp.mdga.message.server.LobbyPlayerLeaveMessage; +import pp.mdga.message.server.PlayerDataMessage; import pp.mdga.message.server.ServerStartGameMessage; +import pp.mdga.message.server.StartBriefingMessage; import pp.mdga.message.server.UpdateReadyMessage; import pp.mdga.message.server.UpdateTSKMessage; import pp.mdga.notification.*; @@ -74,15 +76,24 @@ public void selectStart(){ } @Override - public void received(ServerStartGameMessage msg){ + public void received(StartBriefingMessage msg){ logic.getGame().setBoard(msg.getBoard()); - logic.addNotification(new GameNotification(logic.getGame().getPlayers().get(parent.getOwnPlayerId()).getColor())); - for(Map.Entry entry : msg.getBoard().getPlayerData().entrySet()){ - List pieceIds = new ArrayList<>(); + } + + public void received(PlayerDataMessage msg){ + logic.getGame().getBoard().addPlayerData(msg.getColor(), msg.getPlayerData()); + } + + @Override + public void received(ServerStartGameMessage msg){ + logic.addNotification(new GameNotification(logic.getGame().getPlayerById(parent.getOwnPlayerId()).getColor())); + for (Map.Entry entry : logic.getGame().getBoard().getPlayerData().entrySet()) { + List pieceList = new ArrayList<>(); for(Piece piece : entry.getValue().getPieces()){ - pieceIds.add(piece.getUuid()); + System.out.println(piece.getUuid()); + pieceList.add(piece.getUuid()); } - logic.addNotification(new PlayerInGameNotification(entry.getKey(), pieceIds, logic.getGame().getPlayerByColor(entry.getKey()).getName())); + logic.addNotification(new PlayerInGameNotification(entry.getKey(), pieceList , logic.getGame().getPlayerByColor(entry.getKey()).getName())); } parent.startGame(); } diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/NetworkDialogState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/NetworkDialogState.java index 09212dee..98234319 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/NetworkDialogState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/NetworkDialogState.java @@ -14,34 +14,6 @@ public NetworkDialogState(ClientState parent, ClientGameLogic logic) { this.parent = (DialogsState) parent; } - private boolean checkIP(String IP){ - String[] parts = IP.split("\\."); - - // Step 2: Check if there are exactly 4 parts - if (parts.length != 4) { - return false; - } - - // Step 3: Check each part for valid number - for (String part : parts) { - try { - // Step 4: Convert each part into a number - int num = Integer.parseInt(part); - - // Step 5: Check whether the number lies in between 0 and 255 - if (num < 0 || num > 255) { - return false; - } - } catch (NumberFormatException e) { - // If parsing fails, it's not a valid number - return false; - } - } - - // If all checks passed, return true - return true; - } - @Override public void enter() { } diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/PlayerDataMessage.java b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/PlayerDataMessage.java new file mode 100644 index 00000000..03171e73 --- /dev/null +++ b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/PlayerDataMessage.java @@ -0,0 +1,40 @@ +package pp.mdga.message.server; + +import com.jme3.network.serializing.Serializable; +import pp.mdga.game.Color; +import pp.mdga.game.PlayerData; + +@Serializable +public class PlayerDataMessage extends ServerMessage{ + + private final PlayerData playerData; + private final Color color; + + public PlayerDataMessage(PlayerData playerData, Color color){ + super(); + this.playerData = playerData; + this.color = color; + } + + private PlayerDataMessage(){ + this(null, null); + } + + @Override + public void accept(ServerInterpreter interpreter) { + interpreter.received(this); + } + + @Override + public String getInfoTextKey() { + return ""; + } + + public PlayerData getPlayerData(){ + return playerData; + } + + public Color getColor(){ + return color; + } +} diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerInterpreter.java b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerInterpreter.java index 1ed24edf..4491f9c1 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerInterpreter.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerInterpreter.java @@ -214,4 +214,8 @@ public interface ServerInterpreter { * @param shutdownMessage the SelectTSK message received. */ void received(ShutdownMessage shutdownMessage); + + void received(StartBriefingMessage msg); + + void received(PlayerDataMessage msg); } diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerStartGameMessage.java b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerStartGameMessage.java index 37c22e1e..69e3fb96 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerStartGameMessage.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/ServerStartGameMessage.java @@ -8,28 +8,13 @@ */ @Serializable public class ServerStartGameMessage extends ServerMessage { - /** - * Create ServerStartGameMessage attributes. - */ - private final Board board; /** * Constructs a new ServerStartGame instance. */ public ServerStartGameMessage() { super(); - this.board = null; } - - /** - * Constructor. - * - * @param board as the complete board of this game as a Board object. - */ - public ServerStartGameMessage(Board board) { - this.board = board; - } - /** * Accepts a visitor to process this message. * @@ -40,15 +25,6 @@ public void accept(ServerInterpreter interpreter) { interpreter.received(this); } - /** - * This method will be used to return board attribute of ServerStartGameMessage class. - * - * @return board as a Board object. - */ - public Board getBoard() { - return this.board; - } - /** * Returns a string representation of this message. * diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/message/server/StartBriefingMessage.java b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/StartBriefingMessage.java new file mode 100644 index 00000000..ba465990 --- /dev/null +++ b/Projekte/mdga/model/src/main/java/pp/mdga/message/server/StartBriefingMessage.java @@ -0,0 +1,33 @@ +package pp.mdga.message.server; + +import com.jme3.network.serializing.Serializable; +import pp.mdga.game.Board; + +@Serializable +public class StartBriefingMessage extends ServerMessage { + + private final Board board; + + public StartBriefingMessage(Board board) { + super(); + this.board = board; + } + + private StartBriefingMessage() { + this(null); + } + + public Board getBoard() { + return this.board; + } + + @Override + public void accept(ServerInterpreter interpreter) { + interpreter.received(this); + } + + @Override + public String getInfoTextKey() { + return ""; + } +} diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java b/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java index 708a26d5..c268cc4f 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java @@ -7,7 +7,6 @@ import pp.mdga.message.server.*; import pp.mdga.server.ServerGameLogic; -import java.lang.foreign.StructLayout; import java.util.Map; /** @@ -126,8 +125,12 @@ public void received(LobbyReadyMessage msg, int from) { this.logic.getGame().setAllReady(true); if (this.logic.getGame().allReady()) { + this.logic.getServerSender().broadcast(new StartBriefingMessage(this.logic.getGame().getBoard())); this.initializeGame(); - this.logic.getServerSender().broadcast(new ServerStartGameMessage(this.logic.getGame().getBoard())); + for (Map.Entry entry : logic.getGame().getBoard().getPlayerData().entrySet()) { + this.logic.getServerSender().broadcast(new PlayerDataMessage(entry.getValue(), entry.getKey())); + } + this.logic.getServerSender().broadcast(new ServerStartGameMessage()); } } @@ -173,7 +176,7 @@ public void received(LeaveGameMessage msg, int from) { public void received(StartGameMessage msg, int from) { if (msg.isForceStartGame() || this.logic.getGame().allReady()) { this.initializeGame(); - this.logic.getServerSender().broadcast(new ServerStartGameMessage(this.logic.getGame().getBoard())); + this.logic.getServerSender().broadcast(new ServerStartGameMessage()); this.logic.setCurrentState(this.logic.getGameState()); } } From 4561a962d4ccba9bbdcc2d8ed2ea6a96016dfaf1 Mon Sep 17 00:00:00 2001 From: Felix Koppe Date: Mon, 2 Dec 2024 12:52:07 +0100 Subject: [PATCH 17/28] Fix lobby isSelf logic and no longer assign color on join --- .../java/pp/mdga/client/view/LobbyView.java | 17 ----------------- .../pp/mdga/client/dialogState/LobbyState.java | 3 ++- .../pp/mdga/server/automaton/LobbyState.java | 2 +- 3 files changed, 3 insertions(+), 19 deletions(-) diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/view/LobbyView.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/view/LobbyView.java index 242cae89..e96cbbb7 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/view/LobbyView.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/view/LobbyView.java @@ -152,23 +152,6 @@ public void setTaken(Color color, boolean isTaken, boolean isSelf, String name) if(isTaken) { if(isSelf) { - /*if(own != null) { - switch (color) { - case CYBER: - cyberButton.setTaken(LobbyButton.Taken.NOT, name); - break; - case AIRFORCE: - airforceButton.setTaken(LobbyButton.Taken.NOT, name); - break; - case ARMY: - armyButton.setTaken(LobbyButton.Taken.NOT, name); - break; - case NAVY: - navyButton.setTaken(LobbyButton.Taken.NOT, name); - break; - } - }*/ - own = color; taken = LobbyButton.Taken.SELF; } else { diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java index f468d8d3..6d70ba50 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java @@ -106,7 +106,8 @@ public void received(LobbyPlayerJoinedMessage msg){ if (msg.isHost() && msg.getId() == parent.getOwnPlayerId()){ logic.setHost(true); } - logic.addNotification(new TskSelectNotification(msg.getPlayer().getColor(), msg.getPlayer().getName(), parent.getOwnPlayerId()== msg.getId())); + + logic.addNotification(new TskSelectNotification(msg.getPlayer().getColor(), msg.getPlayer().getName(), msg.getPlayer().getName().equals(parent.getOwnPlayerName()))); logic.getGame().getPlayers().put(msg.getId(), msg.getPlayer()); } diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java b/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java index c268cc4f..1f1bbacb 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java @@ -63,7 +63,7 @@ public void initializeGame() { @Override public void received(JoinedLobbyMessage msg, int from) { Player player = new Player(msg.getName()); - player.setColor(Color.getColorByIndex(this.logic.getGame().getPlayers().size())); + player.setColor(Color.NONE); this.logic.getGame().addPlayer(from, player); for (Map.Entry entry : this.logic.getGame().getPlayers().entrySet()) { this.logic.getServerSender().broadcast(new LobbyPlayerJoinedMessage(entry.getKey(), entry.getValue(), entry.getKey() == this.logic.getGame().getHost())); From 92d2e747482e79199d3f61e5b935bbc75d74d36a Mon Sep 17 00:00:00 2001 From: Felix Koppe Date: Mon, 2 Dec 2024 13:06:59 +0100 Subject: [PATCH 18/28] Fix error regarding color in lobbyState --- .../pp/mdga/server/automaton/LobbyState.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java b/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java index 1f1bbacb..32b400b6 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java @@ -7,6 +7,7 @@ import pp.mdga.message.server.*; import pp.mdga.server.ServerGameLogic; +import java.util.ArrayList; import java.util.Map; /** @@ -115,6 +116,28 @@ public void received(DeselectTSKMessage msg, int from) { */ @Override public void received(LobbyReadyMessage msg, int from) { + //assign a free color + if(this.logic.getGame().getPlayerById(from).getColor() == Color.NONE) { + ArrayList colors = new ArrayList<>(); + colors.add(Color.ARMY); + colors.add(Color.AIRFORCE); + colors.add(Color.NAVY); + colors.add(Color.CYBER); + + for (Map.Entry entry : this.logic.getGame().getPlayers().entrySet()) { + if(colors.contains(entry.getValue().getColor())) { + colors.remove(entry.getValue().getColor()); + } + } + + if(colors.size() < 1) { + throw new RuntimeException("can not assign a color"); + } + + this.logic.getGame().getPlayerById(from).setColor(colors.get(0)); + this.logic.getServerSender().broadcast(new UpdateTSKMessage(from, colors.get(0), true)); + } + this.logic.getGame().getPlayerById(from).setReady(true); this.logic.getServerSender().broadcast(new UpdateReadyMessage(from, true)); for (Map.Entry entry : this.logic.getGame().getPlayers().entrySet()) { From 6c136b78b8f09e194950fa4ff76ec309283524a1 Mon Sep 17 00:00:00 2001 From: Daniel Grigencha Date: Mon, 2 Dec 2024 16:22:50 +0100 Subject: [PATCH 19/28] Updated 'Piece' class. Updated the 'Piece' class by reverting all enumeration to its orgin types. --- .../src/main/java/pp/mdga/game/Piece.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/game/Piece.java b/Projekte/mdga/model/src/main/java/pp/mdga/game/Piece.java index dfe36188..a01c1247 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/game/Piece.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/game/Piece.java @@ -12,17 +12,17 @@ public class Piece { /** * The shield state of the piece. */ - private int shield; + private ShieldState shield; /** * The current state of the piece. */ - private int state; + private PieceState state; /** * The color of the piece. */ - private final int color; + private final Color color; /** * The unique identifier of the piece. @@ -36,15 +36,15 @@ public class Piece { * @param state the state of the piece */ public Piece(Color color, PieceState state, int id) { - this.color = color.ordinal(); - this.state = state.ordinal(); - shield = ShieldState.NONE.ordinal(); + this.color = color; + this.state = state; + shield = ShieldState.NONE; } private Piece() { - color = Color.NONE.ordinal(); - state = PieceState.WAITING.ordinal(); - shield = ShieldState.NONE.ordinal(); + color = Color.NONE; + state = PieceState.WAITING; + shield = ShieldState.NONE; } /** @@ -53,7 +53,7 @@ private Piece() { * @return the color of the piece */ public void setShield(ShieldState shield) { - this.shield = shield.ordinal(); + this.shield = shield; } /** @@ -62,7 +62,7 @@ public void setShield(ShieldState shield) { * @return the color of the piece */ public ShieldState getShield() { - return ShieldState.values()[shield]; + return shield; } /** @@ -71,7 +71,7 @@ public ShieldState getShield() { * @param state the state of the piece */ public void setState(PieceState state) { - this.state = state.ordinal(); + this.state = state; } /** @@ -80,7 +80,7 @@ public void setState(PieceState state) { * @return the color of the piece */ public PieceState getState() { - return PieceState.values()[state]; + return state; } /** @@ -89,7 +89,7 @@ public PieceState getState() { * @return the color of the piece */ public boolean isShielded() { - return shield == ShieldState.ACTIVE.ordinal(); + return shield == ShieldState.ACTIVE; } /** @@ -98,7 +98,7 @@ public boolean isShielded() { * @return the color of the piece */ public boolean isSuppressed() { - return shield == ShieldState.SUPPRESSED.ordinal(); + return shield == ShieldState.SUPPRESSED; } /** @@ -107,7 +107,7 @@ public boolean isSuppressed() { * @return the color of the piece */ public Color getColor() { - return Color.values()[color]; + return color; } /** From 167d898a3cfaf0c3016f7fccb257dd0035b42d17 Mon Sep 17 00:00:00 2001 From: Daniel Grigencha Date: Mon, 2 Dec 2024 16:25:33 +0100 Subject: [PATCH 20/28] Updated 'StartNode' class. Updated the 'StartNode' class by reverting all enumerations to its origin types in it. --- .../model/src/main/java/pp/mdga/game/StartNode.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/game/StartNode.java b/Projekte/mdga/model/src/main/java/pp/mdga/game/StartNode.java index 23161ecf..24b2c267 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/game/StartNode.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/game/StartNode.java @@ -10,7 +10,7 @@ public class StartNode extends Node { /** * The color of the node. */ - private int color; + private Color color; /** * Creates a new start node with the given color. @@ -18,11 +18,11 @@ public class StartNode extends Node { * @param color the color of the node */ public StartNode(Color color) { - this.color = color.ordinal(); + this.color = color; } private StartNode() { - color = Color.NONE.ordinal(); + color = Color.NONE; } /** @@ -31,7 +31,7 @@ private StartNode() { * @return the color of the node */ public Color getColor() { - return Color.values()[color]; + return color; } /** @@ -40,6 +40,6 @@ public Color getColor() { * @param color the new color of the node */ public void setColor(Color color) { - this.color = color.ordinal(); + this.color = color; } } From 1bcb73cff792b37c49d3411abda1afa1f2002897 Mon Sep 17 00:00:00 2001 From: Daniel Grigencha Date: Mon, 2 Dec 2024 16:29:32 +0100 Subject: [PATCH 21/28] Updated 'PlayerData' class. Updated the 'PlayerData' class by adding the 'isFinished' method to it. In Addition, the empty constructor was optimized to initalize all class attributes for serializable cases. --- .../main/java/pp/mdga/game/PlayerData.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/game/PlayerData.java b/Projekte/mdga/model/src/main/java/pp/mdga/game/PlayerData.java index 8fcc85ae..cb2a788b 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/game/PlayerData.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/game/PlayerData.java @@ -43,10 +43,23 @@ public PlayerData(Color color) { } } + /** + * Constructor. + */ private PlayerData() { - homeNodes = null; - waitingArea = null; - pieces = null; + homeNodes = new HomeNode[4]; + waitingArea = new Piece[4]; + pieces = new Piece[4]; + } + + /** + * This method will be used to check if the player is finished. + * ToDo: Currently return always false. Implement logic! + * + * @return true or false. + */ + public boolean isFinished() { + return false; } /** From cb362c4d0cf028240813ad485254c2f6ae785e0c Mon Sep 17 00:00:00 2001 From: Daniel Grigencha Date: Mon, 2 Dec 2024 16:31:57 +0100 Subject: [PATCH 22/28] Used auto-reformate code. --- .../client/src/main/java/pp/mdga/client/MdgaApp.java | 2 +- .../main/java/pp/mdga/server/automaton/LobbyState.java | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java index cb0371c0..2fddea2f 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java @@ -1,9 +1,9 @@ package pp.mdga.client; import com.jme3.app.SimpleApplication; +import com.jme3.system.AppSettings; import com.simsilica.lemur.GuiGlobals; import pp.mdga.client.acoustic.AcousticHandler; -import com.jme3.system.AppSettings; import pp.mdga.client.dialog.JoinDialog; import pp.mdga.client.view.*; diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java b/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java index 32b400b6..167992c2 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/server/automaton/LobbyState.java @@ -49,7 +49,7 @@ public void exit() { * This method will be used to initialize the game and all necessary objects. */ public void initializeGame() { - for (Map.Entry entry: this.logic.getGame().getPlayers().entrySet()) { + for (Map.Entry entry : this.logic.getGame().getPlayers().entrySet()) { this.logic.getGame().getBoard().addPlayerData(entry.getValue().getColor(), new PlayerData(entry.getValue().getColor())); } } @@ -86,7 +86,7 @@ public void received(SelectTSKMessage msg, int from) { } } - if(this.logic.getGame().getPlayerById(from).getColor() != Color.NONE) { + if (this.logic.getGame().getPlayerById(from).getColor() != Color.NONE) { this.logic.getServerSender().broadcast(new UpdateTSKMessage(from, this.logic.getGame().getPlayerById(from).getColor(), false)); } @@ -117,7 +117,7 @@ public void received(DeselectTSKMessage msg, int from) { @Override public void received(LobbyReadyMessage msg, int from) { //assign a free color - if(this.logic.getGame().getPlayerById(from).getColor() == Color.NONE) { + if (this.logic.getGame().getPlayerById(from).getColor() == Color.NONE) { ArrayList colors = new ArrayList<>(); colors.add(Color.ARMY); colors.add(Color.AIRFORCE); @@ -125,12 +125,12 @@ public void received(LobbyReadyMessage msg, int from) { colors.add(Color.CYBER); for (Map.Entry entry : this.logic.getGame().getPlayers().entrySet()) { - if(colors.contains(entry.getValue().getColor())) { + if (colors.contains(entry.getValue().getColor())) { colors.remove(entry.getValue().getColor()); } } - if(colors.size() < 1) { + if (colors.size() < 1) { throw new RuntimeException("can not assign a color"); } From 2118c7289168159b68b63b7650de4986411d9d6c Mon Sep 17 00:00:00 2001 From: Felix Koppe Date: Mon, 2 Dec 2024 16:34:55 +0100 Subject: [PATCH 23/28] Adjust RollDiceNotification --- .../java/pp/mdga/notification/RollDiceNotification.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/notification/RollDiceNotification.java b/Projekte/mdga/model/src/main/java/pp/mdga/notification/RollDiceNotification.java index 13bf849b..14c18e54 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/notification/RollDiceNotification.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/notification/RollDiceNotification.java @@ -11,17 +11,19 @@ public class RollDiceNotification extends Notification{ private int eyes; private boolean turbo; private int multiplier; + private boolean isRanking; /** * Constructor. * @param color the color of the player that rolled the die. * @param eyes the number of eyes that were rolled. */ - public RollDiceNotification(Color color, int eyes) { + public RollDiceNotification(Color color, int eyes, boolean isRanking) { this.color = color; this.eyes = eyes; this.turbo = false; this.multiplier = -1; + this.isRanking = isRanking; } public RollDiceNotification(Color color, int eyes, boolean turbo, int multiplier) { @@ -29,6 +31,7 @@ public RollDiceNotification(Color color, int eyes, boolean turbo, int multiplier this.eyes = eyes; this.turbo = turbo; this.multiplier = multiplier; + this.isRanking = false; } /** @@ -54,4 +57,6 @@ public int getMultiplier() { public boolean isTurbo() { return turbo; } + + public boolean isRanking() { return isRanking; } } From eee6fccde512f29a1b9bd002c8081c8e11716f3f Mon Sep 17 00:00:00 2001 From: Daniel Grigencha Date: Mon, 2 Dec 2024 16:35:40 +0100 Subject: [PATCH 24/28] Updated 'DetermineStartPlayerState' class. Updated the 'DetermineStartPlayerState' class by setting the start state correctly and enter it. --- .../pp/mdga/client/gameState/DetermineStartPlayerState.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/DetermineStartPlayerState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/DetermineStartPlayerState.java index cf3c48c2..4b95fe68 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/DetermineStartPlayerState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/DetermineStartPlayerState.java @@ -25,7 +25,7 @@ public DetermineStartPlayerState(ClientState parent, ClientGameLogic logic) { @Override public void enter() { - state = rollRankingDiceState; + this.setState(this.rollRankingDiceState); } @Override From a2856bb1574634ff7c640e5c1ddf4ed3b95d84e7 Mon Sep 17 00:00:00 2001 From: Cedric Beck Date: Mon, 2 Dec 2024 16:47:28 +0100 Subject: [PATCH 25/28] added rollRankingResults --- .../pp/mdga/client/InputSynchronizer.java | 7 +++- .../src/main/java/pp/mdga/client/MdgaApp.java | 2 +- .../pp/mdga/client/gui/ActionTextHandler.java | 42 ++++++++++++------- .../java/pp/mdga/client/gui/GuiHandler.java | 5 +++ .../pp/mdga/client/gui/PlayerNameHandler.java | 1 + .../java/pp/mdga/client/view/GameView.java | 8 +++- 6 files changed, 46 insertions(+), 19 deletions(-) diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java index b251134f..1f2d5c10 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java @@ -118,8 +118,11 @@ else if(boardSelect != null) { } if(name.equals("Test") &&isPressed){ if(app.getView() instanceof GameView gameView){ -// app.getNotificationSynchronizer().addTestNotification(new FinishNotification(Color.NAVY)); -// app.getNotificationSynchronizer().addTestNotification(new MovePieceNotification()); + gameView.getGuiHandler().rollRankingResult(Color.AIRFORCE, 1); + gameView.getGuiHandler().rollRankingResult(Color.ARMY, 2); + gameView.getGuiHandler().rollRankingResult(Color.NAVY, 3); + gameView.getGuiHandler().rollRankingResult(Color.CYBER, 4); + } } } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java index 5aa92fc0..cb0371c0 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java @@ -106,7 +106,7 @@ public void simpleInitApp() { gameView = new GameView(this); ceremonyView = new CeremonyView(this); - enter(MdgaState.GAME); + enter(MdgaState.MAIN); } /** diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ActionTextHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ActionTextHandler.java index 4dfa0690..8c8c73b9 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ActionTextHandler.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ActionTextHandler.java @@ -10,19 +10,20 @@ import pp.mdga.client.animation.ZoomControl; import pp.mdga.game.Color; -public class ActionTextHandler { + class ActionTextHandler { private Node root; private BitmapFont font; private AppSettings appSettings; + private int ranking; - public ActionTextHandler(Node guiNode, AssetManager assetManager, AppSettings appSettings){ + ActionTextHandler(Node guiNode, AssetManager assetManager, AppSettings appSettings){ root = new Node("actionTextRoot"); guiNode.attachChild(root); root.setLocalTranslation(center(appSettings.getWidth(), appSettings.getHeight(), Vector3f.ZERO)); font = assetManager.loadFont("Fonts/Gunplay.fnt"); this.appSettings = appSettings; - + ranking = 0; } private Node createTextWithSpacing(String[] textArr, float spacing, float size, ColorRGBA[] colorArr) { @@ -74,48 +75,48 @@ private Vector3f centerText(float width, float height, Vector3f pos){ return center(-width, height, pos); } - public void activePlayer(String name, Color color){ + void activePlayer(String name, Color color){ createTopText(new String[]{name," ist dran"}, 10,90,new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0).addControl(new ZoomControl()); } - public void ownActive(Color color){ + void ownActive(Color color){ createTopText(new String[]{"Du"," bist dran"}, 10,90,new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0).addControl(new ZoomControl()); } - public void diceNum(int diceNum, String name, Color color){ + void diceNum(int diceNum, String name, Color color){ createTopText(new String[]{name," würfelt:"}, 10,90,new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0); createTopText(String.valueOf(diceNum), 10, 100, ColorRGBA.White, 100); } - public void diceNumMult(int diceNum,int mult, String name, Color color){ + void diceNumMult(int diceNum,int mult, String name, Color color){ createTopText(new String[]{name," würfelt:"}, 10,90,new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0); createTopText(new String[]{String.valueOf(diceNum), " x" + mult + " = " + (diceNum*mult)}, 20, 100, new ColorRGBA[]{ColorRGBA.White,ColorRGBA.Red}, 100); } - public void ownDice(int diceNum){ + void ownDice(int diceNum){ createTopText(String.valueOf(diceNum), 10, 100, ColorRGBA.White, 0); } - public void ownDiceMult(int diceNum, int mult){ + void ownDiceMult(int diceNum, int mult){ createTopText(new String[]{String.valueOf(diceNum), " x" + mult + " = " + (diceNum*mult)}, 20, 100, new ColorRGBA[]{ColorRGBA.White,ColorRGBA.Red}, 0); } - public void drawCard(String name, Color color){ + void drawCard(String name, Color color){ createTopText(new String[]{name," erhält eine Bonuskarte"}, 7,70, new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0).addControl(new ZoomControl()); } - public void drawCardOwn(Color color){ + void drawCardOwn(Color color){ createTopText(new String[]{"Du"," erhälst eine Bonuskarte"}, 5,70, new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0).addControl(new ZoomControl()); } - public void finishText(String name, Color color){ + void finishText(String name, Color color){ createTopText(new String[]{name," ist fertig!"}, 7,70, new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0).addControl(new ZoomControl()); } - public void finishTextOwn(Color color){ + void finishTextOwn(Color color){ createTopText(new String[]{"Du", " bist fertig!"}, 7,70, new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, 0).addControl(new ZoomControl()); } @@ -131,9 +132,22 @@ private ColorRGBA playerColorToColorRGBA(Color color){ }; } - public void hide(){ + void hide(){ + ranking = 0; root.detachAllChildren(); } + float paddingRanked = 100; + + void rollRankingResult(String name, Color color, int eye){ + createTopText(new String[]{name,": "+eye}, 10,90,new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, paddingRanked*ranking); + ranking++; + } + + void rollRankingResultOwn(Color color, int eye){ + createTopText(new String[]{"Du",": "+eye}, 10,90,new ColorRGBA[]{playerColorToColorRGBA(color),ColorRGBA.White}, paddingRanked*ranking); + ranking++; + } + } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/GuiHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/GuiHandler.java index 8761e3da..91e091eb 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/GuiHandler.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/GuiHandler.java @@ -134,5 +134,10 @@ public void finish(Color color){ else actionTextHandler.finishText(playerNameHandler.getName(color), color); } + public void rollRankingResult(Color color, int eye){ + if(ownColor == color) actionTextHandler.rollRankingResultOwn(color, eye); + else actionTextHandler.rollRankingResult(playerNameHandler.getName(color), color, eye); + } + } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/PlayerNameHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/PlayerNameHandler.java index 1b197d16..2d4bdbf7 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/PlayerNameHandler.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/PlayerNameHandler.java @@ -120,6 +120,7 @@ public void setActivePlayer(Color color) { } public String getName(Color color){ + if(!colorNameMap.containsKey(color)) throw new RuntimeException("color is not in colorNameMap"); return colorNameMap.get(color); } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java index 9d1a7fe5..f28719ac 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/view/GameView.java @@ -65,8 +65,12 @@ public void onEnter() { app.getAcousticHandler().playSound(MdgaSound.START); - app.getNotificationSynchronizer().addTestNotification(new AcquireCardNotification(BonusCard.SHIELD)); - app.getNotificationSynchronizer().addTestNotification(new SelectableCardsNotification(List.of(BonusCard.SHIELD))); +// guiHandler.addPlayer(Color.AIRFORCE, "Cedric"); +// guiHandler.addPlayer(Color.ARMY, "Ben"); +// guiHandler.addPlayer(Color.CYBER, "Felix"); +// guiHandler.addPlayer(Color.NAVY, "Daniel"); + + } @Override From 0411f2ead41f03a5cfdefb11bfb0829b58b15557 Mon Sep 17 00:00:00 2001 From: Hanno Fleischer Date: Mon, 2 Dec 2024 17:08:46 +0100 Subject: [PATCH 26/28] fixed state transitions in gamestateclient automaton --- .../src/main/java/pp/mdga/client/CeremonyState.java | 6 ++++-- .../src/main/java/pp/mdga/client/DialogsState.java | 11 ++++------- .../model/src/main/java/pp/mdga/client/GameState.java | 9 +++++---- .../java/pp/mdga/client/dialogState/LobbyState.java | 2 +- .../client/gameState/DetermineStartPlayerState.java | 4 +++- .../main/java/pp/mdga/client/gameState/TurnState.java | 6 ++++-- .../RollRankingDiceState.java | 4 +++- .../client/gameState/turnState/ChoosePieceState.java | 8 +++++--- .../client/gameState/turnState/PowerCardState.java | 6 ++++-- 9 files changed, 33 insertions(+), 23 deletions(-) diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/CeremonyState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/CeremonyState.java index 38541512..cf6e5e5a 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/CeremonyState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/CeremonyState.java @@ -18,7 +18,7 @@ public CeremonyState(ClientState parent, ClientGameLogic logic) { @Override public void enter() { - currentState = podiumState; + setState(podiumState); logic.addNotification(createCeremonyNotification()); } @@ -28,7 +28,9 @@ public void exit() { } public void setState(CeremonyStates state){ - this.currentState.exit(); + if(this.currentState != null){ + this.currentState.exit(); + } state.enter(); currentState = state; } diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/DialogsState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/DialogsState.java index c3f33c97..c8578cd3 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/DialogsState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/DialogsState.java @@ -30,13 +30,15 @@ public void exit(){ @Override public void enter(){ - currentState = startDialogState; + setState(startDialogState); ownPlayerID = 0; ownPlayerName = null; } public void setState(DialogStates newState){ - currentState.exit(); + if(currentState != null){ + currentState.exit(); + } newState.enter(); currentState = newState; } @@ -69,11 +71,6 @@ public StartDialogState getStartDialog() { return startDialogState; } - public void startGame(){ - exit(); - logic.setState(logic.getGameState()); - } - @Override public void selectLeave(){ currentState.selectLeave(); diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/GameState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/GameState.java index af449db8..31b3f340 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/GameState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/GameState.java @@ -27,7 +27,6 @@ public class GameState extends ClientState { */ public GameState(ClientState parent, ClientGameLogic logic) { super(parent, logic); - state = determineStartPlayerState; } /** @@ -35,7 +34,7 @@ public GameState(ClientState parent, ClientGameLogic logic) { */ @Override public void enter() { - + this.setState(this.determineStartPlayerState); } /** @@ -52,8 +51,10 @@ public void exit() { * @param newState the state to be set */ public void setState(GameStates newState){ - state.exit(); - state.enter(); + if(this.state != null){ + this.state.exit(); + } + newState.enter(); state = newState; } diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java index 6d70ba50..2d48cbe1 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/dialogState/LobbyState.java @@ -95,7 +95,7 @@ public void received(ServerStartGameMessage msg){ } logic.addNotification(new PlayerInGameNotification(entry.getKey(), pieceList , logic.getGame().getPlayerByColor(entry.getKey()).getName())); } - parent.startGame(); + logic.setState(logic.getGameState()); } @Override diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/DetermineStartPlayerState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/DetermineStartPlayerState.java index 4b95fe68..4794785a 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/DetermineStartPlayerState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/DetermineStartPlayerState.java @@ -34,7 +34,9 @@ public void exit() { } public void setState(DetermineStartPlayerStates state) { - this.state.exit(); + if(this.state != null){ + this.state.exit(); + } state.enter(); this.state = state; } diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/TurnState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/TurnState.java index b59a35b8..5f075eff 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/TurnState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/TurnState.java @@ -31,7 +31,7 @@ public TurnState(ClientState parent, ClientGameLogic logic) { @Override public void enter() { - state = powerCardState; + this.setState(this.powerCardState); } @Override @@ -40,7 +40,9 @@ public void exit() { } public void setState(TurnStates state){ - this.state.exit(); + if(this.state != null){ + this.state.exit(); + } state.enter(); this.state = state; } diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/determineStartPlayerState/RollRankingDiceState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/determineStartPlayerState/RollRankingDiceState.java index 3c1ec5b9..e6a98522 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/determineStartPlayerState/RollRankingDiceState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/determineStartPlayerState/RollRankingDiceState.java @@ -6,6 +6,7 @@ import pp.mdga.message.client.RequestDieMessage; import pp.mdga.message.server.DieMessage; import pp.mdga.notification.DiceNowNotification; +import pp.mdga.notification.RollDiceNotification; public class RollRankingDiceState extends DetermineStartPlayerStates { @@ -23,16 +24,17 @@ public void enter() { @Override public void exit() { - } @Override public void selectDice(){ + System.out.println("selectDice"); logic.send(new RequestDieMessage()); } @Override public void received(DieMessage msg){ + logic.addNotification(new RollDiceNotification(logic.getGame().getPlayerById(logic.getDialogs().getOwnPlayerId()).getColor(), msg.getDiceEye(),true)); parent.setState(parent.getWaitRanking()); } } diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/turnState/ChoosePieceState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/turnState/ChoosePieceState.java index b1a0c7e3..47dce439 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/turnState/ChoosePieceState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/turnState/ChoosePieceState.java @@ -24,7 +24,7 @@ public ChoosePieceState(ClientState parent, ClientGameLogic logic) { @Override public void enter() { - currentState = noPieceState; + this.setState(this.noPieceState); } @Override @@ -34,9 +34,11 @@ public void exit() { } public void setState(ChoosePieceStates state){ - currentState.exit(); + if(currentState != null){ + currentState.exit(); + } + state.enter(); currentState = state; - currentState.enter(); } @Override diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/turnState/PowerCardState.java b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/turnState/PowerCardState.java index fd80b68d..5a5fd5c3 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/turnState/PowerCardState.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/client/gameState/turnState/PowerCardState.java @@ -31,7 +31,7 @@ public PowerCardState(ClientState parent, ClientGameLogic logic) { @Override public void enter() { - state = choosePowerCardState; + this.setState(this.choosePowerCardState); } public void exit() { @@ -40,7 +40,9 @@ public void exit() { } public void setState(PowerCardStates state) { - this.state.exit(); + if(this.state != null){ + this.state.exit(); + } state.enter(); this.state = state; } From 208261c6bfc27a6e394bca85270ff100a88a0ec5 Mon Sep 17 00:00:00 2001 From: Cedric Beck Date: Mon, 2 Dec 2024 17:11:55 +0100 Subject: [PATCH 27/28] added clickDice Action + modelSync --- .../java/pp/mdga/client/InputSynchronizer.java | 18 ++++++++++++------ .../pp/mdga/client/gui/ActionTextHandler.java | 5 ++++- .../java/pp/mdga/client/gui/GuiHandler.java | 1 + 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java index 1f2d5c10..4e22978d 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java @@ -17,6 +17,7 @@ import pp.mdga.client.board.OutlineControl; import pp.mdga.client.board.PieceControl; import pp.mdga.client.gui.CardControl; +import pp.mdga.client.gui.DiceControl; import pp.mdga.client.view.GameView; import pp.mdga.game.BonusCard; import pp.mdga.game.Color; @@ -93,10 +94,15 @@ public void onAction(String name, boolean isPressed, float tpf) { } if(name.equals("Click") && isPressed) { if (app.getView() instanceof GameView gameView) { + DiceControl diceSelect = checkHover(gameView.getGuiHandler().getCardLayerCamera(), gameView.getGuiHandler().getCardLayerRootNode(), DiceControl.class); CardControl cardLayerSelect = checkHover(gameView.getGuiHandler().getCardLayerCamera(), gameView.getGuiHandler().getCardLayerRootNode(), CardControl.class); OutlineControl boardSelect = checkHover(app.getCamera(), app.getRootNode(), OutlineControl.class); - if(cardLayerSelect != null) { + if(diceSelect != null) { + app.getModelSynchronize().rolledDice(); + gameView.getGuiHandler().hideText(); + } + else if(cardLayerSelect != null) { //cardSelect if(cardLayerSelect.isSelectable()) gameView.getGuiHandler().selectCard(cardLayerSelect); } @@ -118,11 +124,11 @@ else if(boardSelect != null) { } if(name.equals("Test") &&isPressed){ if(app.getView() instanceof GameView gameView){ - gameView.getGuiHandler().rollRankingResult(Color.AIRFORCE, 1); - gameView.getGuiHandler().rollRankingResult(Color.ARMY, 2); - gameView.getGuiHandler().rollRankingResult(Color.NAVY, 3); - gameView.getGuiHandler().rollRankingResult(Color.CYBER, 4); - +// gameView.getGuiHandler().rollRankingResult(Color.AIRFORCE, 1); +// gameView.getGuiHandler().rollRankingResult(Color.ARMY, 2); +// gameView.getGuiHandler().rollRankingResult(Color.NAVY, 3); +// gameView.getGuiHandler().rollRankingResult(Color.CYBER, 4); + gameView.getGuiHandler().showDice(); } } } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ActionTextHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ActionTextHandler.java index 8c8c73b9..b5bd3571 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ActionTextHandler.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/ActionTextHandler.java @@ -134,7 +134,7 @@ private ColorRGBA playerColorToColorRGBA(Color color){ void hide(){ ranking = 0; - root.detachAllChildren(); + root.detachAllChildren(); } float paddingRanked = 100; @@ -149,5 +149,8 @@ void rollRankingResultOwn(Color color, int eye){ ranking++; } + void diceNow(){ + createTopText("Klicke zum Würfeln", 5, 80, ColorRGBA.White, 0); + } } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/GuiHandler.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/GuiHandler.java index 91e091eb..d4128081 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/GuiHandler.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/gui/GuiHandler.java @@ -67,6 +67,7 @@ public void showRolledDice(int rollNum, Color color) { public void showDice() { cardLayerHandler.showDice(); + actionTextHandler.diceNow(); } public void hideDice() { From f21fd9b0a66aca701dd2c8232a7fae9390d0d379 Mon Sep 17 00:00:00 2001 From: Cedric Beck Date: Mon, 2 Dec 2024 17:28:37 +0100 Subject: [PATCH 28/28] added setPauseOnLostFocus(false) --- .../src/main/java/pp/mdga/client/InputSynchronizer.java | 1 - .../mdga/client/src/main/java/pp/mdga/client/MdgaApp.java | 1 + .../java/pp/mdga/client/NotificationSynchronizer.java | 1 + .../java/pp/mdga/notification/RollDiceNotification.java | 8 ++++++++ 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java index 4e22978d..807a37c4 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/InputSynchronizer.java @@ -100,7 +100,6 @@ public void onAction(String name, boolean isPressed, float tpf) { if(diceSelect != null) { app.getModelSynchronize().rolledDice(); - gameView.getGuiHandler().hideText(); } else if(cardLayerSelect != null) { //cardSelect diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java index 2fddea2f..9eca1ab8 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/MdgaApp.java @@ -82,6 +82,7 @@ public static void main(String[] args) { MdgaApp app = new MdgaApp(); app.setSettings(settings); app.setShowSettings(false); + app.setPauseOnLostFocus(false); app.start(); } diff --git a/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java b/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java index 6e080158..f23eda0e 100644 --- a/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java +++ b/Projekte/mdga/client/src/main/java/pp/mdga/client/NotificationSynchronizer.java @@ -148,6 +148,7 @@ private void handleGame(Notification notification) { } else if (notification instanceof ResumeNotification) { //TODO } else if (notification instanceof RollDiceNotification n) { + gameView.getGuiHandler().hideText(); if(n.getColor() == gameView.getOwnColor()){ guiHandler.rollDice(n.getEyes(), n.isTurbo() ? n.getMultiplier() : -1); } diff --git a/Projekte/mdga/model/src/main/java/pp/mdga/notification/RollDiceNotification.java b/Projekte/mdga/model/src/main/java/pp/mdga/notification/RollDiceNotification.java index 14c18e54..2e6f03e1 100644 --- a/Projekte/mdga/model/src/main/java/pp/mdga/notification/RollDiceNotification.java +++ b/Projekte/mdga/model/src/main/java/pp/mdga/notification/RollDiceNotification.java @@ -18,6 +18,14 @@ public class RollDiceNotification extends Notification{ * @param color the color of the player that rolled the die. * @param eyes the number of eyes that were rolled. */ + public RollDiceNotification(Color color, int eyes) { + this.color = color; + this.eyes = eyes; + this.turbo = false; + this.multiplier = -1; + this.isRanking = false; + } + public RollDiceNotification(Color color, int eyes, boolean isRanking) { this.color = color; this.eyes = eyes;