diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/BoardAppState.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/BoardAppState.java index 815c131..96e4809 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/BoardAppState.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/BoardAppState.java @@ -23,7 +23,6 @@ import com.jme3.util.TangentBinormalGenerator; import pp.monopoly.model.Board; import pp.monopoly.client.gui.BobTheBuilder; import pp.monopoly.client.gui.Toolbar; -import pp.util.FloatMath; import static pp.util.FloatMath.PI; import static pp.util.FloatMath.TWO_PI; @@ -86,11 +85,11 @@ public class BoardAppState extends MonopolyAppState { getApp().getRootNode().detachAllChildren(); getApp().getGuiNode().detachAllChildren(); - getApp().getGuiNode().attachChild(new Toolbar(getApp())); + new Toolbar(getApp()).open(); sceneNode.detachAllChildren(); setupScene(); if (bobTheBuilder == null) { - bobTheBuilder = new BobTheBuilder(getApp(), sceneNode, getGameLogic().getBoard()); + bobTheBuilder = new BobTheBuilder(getApp(), getApp().getRootNode()); getGameLogic().addListener(bobTheBuilder); } getApp().getRootNode().attachChild(viewNode); @@ -108,13 +107,13 @@ public class BoardAppState extends MonopolyAppState { final Board board = getGameLogic().getBoard(); final float mx = 0.5f * board.getWidth(); final float my = 0.5f * board.getHeight(); - // final float radius = 2f * sqrt(mx * mx + my + my); - // final float cos = radius * cos(cameraAngle); - // final float sin = radius * sin(cameraAngle); - // final float x = mx - cos; - // final float y = my - sin; + final float radius = 2f * sqrt(mx * mx + my + my); + final float cos = radius * cos(cameraAngle); + final float sin = radius * sin(cameraAngle); + final float x = mx - cos; + final float y = my - sin; final Camera camera = getApp().getCamera(); - camera.setLocation(new Vector3f(20, ABOVE_SEA_LEVEL, 0)); + camera.setLocation(new Vector3f(x, ABOVE_SEA_LEVEL, y)); camera.lookAt(new Vector3f(0,0, 0), Vector3f.UNIT_Y); camera.update(); @@ -152,16 +151,16 @@ public class BoardAppState extends MonopolyAppState { */ private void setupLights() { final AssetManager assetManager = getApp().getAssetManager(); - // final DirectionalLightShadowRenderer shRend = new DirectionalLightShadowRenderer(assetManager, 2048, 3); - // shRend.setLambda(0.55f); - // shRend.setShadowIntensity(0.6f); - // shRend.setEdgeFilteringMode(EdgeFilteringMode.Bilinear); - // getApp().getViewPort().addProcessor(shRend); + final DirectionalLightShadowRenderer shRend = new DirectionalLightShadowRenderer(assetManager, 2048, 3); + shRend.setLambda(0.55f); + shRend.setShadowIntensity(0.6f); + shRend.setEdgeFilteringMode(EdgeFilteringMode.Bilinear); + getApp().getViewPort().addProcessor(shRend); - // final DirectionalLight sun = new DirectionalLight(); - // sun.setDirection(new Vector3f(-1f, -0.7f, -1f).normalizeLocal()); - // viewNode.addLight(sun); - // shRend.setLight(sun); + final DirectionalLight sun = new DirectionalLight(); + sun.setDirection(new Vector3f(-1f, -0.7f, -1f).normalizeLocal()); + viewNode.addLight(sun); + shRend.setLight(sun); final AmbientLight ambientLight = new AmbientLight(new ColorRGBA(1f, 1f, 1f, 1f)); viewNode.addLight(ambientLight); @@ -194,8 +193,7 @@ public class BoardAppState extends MonopolyAppState { final float y = board.getHeight(); final Box seaMesh = new Box(y, 0.1f, x); final Geometry seaGeo = new Geometry("sea", seaMesh); //NON-NLS - // seaGeo.setLocalTranslation(new Vector3f(y, -0.1f, x)); - // seaMesh.scaleTextureCoordinates(new Vector2f(4f, 4f)); + seaGeo.setLocalTranslation(new Vector3f(0, -0.1f, 0)); final Material seaMat = new Material(getApp().getAssetManager(), "Common/MatDefs/Light/Lighting.j3md"); Texture texture = getApp().getAssetManager().loadTexture("Pictures/board2.png"); seaMat.setTexture("DiffuseMap", texture); diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/BobTheBuilder.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/BobTheBuilder.java index 1d6d63f..31cc495 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/BobTheBuilder.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/BobTheBuilder.java @@ -1,8 +1,13 @@ package pp.monopoly.client.gui; +import java.lang.management.PlatformLoggingMXBean; +import java.util.stream.Collector; +import java.util.stream.Collectors; + import com.jme3.material.Material; import com.jme3.material.RenderState.BlendMode; import com.jme3.math.ColorRGBA; +import com.jme3.math.Vector3f; import com.jme3.renderer.queue.RenderQueue.ShadowMode; import com.jme3.scene.Geometry; import com.jme3.scene.Node; @@ -10,10 +15,12 @@ import com.jme3.scene.Spatial; import com.jme3.scene.shape.Box; import pp.monopoly.client.MonopolyApp; -import pp.monopoly.model.Board; +import pp.monopoly.game.server.Player; import pp.monopoly.model.Figure; import pp.monopoly.model.Hotel; import pp.monopoly.model.House; +import pp.monopoly.model.Item; +import pp.monopoly.notification.UpdatePlayerView; public class BobTheBuilder extends GameBoardSynchronizer { @@ -24,30 +31,42 @@ public class BobTheBuilder extends GameBoardSynchronizer { private static final String HOTEL = "hotel"; //NON-NLS private final MonopolyApp app; - private final Board board; - public BobTheBuilder(MonopolyApp app, Node root, Board board) { + public BobTheBuilder(MonopolyApp app, Node root) { super(app.getGameLogic().getBoard(), root); this.app = app; - this.board = board; addExisting(); } @Override public Spatial visit(Figure figure) { + try { + // Lade das Modell + com.jme3.scene.Spatial model = app.getAssetManager().loadModel( + "models/" + "Spielfiguren/" + figure.getType() + "/" + figure.getType() + ".j3o"); + + // Skaliere und positioniere das Modell + model.setLocalScale(0.5f); + model.setLocalTranslation(figure.getPosition()); + + // Setze die Rotation basierend auf der Feld-ID + model.setLocalRotation(figure.getRot().toQuaternion()); + + return model; + } catch (Exception e) { + System.err.println("Fehler beim Laden des Modells für Spieler " + e.getMessage()); + } return createBox(figure); } @Override public Spatial visit(Hotel hotel) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'visit'"); + return null; } @Override public Spatial visit(House figure) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'visit'"); + return null; } /** @@ -56,7 +75,7 @@ public class BobTheBuilder extends GameBoardSynchronizer { * @param ship the battleship to be represented * @return the geometry representing the battleship as a box */ - private Spatial createBox(Figure figure) { + private Spatial createBox(Item item) { final Box box = new Box(3, 3f, 3); @@ -87,4 +106,15 @@ public class BobTheBuilder extends GameBoardSynchronizer { return material; } + @Override + public void receivedEvent(UpdatePlayerView event) { + clear(); + board.removePlayers(); + for (Player player : app.getGameLogic().getPlayerHandler().getPlayers()) { + board.add(player.getFigure()); + } + for (Item item : board.getItems().stream().filter(p -> p instanceof Figure).collect(Collectors.toList())) { + add(item); + } + } } diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/GameBoardSynchronizer.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/GameBoardSynchronizer.java index 0f9624c..537fdac 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/GameBoardSynchronizer.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/GameBoardSynchronizer.java @@ -4,11 +4,12 @@ import com.jme3.scene.Node; import com.jme3.scene.Spatial; import pp.monopoly.model.Item; import pp.monopoly.model.Visitor; +import pp.monopoly.notification.DiceRollEvent; import pp.monopoly.notification.GameEventListener; import pp.monopoly.notification.ItemAddedEvent; -import pp.monopoly.notification.ItemRemovedEvent; import pp.monopoly.notification.UpdatePlayerView; import pp.monopoly.model.Board; +import pp.monopoly.model.Figure; import pp.view.ModelViewSynchronizer; /** @@ -22,7 +23,7 @@ import pp.view.ModelViewSynchronizer; */ abstract class GameBoardSynchronizer extends ModelViewSynchronizer implements Visitor, GameEventListener { // The board that this synchronizer is responsible for - private final Board board; + protected final Board board; /** * Constructs a new GameBoardSynchronizer. @@ -57,32 +58,23 @@ abstract class GameBoardSynchronizer extends ModelViewSynchronizer impleme board.getItems().forEach(this::add); } - /** - * Handles the event when an item is removed from the board. - * Removes the visual representation of the item from the view if it belongs to the synchronized board. - * - * @param event the event indicating that an item has been removed from the board - */ @Override - public void receivedEvent(ItemRemovedEvent event) { - if (board == event.board()) - delete(event.item()); + public void receivedEvent(UpdatePlayerView event) { + for (Item item : board.getItems()) { + // if(!(item instanceof Figure)) { + delete(item); + add(item); + // } + } } - /** - * Handles the event when an item is added to the board. - * Adds the visual representation of the new item to the view if it belongs to the synchronized board. - * - * @param event the event indicating that an item has been added to the board - */ @Override - public void receivedEvent(ItemAddedEvent event) { - if (board == event.board()) - add(event.item()); + public void receivedEvent(DiceRollEvent event) { + for (Item item : board.getItems()) { + if(item instanceof Figure) { + //???????????????????????????????????????? + } + } } - public void recievedEvent(UpdatePlayerView event) { - clear(); - addExisting(); - } } diff --git a/Projekte/monopoly/model/src/main/java/pp/monopoly/game/client/ClientGameLogic.java b/Projekte/monopoly/model/src/main/java/pp/monopoly/game/client/ClientGameLogic.java index fda6a67..83ba947 100644 --- a/Projekte/monopoly/model/src/main/java/pp/monopoly/game/client/ClientGameLogic.java +++ b/Projekte/monopoly/model/src/main/java/pp/monopoly/game/client/ClientGameLogic.java @@ -8,6 +8,7 @@ import java.util.List; import pp.monopoly.game.server.Player; import pp.monopoly.game.server.PlayerHandler; import pp.monopoly.message.client.ClientMessage; +import pp.monopoly.message.server.BuildInfo; import pp.monopoly.message.server.BuyPropertyRequest; import pp.monopoly.message.server.DiceResult; import pp.monopoly.message.server.EventDrawCard; @@ -23,8 +24,11 @@ import pp.monopoly.message.server.TradeReply; import pp.monopoly.message.server.TradeRequest; import pp.monopoly.message.server.ViewAssetsResponse; import pp.monopoly.model.Board; +import pp.monopoly.model.Hotel; +import pp.monopoly.model.House; import pp.monopoly.model.TradeHandler; import pp.monopoly.model.fields.BoardManager; +import pp.monopoly.model.fields.BuildingProperty; import pp.monopoly.notification.ClientStateEvent; import pp.monopoly.notification.DiceRollEvent; import pp.monopoly.notification.ButtonStatusEvent; @@ -226,6 +230,9 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker { public void received(GameStart msg) { playerHandler = msg.getPlayerHandler(); setState(new WaitForTurnState(this)); + for (Player player : playerHandler.getPlayers()) { + board.add(player.getFigure()); + } notifyListeners(new ButtonStatusEvent(false)); notifyListeners(new UpdatePlayerView()); } @@ -301,4 +308,16 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker { } } + @Override + public void received(BuildInfo msg) { + if (msg.isAdded()) { + BuildingProperty property = ((BuildingProperty)boardManager.getFieldAtIndex(msg.getId())); + if (property.getHotel() == 1 ) { + board.add(new Hotel(property.getId())); + } else { + board.add(new House( property.getHouses(), property.getId())); + } + } + } + } diff --git a/Projekte/monopoly/model/src/main/java/pp/monopoly/game/server/ServerGameLogic.java b/Projekte/monopoly/model/src/main/java/pp/monopoly/game/server/ServerGameLogic.java index 5c2da6d..8e298a4 100644 --- a/Projekte/monopoly/model/src/main/java/pp/monopoly/game/server/ServerGameLogic.java +++ b/Projekte/monopoly/model/src/main/java/pp/monopoly/game/server/ServerGameLogic.java @@ -7,6 +7,8 @@ import java.util.List; import java.util.Set; import java.util.stream.Collectors; +import com.jme3.math.Vector3f; + import pp.monopoly.MonopolyConfig; import pp.monopoly.message.client.AlterProperty; import pp.monopoly.message.client.BuyPropertyResponse; @@ -18,6 +20,7 @@ import pp.monopoly.message.client.RollDice; import pp.monopoly.message.client.TradeOffer; import pp.monopoly.message.client.TradeResponse; import pp.monopoly.message.client.ViewAssetsRequest; +import pp.monopoly.message.server.BuildInfo; import pp.monopoly.message.server.GameOver; import pp.monopoly.message.server.GameStart; import pp.monopoly.message.server.NextPlayerTurn; @@ -209,7 +212,9 @@ public class ServerGameLogic implements ClientInterpreter { String name = msg.getName(); String truc = name.length() > 10 ? name.substring(0, 15) : name; player.setName(truc); - player.setFigure(new Figure(1, -10, -10, Rotation.LEFT, msg.getFigure())); + Figure figure = new Figure(new Vector3f(0, 1, 0), Rotation.NORTH, msg.getFigure()); + player.setFigure(figure); + // board.addFigure(figure); playerHandler.setPlayerReady(player, true); LOGGER.log(Level.DEBUG, "Player {0} is ready", player.getName()); } @@ -407,6 +412,7 @@ public class ServerGameLogic implements ClientInterpreter { for (BuildingProperty field : properties.stream().map(p -> (BuildingProperty) p).collect(Collectors.toList())) { if (boardManager.canBuild(field) && sender.getAccountBalance() >= field.getHousePrice()) { field.build(); + send(playerHandler.getPlayerById(from), new BuildInfo(field.getId(), true)); sender.pay(field.getHousePrice()); } } @@ -418,7 +424,6 @@ public class ServerGameLogic implements ClientInterpreter { } } } - updateAllPlayers(); } diff --git a/Projekte/monopoly/model/src/main/java/pp/monopoly/message/server/BuildInfo.java b/Projekte/monopoly/model/src/main/java/pp/monopoly/message/server/BuildInfo.java new file mode 100644 index 0000000..72a3a9c --- /dev/null +++ b/Projekte/monopoly/model/src/main/java/pp/monopoly/message/server/BuildInfo.java @@ -0,0 +1,34 @@ +package pp.monopoly.message.server; + +import com.jme3.network.serializing.Serializable; + + +@Serializable +public class BuildInfo extends ServerMessage { + + private final int id; + private final boolean added; + + private BuildInfo() { + this(0, false); + } + + public BuildInfo(int id, boolean added) { + this.id = id; + this.added = added; + } + + public int getId() { + return id; + } + + public boolean isAdded() { + return added; + } + + @Override + public void accept(ServerInterpreter interpreter) { + interpreter.received(this); + } + +} diff --git a/Projekte/monopoly/model/src/main/java/pp/monopoly/message/server/ServerInterpreter.java b/Projekte/monopoly/model/src/main/java/pp/monopoly/message/server/ServerInterpreter.java index 42219d1..b7dc8f4 100644 --- a/Projekte/monopoly/model/src/main/java/pp/monopoly/message/server/ServerInterpreter.java +++ b/Projekte/monopoly/model/src/main/java/pp/monopoly/message/server/ServerInterpreter.java @@ -103,4 +103,11 @@ public interface ServerInterpreter { * @param msg the NotificationMessage message received */ void received(NotificationMessage msg); + + /** + * Handles a BuildInfo message received from the server. + * + * @param msg the BuildInfo message received + */ + void received(BuildInfo msg); } diff --git a/Projekte/monopoly/model/src/main/java/pp/monopoly/model/Board.java b/Projekte/monopoly/model/src/main/java/pp/monopoly/model/Board.java index 811e8c8..0f6e433 100644 --- a/Projekte/monopoly/model/src/main/java/pp/monopoly/model/Board.java +++ b/Projekte/monopoly/model/src/main/java/pp/monopoly/model/Board.java @@ -99,6 +99,10 @@ public class Board { notifyListeners((GameEvent) new ItemRemovedEvent(this, item)); } + public void removePlayers() { + items.removeIf(item -> item instanceof Figure); + } + /** * Removes all items from the map and triggers corresponding removal events for each. */ diff --git a/Projekte/monopoly/model/src/main/java/pp/monopoly/model/Figure.java b/Projekte/monopoly/model/src/main/java/pp/monopoly/model/Figure.java index c64a384..df80ead 100644 --- a/Projekte/monopoly/model/src/main/java/pp/monopoly/model/Figure.java +++ b/Projekte/monopoly/model/src/main/java/pp/monopoly/model/Figure.java @@ -1,28 +1,22 @@ package pp.monopoly.model; -import static java.lang.Math.max; -import static java.lang.Math.min; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; +import java.util.Random; +import com.jme3.math.Vector3f; import com.jme3.network.serializing.Serializable; @Serializable public class Figure implements Item{ private final String type; - private final int length; // The length of the Figure - private int x; // The x-coordinate of the Figure's position - private int y; // The y-coordinate of the Figure's position + private Vector3f position; private Rotation rot; // The rotation of the Figure - private final Set damaged = new HashSet<>(); // The set of positions that have been hit on this ship /** * Default constructor for serialization. Initializes a Figure with length 0, - * at position (0, 0), with a default rotation of RIGHT. + * at position (0, 0), with a default rotation of NORTH. */ private Figure() { - this(0, 0, 0, Rotation.RIGHT, "cube"); + this(null, Rotation.NORTH, ""); } /** @@ -30,14 +24,12 @@ public class Figure implements Item{ * * @param length the length of the Figure * @param x the x-coordinate of the Figure's initial position - * @param y the y-coordinate of the Figure's initial position + * @param z the z-coordinate of the Figure's initial position * @param rot the rotation of the Figure */ - public Figure(int length, int x, int y, Rotation rot, String type) { - this.x = x; - this.y = y; + public Figure(Vector3f position, Rotation rot, String type) { + this.position = calculateFieldPosition(0); this.rot = rot; - this.length = length; this.type = type; } @@ -46,8 +38,17 @@ public class Figure implements Item{ * * @return the x-coordinate of the Figure */ - public int getX() { - return x; + public float getX() { + return position.getX(); + } + + /** + * Returns the current z-coordinate of the Figure's position. + * + * @return the z-coordinate of the Figure + */ + public float getZ() { + return position.getZ(); } /** @@ -55,19 +56,17 @@ public class Figure implements Item{ * * @return the y-coordinate of the Figure */ - public int getY() { - return y; + public float getY() { + return position.getY(); } /** - * Moves the Figure to the specified coordinates. + * Returns the current position of the Figure. * - * @param x the new x-coordinate of the Figure's position - * @param y the new y-coordinate of the Figure's position + * @return the position of the Figure */ - public void moveTo(int x, int y) { - this.x = x; - this.y = y; + public Vector3f getPosition() { + return position; } /** @@ -75,8 +74,8 @@ public class Figure implements Item{ * * @param pos the new position of the Figure */ - public void moveTo(IntPosition pos) { - moveTo(pos.getX(), pos.getY()); + public void moveTo(Vector3f pos) { + position = pos; } /** @@ -85,85 +84,62 @@ public class Figure implements Item{ * @param fieldId the position to move to */ public void moveTo(int fieldId) { - moveTo(fieldIdToPosition(fieldId)); + moveTo(calculateFieldPosition(fieldId)); } - private IntPoint fieldIdToPosition(int fieldId) { - if (fieldId < 0 || fieldId > 39) { - throw new IllegalArgumentException("Invalid fieldId: " + fieldId); + private Vector3f calculateFieldPosition(int fieldID) { + float baseX = 0.0f; + float baseZ = 0.0f; + + switch (fieldID) { + case 0: baseX = -9.1f; baseZ = -9.1f; break; + case 1: baseX = -6.5f; baseZ = -9.1f; break; + case 2: baseX = -4.9f; baseZ = -9.1f; break; + case 3: baseX = -3.3f; baseZ = -9.1f; break; + case 4: baseX = -1.6f; baseZ = -9.1f; break; + case 5: baseX = 0.0f; baseZ = -9.1f; break; + case 6: baseX = 1.6f; baseZ = -9.1f; break; + case 7: baseX = 3.3f; baseZ = -9.1f; break; + case 8: baseX = 4.9f; baseZ = -9.1f; break; + case 9: baseX = 6.5f; baseZ = -9.1f; break; + case 10: baseX = 9.1f; baseZ = -9.1f; break; + case 11: baseX = 9.1f; baseZ = -6.5f; break; + case 12: baseX = 9.1f; baseZ = -4.9f; break; + case 13: baseX = 9.1f; baseZ = -3.3f; break; + case 14: baseX = 9.1f; baseZ = -1.6f; break; + case 15: baseX = 9.1f; baseZ = 0.0f; break; + case 16: baseX = 9.1f; baseZ = 1.6f; break; + case 17: baseX = 9.1f; baseZ = 3.3f; break; + case 18: baseX = 9.1f; baseZ = 4.9f; break; + case 19: baseX = 9.1f; baseZ = 6.5f; break; + case 20: baseX = 9.1f; baseZ = 9.1f; break; + case 21: baseX = 6.5f; baseZ = 9.1f; break; + case 22: baseX = 4.9f; baseZ = 9.1f; break; + case 23: baseX = 3.3f; baseZ = 9.1f; break; + case 24: baseX = 1.6f; baseZ = 9.1f; break; + case 25: baseX = 0.0f; baseZ = 9.1f; break; + case 26: baseX = -1.6f; baseZ = 9.1f; break; + case 27: baseX = -3.3f; baseZ = 9.1f; break; + case 28: baseX = -4.9f; baseZ = 9.1f; break; + case 29: baseX = -6.5f; baseZ = 9.1f; break; + case 30: baseX = -9.1f; baseZ = 9.1f; break; + case 31: baseX = -9.1f; baseZ = 6.5f; break; + case 32: baseX = -9.1f; baseZ = 4.9f; break; + case 33: baseX = -9.1f; baseZ = 3.3f; break; + case 34: baseX = -9.1f; baseZ = 1.6f; break; + case 35: baseX = -9.1f; baseZ = 0.0f; break; + case 36: baseX = -9.1f; baseZ = -1.6f; break; + case 37: baseX = -9.1f; baseZ = -3.3f; break; + case 38: baseX = -9.1f; baseZ = -4.9f; break; + case 39: baseX = -9.1f; baseZ = -6.5f; break; + default: throw new IllegalArgumentException("Ungültige Feld-ID: " + fieldID); } - // Determine which edge and position along the edge - if (fieldId <= 9) { - // Bottom edge: From (-10, -10) to (10, -10) - int x = -10 + fieldId * 2; - return new IntPoint(x, -10); - } else if (fieldId <= 19) { - // Right edge: From (10, -10) to (10, 10) - int y = -10 + (fieldId - 10) * 2; - return new IntPoint(10, y); - } else if (fieldId <= 29) { - // Top edge: From (10, 10) to (-10, 10) - int x = 10 - (fieldId - 20) * 2; - return new IntPoint(x, 10); - } else { - // Left edge: From (-10, 10) to (-10, -10) - int y = 10 - (fieldId - 30) * 2; - return new IntPoint(-10, y); - } - } + float xOffset = new Random().nextFloat(); + float zOffset = new Random().nextFloat(); - private Rotation fieldIdToRotation(int fieldId) { - if (fieldId >= 0 && fieldId <= 10) return Rotation.DOWN; - else if (fieldId <= 20) return Rotation.LEFT; - else if (fieldId <= 30) return Rotation.UP; - else if (fieldId <= 39) return Rotation.RIGHT; - else throw new IllegalArgumentException(); - } - - /** - * Returns the length of the Figure. - * - * @return the length of the Figure - */ - public int getLength() { - return length; - } - - /** - * Returns the minimum x-coordinate that the Figure occupies based on its current position and rotation. - * - * @return the minimum x-coordinate of the Figure - */ - public int getMinX() { - return x + min(0, (length - 1) * rot.dx()); - } - - /** - * Returns the maximum x-coordinate that the Figure occupies based on its current position and rotation. - * - * @return the maximum x-coordinate of the Figure - */ - public int getMaxX() { - return x + max(0, (length - 1) * rot.dx()); - } - - /** - * Returns the minimum y-coordinate that the Figure occupies based on its current position and rotation. - * - * @return the minimum y-coordinate of the Figure - */ - public int getMinY() { - return y + min(0, (length - 1) * rot.dy()); - } - - /** - * Returns the maximum y-coordinate that the Figure occupies based on its current position and rotation. - * - * @return the maximum y-coordinate of the Figure - */ - public int getMaxY() { - return y + max(0, (length - 1) * rot.dy()); + //TODO adjust y pos + return new Vector3f(baseX + xOffset, 1, baseZ + zOffset); } /** @@ -184,99 +160,6 @@ public class Figure implements Item{ this.rot = rot; } - /** - * Rotates the Figure by 90 degrees clockwise. - */ - public void rotated() { - setRotation(rot.rotate()); - } - - /** - * Attempts to hit the Figure at the specified position. - * If the position is part of the Figure, the hit is recorded. - * - * @param x the x-coordinate of the position to hit - * @param y the y-coordinate of the position to hit - * @return true if the position is part of the Figure, false otherwise - * @see #contains(int, int) - */ - public boolean hit(int x, int y) { - if (!contains(x, y)) - return false; - damaged.add(new IntPoint(x, y)); - return true; - } - - /** - * Attempts to hit the Figure at the specified position. - * If the position is part of the Figure, the hit is recorded. - * This is a convenience method for {@linkplain #hit(int, int)}. - * - * @param position the position to hit - * @return true if the position is part of the Figure, false otherwise - */ - public boolean hit(IntPosition position) { - return hit(position.getX(), position.getY()); - } - - /** - * Returns the positions of this Figure that have been hit. - * - * @return a set of positions that have been hit - * @see #hit(int, int) - */ - public Set getDamaged() { - return Collections.unmodifiableSet(damaged); - } - - /** - * Checks whether the specified position is covered by the Figure. This method does - * not record a hit, only checks coverage. - * This is a convenience method for {@linkplain #contains(int, int)}. - * - * @param pos the position to check - * @return true if the position is covered by the Figure, false otherwise - */ - public boolean contains(IntPosition pos) { - return contains(pos.getX(), pos.getY()); - } - - /** - * Checks whether the specified position is covered by the Figure. This method does - * not record a hit, only checks coverage. - * - * @param x the x-coordinate of the position to check - * @param y the y-coordinate of the position to check - * @return true if the position is covered by the Figure, false otherwise - */ - public boolean contains(int x, int y) { - return getMinX() <= x && x <= getMaxX() && - getMinY() <= y && y <= getMaxY(); - } - - /** - * Determines if the Figure has been completely destroyed. A Figure is considered - * destroyed if all of its positions have been hit. - * - * @return true if the Figure is destroyed, false otherwise - * @see #hit(int, int) - */ - public boolean isDestroyed() { - return damaged.size() == length; - } - - /** - * Checks whether this Figure collides with another Figure. Two Figures collide - * if any of their occupied positions overlap. - * - * @param other the other Figure to check collision with - * @return true if the Figures collide, false otherwise - */ - public boolean collidesWith(Figure other) { - return other.getMaxX() >= getMinX() && getMaxX() >= other.getMinX() && - other.getMaxY() >= getMinY() && getMaxY() >= other.getMinY(); - } - /** * Returns a string representation of the Figure, including its length, position, * and rotation. @@ -285,7 +168,7 @@ public class Figure implements Item{ */ @Override public String toString() { - return "Ship{length=" + length + ", x=" + x + ", y=" + y + ", rot=" + rot + '}'; //NON-NLS + return "Figur{ x=" + position.getX() + ", z=" + position.getZ() + ", rot=" + rot + '}'; //NON-NLS } /** diff --git a/Projekte/monopoly/model/src/main/java/pp/monopoly/model/House.java b/Projekte/monopoly/model/src/main/java/pp/monopoly/model/House.java index a7e317b..4f9383a 100644 --- a/Projekte/monopoly/model/src/main/java/pp/monopoly/model/House.java +++ b/Projekte/monopoly/model/src/main/java/pp/monopoly/model/House.java @@ -17,7 +17,7 @@ public class House implements Item{ /** * Creates a new house with stage 0. */ - public House() { + private House() { this.stage = 0; this.fieldID = 0; } diff --git a/Projekte/monopoly/model/src/main/java/pp/monopoly/model/Rotation.java b/Projekte/monopoly/model/src/main/java/pp/monopoly/model/Rotation.java index 39d95c1..ddf3abb 100644 --- a/Projekte/monopoly/model/src/main/java/pp/monopoly/model/Rotation.java +++ b/Projekte/monopoly/model/src/main/java/pp/monopoly/model/Rotation.java @@ -1,67 +1,108 @@ -//////////////////////////////////////// -// Programming project code -// UniBw M, 2022, 2023, 2024 -// www.unibw.de/inf2 -// (c) Mark Minas (mark.minas@unibw.de) -//////////////////////////////////////// - package pp.monopoly.model; -/** - * Represents the rotation of a Item and provides functionality related to rotation. - */ +import com.jme3.math.Quaternion; +import com.jme3.math.Vector3f; + import java.io.Serializable; +import static pp.util.FloatMath.PI; +import static pp.util.FloatMath.TWO_PI; + +/** + * Represents the rotation of an item in cardinal directions and provides corresponding 3D rotation quaternions. + */ public enum Rotation implements Serializable { /** - * Represents the item facing upwards. + * Represents the item facing north (positive Z-axis). */ - UP, + NORTH(0, new Quaternion().fromAngleAxis(0, Vector3f.UNIT_Y)), /** - * Represents the item facing rightwards. + * Represents the item facing south (negative Z-axis). */ - RIGHT, + SOUTH(PI, new Quaternion().fromAngleAxis(PI, Vector3f.UNIT_Y)), /** - * Represents the item facing downwards. + * Represents the item facing west (negative X-axis). */ - DOWN, + WEST(3 * PI / 2, new Quaternion().fromAngleAxis(3 * PI / 2, Vector3f.UNIT_Y)), /** - * Represents the item facing leftwards. + * Represents the item facing east (positive X-axis). */ - LEFT; + EAST(PI / 2, new Quaternion().fromAngleAxis(PI / 2, Vector3f.UNIT_Y)); - /** - * Gets the change in x-coordinate corresponding to this rotation. - * - * @return the change in x-coordinate - */ - public int dx() { - return switch (this) { - case UP, DOWN -> 0; - case RIGHT -> 1; - case LEFT -> -1; - }; + private final float radians; + private final Quaternion rotation; + + Rotation(float radians, Quaternion rotation) { + this.radians = radians; + this.rotation = rotation; } /** - * Gets the change in y-coordinate corresponding to this rotation. + * Gets the 3D rotation quaternion corresponding to this rotation. * - * @return the change in y-coordinate + * @return the rotation as a {@link Quaternion}. */ - public int dy() { - return switch (this) { - case UP -> 1; - case LEFT, RIGHT -> 0; - case DOWN -> -1; - }; + public Quaternion toQuaternion() { + return rotation; } /** - * Rotates the orientation clockwise and returns the next rotation. + * Gets the rotation in radians. * - * @return the next rotation after rotating clockwise + * @return the rotation in radians. */ - public Rotation rotate() { + public float radians() { + return radians; + } + + /** + * Rotates clockwise (90 degrees or PI/2 radians) and returns the next rotation. + * + * @return the next rotation after rotating clockwise. + */ + public Rotation rotateClockwise() { return values()[(ordinal() + 1) % values().length]; } + + /** + * Rotates counterclockwise (270 degrees or 3 * PI / 2 radians) and returns the next rotation. + * + * @return the next rotation after rotating counterclockwise. + */ + public Rotation rotateCounterclockwise() { + return values()[(ordinal() - 1 + values().length) % values().length]; + } + + /** + * Rotates by the specified radians and returns the corresponding rotation. + * Valid radians are multiples of PI/2. + * + * @param radians the radians to rotate. Must be a multiple of PI/2. + * @return the resulting rotation. + * @throws IllegalArgumentException if the radians are not a multiple of PI/2. + */ + public Rotation rotateByRadians(float radians) { + if ((radians % (PI / 2)) != 0) { + throw new IllegalArgumentException("Radians must be a multiple of PI/2."); + } + int steps = (int) ((radians / (PI / 2)) % values().length); + if (steps < 0) { + steps += values().length; // Normalize negative steps. + } + return values()[(ordinal() + steps) % values().length]; + } + + /** + * Finds the rotation closest to the specified radians value. + * + * @param radians the radians value. + * @return the nearest rotation. + */ + public static Rotation closestToRadians(float radians) { + float normalized = (radians % TWO_PI + TWO_PI) % TWO_PI; // Normalize to 0-TWO_PI. + if (normalized < PI / 4 || normalized >= 7 * PI / 4) return NORTH; + if (normalized < 3 * PI / 4) return EAST; + if (normalized < 5 * PI / 4) return SOUTH; + return WEST; + } } diff --git a/Projekte/monopoly/server/src/main/java/pp/monopoly/server/MonopolyServer.java b/Projekte/monopoly/server/src/main/java/pp/monopoly/server/MonopolyServer.java index 95f04c4..ef2b4f1 100644 --- a/Projekte/monopoly/server/src/main/java/pp/monopoly/server/MonopolyServer.java +++ b/Projekte/monopoly/server/src/main/java/pp/monopoly/server/MonopolyServer.java @@ -39,6 +39,7 @@ import pp.monopoly.message.client.RollDice; import pp.monopoly.message.client.TradeOffer; import pp.monopoly.message.client.TradeResponse; import pp.monopoly.message.client.ViewAssetsRequest; +import pp.monopoly.message.server.BuildInfo; import pp.monopoly.message.server.BuyPropertyRequest; import pp.monopoly.message.server.DiceResult; import pp.monopoly.message.server.EventDrawCard; @@ -192,6 +193,7 @@ public class MonopolyServer implements MessageListener, Connec Serializer.registerClass(JailEvent.class); Serializer.registerClass(AlterProperty.class); Serializer.registerClass(GameOver.class); + Serializer.registerClass(BuildInfo.class); } /**