mirror of
https://athene2.informatik.unibw-muenchen.de/progproj/gruppen-ht24/Gruppe-02.git
synced 2025-01-31 11:52:29 +01:00
frist working version, TODO: trigger the render events
This commit is contained in:
parent
5f4c6be7b8
commit
b4e2beca3a
@ -0,0 +1,207 @@
|
||||
package pp.monopoly.client;
|
||||
|
||||
import com.jme3.app.Application;
|
||||
import com.jme3.app.state.AppStateManager;
|
||||
import com.jme3.asset.AssetManager;
|
||||
import com.jme3.light.AmbientLight;
|
||||
import com.jme3.light.DirectionalLight;
|
||||
import com.jme3.material.Material;
|
||||
import com.jme3.math.ColorRGBA;
|
||||
import com.jme3.math.Vector2f;
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.renderer.Camera;
|
||||
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
|
||||
import com.jme3.scene.Geometry;
|
||||
import com.jme3.scene.Node;
|
||||
import com.jme3.scene.Spatial;
|
||||
import com.jme3.scene.shape.Box;
|
||||
import com.jme3.shadow.DirectionalLightShadowRenderer;
|
||||
import com.jme3.shadow.EdgeFilteringMode;
|
||||
import com.jme3.texture.Texture;
|
||||
import com.jme3.util.SkyFactory;
|
||||
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;
|
||||
import static pp.util.FloatMath.cos;
|
||||
import static pp.util.FloatMath.sin;
|
||||
import static pp.util.FloatMath.sqrt;
|
||||
|
||||
/**
|
||||
* Manages the rendering and visual aspects of the sea and sky in the Battleship game.
|
||||
* This state is responsible for setting up and updating the sea, sky, and lighting
|
||||
* conditions, and controls the camera to create a dynamic view of the game environment.
|
||||
*/
|
||||
public class BoardAppState extends MonopolyAppState {
|
||||
/**
|
||||
* The path to the unshaded texture material.
|
||||
*/
|
||||
private static final String UNSHADED = "Common/MatDefs/Misc/Unshaded.j3md"; //NON-NLS
|
||||
|
||||
/**
|
||||
* The path to the sea texture material.
|
||||
*/
|
||||
private static final String BoardTexture = "Pictures/board2.png"; //NON-NLS
|
||||
|
||||
/**
|
||||
* The root node for all visual elements in this state.
|
||||
*/
|
||||
private final Node viewNode = new Node("view"); //NON-NLS
|
||||
|
||||
/**
|
||||
* The node containing the scene elements, such as the sea surface.
|
||||
*/
|
||||
private final Node sceneNode = new Node("scene"); //NON-NLS
|
||||
|
||||
/**
|
||||
* Synchronizes the buildings's visual representation with the game logic.
|
||||
*/
|
||||
private BobTheBuilder bobTheBuilder;
|
||||
|
||||
/**
|
||||
* Initializes the state by setting up the sky, lights, and other visual components.
|
||||
* This method is called when the state is first attached to the state manager.
|
||||
*
|
||||
* @param stateManager the state manager
|
||||
* @param application the application
|
||||
*/
|
||||
@Override
|
||||
public void initialize(AppStateManager stateManager, Application application) {
|
||||
super.initialize(stateManager, application);
|
||||
viewNode.attachChild(sceneNode);
|
||||
setupLights();
|
||||
setupSky();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the sea and sky state, setting up the scene and registering any necessary listeners.
|
||||
* This method is called when the state is set to active.
|
||||
*/
|
||||
@Override
|
||||
protected void enableState() {
|
||||
getApp().getRootNode().detachAllChildren();
|
||||
getApp().getGuiNode().detachAllChildren();
|
||||
|
||||
getApp().getGuiNode().attachChild(new Toolbar(getApp()));
|
||||
sceneNode.detachAllChildren();
|
||||
setupScene();
|
||||
if (bobTheBuilder == null) {
|
||||
bobTheBuilder = new BobTheBuilder(getApp(), sceneNode, getGameLogic().getBoard());
|
||||
getGameLogic().addListener(bobTheBuilder);
|
||||
}
|
||||
getApp().getRootNode().attachChild(viewNode);
|
||||
}
|
||||
//TODO remove this only for camera testing
|
||||
private static final float ABOVE_SEA_LEVEL = 10f;
|
||||
private static final float INCLINATION = 2.5f;
|
||||
private float cameraAngle;
|
||||
|
||||
/**
|
||||
* Adjusts the camera position and orientation to create a circular motion around
|
||||
* the center of the map. This provides a dynamic view of the sea and surrounding environment.
|
||||
*/
|
||||
private void adjustCamera() {
|
||||
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 Camera camera = getApp().getCamera();
|
||||
camera.setLocation(new Vector3f(20, ABOVE_SEA_LEVEL, 0));
|
||||
camera.lookAt(new Vector3f(0,0, 0),
|
||||
Vector3f.UNIT_Y);
|
||||
camera.update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the sea and sky state, removing visual elements from the scene and unregistering listeners.
|
||||
* This method is called when the state is set to inactive.
|
||||
*/
|
||||
@Override
|
||||
protected void disableState() {
|
||||
getApp().getRootNode().detachChild(viewNode);
|
||||
if (bobTheBuilder != null) {
|
||||
getGameLogic().removeListener(bobTheBuilder);
|
||||
bobTheBuilder = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the state each frame, moving the camera to simulate it circling around the map.
|
||||
*
|
||||
* @param tpf the time per frame (seconds)
|
||||
*/
|
||||
@Override
|
||||
public void update(float tpf) {
|
||||
super.update(tpf);
|
||||
//TODO remove this only for camera testing
|
||||
cameraAngle += TWO_PI * 0.05f * tpf;
|
||||
adjustCamera();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the lighting for the scene, including directional and ambient lights.
|
||||
* Also configures shadows to enhance the visual depth of the scene.
|
||||
*/
|
||||
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 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the sky in the scene using a skybox with textures for all six directions.
|
||||
* This creates a realistic and immersive environment for the sea.
|
||||
*/
|
||||
private void setupSky() {
|
||||
final AssetManager assetManager = getApp().getAssetManager();
|
||||
final Texture west = assetManager.loadTexture("Pictures/Backdrop/left.jpg"); //NON-NLS
|
||||
final Texture east = assetManager.loadTexture("Pictures/Backdrop/right.jpg"); //NON-NLS
|
||||
final Texture north = assetManager.loadTexture("Pictures/Backdrop/front.jpg"); //NON-NLS
|
||||
final Texture south = assetManager.loadTexture("Pictures/Backdrop/back.jpg"); //NON-NLS
|
||||
final Texture up = assetManager.loadTexture("Pictures/Backdrop/up.jpg"); //NON-NLS
|
||||
final Texture down = assetManager.loadTexture("Pictures/Backdrop/down.jpg"); //NON-NLS
|
||||
final Spatial sky = SkyFactory.createSky(assetManager, west, east, north, south, up, down);
|
||||
// sky.rotate(0, PI, 0);
|
||||
viewNode.attachChild(sky);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the sea surface in the scene. This includes creating the sea mesh,
|
||||
* applying textures, and enabling shadows.
|
||||
*/
|
||||
private void setupScene() {
|
||||
final Board board = getGameLogic().getBoard();
|
||||
final float x = board.getWidth();
|
||||
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));
|
||||
final Material seaMat = new Material(getApp().getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
|
||||
Texture texture = getApp().getAssetManager().loadTexture("Pictures/board2.png");
|
||||
seaMat.setTexture("DiffuseMap", texture);
|
||||
seaGeo.setMaterial(seaMat);
|
||||
seaGeo.setShadowMode(ShadowMode.CastAndReceive);
|
||||
TangentBinormalGenerator.generate(seaGeo);
|
||||
sceneNode.attachChild(seaGeo);
|
||||
}
|
||||
}
|
@ -285,7 +285,7 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
|
||||
|
||||
attachGameSound();
|
||||
attachGameMusic();
|
||||
stateManager.attach(new GameAppState());
|
||||
stateManager.attach(new BoardAppState());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -405,7 +405,7 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
|
||||
*/
|
||||
@Override
|
||||
public void receivedEvent(ClientStateEvent event) {
|
||||
stateManager.getState(GameAppState.class).setEnabled(true);
|
||||
stateManager.getState(BoardAppState.class).setEnabled(logic.isTurn());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,74 +0,0 @@
|
||||
package pp.monopoly.client.gui;
|
||||
|
||||
import com.jme3.scene.Node;
|
||||
import com.jme3.scene.Spatial;
|
||||
|
||||
import pp.monopoly.model.Board;
|
||||
import pp.monopoly.model.Item;
|
||||
import pp.monopoly.model.Visitor;
|
||||
import pp.monopoly.notification.GameEventListener;
|
||||
import pp.monopoly.notification.ItemAddedEvent;
|
||||
import pp.monopoly.notification.ItemRemovedEvent;
|
||||
import pp.view.ModelViewSynchronizer;
|
||||
|
||||
/**
|
||||
* Abstract base class for synchronizing the visual representation of a {@link Board} with its model state.
|
||||
* This class handles the addition and removal of items from the map, ensuring that changes in the model
|
||||
* are accurately reflected in the view.
|
||||
*/
|
||||
abstract class BoardSynchronizer extends ModelViewSynchronizer<Item> implements Visitor<Spatial>, GameEventListener {
|
||||
protected final Board board;
|
||||
|
||||
/**
|
||||
* Constructs a new BoardSynchronizer.
|
||||
*
|
||||
* @param board the game board to synchronize
|
||||
* @param root the root node to which the view representations of the board items are attached
|
||||
*/
|
||||
protected BoardSynchronizer(Board board, Node root) {
|
||||
super(root);
|
||||
this.board = board;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates a model item into its corresponding visual representation.
|
||||
*
|
||||
* @param item the item from the model to be translated
|
||||
* @return the visual representation of the item as a {@link Spatial}
|
||||
*/
|
||||
@Override
|
||||
protected Spatial translate(Item item) {
|
||||
return item.accept(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the existing items from the board to the view during initialization.
|
||||
*/
|
||||
protected void addExisting() {
|
||||
board.getItems().forEach(this::add);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the event when an item is removed from the board.
|
||||
*
|
||||
* @param event the event indicating that an item has been removed from the board
|
||||
*/
|
||||
@Override
|
||||
public void receivedEvent(ItemRemovedEvent event) {
|
||||
if (board == event.getBoard()) {
|
||||
delete(event.getItem());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the event when an item is added to the board.
|
||||
*
|
||||
* @param event the event indicating that an item has been added to the board
|
||||
*/
|
||||
@Override
|
||||
public void receivedEvent(ItemAddedEvent event) {
|
||||
if (board == event.getBoard()) {
|
||||
add(event.getItem());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package pp.monopoly.client.gui;
|
||||
|
||||
import com.jme3.material.Material;
|
||||
import com.jme3.material.RenderState.BlendMode;
|
||||
import com.jme3.math.ColorRGBA;
|
||||
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
|
||||
import com.jme3.scene.Geometry;
|
||||
import com.jme3.scene.Node;
|
||||
import com.jme3.scene.Spatial;
|
||||
import com.jme3.scene.shape.Box;
|
||||
|
||||
import pp.monopoly.client.MonopolyApp;
|
||||
import pp.monopoly.model.Board;
|
||||
import pp.monopoly.model.Figure;
|
||||
import pp.monopoly.model.Hotel;
|
||||
import pp.monopoly.model.House;
|
||||
|
||||
public class BobTheBuilder extends GameBoardSynchronizer {
|
||||
|
||||
private static final String UNSHADED = "Common/MatDefs/Misc/Unshaded.j3md"; //NON-NLS
|
||||
private static final String COLOR = "Color"; //NON-NLS
|
||||
private static final String FIGURE = "figure"; //NON-NLS
|
||||
private static final String HOUSE = "house"; //NON-NLS
|
||||
private static final String HOTEL = "hotel"; //NON-NLS
|
||||
|
||||
private final MonopolyApp app;
|
||||
private final Board board;
|
||||
|
||||
public BobTheBuilder(MonopolyApp app, Node root, Board board) {
|
||||
super(app.getGameLogic().getBoard(), root);
|
||||
this.app = app;
|
||||
this.board = board;
|
||||
addExisting();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spatial visit(Figure figure) {
|
||||
return createBox(figure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spatial visit(Hotel hotel) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'visit'");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spatial visit(House figure) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'visit'");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a simple box to represent a battleship that is not of the "King George V" type.
|
||||
*
|
||||
* @param ship the battleship to be represented
|
||||
* @return the geometry representing the battleship as a box
|
||||
*/
|
||||
private Spatial createBox(Figure figure) {
|
||||
final Box box = new Box(3,
|
||||
3f,
|
||||
3);
|
||||
final Geometry geometry = new Geometry(FIGURE, box);
|
||||
geometry.setMaterial(createColoredMaterial(ColorRGBA.Blue));
|
||||
geometry.setShadowMode(ShadowMode.CastAndReceive);
|
||||
geometry.setLocalTranslation(0, 2, 0);
|
||||
|
||||
return geometry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Material} with the specified color.
|
||||
* If the color includes transparency (i.e., alpha value less than 1),
|
||||
* the material's render state is set to use alpha blending, allowing for
|
||||
* semi-transparent rendering.
|
||||
*
|
||||
* @param color the {@link ColorRGBA} to be applied to the material. If the alpha value
|
||||
* of the color is less than 1, the material will support transparency.
|
||||
* @return a {@link Material} instance configured with the specified color and,
|
||||
* if necessary, alpha blending enabled.
|
||||
*/
|
||||
private Material createColoredMaterial(ColorRGBA color) {
|
||||
final Material material = new Material(app.getAssetManager(), UNSHADED);
|
||||
if (color.getAlpha() < 1f)
|
||||
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
|
||||
material.setColor(COLOR, color);
|
||||
return material;
|
||||
}
|
||||
|
||||
}
|
@ -1,120 +1,88 @@
|
||||
////////////////////////////////////////
|
||||
// Programming project code
|
||||
// UniBw M, 2022, 2023, 2024
|
||||
// www.unibw.de/inf2
|
||||
// (c) Mark Minas (mark.minas@unibw.de)
|
||||
////////////////////////////////////////
|
||||
|
||||
package pp.monopoly.client.gui;
|
||||
|
||||
import com.jme3.material.Material;
|
||||
import com.jme3.material.RenderState.BlendMode;
|
||||
import com.jme3.math.ColorRGBA;
|
||||
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
|
||||
import com.jme3.scene.Geometry;
|
||||
import com.jme3.scene.Node;
|
||||
import com.jme3.scene.Spatial;
|
||||
import com.jme3.scene.shape.Box;
|
||||
|
||||
import pp.monopoly.client.MonopolyApp;
|
||||
import pp.monopoly.game.server.PlayerColor;
|
||||
import pp.monopoly.model.Item;
|
||||
import pp.monopoly.model.Visitor;
|
||||
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.monopoly.model.Rotation;
|
||||
import static pp.util.FloatMath.HALF_PI;
|
||||
import static pp.util.FloatMath.PI;
|
||||
import pp.view.ModelViewSynchronizer;
|
||||
|
||||
/**
|
||||
* The {@code GameBoardSynchronizer} class is responsible for synchronizing the graphical
|
||||
* representation of the Game board and figures with the underlying data model.
|
||||
* It extends the {@link BoardSynchronizer} to provide specific synchronization
|
||||
* logic for the Game board.
|
||||
* Abstract base class for synchronizing the visual representation of a {@link Board} with its model state.
|
||||
* This class handles the addition and removal of items from the board, ensuring that changes in the model
|
||||
* are accurately reflected in the view.
|
||||
* <p>
|
||||
* Subclasses are responsible for providing the specific implementation of how each item in the map
|
||||
* is represented visually by implementing the {@link Visitor} interface.
|
||||
* </p>
|
||||
*/
|
||||
class GameBoardSynchronizer extends BoardSynchronizer {
|
||||
private static final String UNSHADED = "Common/MatDefs/Misc/Unshaded.j3md"; //NON-NLS
|
||||
private static final String LIGHTING = "Common/MatDefs/Light/Lighting.j3md";
|
||||
private static final String COLOR = "Color"; //NON-NLS
|
||||
private static final String FIGURE = "figure"; //NON-NLS
|
||||
|
||||
private final MonopolyApp app;
|
||||
abstract class GameBoardSynchronizer extends ModelViewSynchronizer<Item> implements Visitor<Spatial>, GameEventListener {
|
||||
// The board that this synchronizer is responsible for
|
||||
private final Board board;
|
||||
|
||||
/**
|
||||
* Constructs a {@code GameBoardSynchronizer} object with the specified application, root node, and ship map.
|
||||
* Constructs a new GameBoardSynchronizer.
|
||||
* Initializes the synchronizer with the provided board and the root node for attaching view representations.
|
||||
*
|
||||
* @param app the Monopoly application
|
||||
* @param root the root node to which graphical elements will be attached
|
||||
* @param map the Game Board containing fields and figures
|
||||
* @param map the board to be synchronized
|
||||
* @param root the root node to which the view representations of the board items are attached
|
||||
*/
|
||||
public GameBoardSynchronizer(MonopolyApp app, Node root, Board board) {
|
||||
super(board, root);
|
||||
this.app = app;
|
||||
protected GameBoardSynchronizer(Board board, Node root) {
|
||||
super(root);
|
||||
this.board = board;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates a model item into its corresponding visual representation.
|
||||
* The specific visual representation is determined by the concrete implementation of the {@link Visitor} interface.
|
||||
*
|
||||
* @param item the item from the model to be translated
|
||||
* @return the visual representation of the item as a {@link Spatial}
|
||||
*/
|
||||
@Override
|
||||
protected Spatial translate(Item item) {
|
||||
return item.accept(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the existing items from the board to the view.
|
||||
* This method should be called during initialization to ensure that all current items in the board
|
||||
* are visually represented.
|
||||
*/
|
||||
protected void addExisting() {
|
||||
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());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 recievedEvent(UpdatePlayerView event) {
|
||||
clear();
|
||||
addExisting();
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a {@link Figure} and creates a graphical representation of it.
|
||||
* The representation is a 3D model.
|
||||
*
|
||||
* @param figure the figure to be represented
|
||||
* @return the node containing the graphical representation of the figure
|
||||
*/
|
||||
public Spatial visit(Figure figure) {
|
||||
final Node node = new Node(FIGURE);
|
||||
node.attachChild(createBox(figure));
|
||||
final float x = 1;
|
||||
final float z = 1;
|
||||
node.setLocalTranslation(x, 0f, z);
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a representation of a figure
|
||||
*
|
||||
* @param figure the figure to be represented
|
||||
* @return the geometry representing the figure
|
||||
*/
|
||||
private Spatial createBox(Figure figure) {
|
||||
final Box box = new Box(0.5f * (figure.getMaxY() - figure.getMinY()) + 0.3f,
|
||||
0.3f,
|
||||
0.5f * (figure.getMaxX() - figure.getMinX()) + 0.3f);
|
||||
final Geometry geometry = new Geometry(FIGURE, box);
|
||||
geometry.setMaterial(createColoredMaterial(PlayerColor.PINK.getColor()));
|
||||
geometry.setShadowMode(ShadowMode.CastAndReceive);
|
||||
|
||||
return geometry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Material} with the specified color.
|
||||
* If the color includes transparency (i.e., alpha value less than 1),
|
||||
* the material's render state is set to use alpha blending, allowing for
|
||||
* semi-transparent rendering.
|
||||
*
|
||||
* @param color the {@link ColorRGBA} to be applied to the material. If the alpha value
|
||||
* of the color is less than 1, the material will support transparency.
|
||||
* @return a {@link Material} instance configured with the specified color and,
|
||||
* if necessary, alpha blending enabled.
|
||||
*/
|
||||
private Material createColoredMaterial(ColorRGBA color) {
|
||||
final Material material = new Material(app.getAssetManager(), UNSHADED);
|
||||
if (color.getAlpha() < 1f)
|
||||
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
|
||||
material.setColor(COLOR, color);
|
||||
return material;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the rotation angle for the specified rotation.
|
||||
*
|
||||
* @param rot the rotation of the battleship
|
||||
* @return the rotation angle in radians
|
||||
*/
|
||||
private static float calculateRotationAngle(Rotation rot) {
|
||||
return switch (rot) {
|
||||
case RIGHT -> HALF_PI;
|
||||
case DOWN -> 0f;
|
||||
case LEFT -> -HALF_PI;
|
||||
case UP -> PI;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,9 @@
|
||||
package pp.monopoly.game.client;
|
||||
|
||||
import pp.monopoly.game.server.Player;
|
||||
import pp.monopoly.message.server.NextPlayerTurn;
|
||||
import pp.monopoly.message.server.ViewAssetsResponse;
|
||||
|
||||
/**
|
||||
* Represents the active client state in the Monopoly game.
|
||||
* Extends {@link ClientState}.
|
||||
@ -15,4 +19,22 @@ public class ActiveState extends ClientState {
|
||||
ActiveState(ClientGameLogic logic) {
|
||||
super(logic);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isTurn() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
void recivedNextPlayerTurn(NextPlayerTurn msg) {
|
||||
logic.getBoard().clear();
|
||||
for (Player player : logic.getPlayerHandler().getPlayers()) {
|
||||
logic.getBoard().add(player.getFigure());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void recivedViewAssetsResponse(ViewAssetsResponse msg) {
|
||||
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import java.lang.System.Logger.Level;
|
||||
import java.util.ArrayList;
|
||||
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.BuyPropertyRequest;
|
||||
@ -22,7 +23,6 @@ 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.IntPoint;
|
||||
import pp.monopoly.model.TradeHandler;
|
||||
import pp.monopoly.model.fields.BoardManager;
|
||||
import pp.monopoly.notification.ClientStateEvent;
|
||||
@ -33,6 +33,7 @@ import pp.monopoly.notification.GameEvent;
|
||||
import pp.monopoly.notification.GameEventBroker;
|
||||
import pp.monopoly.notification.GameEventListener;
|
||||
import pp.monopoly.notification.InfoTextEvent;
|
||||
import pp.monopoly.notification.ItemAddedEvent;
|
||||
import pp.monopoly.notification.PopUpEvent;
|
||||
import pp.monopoly.notification.Sound;
|
||||
import pp.monopoly.notification.SoundEvent;
|
||||
@ -54,7 +55,7 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker {
|
||||
private final List<GameEventListener> listeners = new ArrayList<>();
|
||||
|
||||
/** The game board representing the player's current state. */
|
||||
private Board board;
|
||||
private Board board = new Board(10, 10, null);
|
||||
|
||||
/** The current state of the client game logic. */
|
||||
private ClientState state = new LobbyState(this);
|
||||
@ -121,15 +122,6 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker {
|
||||
return tradeHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the preview figure to the specified position.
|
||||
*
|
||||
* @param pos the new position for the preview figure
|
||||
*/
|
||||
public void movePreview(IntPoint pos) {
|
||||
state.movePreview(pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the informational text to be displayed to the player.
|
||||
*
|
||||
@ -204,32 +196,21 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker {
|
||||
state.update(delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the result of a dice roll.
|
||||
*
|
||||
* @param msg the message containing the dice roll result
|
||||
*/
|
||||
public boolean isTurn() {
|
||||
return state.isTurn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void received(DiceResult msg) {
|
||||
playSound(Sound.DICE_ROLL);
|
||||
notifyListeners(new DiceRollEvent(msg.getRollResult().get(0), msg.getRollResult().get(1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles drawing an event card.
|
||||
*
|
||||
* @param msg the message containing the drawn card details
|
||||
*/
|
||||
@Override
|
||||
public void received(EventDrawCard msg) {
|
||||
notifyListeners(new EventCardEvent(msg.getCardDescription()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the game over message.
|
||||
*
|
||||
* @param msg the message containing game over details
|
||||
*/
|
||||
@Override
|
||||
public void received(GameOver msg) {
|
||||
if (msg.isWinner()) {
|
||||
@ -241,23 +222,14 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the start of the game.
|
||||
*
|
||||
* @param msg the game start message
|
||||
*/
|
||||
@Override
|
||||
public void received(GameStart msg) {
|
||||
playerHandler = msg.getPlayerHandler();
|
||||
setState(new WaitForTurnState(this));
|
||||
notifyListeners(new ButtonStatusEvent(false));
|
||||
notifyListeners(new UpdatePlayerView());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles jail-related events.
|
||||
*
|
||||
* @param msg the message containing jail event details
|
||||
*/
|
||||
@Override
|
||||
public void received(JailEvent msg) {
|
||||
if (msg.isGoingToJail()) {
|
||||
@ -266,11 +238,6 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the status of a player.
|
||||
*
|
||||
* @param msg the message containing player status update details
|
||||
*/
|
||||
@Override
|
||||
public void received(PlayerStatusUpdate msg) {
|
||||
playerHandler = msg.getPlayerHandler();
|
||||
@ -278,31 +245,16 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker {
|
||||
notifyListeners(new UpdatePlayerView());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles timeout warnings.
|
||||
*
|
||||
* @param msg the message containing timeout warning details
|
||||
*/
|
||||
@Override
|
||||
public void received(TimeOutWarning msg) {
|
||||
notifyListeners(new PopUpEvent("timeout", msg));
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the player's assets in response to a server query.
|
||||
*
|
||||
* @param msg the message containing the player's assets
|
||||
*/
|
||||
@Override
|
||||
public void received(ViewAssetsResponse msg) {
|
||||
boardManager = msg.getboard();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles trade replies from other players.
|
||||
*
|
||||
* @param msg the message containing the trade reply
|
||||
*/
|
||||
@Override
|
||||
public void received(TradeReply msg) {
|
||||
if (msg.isAccepted()) {
|
||||
@ -314,24 +266,15 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles trade requests from other players.
|
||||
*
|
||||
* @param msg the message containing the trade request details
|
||||
*/
|
||||
@Override
|
||||
public void received(TradeRequest msg) {
|
||||
tradeHandler = msg.getTradeHandler();
|
||||
notifyListeners(new PopUpEvent("tradeRequest", msg));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the transition to the next player's turn.
|
||||
*
|
||||
* @param msg the message indicating it's the next player's turn
|
||||
*/
|
||||
@Override
|
||||
public void received(NextPlayerTurn msg) {
|
||||
setState(new ActiveState(this));
|
||||
notifyListeners(new ButtonStatusEvent(true));
|
||||
}
|
||||
|
||||
@ -357,4 +300,5 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker {
|
||||
notifyListeners(new PopUpEvent("ReceivedRent", msg));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,7 +11,11 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.System.Logger.Level;
|
||||
|
||||
import pp.monopoly.model.IntPoint;
|
||||
import pp.monopoly.message.server.GameStart;
|
||||
import pp.monopoly.message.server.NextPlayerTurn;
|
||||
import pp.monopoly.message.server.NotificationMessage;
|
||||
import pp.monopoly.message.server.PlayerStatusUpdate;
|
||||
import pp.monopoly.message.server.ViewAssetsResponse;
|
||||
|
||||
/**
|
||||
* Defines the behavior and state transitions for the client-side game logic in Monopoly.
|
||||
@ -54,17 +58,39 @@ abstract class ClientState {
|
||||
*
|
||||
* @return true if the player's turn should be shown, false otherwise
|
||||
*/
|
||||
boolean showTurn() {
|
||||
boolean isTurn() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the preview figure to the specified position on the game board.
|
||||
* Starts the battle based on the server message.
|
||||
*
|
||||
* @param pos the new position for the preview figure
|
||||
* @param msg the message indicating whose turn it is to shoot
|
||||
*/
|
||||
void movePreview(IntPoint pos) {
|
||||
ClientGameLogic.LOGGER.log(Level.DEBUG, "movePreview has no effect in {0}", getName()); //NON-NLS
|
||||
void receivedGameStart(GameStart msg) {
|
||||
ClientGameLogic.LOGGER.log(Level.ERROR, "receivedGameStart not allowed in {0}", getName()); //NON-NLS
|
||||
}
|
||||
|
||||
/**
|
||||
* Updateds the view based on the new player status.
|
||||
*
|
||||
* @param msg the message containing the new player status
|
||||
*/
|
||||
void recivedPlayerStatusUpdate(PlayerStatusUpdate msg) {
|
||||
ClientGameLogic.LOGGER.log(Level.ERROR, "recivedPlayerStatusUpdate not allowed in {0}", getName()); //NON-NLS
|
||||
}
|
||||
|
||||
|
||||
void recivedNextPlayerTurn(NextPlayerTurn msg) {
|
||||
ClientGameLogic.LOGGER.log(Level.ERROR, "recivedNextPlayerTurn not allowed in {0}", getName()); //NON-NLS
|
||||
}
|
||||
|
||||
void recivedNotificationMessage(NotificationMessage msg) {
|
||||
ClientGameLogic.LOGGER.log(Level.ERROR, "recivedNotificationMessage not allowed in {0}", getName()); //NON-NLS
|
||||
}
|
||||
|
||||
void recivedViewAssetsResponse(ViewAssetsResponse msg) {
|
||||
ClientGameLogic.LOGGER.log(Level.ERROR, "recivedViewAssetsResponse not allowed in {0}", getName()); //NON-NLS
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,7 @@
|
||||
package pp.monopoly.game.client;
|
||||
|
||||
import pp.monopoly.message.server.GameStart;
|
||||
|
||||
/**
|
||||
* Represents the lobby state of the client in the Monopoly game.
|
||||
* Extends {@link ClientState}.
|
||||
@ -14,4 +16,9 @@ public class LobbyState extends ClientState {
|
||||
LobbyState(ClientGameLogic logic) {
|
||||
super(logic);
|
||||
}
|
||||
|
||||
@Override
|
||||
void receivedGameStart(GameStart msg) {
|
||||
logic.setState(new WaitForTurnState(logic));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
package pp.monopoly.game.client;
|
||||
|
||||
import pp.monopoly.message.server.NextPlayerTurn;
|
||||
|
||||
/**
|
||||
* Represents the state where the client is waiting for their turn in the Monopoly game.
|
||||
* Extends {@link ClientState}.
|
||||
@ -14,4 +16,14 @@ public class WaitForTurnState extends ClientState {
|
||||
WaitForTurnState(ClientGameLogic logic) {
|
||||
super(logic);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isTurn() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
void recivedNextPlayerTurn(NextPlayerTurn msg) {
|
||||
logic.setState(new ActiveState(logic));
|
||||
}
|
||||
}
|
||||
|
@ -91,16 +91,16 @@ public interface ServerInterpreter {
|
||||
void received(NextPlayerTurn msg);
|
||||
|
||||
/**
|
||||
* Handles a NextPlayerTurn message received from the server.
|
||||
* Handles a BuyPropertyRequest message received from the server.
|
||||
*
|
||||
* @param msg the NextPlayerTurn message received
|
||||
* @param msg the BuyPropertyRequest message received
|
||||
*/
|
||||
void received(BuyPropertyRequest msg);
|
||||
|
||||
/**
|
||||
* Handles a NextPlayerTurn message received from the server.
|
||||
* Handles a NotificationMessage message received from the server.
|
||||
*
|
||||
* @param msg the NextPlayerTurn message received
|
||||
* @param msg the NotificationMessage message received
|
||||
*/
|
||||
void received(NotificationMessage msg);
|
||||
}
|
||||
|
@ -1,10 +1,3 @@
|
||||
////////////////////////////////////////
|
||||
// Programming project code
|
||||
// UniBw M, 2022, 2023, 2024
|
||||
// www.unibw.de/inf2
|
||||
// (c) Mark Minas (mark.minas@unibw.de)
|
||||
////////////////////////////////////////
|
||||
|
||||
package pp.monopoly.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -66,7 +59,34 @@ public class Board {
|
||||
*/
|
||||
private void addItem(Item item) {
|
||||
items.add(item);
|
||||
notifyListeners((GameEvent) new ItemAddedEvent(item, null));
|
||||
notifyListeners((GameEvent) new ItemAddedEvent(this, item));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a figure to the map and triggers an item addition event.
|
||||
*
|
||||
* @param figure the figure to be added to the map
|
||||
*/
|
||||
public void add(Figure figure) {
|
||||
addItem(figure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a house to the map and triggers an item addition event.
|
||||
*
|
||||
* @param house the house to be added to the map
|
||||
*/
|
||||
public void add(House house) {
|
||||
addItem(house);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a hotel to the map and triggers an item addition event.
|
||||
*
|
||||
* @param hotel the hotel to be added to the map
|
||||
*/
|
||||
public void add(Hotel hotel) {
|
||||
addItem(hotel);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,7 +96,7 @@ public class Board {
|
||||
*/
|
||||
public void remove(Item item) {
|
||||
items.remove(item);
|
||||
notifyListeners((GameEvent) new ItemRemovedEvent(item, null)); // Falls es ein entsprechendes ItemRemovedEvent gibt
|
||||
notifyListeners((GameEvent) new ItemRemovedEvent(this, item));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -96,6 +116,33 @@ public class Board {
|
||||
private <T extends Item> Stream<T> getItems(Class<T> clazz) {
|
||||
return items.stream().filter(clazz::isInstance).map(clazz::cast);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a stream of all figures currently on the map.
|
||||
*
|
||||
* @return a stream of all figures on the map
|
||||
*/
|
||||
public Stream<Figure> getFigures() {
|
||||
return getItems(Figure.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a stream of all houses currently on the map.
|
||||
*
|
||||
* @return a stream of all houses on the map
|
||||
*/
|
||||
public Stream<House> getHouses() {
|
||||
return getItems(House.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a stream of all hotels currently on the map.
|
||||
*
|
||||
* @return a stream of all hotels on the map
|
||||
*/
|
||||
public Stream<Hotel> getHotels() {
|
||||
return getItems(Hotel.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable list of all items currently on the map.
|
||||
@ -124,28 +171,6 @@ public class Board {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates whether the specified position is within the map boundaries.
|
||||
*
|
||||
* @param pos the position to validate
|
||||
* @return true if the position is within the map, false otherwise
|
||||
*/
|
||||
public boolean isValid(IntPosition pos) {
|
||||
return isValid(pos.getX(), pos.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified coordinates are within the map boundaries.
|
||||
*
|
||||
* @param x the x-coordinate to validate
|
||||
* @param y the y-coordinate to validate
|
||||
* @return true if the coordinates are valid, false otherwise
|
||||
*/
|
||||
public boolean isValid(int x, int y) {
|
||||
return x >= 0 && x < width &&
|
||||
y >= 0 && y < height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the map.
|
||||
*
|
||||
|
@ -0,0 +1,93 @@
|
||||
package pp.monopoly.model;
|
||||
|
||||
import com.jme3.math.Vector3f;
|
||||
|
||||
public class Hotel implements Item{
|
||||
/**
|
||||
* The ID of the field the hotel is on.
|
||||
*/
|
||||
private final int fieldID;
|
||||
|
||||
/**
|
||||
* Creates a new hotel with fieldID 0.
|
||||
*/
|
||||
private Hotel() {
|
||||
this.fieldID = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new hotel on the given field.
|
||||
*
|
||||
* @param fieldID the ID of the field the hotel is on
|
||||
*/
|
||||
public Hotel(int fieldID) {
|
||||
this.fieldID = fieldID;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> T accept(Visitor<T> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(VoidVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the position of the building on the field.
|
||||
*
|
||||
* @return the position of the building on the field
|
||||
*/
|
||||
public Vector3f getBuildingPosition() {
|
||||
float baseX = 0.0f;
|
||||
float baseZ = 0.0f;
|
||||
|
||||
switch (fieldID) {
|
||||
case 0: baseX = -8.4f; baseZ = -7.7f; break;
|
||||
case 1: baseX = -6.3f; baseZ = -7.7f; break;
|
||||
case 2: baseX = -4.7f; baseZ = -7.7f; break;
|
||||
case 3: baseX = -3.1f; baseZ = -7.7f; break;
|
||||
case 4: baseX = -1.4f; baseZ = -7.7f; break;
|
||||
case 5: baseX = 0.2f; baseZ = -7.7f; break;
|
||||
case 6: baseX = 1.8f; baseZ = -7.7f; break;
|
||||
case 7: baseX = 3.5f; baseZ = -7.7f; break;
|
||||
case 8: baseX = 5.1f; baseZ = -7.7f; break;
|
||||
case 9: baseX = 6.7f; baseZ = -7.7f; break;
|
||||
case 10: baseX = 8.2f; baseZ = -7.7f; break;
|
||||
case 11: baseX = 8.2f; baseZ = -6.5f; break; //passt
|
||||
case 12: baseX = 8.2f; baseZ = -4.9f; break; //passt
|
||||
case 13: baseX = 8.2f; baseZ = -3.3f; break; //passt
|
||||
case 14: baseX = 8.2f; baseZ = -1.6f; break; //passt
|
||||
case 15: baseX = 8.2f; baseZ = 0.0f; break; //passt
|
||||
case 16: baseX = 8.2f; baseZ = 1.6f; break; //passt
|
||||
case 17: baseX = 8.2f; baseZ = 3.3f; break; //passt
|
||||
case 18: baseX = 8.2f; baseZ = 4.9f; break; //passt
|
||||
case 19: baseX = 8.2f; baseZ = 6.5f; break; //passt
|
||||
case 20: baseX = 8.2f; baseZ = 7.7f; break;
|
||||
case 21: baseX = 6.5f; baseZ = 7.7f; break;
|
||||
case 22: baseX = 4.9f; baseZ = 7.7f; break;
|
||||
case 23: baseX = 3.3f; baseZ = 7.7f; break;
|
||||
case 24: baseX = 1.6f; baseZ = 7.7f; break;
|
||||
case 25: baseX = 0.0f; baseZ = 7.7f; break;
|
||||
case 26: baseX = -1.6f; baseZ = 7.7f; break;
|
||||
case 27: baseX = -3.3f; baseZ = 7.7f; break;
|
||||
case 28: baseX = -4.9f; baseZ = 7.7f; break;
|
||||
case 29: baseX = -6.5f; baseZ = 7.7f; break;
|
||||
case 30: baseX = -7.2f; baseZ = 7.7f; break;
|
||||
case 31: baseX = -7.2f; baseZ = 6.5f; break;
|
||||
case 32: baseX = -7.2f; baseZ = 4.9f; break;
|
||||
case 33: baseX = -7.2f; baseZ = 3.3f; break;
|
||||
case 34: baseX = -7.2f; baseZ = 1.6f; break;
|
||||
case 35: baseX = -7.2f; baseZ = 0.0f; break;
|
||||
case 36: baseX = -7.2f; baseZ = -1.6f; break;
|
||||
case 37: baseX = -7.2f; baseZ = -3.3f; break;
|
||||
case 38: baseX = -7.2f; baseZ = -4.9f; break;
|
||||
case 39: baseX = -7.2f; baseZ = -6.5f; break;
|
||||
default: throw new IllegalArgumentException("Ungültige Feld-ID: " + fieldID);
|
||||
}
|
||||
|
||||
return new Vector3f(baseX, 0, baseZ);
|
||||
}
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
package pp.monopoly.model;
|
||||
|
||||
import com.jme3.math.Vector3f;
|
||||
import com.jme3.network.serializing.Serializable;
|
||||
|
||||
/**
|
||||
* A class representing a house in the Monopoly game.
|
||||
*/
|
||||
@Serializable
|
||||
public class House implements Item{
|
||||
/**
|
||||
* The stage of the house.
|
||||
*/
|
||||
private final int stage;
|
||||
private final int fieldID;
|
||||
|
||||
/**
|
||||
* Creates a new house with stage 0.
|
||||
*/
|
||||
public House() {
|
||||
this.stage = 0;
|
||||
this.fieldID = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new house with the given stage.
|
||||
*
|
||||
* @param stage the stage of the house
|
||||
*/
|
||||
public House(int stage, int fieldID) {
|
||||
this.stage = stage;
|
||||
this.fieldID = fieldID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the stage of the house.
|
||||
*
|
||||
* @return the stage of the house
|
||||
*/
|
||||
public int getStage() {
|
||||
return stage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(Visitor<T> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(VoidVisitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the position of the building on the field.
|
||||
*
|
||||
* @return the position of the building on the field
|
||||
*/
|
||||
public Vector3f getBuildingPosition() {
|
||||
float baseX = 0.0f;
|
||||
float baseZ = 0.0f;
|
||||
|
||||
switch (fieldID) {
|
||||
case 0: baseX = -8.4f; baseZ = -7.7f; break;
|
||||
case 1: baseX = -6.3f; baseZ = -7.7f; break;
|
||||
case 2: baseX = -4.7f; baseZ = -7.7f; break;
|
||||
case 3: baseX = -3.1f; baseZ = -7.7f; break;
|
||||
case 4: baseX = -1.4f; baseZ = -7.7f; break;
|
||||
case 5: baseX = 0.2f; baseZ = -7.7f; break;
|
||||
case 6: baseX = 1.8f; baseZ = -7.7f; break;
|
||||
case 7: baseX = 3.5f; baseZ = -7.7f; break;
|
||||
case 8: baseX = 5.1f; baseZ = -7.7f; break;
|
||||
case 9: baseX = 6.7f; baseZ = -7.7f; break;
|
||||
case 10: baseX = 8.2f; baseZ = -7.7f; break;
|
||||
case 11: baseX = 8.2f; baseZ = -6.5f; break; //passt
|
||||
case 12: baseX = 8.2f; baseZ = -4.9f; break; //passt
|
||||
case 13: baseX = 8.2f; baseZ = -3.3f; break; //passt
|
||||
case 14: baseX = 8.2f; baseZ = -1.6f; break; //passt
|
||||
case 15: baseX = 8.2f; baseZ = 0.0f; break; //passt
|
||||
case 16: baseX = 8.2f; baseZ = 1.6f; break; //passt
|
||||
case 17: baseX = 8.2f; baseZ = 3.3f; break; //passt
|
||||
case 18: baseX = 8.2f; baseZ = 4.9f; break; //passt
|
||||
case 19: baseX = 8.2f; baseZ = 6.5f; break; //passt
|
||||
case 20: baseX = 8.2f; baseZ = 7.7f; break;
|
||||
case 21: baseX = 6.5f; baseZ = 7.7f; break;
|
||||
case 22: baseX = 4.9f; baseZ = 7.7f; break;
|
||||
case 23: baseX = 3.3f; baseZ = 7.7f; break;
|
||||
case 24: baseX = 1.6f; baseZ = 7.7f; break;
|
||||
case 25: baseX = 0.0f; baseZ = 7.7f; break;
|
||||
case 26: baseX = -1.6f; baseZ = 7.7f; break;
|
||||
case 27: baseX = -3.3f; baseZ = 7.7f; break;
|
||||
case 28: baseX = -4.9f; baseZ = 7.7f; break;
|
||||
case 29: baseX = -6.5f; baseZ = 7.7f; break;
|
||||
case 30: baseX = -7.2f; baseZ = 7.7f; break;
|
||||
case 31: baseX = -7.2f; baseZ = 6.5f; break;
|
||||
case 32: baseX = -7.2f; baseZ = 4.9f; break;
|
||||
case 33: baseX = -7.2f; baseZ = 3.3f; break;
|
||||
case 34: baseX = -7.2f; baseZ = 1.6f; break;
|
||||
case 35: baseX = -7.2f; baseZ = 0.0f; break;
|
||||
case 36: baseX = -7.2f; baseZ = -1.6f; break;
|
||||
case 37: baseX = -7.2f; baseZ = -3.3f; break;
|
||||
case 38: baseX = -7.2f; baseZ = -4.9f; break;
|
||||
case 39: baseX = -7.2f; baseZ = -6.5f; break;
|
||||
default: throw new IllegalArgumentException("Ungültige Feld-ID: " + fieldID);
|
||||
}
|
||||
|
||||
return new Vector3f(baseX, 0, baseZ);
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +1,3 @@
|
||||
////////////////////////////////////////
|
||||
// Programming project code
|
||||
// UniBw M, 2022, 2023, 2024
|
||||
// www.unibw.de/inf2
|
||||
// (c) Mark Minas (mark.minas@unibw.de)
|
||||
////////////////////////////////////////
|
||||
|
||||
package pp.monopoly.model;
|
||||
|
||||
/**
|
||||
@ -22,4 +15,20 @@ public interface Visitor<T> {
|
||||
*/
|
||||
T visit(Figure figure);
|
||||
|
||||
/**
|
||||
* Visits a Hotel element.
|
||||
*
|
||||
* @param hotel the Hotel element to visit
|
||||
* @return the result of visiting the hotel element
|
||||
*/
|
||||
T visit(Hotel hotel);
|
||||
|
||||
/**
|
||||
* Visits a house element.
|
||||
*
|
||||
* @param house the House element to visit
|
||||
* @return the result of visiting the house element
|
||||
*/
|
||||
T visit(House figure);
|
||||
|
||||
}
|
||||
|
@ -1,10 +1,3 @@
|
||||
////////////////////////////////////////
|
||||
// Programming project code
|
||||
// UniBw M, 2022, 2023, 2024
|
||||
// www.unibw.de/inf2
|
||||
// (c) Mark Minas (mark.minas@unibw.de)
|
||||
////////////////////////////////////////
|
||||
|
||||
package pp.monopoly.model;
|
||||
|
||||
/**
|
||||
@ -19,4 +12,18 @@ public interface VoidVisitor {
|
||||
*/
|
||||
void visit(Figure figure);
|
||||
|
||||
/**
|
||||
* Visits a Hotel element.
|
||||
*
|
||||
* @param hotel the Hotel element to visit
|
||||
*/
|
||||
void visit(Hotel hotel);
|
||||
|
||||
/**
|
||||
* Visits a House element.
|
||||
*
|
||||
* @param house the House element to visit
|
||||
*/
|
||||
void visit(House house);
|
||||
|
||||
}
|
||||
|
@ -6,36 +6,10 @@ import pp.monopoly.model.Item;
|
||||
/**
|
||||
* Event that is triggered when an item is added to a board.
|
||||
*/
|
||||
public class ItemAddedEvent {
|
||||
private final Item item;
|
||||
private final Board board;
|
||||
public record ItemAddedEvent(Board board, Item item) implements GameEvent {
|
||||
|
||||
/**
|
||||
* Constructs a new ItemAddedEvent.
|
||||
*
|
||||
* @param item the item that was added
|
||||
* @param board the board to which the item was added
|
||||
*/
|
||||
public ItemAddedEvent(Item item, Board board) {
|
||||
this.item = item;
|
||||
this.board = board;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item that was added.
|
||||
*
|
||||
* @return the added item
|
||||
*/
|
||||
public Item getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the board to which the item was added.
|
||||
*
|
||||
* @return the board
|
||||
*/
|
||||
public Board getBoard() {
|
||||
return board;
|
||||
@Override
|
||||
public void notifyListener(GameEventListener listener) {
|
||||
listener.receivedEvent(this);
|
||||
}
|
||||
}
|
||||
|
@ -1,35 +1,15 @@
|
||||
////////////////////////////////////////
|
||||
// Programming project code
|
||||
// UniBw M, 2022, 2023, 2024
|
||||
// www.unibw.de/inf2
|
||||
// (c) Mark Minas (mark.minas@unibw.de)
|
||||
////////////////////////////////////////
|
||||
|
||||
package pp.monopoly.notification;
|
||||
|
||||
import pp.monopoly.model.Board;
|
||||
import pp.monopoly.model.Item;
|
||||
|
||||
/**
|
||||
* Event when an item gets removed.
|
||||
*
|
||||
* Event that is triggered when an item is removed from a board.
|
||||
*/
|
||||
public class ItemRemovedEvent {
|
||||
private final Item item;
|
||||
private final Board board;
|
||||
public record ItemRemovedEvent(Board board, Item item) implements GameEvent {
|
||||
|
||||
public ItemRemovedEvent(Item item, Board board) {
|
||||
this.item = item;
|
||||
this.board = board;
|
||||
}
|
||||
|
||||
public Item getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public Board getBoard() {
|
||||
return board;
|
||||
@Override
|
||||
public void notifyListener(GameEventListener listener) {
|
||||
listener.receivedEvent(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user