4 Commits

Author SHA1 Message Date
Johannes Schmelz
159927e52c now able to add all nessecary models 2024-12-08 02:16:40 +01:00
Johannes Schmelz
8614faf940 show popups 2024-12-07 22:11:31 +01:00
Johannes Schmelz
4ba43602fa player now moves without animation 2024-12-07 21:58:26 +01:00
Johannes Schmelz
b4e2beca3a frist working version, TODO: trigger the render events 2024-12-07 01:13:17 +01:00
30 changed files with 826 additions and 372 deletions

View File

@@ -3,7 +3,6 @@
// https://github.com/jMonkeyEngine-Contributions/Lemur/wiki/Styling
import com.jme3.math.ColorRGBA
import com.jme3.texture.Texture
import com.simsilica.lemur.*
import com.simsilica.lemur.component.QuadBackgroundComponent
import com.simsilica.lemur.Button
@@ -48,23 +47,6 @@ def orangeBorder = TbtQuadBackgroundComponent.create(
1f, false)
orangeBorder.color = color(1, 0.5, 0, 1) // Orange color
def createCustomBackground(app) {
// Load the texture from the assets
Texture texture = app.getAssetManager().loadTexture("Pictures/kontobg.png")
// Create the TbtQuadBackgroundComponent
def backgroundCustom = TbtQuadBackgroundComponent.create(
texture, // The texture to use
1, 1, 1, // Insets for the 9-patch behavior
126, 126, // The size of the texture
1f, // The scale factor
false // No tiling
)
return backgroundCustom
}
selector("pp") {
font = font("Interface/Fonts/Metropolis/Metropolis-Regular-32.fnt")
}
@@ -87,7 +69,7 @@ selector("label-Bold", "pp") {
selector("label-toolbar", "pp") {
insets = new Insets3f(2, 2, 2, 2)
font = font("Interface/Fonts/Metropolis/Metropolis-Bold-32.fnt")
fontSize = 25
fontSize = 30
color = new ColorRGBA(ColorRGBA.White)
textHAlignment = HAlignment.Center
textVAlignment = VAlignment.Center
@@ -348,7 +330,7 @@ def enabledCommandToolbar = new Command<Button>() {
void execute(Button source) {
if (source.isEnabled()){
source.setColor(ColorRGBA.White)
def orangeBackground = new QuadBackgroundComponent(color(1, 1, 0, 1)); // Orange background
def orangeBackground = new QuadBackgroundComponent(color(1, 0.5, 0, 1)); // Orange background
source.setBackground(orangeBackground);
} else{
source.setColor(ColorRGBA.White)
@@ -384,20 +366,3 @@ selector("button-toolbar", "pp") {
}
selector("button-toolbar2", "pp") { playerColor ->
def validColor = playerColor ?: new ColorRGBA(0, 0, 0, 0) // Vollständig transparent
def playerGradientBackground = new QuadBackgroundComponent(validColor)
// Kein Hintergrundbild, komplett transparent
playerGradientBackground.setColor(new ColorRGBA(0, 0, 0, 0)) // RGBA (Rot, Grün, Blau, Alpha)
background = playerGradientBackground.clone() // Setze den Hintergrund
insets = new Insets3f(3, 3, 3, 3) // Optional: Ränder
textHAlignment = HAlignment.Center // Text-Zentrierung
textVAlignment = VAlignment.Center // Text-Zentrierung
}

View File

@@ -9,6 +9,7 @@ import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.Camera;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
@@ -21,10 +22,11 @@ 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.monopoly.model.Board;
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;
@@ -179,12 +181,12 @@ public class BoardAppState extends MonopolyAppState {
*/
private void setupSky() {
final AssetManager assetManager = getApp().getAssetManager();
final Texture west = assetManager.loadTexture("Pictures/Backdrop/west.jpg"); //NON-NLS
final Texture east = assetManager.loadTexture("Pictures/Backdrop/ost.jpg"); //NON-NLS
final Texture north = assetManager.loadTexture("Pictures/Backdrop/nord.jpg"); //NON-NLS
final Texture south = assetManager.loadTexture("Pictures/Backdrop/sued.jpg"); //NON-NLS
final Texture up = assetManager.loadTexture("Pictures/Backdrop/sued.jpg"); //NON-NLS
final Texture down = assetManager.loadTexture("Pictures/Backdrop/sued.jpg"); //NON-NLS
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);

View File

@@ -0,0 +1,99 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.monopoly.client;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import com.jme3.input.controls.ActionListener;
import com.jme3.scene.Node;
import pp.monopoly.client.gui.TestWorld;
/**
* Represents the state responsible for managing the battle interface within the Battleship game.
* This state handles the display and interaction of the battle map, including the opponent's map.
* It manages GUI components, input events, and the layout of the interface when this state is enabled.
*/
public class GameAppState extends MonopolyAppState {
private static final Logger LOGGER = System.getLogger(MonopolyAppState.class.getName());
/**
* A listener for handling click events in the battle interface.
* When a click is detected, it triggers the corresponding actions on the opponent's map.
*/
private final ActionListener clickListener = (name, isPressed, tpf) -> click(isPressed);
/**
* The root node for all GUI components in the battle state.
*/
private final Node battleNode = new Node("Game"); //NON-NLS
/**
* A view representing the opponent's map in the GUI.
*/
private TestWorld testWorld;
/**
* Enables the battle state by initializing, laying out, and adding GUI components.
* Attaches the components to the GUI node and registers input listeners.
*/
@Override
protected void enableState() {
LOGGER.log(Level.DEBUG, "Enabling game state");
battleNode.detachAllChildren();
initializeGuiComponents();
addGuiComponents();
getApp().getGuiNode().attachChild(battleNode);
}
/**
* Disables the battle state by removing GUI components and unregistering input listeners.
* Also handles cleanup of resources, such as the opponent's map view.
*/
@Override
protected void disableState() {
getApp().getGuiNode().detachChild(battleNode);
getApp().getInputManager().removeListener(clickListener);
}
/**
* Initializes the GUI components used in the battle state.
* Creates the opponent's map view and adds a grid overlay to it.
*/
private void initializeGuiComponents() {
// Initialisiere TestWorld mit Spielern
testWorld = new TestWorld(getApp());
testWorld.initializeScene();
}
/**
* Adds the initialized GUI components to the battle node.
* Currently, it attaches the opponent's map view to the node.
*/
private void addGuiComponents() {
}
/**
* Handles click events in the battle interface. If the event indicates a click (not a release),
* it translates the cursor position to the model's coordinate system and triggers the game logic
* for interacting with the opponent's map.
*
* @param isPressed whether the mouse button is currently pressed (true) or released (false)
*/
private void click(boolean isPressed) {
}
@Override
public void update(float tpf) {
super.update(tpf);
}
}

View File

@@ -13,13 +13,14 @@ import com.jme3.asset.AssetLoadException;
import com.jme3.asset.AssetNotFoundException;
import com.jme3.audio.AudioData;
import com.jme3.audio.AudioNode;
/**
* Handles the background and secondary music in the game.
* Allows playing, stopping, and toggling between background music and a secondary track.
*/
public class GameMusic extends AbstractAppState {
private static final Logger LOGGER = System.getLogger(pp.monopoly.client.GameMusic.class.getName());
private static final Preferences PREFERENCES = getPreferences(pp.monopoly.client.GameMusic.class);
private static final Logger LOGGER = System.getLogger(GameMusic.class.getName());
private static final Preferences PREFERENCES = getPreferences(GameMusic.class);
private static final String ENABLED_PREF = "enabled"; // NON-NLS
private static final String VOLUME_PREF = "volume"; // NON-NLS
@@ -67,9 +68,8 @@ public class GameMusic extends AbstractAppState {
/**
* Plays the main music.
*/
public void playMainMusic() {
private void playMainMusic() {
if (!isEnabled()) {
return; // Sound is disabled
}
@@ -92,10 +92,11 @@ public class GameMusic extends AbstractAppState {
/**
* Plays the secondary music and stops the main music.
*
* @param app The application instance
* @param secondaryMusicFile The file path of the secondary audio file
*/
public void playSecondaryMusic() {
if (!isEnabled()) {
stopAllMusic();
private void playSecondaryMusic() {
if(!isEnabled()) {
return;
}
if (isSecondaryMusicPlaying) {
@@ -114,7 +115,7 @@ public class GameMusic extends AbstractAppState {
/**
* Stops the secondary music.
*/
public void stopSecondaryMusic() {
private void stopSecondaryMusic() {
if (secondaryMusic != null && isSecondaryMusicPlaying) {
secondaryMusic.stop();
isSecondaryMusicPlaying = false;
@@ -126,17 +127,17 @@ public class GameMusic extends AbstractAppState {
* If the secondary track is playing, it stops and resumes the background music.
* If the background music is playing, it pauses and plays the secondary track.
*
* @param app The application instance
* @param secondaryMusicFile The file path of the secondary audio file
*/
public void toggleMusic() {
if (!isEnabled()) {
stopAllMusic();
if(!isEnabled()) {
return;
}
if (isSecondaryMusicPlaying) {
stopSecondaryMusic();
playMainMusic();
} else {
stopMainMusic();
playSecondaryMusic();
}
}
@@ -152,14 +153,6 @@ public class GameMusic extends AbstractAppState {
PREFERENCES.putFloat(VOLUME_PREF, vol);
}
/**
* Stops all music (both main and secondary).
*/
public void stopAllMusic() {
stopMainMusic();
stopSecondaryMusic();
}
/**
* Enables or disables the sound system.
* When disabled, all music stops.
@@ -168,14 +161,13 @@ public class GameMusic extends AbstractAppState {
*/
@Override
public void setEnabled(boolean enabled) {
if (isEnabled() == enabled) return; // Avoid redundant operations
PREFERENCES.putBoolean(ENABLED_PREF, enabled);
if (isEnabled() == enabled) return;
if (enabled) {
playMainMusic();
} else {
stopAllMusic();
stopMainMusic();
stopSecondaryMusic();
}
super.setEnabled(enabled);

View File

@@ -1,5 +1,9 @@
package pp.monopoly.client.gui;
import static com.jme3.material.Materials.LIGHTING;
import java.util.stream.Collectors;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
@@ -10,6 +14,7 @@ import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.game.server.Player;
import pp.monopoly.model.Figure;
import pp.monopoly.model.Hotel;
import pp.monopoly.model.House;
@@ -43,7 +48,7 @@ public class BobTheBuilder extends GameBoardSynchronizer {
// Setze die Rotation basierend auf der Feld-ID
node.setLocalRotation(figure.getRot().toQuaternion());
node.addControl(new FigureControl(figure));
// node.addControl(new FigureControl(figure));
return node;
}
@@ -141,6 +146,14 @@ public class BobTheBuilder extends GameBoardSynchronizer {
@Override
public void receivedEvent(UpdatePlayerView event) {
//TODO player move animation
board.removePlayers();
//TODO transition animation
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);
}
}
}

View File

@@ -1,28 +0,0 @@
package pp.monopoly.client.gui;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.control.AbstractControl;
import pp.monopoly.model.Figure;
public class FigureControl extends AbstractControl {
private final Figure figure;
public FigureControl(Figure figure) {
super();
this.figure = figure;
}
@Override
protected void controlUpdate(float tpf) {
//TODO: animation
}
@Override
protected void controlRender(RenderManager rm, ViewPort vp) {
// No rendering required
}
}

View File

@@ -79,9 +79,8 @@ public class LobbyMenu extends Dialog {
this.app = app;
GameMusic music = app.getStateManager().getState(GameMusic.class);
if (music != null && music.isEnabled()) {
music.playSecondaryMusic();
}
music.toggleMusic();
playerInputField = new TextField("Spieler "+(app.getId()+1));
// Hintergrundbild laden und hinzufügen
addBackgroundImage();
@@ -277,12 +276,6 @@ public class LobbyMenu extends Dialog {
new SettingsMenu(app).open();
}
/**
* Updates the menu at regular intervals.
* Checks if the dropdown selection has been updated and invokes the selection change handler.
*
* @param tpf Time per frame, in seconds, since the last update.
*/
@Override
public void update(float tpf) {
if (selectionRef.update()) {
@@ -290,27 +283,10 @@ public class LobbyMenu extends Dialog {
}
}
/**
* Closes the current menu and transitions music playback.
* Stops the secondary music (if playing) and resumes the main background music
* if music is enabled in the preferences. Ensures smooth transitions in audio.
*/
@Override
public void close() {
GameMusic music = app.getStateManager().getState(GameMusic.class);
if (music != null) {
music.stopSecondaryMusic();
if (music.isEnabled()) {
music.playMainMusic();
}
}
super.close();
}
/**
* Updates the selected figure based on the dropdown menu selection.
*
* @param selector the selected figure
* @param selected the selected figure
*/
private void onDropdownSelectionChanged(Selector<String> selector) {
app.getGameLogic().playSound(Sound.BUTTON);

View File

@@ -51,17 +51,7 @@ public class SettingsMenu extends Dialog {
private final SoundSlider soundSlider;
/**
* Checkbox for toggling sound effects.
*/
private final Checkbox soundCheckbox;
/**
* Checkbox for toggling background music.
*/
private final Checkbox musicCheckbox;
/**
* Constructs the Menu dialog for the Monopoly application.
* Constructs the Menu dialog for the Battleship application.
*
* @param app the MonopolyApp instance
*/
@@ -75,15 +65,11 @@ public class SettingsMenu extends Dialog {
addChild(soundSlider);
soundCheckbox = new Checkbox("Soundeffekte an / aus", new StateCheckboxModel(app, GameSound.class));
addChild(soundCheckbox);
addChild(new Checkbox("Soundeffekte an / aus", new StateCheckboxModel(app, GameSound.class)));
addChild(new Label("Hintergrund Musik", new ElementId("label"))); //NON-NLS
musicCheckbox = new Checkbox("Musik an / aus", new StateCheckboxModel(app, GameMusic.class));
musicCheckbox.addClickCommands(s -> toggleMusicPreference());
addChild(musicCheckbox);
addChild(new Checkbox("Musik an / aus", new StateCheckboxModel(app, GameMusic.class)));
addChild(musicSlider);
addChild(new Button("Zurück zum Spiel", new ElementId("button"))).addClickCommands(s -> ifTopDialog(() -> {
@@ -98,42 +84,16 @@ public class SettingsMenu extends Dialog {
}
/**
* Toggles the music preference based on the state of the musicCheckbox.
* Enables or disables background music and starts playback if enabled.
*/
private void toggleMusicPreference() {
boolean enabled = musicCheckbox.isChecked();
GameMusic gameMusic = app.getStateManager().getState(GameMusic.class);
if (gameMusic != null) {
gameMusic.setEnabled(enabled);
if (enabled) {
gameMusic.playMainMusic();
}
}
}
/**
* Updates the state of the music checkbox to match the current preferences.
* This ensures the checkbox reflects the actual enabled/disabled state of the music.
* Updates the state of the load and save buttons based on the game logic.
*/
@Override
public void update() {
GameMusic gameMusic = app.getStateManager().getState(GameMusic.class);
if (gameMusic != null) {
musicCheckbox.setChecked(gameMusic.isEnabled());
}
}
/**
* Updates UI elements such as sliders and synchronizes the state of the settings menu.
*
* @param delta the time in seconds since the last update
*/
@Override
public void update(float delta) {
musicSlider.update();
soundSlider.update();
update();
}
/**

View File

@@ -0,0 +1,565 @@
package pp.monopoly.client.gui;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.control.AbstractControl;
import com.jme3.texture.Texture;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.client.gui.popups.AcceptTrade;
import pp.monopoly.client.gui.popups.BuildingPropertyCard;
import pp.monopoly.client.gui.popups.ConfirmTrade;
import pp.monopoly.client.gui.popups.EventCardPopup;
import pp.monopoly.client.gui.popups.FoodFieldCard;
import pp.monopoly.client.gui.popups.GateFieldCard;
import pp.monopoly.client.gui.popups.Gulag;
import pp.monopoly.client.gui.popups.GulagInfo;
import pp.monopoly.client.gui.popups.LooserPopUp;
import pp.monopoly.client.gui.popups.NoMoneyWarning;
import pp.monopoly.client.gui.popups.ReceivedRent;
import pp.monopoly.client.gui.popups.RejectTrade;
import pp.monopoly.client.gui.popups.Rent;
import pp.monopoly.client.gui.popups.TimeOut;
import pp.monopoly.client.gui.popups.WinnerPopUp;
import pp.monopoly.game.server.Player;
import pp.monopoly.game.server.PlayerHandler;
import pp.monopoly.message.server.NotificationMessage;
import pp.monopoly.message.server.TradeReply;
import pp.monopoly.model.fields.BuildingProperty;
import pp.monopoly.model.fields.FoodField;
import pp.monopoly.model.fields.GateField;
import pp.monopoly.notification.EventCardEvent;
import pp.monopoly.notification.GameEventListener;
import pp.monopoly.notification.PopUpEvent;
import pp.monopoly.notification.UpdatePlayerView;
/**
* TestWorld zeigt eine einfache Szene mit Spielfeld und Spielfiguren.
*/
public class TestWorld implements GameEventListener {
private final MonopolyApp app;
private PlayerHandler playerHandler;
private CameraController cameraController;
private Toolbar toolbar;
private List<String> existingHouses = new ArrayList<>();
/**
* Konstruktor für die TestWorld.
*
* @param app Die Hauptanwendung
*/
public TestWorld(MonopolyApp app) {
this.app = app;
this.playerHandler = app.getGameLogic().getPlayerHandler();
app.getGameLogic().addListener(this);
cameraController = new CameraController(app.getCamera());
}
/**
* Initialisiert die Szene mit Spielfeld und Figuren.
*/
public void initializeScene() {
// Entferne bestehende Inhalte
app.getGuiNode().detachAllChildren();
app.getRootNode().detachAllChildren();
System.out.println("Szene initialisiert.");
//Füge Inhalte ein
setSkyColor();
createBoard();
addLighting();
createPlayerFigures();
toolbar = new Toolbar(app);
toolbar.open();
}
/**
* Setzt die Hintergrundfarbe der Szene auf hellblau.
*/
private void setSkyColor() {
app.getViewPort().setBackgroundColor(new com.jme3.math.ColorRGBA(0.5f, 0.7f, 1.0f, 1.0f));
}
/**
* Erstellt das Spielfeld und fügt es zur Szene hinzu.
*/
private void createBoard() {
try {
com.jme3.scene.shape.Box box = new com.jme3.scene.shape.Box(10, 0.1f, 10);
com.jme3.scene.Geometry geom = new com.jme3.scene.Geometry("Board", box);
Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
Texture texture = app.getAssetManager().loadTexture("Pictures/board2.png");
mat.setTexture("DiffuseMap", texture);
geom.setMaterial(mat);
geom.setLocalTranslation(0, -0.1f, 0);
com.jme3.math.Quaternion rotation = new com.jme3.math.Quaternion();
rotation.fromAngleAxis(FastMath.HALF_PI, com.jme3.math.Vector3f.UNIT_Y);
geom.setLocalRotation(rotation);
app.getRootNode().attachChild(geom);
} catch (Exception e) {
System.err.println("Fehler beim Erstellen des Spielfelds: " + e.getMessage());
}
}
private void addLighting() {
// Direktionales Licht
DirectionalLight sun = new DirectionalLight();
sun.setColor(ColorRGBA.White);
sun.setDirection(new Vector3f(-0.5f, -0.7f, -1.0f).normalizeLocal());
app.getRootNode().addLight(sun);
// Umgebungslicht
AmbientLight ambient = new AmbientLight();
ambient.setColor(new ColorRGBA(0.6f, 0.6f, 0.6f, 1.0f));
app.getRootNode().addLight(ambient);
}
private com.jme3.math.Quaternion calculateRotationForField(int fieldID) {
com.jme3.math.Quaternion rotation = new com.jme3.math.Quaternion();
// Berechne die Rotation basierend auf der Feld-ID
if (fieldID >= 0 && fieldID <= 9) {
// Untere Seite (0-9)
rotation.fromAngleAxis(0, Vector3f.UNIT_Y); // Richtung: nach oben
} else if (fieldID >= 10 && fieldID <= 19) {
// Rechte Seite (10-19)
rotation.fromAngleAxis(FastMath.HALF_PI, Vector3f.UNIT_Y); // Richtung: nach links
} else if (fieldID >= 20 && fieldID <= 29) {
// Obere Seite (20-29)
rotation.fromAngleAxis(FastMath.PI, Vector3f.UNIT_Y); // Richtung: nach unten
} else if (fieldID >= 30 && fieldID <= 39) {
// Linke Seite (30-39)
rotation.fromAngleAxis(3 * FastMath.HALF_PI, Vector3f.UNIT_Y); // Richtung: nach rechts
}
// Korrigiere die Richtung für die Quadranten 1019 und 3039 (gegenüberliegende Richtung)
if ((fieldID >= 10 && fieldID <= 19) || (fieldID >= 30 && fieldID <= 39)) {
com.jme3.math.Quaternion oppositeDirection = new com.jme3.math.Quaternion();
oppositeDirection.fromAngleAxis(FastMath.PI, Vector3f.UNIT_Y); // 180° drehen
rotation = rotation.multLocal(oppositeDirection);
}
// Füge zusätzliche 90° nach links hinzu
com.jme3.math.Quaternion leftTurn = new com.jme3.math.Quaternion();
leftTurn.fromAngleAxis(FastMath.HALF_PI, Vector3f.UNIT_Y); // 90° nach links
rotation = rotation.multLocal(leftTurn);
return rotation;
}
/**
* Erstellt die Spielfiguren basierend auf der bereits bekannten Spielerliste.
*/
private void createPlayerFigures() {
for (Player player : playerHandler.getPlayers()) {
try {
// Lade das Modell
com.jme3.scene.Spatial model = app.getAssetManager().loadModel(
"models/" + "Spielfiguren/" + player.getFigure().getType() + "/" + player.getFigure().getType() + ".j3o");
// Skaliere und positioniere das Modell
model.setLocalScale(0.5f);
Vector3f startPosition = calculateFieldPosition(player.getFieldID(), player.getId());
model.setLocalTranslation(startPosition);
// Setze die Rotation basierend auf der Feld-ID
model.setLocalRotation(calculateRotationForField(player.getFieldID()));
model.setName("PlayerFigure_" + player.getId());
// Füge das Modell zur Szene hinzu
app.getRootNode().attachChild(model);
} catch (Exception e) {
System.err.println("Fehler beim Laden des Modells für Spieler " + player.getId() + ": " + e.getMessage());
}
}
}
private Vector3f calculateFieldPosition(int fieldID, int playerIndex) {
float offset = 0.1f;
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);
}
float xOffset = (playerIndex % 2) * offset;
float zOffset = (playerIndex / 2) * offset;
return new Vector3f(baseX + xOffset, 0, baseZ + zOffset);
}
private void movePlayerFigure(Player player) {
int playerIndexOnField = calculatePlayerIndexOnField(player.getFieldID(), player.getId());
String figureName = "PlayerFigure_" + player.getId();
com.jme3.scene.Spatial figure = app.getRootNode().getChild(figureName);
if (figure != null) {
// Füge einen Delay hinzu (z.B. 3 Sekunden)
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
app.enqueue(() -> {
// Setze die Position
Vector3f targetPosition = calculateFieldPosition(player.getFieldID(), player.getId());
figure.setLocalTranslation(targetPosition);
// Aktualisiere die Rotation basierend auf der Feld-ID
figure.setLocalRotation(calculateRotationForField(player.getFieldID()));
});
}
}, 3000); // 3000 Millisekunden Delay
} else {
System.err.println("Figur für Spieler " + player.getId() + " nicht gefunden.");
}
}
private int getFieldIDFromPosition(Vector3f position) {
for (int fieldID = 0; fieldID < 40; fieldID++) {
Vector3f fieldPosition = calculateFieldPosition(fieldID, 0);
if (fieldPosition.distance(position) < 0.5f) { // Toleranz für Positionserkennung
return fieldID;
}
}
throw new IllegalArgumentException("Position entspricht keinem gültigen Feld: " + position);
}
/**
* Berechnet den Eckpunkt basierend auf Start- und Zielposition.
*
* @param startPosition Die Startposition der Figur.
* @param targetPosition Die Zielposition der Figur.
* @return Die Position der Ecke, die passiert werden muss.
*/
private Vector3f calculateCornerPosition(Vector3f startPosition, Vector3f targetPosition) {
// Ziel: Immer entlang der Spielfeldkante navigieren
float deltaX = targetPosition.x - startPosition.x;
float deltaZ = targetPosition.z - startPosition.z;
// Überprüfen, ob Bewegung entlang X oder Z-Koordinate zuerst erfolgen soll
if (deltaX != 0 && deltaZ != 0) {
if (Math.abs(deltaX) > Math.abs(deltaZ)) {
// Bewegung entlang X zuerst
return new Vector3f(targetPosition.x, 0, startPosition.z);
} else {
// Bewegung entlang Z zuerst
return new Vector3f(startPosition.x, 0, targetPosition.z);
}
} else {
// Bewegung ist bereits entlang einer Achse (keine Ecke erforderlich)
return targetPosition;
}
}
private List<Vector3f> calculatePath(int startFieldID, int targetFieldID, int playerIndex) {
List<Vector3f> pathPoints = new ArrayList<>();
// Bewegung im Uhrzeigersinn
if (startFieldID < targetFieldID) {
for (int i = startFieldID; i <= targetFieldID; i++) {
// Füge Ecken hinzu, falls sie überschritten werden
if (i == 10 || i == 20 || i == 30 || i == 0) {
pathPoints.add(calculateFieldPosition(i, playerIndex));
}
}
} else {
// Bewegung über das Ende des Spielfelds hinaus (z.B. von 39 zu 5)
for (int i = startFieldID; i < 40; i++) {
if (i == 10 || i == 20 || i == 30 || i == 0) {
pathPoints.add(calculateFieldPosition(i, playerIndex));
}
}
for (int i = 0; i <= targetFieldID; i++) {
if (i == 10 || i == 20 || i == 30 || i == 0) {
pathPoints.add(calculateFieldPosition(i, playerIndex));
}
}
}
// Füge das Ziel hinzu
pathPoints.add(calculateFieldPosition(targetFieldID, playerIndex));
return pathPoints;
}
private int calculatePlayerIndexOnField(int fieldID, int playerID) {
List<Player> playersOnField = playerHandler.getPlayers().stream()
.filter(p -> p.getFieldID() == fieldID)
.toList();
for (int i = 0; i < playersOnField.size(); i++) {
if (playersOnField.get(i).getId() == playerID) {
return i;
}
}
return 0;
}
private void animateMovementAlongPath(com.jme3.scene.Spatial figure, List<Vector3f> pathPoints) {
float animationDurationPerSegment = 2.5f; // Langsamere Animation (2.5 Sekunden pro Segment)
int[] currentSegment = {0};
app.enqueue(() -> {
figure.addControl(new AbstractControl() {
private float elapsedTime = 0.0f;
@Override
protected void controlUpdate(float tpf) {
if (currentSegment[0] >= pathPoints.size() - 1) {
this.setEnabled(false); // Animation abgeschlossen
return;
}
elapsedTime += tpf;
float progress = Math.min(elapsedTime / animationDurationPerSegment, 1.0f);
Vector3f start = pathPoints.get(currentSegment[0]);
Vector3f end = pathPoints.get(currentSegment[0] + 1);
Vector3f interpolatedPosition = start.interpolateLocal(end, progress);
figure.setLocalTranslation(interpolatedPosition);
if (progress >= 1.0f) {
elapsedTime = 0.0f;
currentSegment[0]++;
}
}
@Override
protected void controlRender(RenderManager rm, ViewPort vp) {
// Nicht benötigt
}
});
});
}
@Override
public void receivedEvent(PopUpEvent event) {
if (event.msg().equals("Buy")) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
app.enqueue(() -> {
int field = app.getGameLogic().getPlayerHandler().getPlayerById(app.getId()).getFieldID();
Object fieldObject = app.getGameLogic().getBoardManager().getFieldAtIndex(field);
if (fieldObject instanceof BuildingProperty) {
new BuildingPropertyCard(app).open();
} else if (fieldObject instanceof GateField) {
new GateFieldCard(app).open();
} else if (fieldObject instanceof FoodField) {
new FoodFieldCard(app).open();
}
});
}
}, 2500);
} else if (event.msg().equals("Winner")) {
new WinnerPopUp(app).open();
} else if (event.msg().equals("Looser")) {
new LooserPopUp(app).open();
} else if (event.msg().equals("timeout")) {
new TimeOut(app).open();
} else if (event.msg().equals("tradeRequest")) {
new ConfirmTrade(app).open();
} else if (event.msg().equals("goingToJail")) {
new Gulag(app).open();
} else if (event.msg().equals("NoMoneyWarning")) {
new NoMoneyWarning(app).open();
} else if(event.msg().equals("rent")) {
new Rent(app, ( (NotificationMessage) event.message()).getRentOwner(), ( (NotificationMessage) event.message()).getRentAmount() ).open();
} else if (event.msg().equals("jailtryagain")) {
new GulagInfo(app, 1).open();
} else if (event.msg().equals("jailpay")) {
new GulagInfo(app, 3).open();
} else if (event.msg().equals("tradepos")) {
new AcceptTrade(app, (TradeReply) event.message()).open();
} else if (event.msg().equals("tradeneg")) {
new RejectTrade(app, (TradeReply) event.message()).open();
} else if (event.msg().equals("ReceivedRent")) {
new ReceivedRent(app, ( (NotificationMessage) event.message()).getRentOwner(), ( (NotificationMessage) event.message()).getRentAmount() ).open();
}
}
private Vector3f calculateBuildingPosition(int fieldID) {
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);
}
private void updateHousesOnBoard() {
app.enqueue(() -> {
List<BuildingProperty> propertiesWithBuildings = app.getGameLogic().getBoardManager().getPropertiesWithBuildings();
for (BuildingProperty property : propertiesWithBuildings) {
int houseCount = property.getHouses();
int hotelCount = property.getHotel();
String uniqueIdentifier = "Building_" + property.getId() + "_" + (hotelCount > 0 ? "Hotel" : houseCount);
if (existingHouses.contains(uniqueIdentifier)) continue;
try {
String modelPath = hotelCount > 0
? "models/Hotel/Hotel.j3o"
: "models/Haus/" + houseCount + "Haus.j3o";
com.jme3.scene.Spatial buildingModel = app.getAssetManager().loadModel(modelPath);
Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
buildingModel.setMaterial(mat);
buildingModel.setLocalScale(0.5f);
Vector3f position = calculateBuildingPosition(property.getId()).add(0, 0.5f, 0);
buildingModel.setLocalTranslation(position);
com.jme3.math.Quaternion rotation = new com.jme3.math.Quaternion();
if (property.getId() >= 1 && property.getId() <= 10) {
rotation.fromAngleAxis(FastMath.HALF_PI, Vector3f.UNIT_Y);
} else if (property.getId() >= 21 && property.getId() <= 30) {
rotation.fromAngleAxis(3 * FastMath.HALF_PI, Vector3f.UNIT_Y);
} else if (property.getId() >= 31 && property.getId() <= 39) {
rotation.fromAngleAxis(FastMath.PI, Vector3f.UNIT_Y);
}
buildingModel.setLocalRotation(rotation);
buildingModel.setName(uniqueIdentifier);
app.getRootNode().attachChild(buildingModel);
existingHouses.add(uniqueIdentifier);
} catch (Exception e) {
System.err.println("Fehler beim Hinzufügen eines Gebäudes: " + e.getMessage());
}
}
});
}
@Override
public void receivedEvent(EventCardEvent event) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
app.enqueue(() -> new EventCardPopup(app, event.description()).open());
}
}, 2500);
}
@Override
public void receivedEvent(UpdatePlayerView event) {
this.playerHandler = app.getGameLogic().getPlayerHandler();
for (Player player : playerHandler.getPlayers()) {
movePlayerFigure(player);
}
updateHousesOnBoard();
}
}

View File

@@ -19,7 +19,6 @@ import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.client.gui.popups.Bankrupt;
import pp.monopoly.game.server.Player;
import pp.monopoly.game.server.PlayerColor;
import pp.monopoly.game.server.PlayerHandler;
import pp.monopoly.message.client.EndTurn;
import pp.monopoly.message.client.RollDice;
@@ -105,7 +104,6 @@ public class Toolbar extends Dialog implements GameEventListener {
/**Indicates if the bankrupt PopUp has already been shown */
private boolean bankruptPopUp = false;
/**
* Constructs the toolbar for the Monopoly application.
* <p>
@@ -124,21 +122,6 @@ public class Toolbar extends Dialog implements GameEventListener {
toolbarContainer = createToolbarContainer();
app.getGuiNode().attachChild(toolbarContainer);
Button dice2Button = createDice2Button();
app.getGuiNode().attachChild(dice2Button);
// Neues Label mit Bild als Hintergrund
Label imageLabel = new Label("");
IconComponent imageIcon = new IconComponent("Pictures/CyanBackground.png");
imageIcon.setIconSize(new Vector2f(450, 200));
imageLabel.setIcon(imageIcon);
// Setze die Position des Labels
imageLabel.setLocalTranslation(20, 205, 0);
// Füge das Label zur GUI hinzu
app.getGuiNode().attachChild(imageLabel);
}
private Container createToolbarContainer() {
@@ -148,74 +131,66 @@ public class Toolbar extends Dialog implements GameEventListener {
Texture backgroundToolbar = app.getAssetManager().loadTexture("Pictures/toolbarbg.png");
QuadBackgroundComponent background = new QuadBackgroundComponent(backgroundToolbar);
container.setBackground(background);
// Spielerfarbe des aktuellen Spielers abrufen
// Spielerfarbe abrufen
Player currentPlayer = playerHandler.getPlayerById(app.getId());
PlayerColor currentPlayerColor = Player.getColor(currentPlayer.getId());
// Oberer Balken mit der Spielerfarbe
ColorRGBA playerColor = Player.getColor(currentPlayer.getId()).getColor();
// Oberer Balken
Container playerColorBar = new Container();
playerColorBar.setPreferredSize(new Vector3f(app.getCamera().getWidth(), 5, 0)); // Höhe des oberen Balkens
playerColorBar.setBackground(new QuadBackgroundComponent(currentPlayerColor.getColor())); // Use player color
playerColorBar.setLocalTranslation(0, 205, 3); // Position über der Toolbar
playerColorBar.setPreferredSize(new Vector3f(app.getCamera().getWidth(), 15, 0)); // Höhe des oberen Balkens
playerColorBar.setBackground(new QuadBackgroundComponent(playerColor));
playerColorBar.setLocalTranslation(0, 210, 3); // Position über der Toolbar
app.getGuiNode().attachChild(playerColorBar);
// Unterer Balken mit der Spielerfarbe
// unterer Balken
Container playerColorBarbot = new Container();
playerColorBarbot.setPreferredSize(new Vector3f(app.getCamera().getWidth(), 10, 0)); // Höhe des unteren Balkens
playerColorBarbot.setBackground(new QuadBackgroundComponent(currentPlayerColor.getColor())); // Use player color
playerColorBarbot.setLocalTranslation(0, 5, 3); // Position über der Toolbar
playerColorBarbot.setPreferredSize(new Vector3f(app.getCamera().getWidth(), 10, 0)); // Höhe des oberen Balkens
playerColorBarbot.setBackground(new QuadBackgroundComponent(playerColor));
playerColorBarbot.setLocalTranslation(0, 10, 3); // Position über der Toolbar
app.getGuiNode().attachChild(playerColorBarbot);
// Linker Balken mit der Spielerfarbe
// Linker Balken
Container leftBar = new Container();
leftBar.setPreferredSize(new Vector3f(5, 210, 0)); // Breite 5, Höhe 210
leftBar.setBackground(new QuadBackgroundComponent(currentPlayerColor.getColor())); // Use player color
leftBar.setPreferredSize(new Vector3f(10, 210, 0)); // Breite 10, Höhe 210
leftBar.setBackground(new QuadBackgroundComponent(playerColor));
leftBar.setLocalTranslation(0, 200, 3); // Position am linken Rand
app.getGuiNode().attachChild(leftBar);
// Rechter Balken mit der Spielerfarbe
// Rechter Balken
Container rightBar = new Container();
rightBar.setPreferredSize(new Vector3f(5, 210, 0)); // Breite 5, Höhe 210
rightBar.setBackground(new QuadBackgroundComponent(currentPlayerColor.getColor())); // Use player color
rightBar.setLocalTranslation(app.getCamera().getWidth() - 5, 200, 2); // Position am rechten Rand
rightBar.setPreferredSize(new Vector3f(10, 210, 0)); // Breite 10, Höhe 210
rightBar.setBackground(new QuadBackgroundComponent(playerColor));
rightBar.setLocalTranslation(app.getCamera().getWidth() - 10, 200, 2); // Position am rechten Rand
app.getGuiNode().attachChild(rightBar);
// Übersicht und Konto
accountContainer = container.addChild(new Container());
overviewContainer = container.addChild(new Container());
accountContainer.setBackground(new QuadBackgroundComponent(ColorRGBA.Yellow)); // Debug-Farbe
overviewContainer.setBackground(new QuadBackgroundComponent(ColorRGBA.Green)); // Debug-Farbe;
receivedEvent(new UpdatePlayerView()); // Initiale Aktualisierung
// Würfel-Bereich
container.addChild(createDiceSection());
// Aktionsmenü
Container menuContainer = container.addChild(new Container());
menuContainer.addChild(createTradeButton(currentPlayerColor));
menuContainer.addChild(createPropertyMenuButton(currentPlayerColor));
menuContainer.addChild(createEndTurnButton(currentPlayerColor));
menuContainer.addChild(createTradeButton());
menuContainer.addChild(createPropertyMenuButton());
menuContainer.addChild(createEndTurnButton());
menuContainer.setBackground(null);
return container;
}
private Container createDiceSection() {
Container diceContainer = new Container(new SpringGridLayout(Axis.X, Axis.Y));
diceContainer.addChild(createDiceDisplay());
diceContainer.setBackground(null);
diceButton = new Button("", new ElementId("button-toolbar2"));
diceButton.setPreferredSize(new Vector3f(200, 50, 10));
// Unsichtbaren Hintergrund setzen
QuadBackgroundComponent transparentBackground = new QuadBackgroundComponent(new ColorRGBA(0, 0, 0, 0.0f)); // Transparent
diceButton.setBackground(transparentBackground);
// Verschieben um 200 nach links
diceButton.setLocalTranslation(-200, 0, 0); // X: -200, Y: 0, Z: 0 (bleibt in derselben Höhe)
diceButton = new Button("Würfeln", new ElementId("button-toolbar"));
diceButton.setPreferredSize(new Vector3f(200, 50, 0));
diceButton.addClickCommands(s -> ifTopDialog(() -> {
diceButton.setEnabled(false);
endTurnButton.setEnabled(true);
@@ -224,32 +199,8 @@ public class Toolbar extends Dialog implements GameEventListener {
app.getGameLogic().playSound(Sound.BUTTON);
}));
diceContainer.addChild(diceButton);
return diceContainer;
}
private Button createDice2Button() {
// Erstelle den Button
Button dice2Button = new Button("", new ElementId("button-toolbar2"));
dice2Button.setPreferredSize(new Vector3f(300, 200, 10)); // Setze die Größe
// Setze einen unsichtbaren Hintergrund
QuadBackgroundComponent transparentBackground = new QuadBackgroundComponent(new ColorRGBA(0, 0, 0, 0.2f)); // Halbdurchsichtig
dice2Button.setBackground(transparentBackground);
// Positioniere den Button unabhängig
dice2Button.setLocalTranslation(500, 200, 8); // Setze X, Y, Z für eine feste Position
// Füge Klickverhalten hinzu
dice2Button.addClickCommands(s -> ifTopDialog(() -> {
dice2Button.setEnabled(false); // Deaktiviere den Button nach Klick
endTurnButton.setEnabled(true); // Aktiviere den EndTurn-Button
startDiceAnimation(); // Starte die Animation
app.getGameLogic().send(new RollDice()); // Sende die Nachricht
app.getGameLogic().playSound(Sound.BUTTON); // Spiele den Sound
}));
return dice2Button;
return diceContainer;
}
private Container createDiceDisplay() {
@@ -282,110 +233,71 @@ public class Toolbar extends Dialog implements GameEventListener {
return container;
}
private Button createTradeButton(PlayerColor playerColor) {
tradeButton = new Button("", new ElementId("button-toolbar2"));
tradeButton.setPreferredSize(new Vector3f(150, 50, 0)); // Größe setzen
// Setze den Hintergrund
QuadBackgroundComponent background = new QuadBackgroundComponent(playerColor.getColor());
Texture gradientTexture = app.getAssetManager().loadTexture("Textures/gradient.png");
if (gradientTexture != null) {
background.setTexture(gradientTexture);
}
tradeButton.setBackground(background);
// Icon hinzufügen
private Button createTradeButton() {
tradeButton = new Button("", new ElementId("button-toolbar"));
tradeButton.setPreferredSize(new Vector3f(150, 50, 0));
String iconTradePath = "icons/icon-handeln.png";
IconComponent iconTrade = new IconComponent(iconTradePath);
iconTrade.setHAlignment(HAlignment.Center);
iconTrade.setVAlignment(VAlignment.Center);
iconTrade.setIconSize(new Vector2f(100, 100));
tradeButton.setIcon(iconTrade);
// Klickverhalten
tradeButton.setFontSize(40);
// Add click behavior
tradeButton.addClickCommands(source -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
new ChoosePartner(app).open();
}));
return tradeButton;
}
private Button createPropertyMenuButton(PlayerColor playerColor) {
propertyMenuButton = new Button("", new ElementId("button-toolbar2"));
private Button createPropertyMenuButton() {
propertyMenuButton = new Button("", new ElementId("button-toolbar"));
propertyMenuButton.setPreferredSize(new Vector3f(150, 50, 0));
// Setze den Hintergrund
QuadBackgroundComponent background = new QuadBackgroundComponent(playerColor.getColor());
Texture gradientTexture = app.getAssetManager().loadTexture("Textures/gradient.png");
if (gradientTexture != null) {
background.setTexture(gradientTexture);
}
propertyMenuButton.setBackground(background);
// Icon hinzufügen
String iconBuildingPath = "icons/icon-gebaude.png";
IconComponent iconBuilding = new IconComponent(iconBuildingPath);
iconBuilding.setHAlignment(HAlignment.Center);
iconBuilding.setVAlignment(VAlignment.Center);
iconBuilding.setIconSize(new Vector2f(75, 75));
propertyMenuButton.setIcon(iconBuilding);
// Schriftgröße und Klick-Kommandos
propertyMenuButton.setFontSize(30);
propertyMenuButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
new BuildingAdminMenu(app).open();
}));
return propertyMenuButton;
}
private Button createEndTurnButton(PlayerColor playerColor) {
// Erstelle den Button
endTurnButton = new Button("", new ElementId("button-toolbar2"));
endTurnButton.setFontSize(28); // Setze die Schriftgröße
endTurnButton.setPreferredSize(new Vector3f(150, 50, 0)); // Setze die Größe
// Setze den Hintergrund
QuadBackgroundComponent background = new QuadBackgroundComponent(ColorRGBA.Gray); // Standardgrau
Texture gradientTexture = app.getAssetManager().loadTexture("Textures/gradient.png"); // Lade Gradient-Textur
if (gradientTexture != null) {
background.setTexture(gradientTexture); // Füge die Textur hinzu, wenn verfügbar
} else {
System.err.println("Gradient texture not found for EndTurn button!");
}
endTurnButton.setBackground(background);
// Füge das Icon hinzu
private Button createEndTurnButton() {
endTurnButton = new Button("", new ElementId("button-toolbar"));
endTurnButton.setFontSize(28);
endTurnButton.setPreferredSize(new Vector3f(150, 50, 0));
String iconEndTurnPath = "icons/icon-zugbeenden.png";
IconComponent iconEndTurn = new IconComponent(iconEndTurnPath);
iconEndTurn.setHAlignment(HAlignment.Center);
iconEndTurn.setVAlignment(VAlignment.Center);
iconEndTurn.setIconSize(new Vector2f(75, 75)); // Größe des Icons
iconEndTurn.setIconSize(new Vector2f(75, 75));
endTurnButton.setIcon(iconEndTurn);
// Klickverhalten für den Button
endTurnButton.addClickCommands(source -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON); // Spiele den Klick-Sound ab
Player currentPlayer = app.getGameLogic().getPlayerHandler().getPlayerById(app.getId());
// Überprüfe den Kontostand des Spielers
if (currentPlayer.getAccountBalance() < 0 && !bankruptPopUp) {
new Bankrupt(app).open(); // Öffne den Bankrott-Dialog
endTurnButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
if (app.getGameLogic().getPlayerHandler().getPlayerById(app.getId()).getAccountBalance() < 0 && !bankruptPopUp) {
new Bankrupt(app).open();
bankruptPopUp = true;
} else {
bankruptPopUp = false;
app.getGameLogic().send(new EndTurn()); // Sende EndTurn-Nachricht
receivedEvent(new ButtonStatusEvent(false)); // Aktualisiere die Button-Statusanzeige
app.getGameLogic().send(new EndTurn());
receivedEvent(new ButtonStatusEvent(false));
}
}));
// Debug-Log hinzufügen
System.out.println("End Turn Button created successfully.");
return endTurnButton;
}
@@ -487,13 +399,6 @@ public class Toolbar extends Dialog implements GameEventListener {
playerHandler.getPlayerById(app.getId()).getNumJailCard() + "",
new ElementId("label-account")
));
// Setze accountContainer auf Z-Ebene 2
accountContainer.setLocalTranslation(accountContainer.getLocalTranslation().x, accountContainer.getLocalTranslation().y, 5);
// Setze overviewContainer auf Z-Ebene 2
overviewContainer.setLocalTranslation(overviewContainer.getLocalTranslation().x, overviewContainer.getLocalTranslation().y, 5);
accountContainer.setBackground(null);
overviewContainer.addChild(new Label("Übersicht", new ElementId("label-toolbar")));
@@ -510,8 +415,6 @@ public class Toolbar extends Dialog implements GameEventListener {
// Farbe setzen
playerLabel.setColor(playerColor);
playerLabel.setFontSize(20);
// Label zum Container hinzufügen
overviewContainer.addChild(playerLabel);
@@ -528,18 +431,10 @@ public class Toolbar extends Dialog implements GameEventListener {
@Override
public void receivedEvent(ButtonStatusEvent event) {
boolean enabled = event.buttonsEnabled();
if (diceButton != null) {
diceButton.setEnabled(enabled);
}
if (tradeButton != null) {
tradeButton.setEnabled(enabled);
}
if (propertyMenuButton != null) {
propertyMenuButton.setEnabled(enabled);
}
if (endTurnButton != null) {
endTurnButton.setEnabled(false);
}
diceButton.setEnabled(enabled);
tradeButton.setEnabled(enabled);
propertyMenuButton.setEnabled(enabled);
endTurnButton.setEnabled(false);
}
/**

View File

@@ -40,8 +40,8 @@ public class BuyHouse extends Dialog {
/** Background container providing a border for the popup. */
private final Container backgroundContainer;
/** Label to display selected properties. */
private Label selectionDisplay;
/** TextField to display selected properties. */
private TextField selectionDisplay;
/** Reference for tracking dropdown selection changes. */
private VersionedReference<Set<Integer>> selectionRef;
@@ -162,7 +162,7 @@ public class BuyHouse extends Dialog {
selectionRef = propertySelector.getSelectionModel().createReference();
// Initialize the selection display here
selectionDisplay = new Label("");
selectionDisplay = new TextField(""); // Create TextField for displaying selections
selectionDisplay.setPreferredSize(new Vector3f(300, 30, 0));
dropdownContainer.addChild(selectionDisplay); // Add it to the dropdown container

View File

@@ -45,8 +45,8 @@ public class RepayMortage extends Dialog {
/** Background container providing a border for the popup. */
private final Container backgroundContainer;
/** Label to display selected properties. */
private Label selectionDisplay;
/** Text field to display selected properties. */
private TextField selectionDisplay;
/** Reference to track property selections in the dropdown menu. */
private VersionedReference<Set<Integer>> selectionRef;
@@ -166,7 +166,7 @@ public class RepayMortage extends Dialog {
selectionRef = propertySelector.getSelectionModel().createReference();
// Initialize the selection display here
selectionDisplay = new Label(""); // Create TextField for displaying selections
selectionDisplay = new TextField(""); // Create TextField for displaying selections
selectionDisplay.setPreferredSize(new Vector3f(300, 30, 0));
dropdownContainer.addChild(selectionDisplay); // Add it to the dropdown container

View File

@@ -45,8 +45,8 @@ public class SellHouse extends Dialog {
/** Background container providing a styled border around the main dialog. */
private final Container backgroundContainer;
/** Label to display selected properties. */
private Label selectionDisplay;
/** Text field to display selected properties. */
private TextField selectionDisplay;
/** Reference to track selection changes in the property selector. */
private VersionedReference<Set<Integer>> selectionRef;
@@ -86,7 +86,7 @@ public class SellHouse extends Dialog {
title.setFontSize(48);
title.setColor(ColorRGBA.Black);
//Unterteilung des sellHouseContainer in drei "Untercontainer"
//Unterteilund des sellHouseContainer in drei "Untercontainer"
Container upContainer = sellhouseContainer.addChild(new Container());
Container middleContainer = sellhouseContainer.addChild(new Container());
Container downContainer = sellhouseContainer.addChild(new Container());
@@ -172,7 +172,7 @@ public class SellHouse extends Dialog {
selectionRef = propertySelector.getSelectionModel().createReference();
// Initialize the selection display here
selectionDisplay = new Label("");
selectionDisplay = new TextField(""); // Create TextField for displaying selections
selectionDisplay.setPreferredSize(new Vector3f(300, 30, 0));
dropdownContainer.addChild(selectionDisplay); // Add it to the dropdown container

View File

@@ -46,8 +46,8 @@ public class TakeMortage extends Dialog {
/** Background container providing a styled border around the main dialog. */
private final Container backgroundContainer;
/** Label to display selected properties. */
private Label selectionDisplay;
/** Text field to display selected properties. */
private TextField selectionDisplay;
/** Reference to track selection changes in the property selector. */
private VersionedReference<Set<Integer>> selectionRef;
@@ -172,7 +172,7 @@ public class TakeMortage extends Dialog {
selectionRef = propertySelector.getSelectionModel().createReference();
// Initialize the selection display here
selectionDisplay = new Label(""); // Create TextField for displaying selections
selectionDisplay = new TextField(""); // Create TextField for displaying selections
selectionDisplay.setPreferredSize(new Vector3f(300, 30, 0));
dropdownContainer.addChild(selectionDisplay); // Add it to the dropdown container

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 KiB

View File

@@ -1,4 +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}.
@@ -19,4 +24,17 @@ public class ActiveState extends ClientState {
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) {
}
}

View File

@@ -5,8 +5,6 @@ import java.lang.System.Logger.Level;
import java.util.ArrayList;
import java.util.List;
import com.jme3.math.Vector3f;
import pp.monopoly.game.server.Player;
import pp.monopoly.game.server.PlayerHandler;
import pp.monopoly.message.client.ClientMessage;
@@ -26,10 +24,8 @@ 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.Figure;
import pp.monopoly.model.Hotel;
import pp.monopoly.model.House;
import pp.monopoly.model.Rotation;
import pp.monopoly.model.TradeHandler;
import pp.monopoly.model.fields.BoardManager;
import pp.monopoly.model.fields.BuildingProperty;
@@ -235,7 +231,7 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker {
playerHandler = msg.getPlayerHandler();
setState(new WaitForTurnState(this));
for (Player player : playerHandler.getPlayers()) {
board.add(new Figure(Vector3f.ZERO, Rotation.NORTH, player.getFigure()));
board.add(player.getFigure());
}
notifyListeners(new ButtonStatusEvent(false));
notifyListeners(new UpdatePlayerView());

View File

@@ -23,6 +23,7 @@ import pp.monopoly.message.server.NextPlayerTurn;
import pp.monopoly.message.server.NotificationMessage;
import pp.monopoly.message.server.PlayerStatusUpdate;
import pp.monopoly.model.FieldVisitor;
import pp.monopoly.model.Figure;
import pp.monopoly.model.card.Card;
import pp.monopoly.model.fields.BuildingProperty;
import pp.monopoly.model.fields.EventField;
@@ -43,7 +44,7 @@ public class Player implements FieldVisitor<Void>{
private final int id;
private String name;
private int accountBalance = 15000;
private String figure;
private Figure figure;
private Set<Integer> properties = new HashSet<>();
private int getOutOfJailCard;
private int fieldID;
@@ -81,19 +82,11 @@ public class Player implements FieldVisitor<Void>{
this.handler = handler;
}
/**
* Set the figure of the player
* @param figure the figure to be set
*/
public void setFigure(String figure) {
public void setFigure(Figure figure) {
this.figure = figure;
}
/**
* Returns the figure of the player
* @return the figure of the player
*/
public String getFigure() {
public Figure getFigure(){
return figure;
}
@@ -187,6 +180,7 @@ public class Player implements FieldVisitor<Void>{
earnMoney(2000); // Passing GO gives money
}
fieldID = (fieldID + steps) % 40;
figure.moveTo(fieldID);
handler.getLogic().send(this, new PlayerStatusUpdate(handler));
handler.getLogic().getBoardManager().getFieldAtIndex(fieldID).accept(this);
return fieldID;
@@ -200,6 +194,7 @@ public class Player implements FieldVisitor<Void>{
public int setPosition(int position){
if(position < 40 && position >= 0) {
fieldID = position;
figure.moveTo(fieldID);
handler.getLogic().send(this, new PlayerStatusUpdate(handler));
handler.getLogic().getBoardManager().getFieldAtIndex(fieldID).accept(this);
}
@@ -217,6 +212,7 @@ public class Player implements FieldVisitor<Void>{
earnMoney(2000);
}
fieldID = position;
figure.moveTo(fieldID);
handler.getLogic().send(this, new PlayerStatusUpdate(handler));
handler.getLogic().getBoardManager().getFieldAtIndex(fieldID).accept(this);
}

View File

@@ -3,9 +3,11 @@ package pp.monopoly.game.server;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import java.util.HashSet;
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;
@@ -27,6 +29,8 @@ import pp.monopoly.message.server.ServerMessage;
import pp.monopoly.message.server.TradeReply;
import pp.monopoly.message.server.TradeRequest;
import pp.monopoly.message.server.ViewAssetsResponse;
import pp.monopoly.model.Figure;
import pp.monopoly.model.Rotation;
import pp.monopoly.model.TradeHandler;
import pp.monopoly.model.card.DeckHelper;
import pp.monopoly.model.fields.BoardManager;
@@ -219,7 +223,8 @@ public class ServerGameLogic implements ClientInterpreter {
String name = msg.getName();
String truc = name.length() > 10 ? name.substring(0, 15) : name;
player.setName(truc);
player.setFigure(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());