Aufgabe 13: 1.Shell implementiert 2.ShellControl 3.ShellAnimation 4.State für Shell

This commit is contained in:
Dennis_Malkmus 2024-10-14 04:54:05 +02:00
parent 7076e204af
commit a0dffbfc34
15 changed files with 369515 additions and 378901 deletions

View File

@ -8,10 +8,12 @@
package pp.battleship.client.gui; package pp.battleship.client.gui;
import com.jme3.math.ColorRGBA; import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry; import com.jme3.scene.Geometry;
import com.jme3.scene.Node; import com.jme3.scene.Node;
import com.jme3.scene.Spatial; import com.jme3.scene.Spatial;
import pp.battleship.model.Battleship; import pp.battleship.model.Battleship;
import pp.battleship.model.Shell;
import pp.battleship.model.Shot; import pp.battleship.model.Shot;
import pp.util.Position; import pp.util.Position;
@ -36,6 +38,7 @@ class MapViewSynchronizer extends ShipMapSynchronizer {
// The MapView associated with this synchronizer // The MapView associated with this synchronizer
private final MapView view; private final MapView view;
private Shell shell;
/** /**
* Constructs a new MapViewSynchronizer for the given MapView. * Constructs a new MapViewSynchronizer for the given MapView.
@ -122,4 +125,19 @@ class MapViewSynchronizer extends ShipMapSynchronizer {
private Geometry shipLine(float x1, float y1, float x2, float y2, ColorRGBA color) { 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); return view.getApp().getDraw().makeFatLine(x1, y1, x2, y2, SHIP_DEPTH, color, SHIP_LINE_WIDTH);
} }
/**
*
* @param deltaTime
*/
public void update(float deltaTime) {
if (shell != null) {
shell.updatePosition(deltaTime);
drawShell(shell.getCurrentPosition());
}
}
private void drawShell(Vector3f position) {
// Methode zum Zeichnen des Geschosses auf der 2D-Karte TODO
}
} }

View File

@ -1,7 +1,7 @@
# Blender 4.2.2 LTS MTL File: 'None' # Blender 4.2.2 LTS MTL File: 'None'
# www.blender.org # www.blender.org
newmtl Main newmtl Main.002
Ns 319.999939 Ns 319.999939
Ka 1.000000 1.000000 1.000000 Ka 1.000000 1.000000 1.000000
Kd 0.490000 0.257495 0.132300 Kd 0.490000 0.257495 0.132300
@ -11,37 +11,7 @@ Ni 1.500000
d 1.000000 d 1.000000
illum 2 illum 2
newmtl Mat newmtl Mat.016
Ns 319.999939
Ka 1.000000 1.000000 1.000000
Kd 0.340000 0.164333 0.000000
Ks 1.000000 1.000000 1.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Mat.1
Ns 319.999939
Ka 1.000000 1.000000 1.000000
Kd 0.190000 0.077615 0.017100
Ks 1.000000 1.000000 1.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Mat.1_1
Ns 319.999939
Ka 1.000000 1.000000 1.000000
Kd 0.320000 0.151520 0.060800
Ks 1.000000 1.000000 1.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Mat.2
Ns 319.999939 Ns 319.999939
Ka 1.000000 1.000000 1.000000 Ka 1.000000 1.000000 1.000000
Kd 0.000000 0.000000 0.000000 Kd 0.000000 0.000000 0.000000
@ -51,37 +21,17 @@ Ni 1.500000
d 1.000000 d 1.000000
illum 2 illum 2
newmtl Mat.3 newmtl Mat.017
Ns 319.999939 Ns 319.999939
Ka 1.000000 1.000000 1.000000 Ka 1.000000 1.000000 1.000000
Kd 0.160000 0.151680 0.147200 Kd 0.190000 0.077615 0.017100
Ks 1.000000 1.000000 1.000000 Ks 1.000000 1.000000 1.000000
Ke 0.000000 0.000000 0.000000 Ke 0.000000 0.000000 0.000000
Ni 1.500000 Ni 1.500000
d 1.000000 d 1.000000
illum 2 illum 2
newmtl Mat.4 newmtl Mat.018
Ns 319.999939
Ka 1.000000 1.000000 1.000000
Kd 0.990000 0.990000 0.990000
Ks 1.000000 1.000000 1.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Mat.5
Ns 319.999939
Ka 1.000000 1.000000 1.000000
Kd 0.070000 0.062265 0.058100
Ks 1.000000 1.000000 1.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Mat.6
Ns 319.999939 Ns 319.999939
Ka 1.000000 1.000000 1.000000 Ka 1.000000 1.000000 1.000000
Kd 0.266600 0.466860 0.620000 Kd 0.266600 0.466860 0.620000
@ -91,7 +41,47 @@ Ni 1.500000
d 1.000000 d 1.000000
illum 2 illum 2
newmtl Mat.7 newmtl Mat.019
Ns 319.999939
Ka 1.000000 1.000000 1.000000
Kd 0.990000 0.990000 0.990000
Ks 1.000000 1.000000 1.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Mat.020
Ns 319.999939
Ka 1.000000 1.000000 1.000000
Kd 0.070000 0.062265 0.058100
Ks 1.000000 1.000000 1.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Mat.021
Ns 319.999939
Ka 1.000000 1.000000 1.000000
Kd 0.160000 0.151680 0.147200
Ks 1.000000 1.000000 1.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Mat.022
Ns 319.999939
Ka 1.000000 1.000000 1.000000
Kd 0.340000 0.164333 0.000000
Ks 1.000000 1.000000 1.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Mat.023
Ns 319.999939 Ns 319.999939
Ka 1.000000 1.000000 1.000000 Ka 1.000000 1.000000 1.000000
Kd 0.940000 0.561180 0.206800 Kd 0.940000 0.561180 0.206800
@ -101,7 +91,17 @@ Ni 1.500000
d 1.000000 d 1.000000
illum 2 illum 2
newmtl Sail newmtl Mat.1_1.002
Ns 319.999939
Ka 1.000000 1.000000 1.000000
Kd 0.320000 0.151520 0.060800
Ks 1.000000 1.000000 1.000000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl Sail.002
Ns 319.999939 Ns 319.999939
Ka 1.000000 1.000000 1.000000 Ka 1.000000 1.000000 1.000000
Kd 0.070000 0.070000 0.070000 Kd 0.070000 0.070000 0.070000

View File

@ -1,7 +1,7 @@
# Blender 4.2.2 LTS MTL File: 'None' # Blender 4.2.2 LTS MTL File: 'None'
# www.blender.org # www.blender.org
newmtl DeckStuff newmtl DeckStuff.003
Ns 20.000006 Ns 20.000006
Ka 1.000000 1.000000 1.000000 Ka 1.000000 1.000000 1.000000
Kd 0.184314 0.600000 0.792157 Kd 0.184314 0.600000 0.792157
@ -11,7 +11,7 @@ Ni 1.500000
d 1.000000 d 1.000000
illum 1 illum 1
newmtl Hull newmtl Hull.003
Ns 20.000006 Ns 20.000006
Ka 1.000000 1.000000 1.000000 Ka 1.000000 1.000000 1.000000
Kd 0.701961 0.678431 0.019608 Kd 0.701961 0.678431 0.019608
@ -21,7 +21,7 @@ Ni 1.500000
d 1.000000 d 1.000000
illum 1 illum 1
newmtl MastsRigging newmtl MastsRigging.003
Ns 20.000006 Ns 20.000006
Ka 1.000000 1.000000 1.000000 Ka 1.000000 1.000000 1.000000
Kd 0.086275 0.768628 0.117647 Kd 0.086275 0.768628 0.117647
@ -31,7 +31,7 @@ Ni 1.500000
d 1.000000 d 1.000000
illum 1 illum 1
newmtl Poopdeck newmtl Poopdeck.003
Ns 20.000006 Ns 20.000006
Ka 1.000000 1.000000 1.000000 Ka 1.000000 1.000000 1.000000
Kd 0.976471 0.211765 0.211765 Kd 0.976471 0.211765 0.211765
@ -41,7 +41,7 @@ Ni 1.500000
d 1.000000 d 1.000000
illum 1 illum 1
newmtl Sail newmtl Sail.007
Ns 20.000006 Ns 20.000006
Ka 1.000000 1.000000 1.000000 Ka 1.000000 1.000000 1.000000
Kd 0.588000 0.588000 0.588000 Kd 0.588000 0.588000 0.588000

View File

@ -1,8 +1,8 @@
# Blender MTL File: 'ShipV_0002.blend' # Blender 4.2.2 LTS MTL File: 'None'
# Material Count: 3 # www.blender.org
newmtl map_ShipV_001 newmtl map_ShipV_001
Ns 225.000000 Ns 224.999985
Ka 1.000000 1.000000 1.000000 Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.144874 0.000708 Kd 0.800000 0.144874 0.000708
Ks 0.500000 0.500000 0.500000 Ks 0.500000 0.500000 0.500000
@ -12,7 +12,7 @@ d 1.000000
illum 2 illum 2
newmtl map_ShipV_002 newmtl map_ShipV_002
Ns 225.000000 Ns 224.999985
Ka 1.000000 1.000000 1.000000 Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.035888 0.004678 Kd 0.800000 0.035888 0.004678
Ks 0.500000 0.500000 0.500000 Ks 0.500000 0.500000 0.500000
@ -22,7 +22,7 @@ d 1.000000
illum 2 illum 2
newmtl map_ShipV_003 newmtl map_ShipV_003
Ns 225.000000 Ns 224.999985
Ka 1.000000 1.000000 1.000000 Ka 1.000000 1.000000 1.000000
Kd 0.001405 0.006690 0.800000 Kd 0.001405 0.006690 0.800000
Ks 0.500000 0.500000 0.500000 Ks 0.500000 0.500000 0.500000

View File

@ -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.");
}
}

View File

@ -9,7 +9,9 @@ package pp.battleship.game.server;
import pp.battleship.BattleshipConfig; import pp.battleship.BattleshipConfig;
import pp.battleship.message.client.ClientInterpreter; import pp.battleship.message.client.ClientInterpreter;
import pp.battleship.message.client.ClientMessage;
import pp.battleship.message.client.MapMessage; import pp.battleship.message.client.MapMessage;
import pp.battleship.message.client.ShellAnimationFinishedMessage;
import pp.battleship.message.client.ShootMessage; import pp.battleship.message.client.ShootMessage;
import pp.battleship.message.server.EffectMessage; import pp.battleship.message.server.EffectMessage;
import pp.battleship.message.server.GameDetails; import pp.battleship.message.server.GameDetails;
@ -35,6 +37,7 @@ public class ServerGameLogic implements ClientInterpreter {
private final BattleshipConfig config; private final BattleshipConfig config;
private final List<Player> players = new ArrayList<>(2); private final List<Player> players = new ArrayList<>(2);
private final Set<Player> readyPlayers = new HashSet<>(); private final Set<Player> readyPlayers = new HashSet<>();
private Set<Integer> playersFinishedShellAnimation = new HashSet<>();
private final ServerSender serverSender; private final ServerSender serverSender;
private Player activePlayer; private Player activePlayer;
private ServerState state = ServerState.WAIT; private ServerState state = ServerState.WAIT;
@ -196,6 +199,11 @@ public class ServerGameLogic implements ClientInterpreter {
*/ */
void shoot(Player p, IntPoint pos) { void shoot(Player p, IntPoint pos) {
if (p != activePlayer) return; if (p != activePlayer) return;
setState(ServerState.SHELL_IN_FLIGHT);
// setState(ServerState.BATTLE);
final Player otherPlayer = getOpponent(activePlayer); final Player otherPlayer = getOpponent(activePlayer);
final Battleship selectedShip = otherPlayer.getMap().findShipAt(pos); final Battleship selectedShip = otherPlayer.getMap().findShipAt(pos);
if (selectedShip == null) { if (selectedShip == null) {
@ -225,5 +233,30 @@ public class ServerGameLogic implements ClientInterpreter {
} }
} }
} }
/**
* Handles the reception of ShellAnimationFinishedMessage.
* This method is called when a client signals that its shell animation is complete.
*
* @param msg the received ShellAnimationFinishedMessage
* @param from the ID of the sender client
*/
@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.");
}
}
} }

View File

@ -29,5 +29,8 @@ enum ServerState {
/** /**
* The game has ended because all the ships of one player have been destroyed. * The game has ended because all the ships of one player have been destroyed.
*/ */
GAME_OVER GAME_OVER,
//Game stays frozen as long as firing animation is running
SHELL_IN_FLIGHT
} }

View File

@ -10,6 +10,7 @@ package pp.battleship.game.singlemode;
import pp.battleship.message.client.ClientInterpreter; import pp.battleship.message.client.ClientInterpreter;
import pp.battleship.message.client.ClientMessage; import pp.battleship.message.client.ClientMessage;
import pp.battleship.message.client.MapMessage; import pp.battleship.message.client.MapMessage;
import pp.battleship.message.client.ShellAnimationFinishedMessage;
import pp.battleship.message.client.ShootMessage; import pp.battleship.message.client.ShootMessage;
import pp.battleship.model.Battleship; import pp.battleship.model.Battleship;
@ -72,4 +73,11 @@ class Copycat implements ClientInterpreter {
private static Battleship copy(Battleship ship) { private static Battleship copy(Battleship ship) {
return new Battleship(ship.getLength(), ship.getX(), ship.getY(), ship.getRot()); return new Battleship(ship.getLength(), ship.getX(), ship.getY(), ship.getRot());
} }
@Override
public void received(ShellAnimationFinishedMessage shellAnimationFinishedMessage, int from) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'received'");
}
} }

View File

@ -25,5 +25,7 @@ public interface ClientInterpreter {
* @param msg the MapMessage to be processed * @param msg the MapMessage to be processed
* @param from the connection ID from which the message was received * @param from the connection ID from which the message was received
*/ */
void received(MapMessage msg, int from); // TODO
void received(ShellAnimationFinishedMessage shellAnimationFinishedMessage, int from);
} }

View File

@ -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);
}
}

View File

@ -0,0 +1,46 @@
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;
}
}

View File

@ -0,0 +1,47 @@
package pp.battleship.model;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Spatial;
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
}
}