fixing shell

This commit is contained in:
Luca Puderbach
2024-10-20 04:30:57 +02:00
parent 04d16a2882
commit e4a24c3070
20 changed files with 258 additions and 50 deletions

View File

@@ -12,9 +12,9 @@ import java.lang.System.Logger.Level;
import pp.battleship.message.client.ShootMessage;
import pp.battleship.message.server.EffectMessage;
import pp.battleship.model.IntPoint;
import pp.battleship.model.Shell;
import pp.battleship.model.ShipMap;
import pp.battleship.notification.Sound;
import pp.battleship.model.Shell;
/**
* Represents the state of the client where players take turns to attack each other's ships.

View File

@@ -15,6 +15,7 @@ import java.util.List;
import java.util.Set;
import pp.battleship.BattleshipConfig;
import pp.battleship.message.client.AnimationFinishedMessage;
import pp.battleship.message.client.ClientInterpreter;
import pp.battleship.message.client.MapMessage;
import pp.battleship.message.client.ShootMessage;
@@ -24,7 +25,7 @@ import pp.battleship.message.server.ServerMessage;
import pp.battleship.message.server.StartBattleMessage;
import pp.battleship.model.Battleship;
import pp.battleship.model.IntPoint;
import pp.battleship.message.client.AnimationFinishedMessage;
/**
* Controls the server-side game logic for Battleship.
@@ -243,12 +244,33 @@ public class ServerGameLogic implements ClientInterpreter {
return ships.stream().allMatch(ship -> isInBounds(ship) &&
ship.getPositions().stream().allMatch(belegt::add));
}
// public void displayError(String message) {
// System.out.println("Fehlermeldung: " + message);
// // Optional: GUI-Element aktualisieren, um die Nachricht anzuzeigen
// }
/**
* Handles the reception of a AnimationFinishedMessage.
*
* @param msg the received MapMessage
* @param from the ID of the sender client
*/
@Override
public void received(AnimationFinishedMessage msg, int from) {
if (state != ServerState.ANIMATION) {
LOGGER.log(Level.ERROR, "animation finished not allowed in {0}", state);
}
else {
LOGGER.log(Level.DEBUG, "anim received from {0}", getPlayerById(from));
Player player = getPlayerById(from);
if (!waitPlayers.add(player)) {
LOGGER.log(Level.ERROR, "{0} already sent animation finished", player); //NON-NLS
return;
}
if (waitPlayers.size() == 2) {
waitPlayers = new HashSet<>();
setState(ServerState.BATTLE);
}
}
}
}

View File

@@ -29,5 +29,10 @@ enum ServerState {
/**
* The game has ended because all the ships of one player have been destroyed.
*/
GAME_OVER
GAME_OVER,
/**
* The server is waiting for all clients to finish the shoot animation.
*/
ANIMATION
}

View File

@@ -7,6 +7,7 @@
package pp.battleship.game.singlemode;
import pp.battleship.message.client.AnimationFinishedMessage;
import pp.battleship.message.client.ClientInterpreter;
import pp.battleship.message.client.ClientMessage;
import pp.battleship.message.client.MapMessage;
@@ -72,4 +73,10 @@ class Copycat implements ClientInterpreter {
private static Battleship copy(Battleship ship) {
return new Battleship(ship.getLength(), ship.getX(), ship.getY(), ship.getRot());
}
@Override
public void received(AnimationFinishedMessage msg, int from) {
copiedMessage = msg;
}
}

View File

@@ -0,0 +1,25 @@
package pp.battleship.message.client;
import com.jme3.network.serializing.Serializable;
/**
* Represents a message indicating that an animation has finished on the client side.
*/
@Serializable
public class AnimationFinishedMessage extends ClientMessage {
public AnimationFinishedMessage() {
super();
}
/**
* Accepts a visitor to process this message.
*
* @param interpreter the visitor to process this message
* @param from the connection ID from which the message was received
*/
@Override
public void accept(ClientInterpreter interpreter, int from) {
interpreter.received(this, from);
}
}

View File

@@ -26,4 +26,12 @@ public interface ClientInterpreter {
* @param from the connection ID from which the message was received
*/
void received(MapMessage msg, int from);
/**
* Processes a received AnimationFinishedMessage.
*
* @param msg the MapMessage to be processed
* @param from the connection ID from which the message was received
*/
void received(AnimationFinishedMessage msg, int from);
}

View File

@@ -0,0 +1,126 @@
package pp.battleship.model;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
/**
* The {@code Shell} class represents a projectile fired by a ship in the Battleship game.
* It models the position and rotation of the projectile and allows for its movement along
* a Bezier curve.
*/
public class Shell implements Item {
/**
* Initial position of the shell
*/
private final static Vector3f INIT_POS = new Vector3f(-3, 7, -3);
/**
* The overshot difference vector used to get a shallower flight path
*/
private final static Vector3f OVER_SHOT_DIFF = new Vector3f(-1, -1, -1);
// Target shot position
private final Vector3f shotPosition;
// Position on top of shotPosition used for Bezier curve
private final Vector3f overShotPosition;
// Current position of the shell
private Vector3f position;
// Current rotation of the shell
private final Quaternion rotation;
/**
* Constructs a new {@code Shell} object using the given {@code Shot} target.
* The initial position, target position, and overshot position are calculated.
*
* @param shot The target {@code Shot} object containing the destination coordinates.
*/
public Shell(Shot shot) {
this.shotPosition = new Vector3f(shot.getX(), 0, shot.getY());
this.overShotPosition = new Vector3f(shotPosition.x, INIT_POS.y, shotPosition.z).add(OVER_SHOT_DIFF);
this.position = INIT_POS;
this.rotation = new Quaternion();
}
/**
* Gets the current position of the shell.
*
* @return The current position as a {@code Vector3f}.
*/
public Vector3f getPosition() {
return this.position;
}
/**
* Gets the current rotation of the shell.
*
* @return The current rotation as a {@code Quaternion}.
*/
public Quaternion getRotation() {
return this.rotation;
}
/**
* Moves the shell along a Bezier curve based on the given time factor {@code t}.
* The position and rotation of the shell are updated.
*
* @param t The time factor between 0 and 1, representing the progress of the shell's flight.
*/
public void move(float t) {
if (t > 1f) t = 1f;
Vector3f newPosition = bezInt(INIT_POS, overShotPosition, shotPosition, t);
updateRotation(position, newPosition);
this.position = newPosition;
}
/**
* Performs a quadratic Bezier interpolation between three points based on the time factor {@code t}.
*
* @param p1 The start position.
* @param p2 The overshot position.
* @param p3 The target position.
* @param t The time factor for interpolation.
* @return The interpolated position as a {@code Vector3f}.
*/
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);
}
/**
* Performs linear interpolation between two points {@code p1} and {@code p2} based on the time factor {@code t}.
*
* @param p1 The start position.
* @param p2 The end position.
* @param t The time factor for interpolation.
* @return The interpolated position as a {@code Vector3f}.
*/
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);
}
/**
* Updates the rotation of the shell to face the new position along its flight path.
*
* @param oldPos The previous position of the shell.
* @param newPos The new position of the shell.
*/
private void updateRotation(Vector3f oldPos, Vector3f newPos) {
Vector3f direction = newPos.subtract(oldPos).normalize();
if (direction.lengthSquared() > 0) {
this.rotation.lookAt(direction, Vector3f.UNIT_Y);
}
}
@Override
public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
@Override
public void accept(VoidVisitor visitor) {
visitor.visit(this);
}
}

View File

@@ -249,4 +249,8 @@ public class ShipMap {
if (eventBroker != null)
eventBroker.notifyListeners(event);
}
public void add(Shell shell) {
addItem(shell);
}
}

View File

@@ -28,4 +28,13 @@ public interface Visitor<T> {
* @return the result of visiting the Battleship element
*/
T visit(Battleship ship);
/**
* Visits a Shell element
*
* @param shell the Shell element to visit
* @return the result of visitung the Battleship element
*/
T visit(Shell shell);
}

View File

@@ -25,4 +25,11 @@ public interface VoidVisitor {
* @param ship the Battleship element to visit
*/
void visit(Battleship ship);
/**
* Visits a Shell element
* @param shell the Shell element to visit
*/
void visit(Shell shell);
}

View File

@@ -22,5 +22,9 @@ public enum Sound {
/**
* Sound of a ship being destroyed.
*/
DESTROYED_SHIP
DESTROYED_SHIP,
/**
* Sound of flying Shell
*/
SHELL_FLYING
}