From e0bea47583f58a4bcfef385f606eb23bea88c4ff Mon Sep 17 00:00:00 2001 From: Tamino Mueller Date: Mon, 14 Oct 2024 08:39:59 +0200 Subject: [PATCH] task 13 --- .../client/gui/MapViewSynchronizer.java | 15 +++ .../game/client/ShootingAnimationState.java | 93 +++++++++++++++++++ .../game/server/ServerGameLogic.java | 21 +++++ .../battleship/game/singlemode/Copycat.java | 6 ++ .../message/client/ClientInterpreter.java | 1 + .../client/ShellAnimationFinishedMessage.java | 10 ++ .../main/java/pp/battleship/model/Shell.java | 47 ++++++++++ .../pp/battleship/model/ShellControl.java | 46 +++++++++ 8 files changed, 239 insertions(+) create mode 100644 Projekte/battleship/model/src/main/java/pp/battleship/game/client/ShootingAnimationState.java create mode 100644 Projekte/battleship/model/src/main/java/pp/battleship/message/client/ShellAnimationFinishedMessage.java create mode 100644 Projekte/battleship/model/src/main/java/pp/battleship/model/Shell.java create mode 100644 Projekte/battleship/model/src/main/java/pp/battleship/model/ShellControl.java diff --git a/Projekte/battleship/client/src/main/java/pp/battleship/client/gui/MapViewSynchronizer.java b/Projekte/battleship/client/src/main/java/pp/battleship/client/gui/MapViewSynchronizer.java index a6075fd..dd3fc56 100644 --- a/Projekte/battleship/client/src/main/java/pp/battleship/client/gui/MapViewSynchronizer.java +++ b/Projekte/battleship/client/src/main/java/pp/battleship/client/gui/MapViewSynchronizer.java @@ -8,10 +8,12 @@ package pp.battleship.client.gui; import com.jme3.math.ColorRGBA; +import com.jme3.math.Vector3f; import com.jme3.scene.Geometry; import com.jme3.scene.Node; import com.jme3.scene.Spatial; import pp.battleship.model.Battleship; +import pp.battleship.model.Shell; import pp.battleship.model.Shot; import pp.util.Position; @@ -36,6 +38,7 @@ class MapViewSynchronizer extends ShipMapSynchronizer { // The MapView associated with this synchronizer private final MapView view; + private Shell shell; /** * Constructs a new MapViewSynchronizer for the given MapView. @@ -122,4 +125,16 @@ class MapViewSynchronizer extends ShipMapSynchronizer { private Geometry shipLine(float x1, float y1, float x2, float y2, ColorRGBA color) { return view.getApp().getDraw().makeFatLine(x1, y1, x2, y2, SHIP_DEPTH, color, SHIP_LINE_WIDTH); } + public void update(float deltaTime) { + if (shell != null) { + shell.updatePosition(deltaTime); + drawShell(shell.getCurrentPosition()); + } + } + + private void drawShell(Vector3f position){ + //TODO implement + } + + } diff --git a/Projekte/battleship/model/src/main/java/pp/battleship/game/client/ShootingAnimationState.java b/Projekte/battleship/model/src/main/java/pp/battleship/game/client/ShootingAnimationState.java new file mode 100644 index 0000000..2ad0ead --- /dev/null +++ b/Projekte/battleship/model/src/main/java/pp/battleship/game/client/ShootingAnimationState.java @@ -0,0 +1,93 @@ +package pp.battleship.game.client; + +import pp.battleship.message.client.ShellAnimationFinishedMessage; +import pp.battleship.message.server.EffectMessage; +import pp.battleship.model.Shell; + +import java.lang.System.Logger.Level; + +/** + * This class represents the client state during a shooting animation. + * It handles the logic for the animation of a fired shell and ensures + * that the client notifies the server when the animation is complete. + */ +public class ShootingAnimationState extends ClientState { + + // The shell object representing the fired shell's movement + private final Shell shell; + + /** + * Constructs the ShootingAnimationState with the given game logic and shell. + * + * @param logic the game logic instance managing the state + * @param shell the shell object representing the fired projectile + */ + ShootingAnimationState(ClientGameLogic logic, Shell shell) { + super(logic); + this.shell = shell; + } + + /** + * Indicates that the battle scene should be shown in this state. + * + * @return true because the battle view is active during the shooting animation + */ + @Override + public boolean showBattle() { + return true; + } + + /** + * Handles the effect message received from the server. + * Logs the received effect for debugging purposes. + * + * @param msg the effect message received from the server + */ + @Override + void receivedEffect(EffectMessage msg) { + ClientGameLogic.LOGGER.log(Level.INFO, "report effect: {0}", msg); //NON-NLS + // Here, you could implement additional logic to display the effects of the shot, + // like a visual indication of a hit or a miss. + } + + /** + * Called once per frame to update the shell's position and check if it has reached the target. + * If the shell reaches the target, a message is sent to the server. + * + * @param deltaTime time in seconds since the last update call + */ + @Override + public void update(float deltaTime) { + if (shell != null) { + // Update the position of the shell based on the elapsed time + shell.updatePosition(deltaTime); + + // Check if the shell has reached its target + if (shell.isAtTarget()) { + // If the shell has reached the target, notify the server that the animation is complete + sendAnimationCompleteMessage(); + } + } + } + + /** + * Sends a message to the server indicating that the shooting animation has finished. + */ + private void sendAnimationCompleteMessage() { + ShellAnimationFinishedMessage message = new ShellAnimationFinishedMessage(); + // Send the message to the server via the game's logic communication system + logic.send(message); + logic.setState(new BattleState(logic, true)); + ClientGameLogic.LOGGER.log(Level.INFO, "Shell animation complete, message sent to server."); + } + + /** + * Optionally, you can add an entry method if there is any setup that needs to happen when entering the state. + * By default, this is empty. + */ + @Override + void entry() { + super.entry(); // Call the parent entry method + ClientGameLogic.LOGGER.log(Level.INFO, "Entered ShootingAnimationState."); + } +} diff --git a/Projekte/battleship/model/src/main/java/pp/battleship/game/server/ServerGameLogic.java b/Projekte/battleship/model/src/main/java/pp/battleship/game/server/ServerGameLogic.java index 1980d29..813a400 100644 --- a/Projekte/battleship/model/src/main/java/pp/battleship/game/server/ServerGameLogic.java +++ b/Projekte/battleship/model/src/main/java/pp/battleship/game/server/ServerGameLogic.java @@ -10,6 +10,7 @@ package pp.battleship.game.server; import pp.battleship.BattleshipConfig; import pp.battleship.message.client.ClientInterpreter; import pp.battleship.message.client.MapMessage; +import pp.battleship.message.client.ShellAnimationFinishedMessage; import pp.battleship.message.client.ShootMessage; import pp.battleship.message.server.EffectMessage; import pp.battleship.message.server.GameDetails; @@ -35,6 +36,7 @@ public class ServerGameLogic implements ClientInterpreter { private final BattleshipConfig config; private final List players = new ArrayList<>(2); private final Set readyPlayers = new HashSet<>(); + private Set playersFinishedShellAnimation = new HashSet<>(); private final ServerSender serverSender; private Player activePlayer; private ServerState state = ServerState.WAIT; @@ -155,6 +157,7 @@ public class ServerGameLogic implements ClientInterpreter { playerReady(getPlayerById(from), msg.getShips()); } + /** * Handles the reception of a ShootMessage. * @@ -255,6 +258,24 @@ public class ServerGameLogic implements ClientInterpreter { } return true; } + @Override + public void received(ShellAnimationFinishedMessage msg, int from) { + // Add the player to the set of players who have finished the animation + playersFinishedShellAnimation.add(from); + + // Check if both players have finished the shell animation + if (playersFinishedShellAnimation.size() == 2) { + // Clear the set of players who have finished the animation for the next shot + playersFinishedShellAnimation.clear(); + + // Transition back to the BATTLE state + setState(ServerState.BATTLE); + + // Log the completion of the shell animation + LOGGER.log(Level.INFO, "Both players finished shell animation. Returning to BATTLE state."); + } + } + } diff --git a/Projekte/battleship/model/src/main/java/pp/battleship/game/singlemode/Copycat.java b/Projekte/battleship/model/src/main/java/pp/battleship/game/singlemode/Copycat.java index f6e89be..c6ff54f 100644 --- a/Projekte/battleship/model/src/main/java/pp/battleship/game/singlemode/Copycat.java +++ b/Projekte/battleship/model/src/main/java/pp/battleship/game/singlemode/Copycat.java @@ -10,6 +10,7 @@ package pp.battleship.game.singlemode; import pp.battleship.message.client.ClientInterpreter; import pp.battleship.message.client.ClientMessage; import pp.battleship.message.client.MapMessage; +import pp.battleship.message.client.ShellAnimationFinishedMessage; import pp.battleship.message.client.ShootMessage; import pp.battleship.model.Battleship; @@ -63,6 +64,11 @@ class Copycat implements ClientInterpreter { copiedMessage = new MapMessage(msg.getShips().stream().map(Copycat::copy).toList()); } + @Override + public void received(ShellAnimationFinishedMessage shellAnimationFinishedMessage, int from) { + throw new UnsupportedOperationException("Unimplemented method 'received'"); + } + /** * Creates a copy of the provided {@link Battleship}. * diff --git a/Projekte/battleship/model/src/main/java/pp/battleship/message/client/ClientInterpreter.java b/Projekte/battleship/model/src/main/java/pp/battleship/message/client/ClientInterpreter.java index 6a50c1d..d14d2f5 100644 --- a/Projekte/battleship/model/src/main/java/pp/battleship/message/client/ClientInterpreter.java +++ b/Projekte/battleship/model/src/main/java/pp/battleship/message/client/ClientInterpreter.java @@ -26,4 +26,5 @@ public interface ClientInterpreter { * @param from the connection ID from which the message was received */ void received(MapMessage msg, int from); + void received(ShellAnimationFinishedMessage shellAnimationFinishedMessage, int from); } diff --git a/Projekte/battleship/model/src/main/java/pp/battleship/message/client/ShellAnimationFinishedMessage.java b/Projekte/battleship/model/src/main/java/pp/battleship/message/client/ShellAnimationFinishedMessage.java new file mode 100644 index 0000000..dba92d2 --- /dev/null +++ b/Projekte/battleship/model/src/main/java/pp/battleship/message/client/ShellAnimationFinishedMessage.java @@ -0,0 +1,10 @@ +package pp.battleship.message.client; + +public class ShellAnimationFinishedMessage extends ClientMessage{ + + @Override + public void accept(ClientInterpreter interpreter, int from) { + interpreter.received(this, from); + } + +} diff --git a/Projekte/battleship/model/src/main/java/pp/battleship/model/Shell.java b/Projekte/battleship/model/src/main/java/pp/battleship/model/Shell.java new file mode 100644 index 0000000..c0d488c --- /dev/null +++ b/Projekte/battleship/model/src/main/java/pp/battleship/model/Shell.java @@ -0,0 +1,47 @@ +package pp.battleship.model; + +import com.jme3.math.Vector3f; + +public class Shell { + private Vector3f startPosition; + private Vector3f targetPosition; + private Vector3f currentPosition; + private float speed; + private boolean isAtTarget; + + public Shell(Vector3f startPosition, Vector3f targetPosition, float speed) { + this.startPosition = startPosition; + this.targetPosition = targetPosition; + this.currentPosition = new Vector3f(startPosition); + this.speed = speed; + this.isAtTarget = true; + } + + // Aktualisiert die Position des Geschosses basierend auf der verstrichenen Zeit + public void updatePosition(float deltaTime) { + if (!isAtTarget) { + // Berechne die Richtung des Geschosses + Vector3f direction = targetPosition.subtract(currentPosition).normalize(); + // Berechne die Bewegung basierend auf der Geschwindigkeit und der verstrichenen Zeit + Vector3f movement = direction.mult(speed * deltaTime); + currentPosition.addLocal(movement); + + // Prüfe, ob das Geschoss das Ziel erreicht hat + if (currentPosition.distance(targetPosition) < speed * deltaTime) { + currentPosition.set(targetPosition); + isAtTarget = true; + } + } + } + + // Gibt die aktuelle Position des Geschosses zurück + public Vector3f getCurrentPosition() { + return currentPosition; + } + + // Überprüft, ob das Geschoss das Ziel erreicht hat + public boolean isAtTarget() { + return isAtTarget; + } +} + diff --git a/Projekte/battleship/model/src/main/java/pp/battleship/model/ShellControl.java b/Projekte/battleship/model/src/main/java/pp/battleship/model/ShellControl.java new file mode 100644 index 0000000..ec92152 --- /dev/null +++ b/Projekte/battleship/model/src/main/java/pp/battleship/model/ShellControl.java @@ -0,0 +1,46 @@ +package pp.battleship.model; + +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import com.jme3.scene.control.AbstractControl; + +public class ShellControl extends AbstractControl { + + private Shell shell; // Das Shell-Objekt, das die Bewegung des Geschosses enthält + + public ShellControl(Shell shell) { + this.shell = shell; + } + + // Die Methode wird in jedem Frame aufgerufen, um die Logik zu aktualisieren + @Override + protected void controlUpdate(float deltaTime) { + if (shell != null) { + // Aktualisiere die Position des Geschosses basierend auf der verstrichenen Zeit + shell.updatePosition(deltaTime); + + // Setze die neue Position des Geschosses im 3D-Raum + spatial.setLocalTranslation(shell.getCurrentPosition()); + + // Optionale Animation oder Effekte hinzufügen (z.B. Rauch oder Funkenflug) + // addParticleEffects(); + } + } + + + // Setze das Shell-Objekt neu, um es während des Spiels zu ändern + public void setShell(Shell shell) { + this.shell = shell; + } + + // Gibt das aktuell verwendete Shell-Objekt zurück + public Shell getShell() { + return this.shell; + } + + @Override + protected void controlRender(RenderManager rm, ViewPort vp) { + // TODO Auto-generated method stub + } +} +