26 Commits

Author SHA1 Message Date
Johannes Schmelz
4ecccc5951 Merge branch 'gui' into 'connect'
# Conflicts:
#   Projekte/monopoly/client/src/main/java/pp/monopoly/client/MonopolyApp.java
#   Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/LobbyMenu.java
#   Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/popups/BuildingPropertyCard.java
#   Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/popups/BuyCard.java
#   Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/popups/FoodFieldCard.java
#   Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/popups/GateFieldCard.java
#   Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/popups/WinnerPopUp.java
#   Projekte/monopoly/model/src/main/java/pp/monopoly/game/client/ClientGameLogic.java
2024-11-25 02:45:02 +00:00
Johannes Schmelz
f90ce5aa81 all button sounds now 2024-11-25 03:35:32 +01:00
Yvonne Schmidt
4a9eba255b restyled selector 2024-11-25 03:24:00 +01:00
Johannes Schmelz
4713a526b3 Merge branch 'connect' of https://athene2.informatik.unibw-muenchen.de/progproj/gruppen-ht24/Gruppe-02 into connect 2024-11-25 03:08:01 +01:00
Johannes Schmelz
362c0e5679 added serialisables 2024-11-25 03:07:57 +01:00
Yvonne Schmidt
fab2457715 added header to CreateGameMenu 2024-11-25 02:51:43 +01:00
Yvonne Schmidt
7b3f31f099 Merge remote-tracking branch 'origin/connect' into connect
# Conflicts:
#	Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CreateGameMenu.java
2024-11-25 02:48:26 +01:00
Johannes Schmelz
ed105f1b70 cleanup 2024-11-25 02:43:58 +01:00
Yvonne Schmidt
cd4331aee3 added header to CreateGameMenu 2024-11-25 02:43:08 +01:00
Simon Wilkening
687d1621fc EventCard erweitert 2024-11-25 00:06:12 +01:00
Johannes Schmelz
a6944aa6e3 added dice images 2024-11-24 23:38:22 +01:00
Johannes Schmelz
b8365c76a1 fix mac executable 2024-11-24 22:58:47 +01:00
Johannes Schmelz
19216cc174 refactor 2024-11-24 22:57:19 +01:00
Johannes Schmelz
c6a23b9b8e execute for apple 2024-11-24 22:56:52 +01:00
Johannes Schmelz
c0f42fb1eb refactor 2024-11-24 22:50:52 +01:00
Tamino Mueller
160873e2cc added pictures and popups fixed 2024-11-24 22:42:32 +01:00
Tamino Mueller
8df859bbef Merge remote-tracking branch 'origin/gui' into gui 2024-11-24 22:34:54 +01:00
Tamino Mueller
e30d10a85d Pop-Up hinzugefügt 2024-11-24 22:34:19 +01:00
Yvonne Schmidt
bafc3f1db6 Merge remote-tracking branch 'origin/gui' into gui 2024-11-24 19:25:12 +01:00
Yvonne Schmidt
03571fcf74 code cleanup in der lobby 2024-11-24 19:24:51 +01:00
Johannes Schmelz
e7a6802488 fixed buyProperty 2024-11-24 19:14:56 +01:00
Yvonne Schmidt
a6e6b5e158 lobby übergibt figur 2024-11-24 19:05:28 +01:00
Simon Wilkening
74c3d925e6 TODOs und Kommentare ergänst 2024-11-24 19:04:58 +01:00
Yvonne Schmidt
f67fa4d7f0 lobby übergibt namen 2024-11-24 18:39:32 +01:00
Simon Wilkening
225a8c0e08 BuildingPropertyCard adjusted 2024-11-24 18:11:42 +01:00
Yvonne Schmidt
9a6ce27fe1 lobby uebergibt farbe und startgeld 2024-11-24 18:07:39 +01:00
28 changed files with 417 additions and 96 deletions

View File

@@ -0,0 +1,18 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="MonopolyApp (Mac)" type="Application" factoryName="Application"
singleton="false">
<option name="MAIN_CLASS_NAME" value="pp.monopoly.client.MonopolyApp"/>
<module name="Projekte.monopoly.client.main"/>
<option name="VM_PARAMETERS" value="-XstartOnFirstThread"/>
<option name="WORKING_DIRECTORY" value="$MODULE_WORKING_DIR$"/>
<extension name="coverage">
<pattern>
<option name="PATTERN" value="pp.monopoly.client.*"/>
<option name="ENABLED" value="true"/>
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true"/>
</method>
</configuration>
</component>

View File

@@ -28,6 +28,7 @@ import pp.monopoly.game.client.ServerConnection;
import pp.monopoly.notification.ClientStateEvent;
import pp.monopoly.notification.GameEventListener;
import pp.monopoly.notification.InfoTextEvent;
import pp.monopoly.notification.Sound;
import pp.dialog.DialogBuilder;
import pp.dialog.DialogManager;
import pp.graphics.Draw;
@@ -228,6 +229,7 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
private void setupGui() {
GuiGlobals.initialize(this);
BaseStyles.loadStyleResources(STYLES_SCRIPT);
BaseStyles.loadGlassStyle();
GuiGlobals.getInstance().getStyles().setDefaultStyle("pp"); //NON-NLS
final BitmapFont normalFont = assetManager.loadFont(FONT); //NON-NLS
topText = new BitmapText(normalFont);
@@ -415,8 +417,11 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
DialogBuilder.simple(dialogManager)
.setTitle(lookup("dialog.question"))
.setText(question)
.setOkButton(lookup("button.yes"), yesAction)
.setNoButton(lookup("button.no"))
.setOkButton(lookup("button.yes"), d -> {
getGameLogic().playSound(Sound.BUTTON); // Play sound
yesAction.run(); // Execute the original yesAction
})
.setNoButton(lookup("button.no"), d -> getGameLogic().playSound(Sound.BUTTON))
.build()
.open();
}
@@ -430,7 +435,7 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
DialogBuilder.simple(dialogManager)
.setTitle(lookup("dialog.error"))
.setText(errorMessage)
.setOkButton(lookup("button.ok"))
.setOkButton(lookup("button.ok"), d -> getGameLogic().playSound(Sound.BUTTON))
.build()
.open();
}

View File

@@ -25,6 +25,7 @@ import com.simsilica.lemur.component.SpringGridLayout;
import static pp.monopoly.Resources.lookup;
import com.simsilica.lemur.style.ElementId;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.client.NetworkSupport;
import pp.monopoly.notification.Sound;
@@ -65,7 +66,7 @@ public class CreateGameMenu extends Dialog {
final MonopolyApp app = network.getApp();
int screenWidth = app.getContext().getSettings().getWidth();
int screenWidth = app.getContext().getSettings().getWidth();
int screenHeight = app.getContext().getSettings().getHeight();
// Set up the background image
@@ -78,7 +79,7 @@ public class CreateGameMenu extends Dialog {
background.setLocalTranslation(0, 0, -1); // Ensure it is behind other GUI elements
app.getGuiNode().attachChild(background);
addChild(new Label("Spiel erstellen", new ElementId("header"))); //NON-NLS
final Container input = new Container(new SpringGridLayout());
input.addChild(new Label(lookup("host.name") + ": "));
input.addChild(host, 1);
@@ -88,27 +89,27 @@ public class CreateGameMenu extends Dialog {
addChild(input);
// "Abbrechen"-Button
cancelButton.setPreferredSize(new Vector3f(120, 40, 0));
cancelButton.addClickCommands(source -> close());
addChild(cancelButton);
cancelButton.addClickCommands(s -> ifTopDialog(() -> {
this.close();
new StartMenu(app);
app.getGameLogic().playSound(Sound.BUTTON);
this.close();
new StartMenu(network.getApp()).open();
}));
addChild(cancelButton);
// "Selber hosten"-Button
addChild(serverButton).addClickCommands(s -> ifTopDialog(() -> {
serverButton.addClickCommands(s -> ifTopDialog( () -> {
network.getApp().getGameLogic().playSound(Sound.BUTTON);
startServerInThread();
app.getGameLogic().playSound(Sound.BUTTON);
}));
} ));
addChild(serverButton);
// "Beitreten"-Button
joinButton.setPreferredSize(new Vector3f(120, 40, 0));
addChild(joinButton);
joinButton.addClickCommands(s -> ifTopDialog(() -> {
connect();
joinButton.addClickCommands(s -> ifTopDialog( () -> {
app.getGameLogic().playSound(Sound.BUTTON);
connect();
}));
addChild(joinButton);
}
/**
@@ -155,7 +156,7 @@ public class CreateGameMenu extends Dialog {
@Override
public void escape() {
close();
new SettingsMenu(network.getApp()).open();
}
/**
@@ -218,7 +219,6 @@ public class CreateGameMenu extends Dialog {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
connect();

View File

@@ -38,6 +38,13 @@ public class LobbyMenu extends Dialog {
private Geometry circle;
private Container lowerLeftMenu;
private Container lowerRightMenu;
private ColorRGBA playerColor= ColorRGBA.Gray;
private PlayerHandler playerHandler;
private TextField startingCapital;
private TextField playerInputField;
private Selector<String> figureDropdown;
private TextField playerInputField = new TextField("Spieler 1");
private TextField startingCapital = new TextField("15000");
@@ -47,19 +54,20 @@ public class LobbyMenu extends Dialog {
super(app.getDialogManager());
this.app = app;
// Hintergrundbild laden und hinzufügen
addBackgroundImage();
app.getGuiNode().detachAllChildren(); // Entfernt das CreateGameMenu (inklusive Hintergrund)
addBackgroundImage();// Hintergrundbild laden und hinzufügen
QuadBackgroundComponent translucentWhiteBackground =
new QuadBackgroundComponent(new ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f));
menuContainer = new Container(new SpringGridLayout(Axis.Y, Axis.X));
menuContainer.setPreferredSize(new Vector3f(1000, 600, 0)); // Fixed size of the container
menuContainer.setPreferredSize(new Vector3f(1000, 600, 0));
menuContainer.setBackground(translucentWhiteBackground);
// Create a smaller horizontal container for the label, input field, and spacers
Container horizontalContainer = menuContainer.addChild(new Container(new SpringGridLayout(Axis.X, Axis.Y)));
horizontalContainer.setPreferredSize(new Vector3f(600, 40, 0)); // Adjust container size
horizontalContainer.setPreferredSize(new Vector3f(600, 40, 0));
horizontalContainer.setBackground(null);
Label title = horizontalContainer.addChild(new Label("Startkapital:", new ElementId("label-Bold")));
@@ -98,15 +106,16 @@ public class LobbyMenu extends Dialog {
playerInputField.setPreferredSize(new Vector3f(100, 20, 0));
playerInputField.setInsets(new Insets3f(5, 10, 5, 10)); // Add padding for the text inside the field
playerInputField.setInsets(new Insets3f(5, 10, 5, 10));
playerInputField.setBackground(new QuadBackgroundComponent(ColorRGBA.Black));
playerInputContainer.addChild(playerInputField);
// Spacer (Center Circle Area)
Label spacer = dropdownContainer.addChild(new Label(""));
spacer.setPreferredSize(new Vector3f(200, 200, 0)); // Adjust this to fit the center graphic
spacer.setPreferredSize(new Vector3f(200, 200, 0));
// Figur Dropdown
Container figureDropdownContainer = dropdownContainer.addChild(new Container(new SpringGridLayout(Axis.Y, Axis.X)));
figureDropdownContainer.setPreferredSize(new Vector3f(150, 80, 0));
figureDropdownContainer.addChild(new Label("Figur:"));
figureDropdownContainer.setBackground(null);
@@ -120,7 +129,11 @@ public class LobbyMenu extends Dialog {
Selector<String> figureDropdown = new Selector<>(figures, "glass");
figureDropdown.setBackground(new QuadBackgroundComponent(ColorRGBA.DarkGray));
figureDropdown.setPreferredSize(new Vector3f(100, 20, 0));
figureDropdown.setPreferredSize(new Vector3f(150, 140, 0));
Vector3f dimens = figureDropdownContainer.getPreferredSize();
Vector3f dimens2 = figureDropdown.getPopupContainer().getPreferredSize();
dimens2.setX( dimens.getX() );
figureDropdown.getPopupContainer().setPreferredSize( dimens2 );
figureDropdownContainer.addChild(figureDropdown);
addSelectionActionListener(figureDropdown, this::onDropdownSelectionChanged);
@@ -131,11 +144,11 @@ public class LobbyMenu extends Dialog {
buttonContainer.setBackground(null);
// Lower-left container for "Abbrechen" button
lowerLeftMenu = new Container();
Button cancelButton = new Button("Abbrechen");
Button cancelButton = new Button("Beenden");
cancelButton.setPreferredSize(new Vector3f(200, 60, 0)); // Set size to match the appearance in the image
cancelButton.setFontSize(18); // Adjust font size
cancelButton.addClickCommands(s -> ifTopDialog(() -> {
this.close();
app.closeApp();
app.getGameLogic().playSound(Sound.BUTTON);
}));
lowerLeftMenu.addChild(cancelButton);
@@ -155,13 +168,14 @@ public class LobbyMenu extends Dialog {
app.getGameLogic().playSound(Sound.BUTTON);
}));
lowerRightMenu.addChild(readyButton);
//TODO aktivieren des Spielers in den ready Status und Sprung in den nächsten Menüzustand
// Position the container near the bottom-right corner
lowerRightMenu.setLocalTranslation(new Vector3f(app.getCamera().getWidth() - 320, 170, 3)); // X: 220px from the right, Y: 50px above the bottom
app.getGuiNode().attachChild(lowerRightMenu);
// Add a colored circle between the input field and the dropdown menu
circle = createCircle( ColorRGBA.Red); // 50 is the diameter, Red is the color
circle = createCircle(); // 50 is the diameter, Red is the color
circle.setLocalTranslation(new Vector3f(
(app.getCamera().getWidth()) / 2, // Center horizontally
(app.getCamera().getHeight() / 2) - 90, // Adjust Y position
@@ -178,7 +192,59 @@ public class LobbyMenu extends Dialog {
app.getGuiNode().attachChild(menuContainer);
}
/**
* Apply the starting capital only if the current player is the host.
*/
private void applyStartingCapital(int playerID) {
Player currentPlayer = playerHandler.getPlayerById(playerID);
// Check if the current player is the host
if (currentPlayer.equals(playerHandler.getHostPlayer())) {
try {
// Parse and validate starting capital
int startBalance = Integer.parseInt(startingCapital.getText().replaceAll("[^\\d]", ""));
if (startBalance < 0) throw new NumberFormatException("Starting capital must be positive.");
// Apply the starting balance to all players
playerHandler.setStartBalance(startBalance);
System.out.println("Starting balance set to: " + startBalance);
} catch (NumberFormatException e) {
System.err.println("Invalid starting capital: " + e.getMessage());
}
} else {
System.out.println("Only the host can set the starting balance.");
}
}
/**
* Apply the player name from the input field.
*/
private void applyPlayerName(int playerID) {
Player currentPlayer = playerHandler.getPlayerById(playerID);
String playerName = playerInputField.getText().trim();
if (!playerName.isEmpty()) {
currentPlayer.setName(playerName);
System.out.println("Player name set to: " + playerName);
} else {
System.err.println("Invalid player name: Name cannot be empty.");
}
}
/**
* Apply the selected figure to the player.
*/
private void applyFigure(int playerID) {
Player currentPlayer = playerHandler.getPlayerById(playerID);
String selectedFigure = figureDropdown.getSelectedItem();
if (selectedFigure != null && !selectedFigure.isEmpty()) {
currentPlayer.setFigure(new Figure(0, 0, 0, Rotation.RIGHT, "selectedFigure"));
System.out.println("Player figure set to: " + selectedFigure);
} else {
System.err.println("Invalid figure selection.");
}
}
/**
* Lädt das Hintergrundbild und fügt es als geometrische Ebene hinzu.
@@ -195,21 +261,32 @@ public class LobbyMenu extends Dialog {
app.getGuiNode().attachChild(background);
}
private Geometry createCircle(ColorRGBA color) {
private Geometry createCircle() {
Sphere sphere = new Sphere(90,90,60.0f);
Geometry circleGeometry = new Geometry("Circle", sphere);
// Create a material with a solid color
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", color); // Set the desired color
material.setColor("Color", playerColor); // Set the desired color
circleGeometry.setMaterial(material);
return circleGeometry;
}
public void setPlayerColor(ColorRGBA newColor) {
this.playerColor = newColor;
// Update the circle's color
if (circle != null) {
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", playerColor);
circle.setMaterial(material);
}
}
/**
* Schaltet den "Bereit"-Status um.
* Assigns a color to the player based on their ID.
*
* @param playerID the player's ID
*/
private void toggleReady() {
app.getGameLogic().send(new PlayerReady(true, playerInputField.getText(), figure, Integer.parseInt(startingCapital.getText())));
@@ -217,7 +294,7 @@ public class LobbyMenu extends Dialog {
@Override
public void escape() {
super.close();
new SettingsMenu(app).open();
}
/**

View File

@@ -1,7 +1,6 @@
package pp.monopoly.client.gui;
import com.simsilica.lemur.Slider;
import pp.monopoly.client.GameMusic;
import pp.monopoly.client.GameSound;
public class SoundSlider extends Slider {

View File

@@ -22,8 +22,6 @@ import pp.monopoly.client.gui.GameMenu;
*/
public class StartMenu extends Dialog {
private final MonopolyApp app;
private Container logoContainer;
private Container unibwLogoContainer;
/**
* Constructs the Startup Menu dialog for the Monopoly application.

View File

@@ -23,7 +23,7 @@ public class BuildingPropertyCard extends Dialog {
private final Geometry overlayBackground;
private final Container buildingPropertyContainer;
private final Container backgroundContainer;
private int index = 39;
private int index = 37;
public BuildingPropertyCard(MonopolyApp app) {
super(app.getDialogManager());
@@ -121,8 +121,8 @@ public class BuildingPropertyCard extends Dialog {
app.getGuiNode().detachChild(buildingPropertyContainer); // Entferne das Menü
app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand
app.getGuiNode().detachChild(overlayBackground); // Entferne das Overlay
// app.setSettingsMenuOpen(false); // Menü als geschlossen markieren
// app.unblockInputs(); // Eingaben wieder aktivieren
app.setSettingsMenuOpen(false); // Menü als geschlossen markieren TODO passt diese Variable noch (zu finden unter den Temps in MonopolyApp
app.unblockInputs(); // Eingaben wieder aktivieren
System.out.println("SettingsMenu geschlossen."); // Debugging-Ausgabe
}

View File

@@ -3,14 +3,16 @@ package pp.monopoly.client.gui.popups;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.*;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.model.fields.BuildingProperty;
/**
* SettingsMenu ist ein Overlay-Menü, das durch ESC aufgerufen werden kann.
@@ -18,13 +20,18 @@ import pp.monopoly.client.MonopolyApp;
public class BuyCard extends Dialog {
private final MonopolyApp app;
private final Geometry overlayBackground;
private final Container settingsContainer;
private final Container buyCardContainer;
private final Container backgroundContainer;
private int index = 37;
public BuyCard(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
//Generate the corresponfing field
BuildingProperty field = (BuildingProperty) app.getBoardManager().getFieldAtIndex(index);
// Halbtransparentes Overlay hinzufügen
overlayBackground = createOverlayBackground();
app.getGuiNode().attachChild(overlayBackground);
@@ -34,52 +41,55 @@ public class BuyCard extends Dialog {
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Darker background
app.getGuiNode().attachChild(backgroundContainer);
// Hauptcontainer für das Menü
settingsContainer = new Container();
settingsContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.1f, 0.1f, 0.1f, 0.9f)));
// Hauptcontainer für die Gebäudekarte
buyCardContainer = new Container();
buyCardContainer.setBackground(new QuadBackgroundComponent(field.getColor().getColor()));
// Titel
Label settingsTitle = settingsContainer.addChild(new Label("Gebäude 30", new ElementId("settings-title"))); //TODO Dynamische Gebäudezahl einfügen
Label settingsTitle = buyCardContainer.addChild(new Label( field.getName(), new ElementId("settings-title")));
settingsTitle.setFontSize(48);
int i = 0;
int a = 10;
int b = -45;
// Effekt-Sound: Slider und Checkbox
Container propertyValuesContainer = settingsContainer.addChild(new Container());
propertyValuesContainer.addChild(new Label("Preis:" + i, new ElementId("label-Text")));//TODO Variable hier einsetzen
propertyValuesContainer.addChild(new Label("Miete:" + a, new ElementId("label-Text")));//TODO Variable hier einsetzen
propertyValuesContainer.addChild(new Label("Hypothek:" + b, new ElementId("label-Text")));//TODO Variable hier einsetzen
// Text, der auf der Karte steht
// Die Preise werden dynamisch dem BoardManager entnommen
Container propertyValuesContainer = buyCardContainer.addChild(new Container());
propertyValuesContainer.addChild(new Label("„Grundstückswert: " + field.getPrice() + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile
propertyValuesContainer.addChild(new Label("„Miete allein: " + field.getAllRent().get(0)+ " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("-mit 1 Haus: " + field.getAllRent().get(1) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("-mit 2 Häuser: " + field.getAllRent().get(2) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("-mit 3 Häuser: " + field.getAllRent().get(3) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„-mit 4 Häuser: " + field.getAllRent().get(4) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„-mit 1 Hotel: " + field.getAllRent().get(5) + " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("„-1 Haus kostet: " + field.getHousePrice()+ " EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile
propertyValuesContainer.addChild(new Label("„Hypothek: " + field.getHypo() + " EUR", new ElementId("label-Text")));
propertyValuesContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
// Beenden-Button
Button quitButton = settingsContainer.addChild(new Button("Beenden", new ElementId("button")));
Button quitButton = buyCardContainer.addChild(new Button("Beenden", new ElementId("button")));
quitButton.setFontSize(32);
// Kaufen-Button
Button buyButton = settingsContainer.addChild(new Button("Kaufen", new ElementId("button")));
Button buyButton = buyCardContainer.addChild(new Button("Kaufen", new ElementId("button")));
buyButton.setFontSize(32);
float padding = 10; // Padding around the settingsContainer for the background
backgroundContainer.setPreferredSize(settingsContainer.getPreferredSize().addLocal(padding, padding, 0));
backgroundContainer.setPreferredSize(buyCardContainer.getPreferredSize().addLocal(padding, padding, 0));
// Zentriere das Menü
settingsContainer.setLocalTranslation(
(app.getCamera().getWidth() - settingsContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + settingsContainer.getPreferredSize().y) / 2,
buyCardContainer.setLocalTranslation(
(app.getCamera().getWidth() - buyCardContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + buyCardContainer.getPreferredSize().y) / 2,
8
);
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - settingsContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + settingsContainer.getPreferredSize().y+ padding) / 2,
(app.getCamera().getWidth() - buyCardContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + buyCardContainer.getPreferredSize().y+ padding) / 2,
7
);
app.getGuiNode().attachChild(settingsContainer);
app.getGuiNode().attachChild(buyCardContainer);
}
/**
@@ -104,13 +114,11 @@ public class BuyCard extends Dialog {
@Override
public void close() {
System.out.println("Schließe SettingsMenu..."); // Debugging-Ausgabe
app.getGuiNode().detachChild(settingsContainer); // Entferne das Menü
app.getGuiNode().detachChild(buyCardContainer); // Entferne das Menü
app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand
app.getGuiNode().detachChild(overlayBackground); // Entferne das Overlay
// app.setSettingsMenuOpen(false); // Menü als geschlossen markieren
// app.unblockInputs(); // Eingaben wieder aktivieren
app.setSettingsMenuOpen(false); // Menü als geschlossen markieren TODO passt diese Variable noch (zu finden unter den Temps in MonopolyApp
app.unblockInputs(); // Eingaben wieder aktivieren
System.out.println("SettingsMenu geschlossen."); // Debugging-Ausgabe
}
}

View File

@@ -0,0 +1,118 @@
package pp.monopoly.client.gui.popups;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.model.card.Card; // TODO für den Import der Queue notwendig
/**
* SettingsMenu ist ein Overlay-Menü, das durch ESC aufgerufen werden kann.
*/
public class EventCard extends Dialog {
private final MonopolyApp app;
private final Geometry overlayBackground;
private final Container eventCardContainer;
private final Container backgroundContainer;
public EventCard(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
//Generate the corresponfing field
Card card = app.getDeckHelper().drawCard(); // TODO nimmt die Karten gerade unabhängig aus dem DeckHelper
// Halbtransparentes Overlay hinzufügen
overlayBackground = createOverlayBackground();
app.getGuiNode().attachChild(overlayBackground);
// Create the background container
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Darker background
app.getGuiNode().attachChild(backgroundContainer);
// Hauptcontainer für die Gebäudekarte
eventCardContainer = new Container();
eventCardContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f)));
// Titel
// Die Namen werden dynamisch dem BoardManager entnommen
Label gateFieldTitle = eventCardContainer.addChild(new Label("Ereigniskarte", new ElementId("settings-title")));
gateFieldTitle.setFontSize(48);
gateFieldTitle.setColor(ColorRGBA.Black);
// Text, der auf der Karte steht
// Die Preise werden dynamisch dem BoardManager entnommen
Container propertyValuesContainer = eventCardContainer.addChild(new Container());
propertyValuesContainer.addChild(new Label(card.getDescription(), new ElementId("label-Text")));
propertyValuesContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
// Beenden-Button
Button quitButton = eventCardContainer.addChild(new Button("Jawohl", new ElementId("button")));
quitButton.setFontSize(32);
quitButton.addClickCommands(source -> close());
// TODO Kaufen-Button wird nicht mehr benötigt, prüfen ob weg kann
//Button buyButton = buyCardContainer.addChild(new Button("Kaufen", new ElementId("button")));
//buyButton.setFontSize(32);
float padding = 10; // Padding around the settingsContainer for the background
backgroundContainer.setPreferredSize(eventCardContainer.getPreferredSize().addLocal(padding, padding, 0));
// Zentriere das Menü
eventCardContainer.setLocalTranslation(
(app.getCamera().getWidth() - eventCardContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + eventCardContainer.getPreferredSize().y) / 2,
8
);
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - eventCardContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + eventCardContainer.getPreferredSize().y+ padding) / 2,
7
);
app.getGuiNode().attachChild(eventCardContainer);
}
/**
* Erstellt einen halbtransparenten Hintergrund für das Menü.
*
* @return Geometrie des Overlays
*/
private Geometry createOverlayBackground() {
Quad quad = new Quad(app.getCamera().getWidth(), app.getCamera().getHeight());
Geometry overlay = new Geometry("Overlay", quad);
Material material = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
material.setColor("Color", new ColorRGBA(0, 0, 0, 0.5f)); // Halbtransparent
material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
overlay.setMaterial(material);
overlay.setLocalTranslation(0, 0, 0);
return overlay;
}
/**
* Schließt das Menü und entfernt die GUI-Elemente.
*/
@Override
public void close() {
System.out.println("Schließe SettingsMenu..."); // Debugging-Ausgabe
app.getGuiNode().detachChild(eventCardContainer); // Entferne das Menü
app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand
app.getGuiNode().detachChild(overlayBackground); // Entferne das Overlay
app.setBuyCardPopupOpen(false); // Menü als geschlossen markieren TODO passt diese Variable noch (zu finden unter den Temps in MonopolyApp
app.unblockInputs(); // Eingaben wieder aktivieren
System.out.println("SettingsMenu geschlossen."); // Debugging-Ausgabe
}
}

View File

@@ -5,7 +5,6 @@ import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Quad;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.QuadBackgroundComponent;
@@ -125,8 +124,8 @@ public class FoodFieldCard extends Dialog {
app.getGuiNode().detachChild(foodFieldContainer); // Entferne das Menü
app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand
app.getGuiNode().detachChild(overlayBackground); // Entferne das Overlay
// app.setSettingsMenuOpen(false); // Menü als geschlossen markieren
// app.unblockInputs(); // Eingaben wieder aktivieren
app.setSettingsMenuOpen(false); // Menü als geschlossen markieren TODO passt diese Variable noch (zu finden unter den Temps in MonopolyApp
app.unblockInputs(); // Eingaben wieder aktivieren
System.out.println("SettingsMenu geschlossen."); // Debugging-Ausgabe
}

View File

@@ -45,9 +45,9 @@ public class GateFieldCard extends Dialog {
// Titel
// Die Namen werden dynamisch dem BoardManager entnommen
Label settingsTitle = gateFieldContainer.addChild(new Label(field.getName(), new ElementId("settings-title")));
settingsTitle.setFontSize(48);
settingsTitle.setColor(ColorRGBA.Black);
Label gateFieldTitle = gateFieldContainer.addChild(new Label(field.getName(), new ElementId("settings-title")));
gateFieldTitle.setFontSize(48);
gateFieldTitle.setColor(ColorRGBA.Black);
// Text, der auf der Karte steht
// Die Preise werden dynamisch dem BoardManager entnommen
@@ -118,8 +118,8 @@ public class GateFieldCard extends Dialog {
app.getGuiNode().detachChild(gateFieldContainer); // Entferne das Menü
app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand
app.getGuiNode().detachChild(overlayBackground); // Entferne das Overlay
// app.setSettingsMenuOpen(false); // Menü als geschlossen markieren
// app.unblockInputs(); // Eingaben wieder aktivieren
app.setSettingsMenuOpen(false); // Menü als geschlossen markieren TODO passt diese Variable noch (zu finden unter den Temps in MonopolyApp
app.unblockInputs(); // Eingaben wieder aktivieren
System.out.println("SettingsMenu geschlossen."); // Debugging-Ausgabe
}

View File

@@ -0,0 +1,55 @@
package pp.monopoly.client.gui.popups;
import com.jme3.asset.TextureKey;
import com.jme3.math.Vector2f;
import com.jme3.texture.Texture;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.IconComponent;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
public class LoserPopUp extends Dialog {
private final MonopolyApp app;
/**
* Constructs a new NetworkDialog.
*
* @param network The NetworkSupport instance to be used for network operations.
*/
public LoserPopUp(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
initializeDialog();
}
/**
* Initializes the dialog with input fields and connection buttons.
*/
private void initializeDialog() {
Container inputContainer = new Container();
// Titel und Eingabefelder für Host und Port
inputContainer.addChild(new Label("Schade, du hast leider verloren!"));
inputContainer.addChild(new Label("Die nächste Runde wird besser!"));
Label imageLabel = new Label("");
TextureKey key = new TextureKey("Pictures/MonopolyLoser.png", true);
Texture texture = app.getAssetManager().loadTexture(key);
IconComponent icon = new IconComponent(texture.toString()); // Icon mit Textur erstellen
icon.setIconSize(new Vector2f(155f, 120f)); // Skalierung des Bildes
imageLabel.setIcon(icon); // Setze das Icon im Label
inputContainer.addChild(imageLabel);
Button cancelButton = inputContainer.addChild(new Button("Spiel beenden"));
cancelButton.addClickCommands(source -> ifTopDialog(app::closeApp));
inputContainer.setLocalTranslation(300,500,0);
attachChild(inputContainer);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

View File

@@ -5,7 +5,7 @@ import java.lang.System.Logger.Level;
import java.util.ArrayList;
import java.util.List;
import pp.monopoly.game.server.PlayerHandler;
import pp.monopoly.game.server.Player;
import pp.monopoly.message.client.ClientMessage;
import pp.monopoly.message.server.BuyPropertyResponse;
import pp.monopoly.message.server.DiceResult;
@@ -52,7 +52,7 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker {
/** The current state of the client game logic. */
private ClientState state = new LobbyState(this);
private PlayerHandler playerHandler;
private List<Player> players;
private BoardManager boardManager = new BoardManager();
@@ -94,8 +94,8 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker {
state.entry();
}
public PlayerHandler getPlayerHandler() {
return playerHandler;
public List<Player> getPlayers() {
return players;
}
/**
@@ -226,7 +226,7 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker {
@Override
public void received(EventDrawCard msg) {
setInfoText("Event card drawn: " + msg.getCardDescription());
//event card logic
// Kartenlogik
playSound(Sound.EVENT_CARD);
}
@@ -255,7 +255,7 @@ public class ClientGameLogic implements ServerInterpreter, GameEventBroker {
*/
@Override
public void received(GameStart msg) {
playerHandler = msg.getPlayerHandler();
players = msg.getPlayers();
setInfoText("The game has started! Good luck!");
setState(new WaitForTurnState(this));
}

View File

@@ -10,6 +10,8 @@ package pp.monopoly.game.server;
import java.util.List;
import java.util.Random;
import com.jme3.network.serializing.Serializable;
import pp.monopoly.message.server.DiceResult;
import pp.monopoly.model.FieldVisitor;
import pp.monopoly.model.Figure;
@@ -28,6 +30,7 @@ import pp.monopoly.model.fields.WacheField;
/**
* Class representing a player
*/
@Serializable
public class Player implements FieldVisitor<Void>{
private final int id;
private String name;
@@ -40,6 +43,14 @@ public class Player implements FieldVisitor<Void>{
private final PlayerHandler handler;
private PlayerState state = new LobbyState();
/**
* Default constructor for serialization purposes.
*/
private Player(){
id = 0;
handler = null;
}
/**
* Constructs a player with the speciefied params
* @param id the id of the player
@@ -84,7 +95,7 @@ public class Player implements FieldVisitor<Void>{
* Set the name of the Player
* @param name the new name
*/
void setName(String name) {
public void setName(String name) {
this.name = name;
}
@@ -168,6 +179,7 @@ public class Player implements FieldVisitor<Void>{
public void buyProperty(PropertyField property) {
if (property.getOwner() == null && accountBalance >= property.getPrice()) {
properties.add(property);
property.setOwner(this);
pay(property.getPrice());
}
}

View File

@@ -8,10 +8,13 @@ import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import com.jme3.network.serializing.Serializable;
import pp.monopoly.model.LimitedLinkedList;
/**
* A class for helping with player actions and managing thier turns
*/
@Serializable
public class PlayerHandler {
private List<Player> players = new LimitedLinkedList<>(6);
private Set<Player> readyPlayers = new HashSet<>();
@@ -19,6 +22,11 @@ public class PlayerHandler {
private Player hostPlayer;
private Player extra = null;
/**
* Default constructor for serialization purposes.
*/
private PlayerHandler() {}
/**
* Contructs a PlayerHandler
* @param logic the {@link ServerGameLogic} this PlayerHandler is a part of
@@ -157,7 +165,7 @@ public class PlayerHandler {
* @param id the id to be searched for
* @return the player with the required id
*/
Player getPlayerById(int id) {
public Player getPlayerById(int id) {
for (Player player : players) {
if (player.getId() == id) return player;
}
@@ -176,7 +184,7 @@ public class PlayerHandler {
players.get(0).setActive();
}
void setStartBalance(int amount) {
public void setStartBalance(int amount) {
for (Player player : players) {
player.setAccountBalance(amount);
}

View File

@@ -204,7 +204,7 @@ public class ServerGameLogic implements ClientInterpreter {
if(playerHandler.allPlayersReady()) {
playerHandler.setStartBalance(startMoney);
for (Player p : playerHandler.getPlayers()) {
send(p, new GameStart(playerHandler));
send(p, new GameStart(playerHandler.getPlayers()));
}
playerHandler.randomOrder();
send(playerHandler.getPlayerAtIndex(0), new NextPlayerTurn(playerHandler.getPlayerAtIndex(0)));

View File

@@ -1,25 +1,27 @@
package pp.monopoly.message.server;
import java.util.List;
import com.jme3.network.serializing.Serializable;
import pp.monopoly.game.server.PlayerHandler;
import pp.monopoly.game.server.Player;
@Serializable
public class GameStart extends ServerMessage{
private PlayerHandler ph;
private List<Player> players;
/**
* Default constructor for serialization purposes.
*/
private GameStart() { /* empty */ }
public GameStart(PlayerHandler ph) {
this.ph = ph;
public GameStart(List<Player> players) {
this.players = players;
}
public PlayerHandler getPlayerHandler() {
return ph;
public List<Player> getPlayers() {
return players;
}
@Override

View File

@@ -4,9 +4,12 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import com.jme3.network.serializing.Serializable;
import static java.lang.Math.max;
import static java.lang.Math.min;
@Serializable
public class Figure implements Item{
private final String type;
private final int length; // The length of the Figure

View File

@@ -2,14 +2,22 @@ package pp.monopoly.model;
import java.util.LinkedList;
import com.jme3.network.serializing.Serializable;
/**
* A LinkedList with a maximum size limit.
*
* @param <E> the type of elements held in this collection
*/
@Serializable
public class LimitedLinkedList<E> extends LinkedList<E> {
private final int maxSize;
private int maxSize;
/**
* Default constructor for serialization purposes.
*/
private LimitedLinkedList() {}
/**
* Constructs a LimitedLinkedList with the specified maximum size.

View File

@@ -15,9 +15,9 @@ public class Card {
visitor.visit(this, player);
}
String getDescription() {
public String getDescription() {
return description;
}
} // TODO wird gerade in der EventCard zur erstellung des Popup genutzt
String getKeyword() {
return keyword;

View File

@@ -26,6 +26,7 @@ import com.jme3.network.serializing.Serializer;
import pp.monopoly.MonopolyConfig;
import pp.monopoly.game.server.Player;
import pp.monopoly.game.server.PlayerHandler;
import pp.monopoly.game.server.ServerGameLogic;
import pp.monopoly.game.server.ServerSender;
import pp.monopoly.message.client.BuyPropertyRequest;
@@ -36,8 +37,12 @@ import pp.monopoly.message.client.RollDice;
import pp.monopoly.message.client.TradeOffer;
import pp.monopoly.message.client.TradeResponse;
import pp.monopoly.message.client.ViewAssetsRequest;
import pp.monopoly.message.server.GameStart;
import pp.monopoly.message.server.NextPlayerTurn;
import pp.monopoly.message.server.ServerMessage;
import pp.monopoly.model.Figure;
import pp.monopoly.model.IntPoint;
import pp.monopoly.model.LimitedLinkedList;
/**
* Server implementing the visitor pattern as MessageReceiver for ClientMessages
@@ -119,6 +124,12 @@ public class MonopolyServer implements MessageListener<HostedConnection>, Connec
Serializer.registerClass(TradeOffer.class);
Serializer.registerClass(TradeResponse.class);
Serializer.registerClass(ViewAssetsRequest.class);
Serializer.registerClass(GameStart.class);
Serializer.registerClass(LimitedLinkedList.class);
Serializer.registerClass(NextPlayerTurn.class);
Serializer.registerClass(Player.class);
Serializer.registerClass(Figure.class);
Serializer.registerClass(PlayerHandler.class);
}
private void registerListeners() {