This commit is contained in:
Johannes Schmelz 2024-11-28 19:42:07 +01:00
commit e7a06159bb
14 changed files with 439 additions and 13 deletions

View File

@ -71,6 +71,11 @@ selector("label-Text", "pp") {
color = buttonEnabledColor
}
selector("card-label", "pp") {
insets = new Insets3f(2, 2, 2, 2)
color = ColorRGBA.Black
}
selector("header", "pp") {
font = font("Interface/Fonts/Metropolis/Metropolis-Bold-42.fnt")
insets = new Insets3f(2, 2, 2, 2)
@ -292,3 +297,37 @@ selector("selector.item.label", "hover") {
background = new QuadBackgroundComponent(new ColorRGBA(0.2f, 0.6f, 1.0f, 0.9f)) // Highlighted background
}
def enabledCommandToolbar = new Command<Button>() {
void execute(Button source) {
if (source.isEnabled())
source.setColor(ColorRGBA.White)
else
source.setColor(ColorRGBA.Gray)
}
}
def stdButtonCommandsToolbar = [
(ButtonAction.Down) : [pressedCommand],
(ButtonAction.Up) : [pressedCommand],
(ButtonAction.Enabled) : [enabledCommandToolbar],
(ButtonAction.Disabled): [enabledCommandToolbar]
]
selector("button-toolbar", "pp") {
def outerBackground = new QuadBackgroundComponent(color(1, 0.5, 0, 1)) // Orange border
def innerBackground = new QuadBackgroundComponent(buttonBgColor) // Inner button background
// Apply the outer border as the main background
background = outerBackground
// Use insets to create a margin/padding effect for the inner background
insets = new Insets3f(3, 3, 3, 3) // Adjust the border thickness
textHAlignment = HAlignment.Center
textVAlignment = VAlignment.Center
buttonCommands = stdButtonCommandsToolbar
}

View File

@ -21,15 +21,11 @@ import com.jme3.system.AppSettings;
import com.simsilica.lemur.GuiGlobals;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.style.BaseStyles;
import pp.monopoly.client.gui.popups.*;
import pp.monopoly.game.client.MonopolyClient;
import pp.monopoly.client.gui.SettingsMenu;
import pp.monopoly.client.gui.StartMenu;
import pp.monopoly.client.gui.TestWorld;
import pp.monopoly.client.gui.popups.BuildingPropertyCard;
import pp.monopoly.client.gui.popups.BuyCard;
import pp.monopoly.client.gui.popups.EventCard;
import pp.monopoly.client.gui.popups.FoodFieldCard;
import pp.monopoly.client.gui.popups.GateFieldCard;
import pp.monopoly.game.client.ClientGameLogic;
import pp.monopoly.game.client.ServerConnection;
import pp.monopoly.notification.ClientStateEvent;
@ -134,6 +130,7 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
private FoodFieldCard foodField;
private GateFieldCard gateField;
private BuyCard buyCard;
private LooserPopUp looserpopup;
private boolean isBuyCardPopupOpen = false;
private final ActionListener BListener = (name, isPressed, tpf) -> handleB(isPressed);
private final ActionListener TListener = (name, isPressed, tpf) -> handleT(isPressed);
@ -278,7 +275,7 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga
//logik zum wechselnden erscheinen und verschwinden beim drücken von B //TODO süäter entfernen
private void handleB(boolean isPressed) {
if (isPressed) {
Dialog tmp = new BuyCard(this);
Dialog tmp = new SellHouse(this);
tmp.open();
}
}

View File

@ -77,7 +77,7 @@ public class BuildingAdminMenu extends Dialog {
Container overviewColumn = new Container(new SpringGridLayout(Axis.Y, Axis.X));
overviewColumn.addChild(new Label("Übersicht:")).setFontSize(30);
//Building Overview Button
overviewButton.setPreferredSize(new Vector3f(200, 50, 0));
overviewButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
@ -99,12 +99,14 @@ public class BuildingAdminMenu extends Dialog {
Container buildColumn = new Container(new SpringGridLayout(Axis.Y, Axis.X));
buildColumn.addChild(new Label("Bauen:")).setFontSize(30);
// Build Houses Button
buildButton.setPreferredSize(new Vector3f(200, 50, 0));
buildButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
}));
buildColumn.addChild(buildButton);
//Demolish Houses Button
demolishButton.setPreferredSize(new Vector3f(200, 50, 0));
demolishButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
@ -118,12 +120,14 @@ public class BuildingAdminMenu extends Dialog {
Container mortgageColumn = new Container(new SpringGridLayout(Axis.Y, Axis.X));
mortgageColumn.addChild(new Label("Hypotheken:")).setFontSize(30);
// Lend Mortgage Button
takeMortgageButton.setPreferredSize(new Vector3f(200, 50, 0));
takeMortgageButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
}));
mortgageColumn.addChild(takeMortgageButton);
//Repay Mortgage Button
payMortgageButton.setPreferredSize(new Vector3f(200, 50, 0));
payMortgageButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);

View File

@ -0,0 +1,148 @@
package pp.monopoly.client.gui;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.control.AbstractControl;
import com.simsilica.lemur.*;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.component.SpringGridLayout;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import java.util.ArrayList;
import java.util.List;
/**
* PropertyOverviewMenu is a dialog for displaying the player's properties in the game.
*/
public class PropertyOverviewMenu extends Dialog {
private final MonopolyApp app;
private final Container mainContainer;
private final Container displayContainer;
private final Slider horizontalSlider;
private final List<Container> cards;
/**
* Constructs the PropertyOverviewMenu dialog.
*
* @param app The Monopoly application instance.
*/
public PropertyOverviewMenu(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
// Make the menu fullscreen
Vector3f screenSize = new Vector3f(app.getCamera().getWidth(), app.getCamera().getHeight(), 0);
// Main container for the menu layout
mainContainer = new Container();
mainContainer.setPreferredSize(screenSize); // Make fullscreen
mainContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(1.0f, 1.0f, 1.0f, 0.8f))); // Semi-transparent background
// Header label
Label headerLabel = mainContainer.addChild(new Label("Meine Grundstücke", new ElementId("header")));
headerLabel.setFontSize(40);
// Central display container (to hold the "Gebäude" cards)
displayContainer = mainContainer.addChild(new Container(new SpringGridLayout(Axis.X, Axis.Y, FillMode.Even, FillMode.None))); // Horizontal layout
displayContainer.setPreferredSize(new Vector3f(screenSize.x - 300, 550, 0)); // Take up the remaining width
displayContainer.setBackground(new QuadBackgroundComponent(ColorRGBA.Gray));
displayContainer.setLocalTranslation(0, 0, 11);
// Add some placeholder "Gebäude" cards to the display container
cards = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Container card = createGebäudeCard("Gebäude " + (i + 1), 320, 28);
cards.add(card); // Keep track of cards for scrolling
}
// Initially add only visible cards to the displayContainer
refreshVisibleCards(0);
// Horizontal slider for scrolling through cards
horizontalSlider = mainContainer.addChild(new Slider(Axis.X));
horizontalSlider.setPreferredSize(new Vector3f(screenSize.x - 300, 20, 5));
horizontalSlider.setModel(new DefaultRangedValueModel(0, Math.max(0, cards.size() - 5), 0));
horizontalSlider.addControl(new SliderValueChangeListener());
// Add the "Zurück" button at the bottom
Button backButton = mainContainer.addChild(new Button("Zurück", new ElementId("button")));
backButton.setPreferredSize(new Vector3f(200, 60, 0));
backButton.addClickCommands(source -> this.close());
// Attach the main container to the GUI node
app.getGuiNode().attachChild(mainContainer);
mainContainer.setLocalTranslation(
0,
app.getCamera().getHeight(), // Align to the top
10
);
}
/**
* Creates a "Gebäude" card container with the given information.
*
* @param title The title of the card (e.g., "Gebäude 1").
* @param propertyValue The property value.
* @param rent The rent amount.
* @return A styled container representing a "Gebäude" card.
*/
private Container createGebäudeCard(String title, int propertyValue, int rent) {
Container card = new Container();
card.setPreferredSize(new Vector3f(150, 200, 2)); // Increase width and height for better visibility
card.setBackground(new QuadBackgroundComponent(ColorRGBA.Gray));
card.addChild(new Label(title, new ElementId("card-label"))).setFontSize(14);
card.addChild(new Label("Grundstückswert: €" + propertyValue, new ElementId("card-label"))).setFontSize(12);
card.addChild(new Label("Miete allein: €" + rent, new ElementId("card-label"))).setFontSize(12);
card.addChild(new Label("1 Haus: €50", new ElementId("card-label"))).setFontSize(12);
card.addChild(new Label("Hypothekenwert: €160", new ElementId("card-label"))).setFontSize(12);
return card;
}
/**
* Updates the visible cards in the displayContainer based on the slider value.
*
* @param startIndex The starting index of the visible cards.
*/
private void refreshVisibleCards(int startIndex) {
displayContainer.clearChildren(); // Remove all current children
int maxVisible = 5; // Number of cards to display at once
for (int i = startIndex; i < startIndex + maxVisible && i < cards.size(); i++) {
displayContainer.addChild(cards.get(i));
}
}
/**
* Custom listener for slider value changes.
*/
private class SliderValueChangeListener extends AbstractControl {
@Override
protected void controlUpdate(float tpf) {
// Get the slider's current value and refresh visible cards
int sliderValue = (int) ((Slider) getSpatial()).getModel().getValue();
refreshVisibleCards(sliderValue);
}
@Override
protected void controlRender(RenderManager renderManager, ViewPort viewPort) {
// No rendering logic needed
}
}
/**
* Closes the dialog and detaches it from the GUI node.
*/
@Override
public void close() {
app.getGuiNode().detachChild(mainContainer);
super.close();
}
}

View File

@ -88,7 +88,7 @@ public class Toolbar extends Dialog implements GameEventListener {
diceContainer.addChild(horizontalContainer);
// Würfeln-Button
diceButton = new Button("Würfeln");
diceButton = new Button("Würfeln", new ElementId("button-toolbar"));
diceButton.setPreferredSize(new Vector3f(200, 50, 0));
diceButton.addClickCommands(s -> ifTopDialog(() -> {
diceButton.setEnabled(false);
@ -109,7 +109,7 @@ public class Toolbar extends Dialog implements GameEventListener {
}
private Button addTradeMenuButton() {
tradeButton = new Button("Handeln");
tradeButton = new Button("Handeln", new ElementId("button-toolbar"));
tradeButton.setPreferredSize(new Vector3f(150, 50, 0));
tradeButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
@ -119,17 +119,19 @@ public class Toolbar extends Dialog implements GameEventListener {
}
private Button addPropertyMenuButton() {
propertyMenuButton = new Button("Grundstücke");
propertyMenuButton = new Button("Grundstücke", new ElementId("button-toolbar"));
propertyMenuButton.setPreferredSize(new Vector3f(150, 50, 0));
propertyMenuButton.setFontSize(30);
propertyMenuButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
new BuildingAdminMenu(app).open();
// new BuildingAdminMenu(app).open();
new PropertyOverviewMenu(app).open();
}));
return propertyMenuButton;
}
private Button addEndTurnButton() {
endTurnButton = new Button("Zug beenden");
endTurnButton = new Button("Zug beenden", new ElementId("button-toolbar"));
endTurnButton.setPreferredSize(new Vector3f(150, 50, 0));
endTurnButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);

View File

@ -28,7 +28,7 @@ public class BuyCard extends Dialog {
this.app = app;
//Generate the corresponfing field
int index = app.getGameLogic().getPlayerHandler().getPlayers().get(0).getFieldID();
int index = app.getGameLogic().getPlayerHandler().getPlayers().get(0).getFieldID();;
BuildingProperty field = (BuildingProperty) new BoardManager().getFieldAtIndex(index);
// Create the background container

View File

@ -0,0 +1,119 @@
package pp.monopoly.client.gui.popups;
import com.jme3.math.ColorRGBA;
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.client.gui.SettingsMenu;
import pp.monopoly.message.client.BuyPropertyRequest;
import pp.monopoly.notification.Sound;
/**
* SettingsMenu ist ein Overlay-Menü, das durch ESC aufgerufen werden kann.
*/
public class ConfirmTrade extends Dialog {
private final MonopolyApp app;
private final Container confirmTradeContainer;
private final Container backgroundContainer;
public ConfirmTrade(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
//Generate the corresponfing field
//int index = app.getGameLogic().getPlayerHandler().getPlayers().get(0).getFieldID();;
// BuildingProperty field = (BuildingProperty) new BoardManager().getFieldAtIndex(index);
// Create the background container
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Darker background
attachChild(backgroundContainer);
// Hauptcontainer für die Gebäudekarte
confirmTradeContainer = new Container();
Label title = confirmTradeContainer.addChild(new Label( "Handel", new ElementId("label-Bold"))); //TODO ggf die Buttons Sprachabhängig von den Properties machen
title.setFontSize(48);
title.setColor(ColorRGBA.Black);
// Text, der auf der Karte steht
// Die Preise werden dynamisch dem BoardManager entnommen
Container propertyValuesContainer = confirmTradeContainer.addChild(new Container());
propertyValuesContainer.addChild(new Label("„Spieler XXX möchte:", new ElementId("label-Text"))); //TODO hier überall die entsprechenden Variablen einfügen
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile
propertyValuesContainer.addChild(new Label("- XXX Gebäude", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("- XXX EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("- XXX Sonderkaten", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile
propertyValuesContainer.addChild(new Label("gegen:", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile
propertyValuesContainer.addChild(new Label("- XXX Gebäude", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("- XXX EUR", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("- XXX Sonderkaten", new ElementId("label-Text")));
propertyValuesContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile
propertyValuesContainer.addChild(new Label("tauschen, willst du das Angebot annehmen?", new ElementId("label-Text")));
propertyValuesContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
// Beenden-Button
Button declineButton = confirmTradeContainer.addChild(new Button("Ablehnen", new ElementId("button"))); //TODO ggf die Buttons Sprachabhängig von den Properties machen
declineButton.setFontSize(32);
declineButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
// Kaufen-Button
Button negotiateButton = confirmTradeContainer.addChild(new Button("Verhandeln", new ElementId("button"))); //TODO ggf die Buttons Sprachabhängig von den Properties machen
negotiateButton.setFontSize(32);
negotiateButton.addClickCommands(s -> ifTopDialog( () -> {
app.getGameLogic().playSound(Sound.BUTTON);
app.getGameLogic().send(new BuyPropertyRequest());
}));
// Kaufen-Button
Button confirmButton = confirmTradeContainer.addChild(new Button("Bestätigen", new ElementId("button"))); //TODO ggf die Buttons Sprachabhängig von den Properties machen
confirmButton.setFontSize(32);
confirmButton.addClickCommands(s -> ifTopDialog( () -> {
app.getGameLogic().playSound(Sound.BUTTON);
app.getGameLogic().send(new BuyPropertyRequest());
}));
float padding = 10; // Padding around the settingsContainer for the background
backgroundContainer.setPreferredSize(confirmTradeContainer.getPreferredSize().addLocal(padding, padding, 0));
// Zentriere das Menü
confirmTradeContainer.setLocalTranslation(
(app.getCamera().getWidth() - confirmTradeContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + confirmTradeContainer.getPreferredSize().y) / 2,
8
);
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - confirmTradeContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + confirmTradeContainer.getPreferredSize().y+ padding) / 2,
7
);
app.getGuiNode().attachChild(confirmTradeContainer);
}
/**
* Schließt das Menü und entfernt die GUI-Elemente.
*/
@Override
public void close() {
app.getGuiNode().detachChild(confirmTradeContainer); // Entferne das Menü
app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand
super.close();
}
@Override
public void escape() {
new SettingsMenu(app).open();
}
}

View File

@ -0,0 +1,117 @@
package pp.monopoly.client.gui.popups;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.component.IconComponent;
import com.simsilica.lemur.component.QuadBackgroundComponent;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.monopoly.client.MonopolyApp;
import pp.monopoly.client.gui.SettingsMenu;
import pp.monopoly.message.client.BuyPropertyRequest;
import pp.monopoly.notification.Sound;
/**
* SettingsMenu ist ein Overlay-Menü, das durch ESC aufgerufen werden kann.
*/
public class SellHouse extends Dialog {
private final MonopolyApp app;
private final Container sellhouseContainer;
private final Container backgroundContainer;
public SellHouse(MonopolyApp app) {
super(app.getDialogManager());
this.app = app;
//Generate the corresponfing field
//int index = app.getGameLogic().getPlayerHandler().getPlayers().get(0).getFieldID();;
// BuildingProperty field = (BuildingProperty) new BoardManager().getFieldAtIndex(index);
// Create the background container
backgroundContainer = new Container();
backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Darker background
attachChild(backgroundContainer);
// Hauptcontainer für die Gebäudekarte
sellhouseContainer = new Container();
Label title = sellhouseContainer.addChild(new Label( "Gebäude Abreißen", new ElementId("label-Bold"))); //TODO ggf die Buttons Sprachabhängig von den Properties machen
title.setFontSize(48);
title.setColor(ColorRGBA.Black);
Container upContainer = sellhouseContainer.addChild(new Container());
Container middleContainer = sellhouseContainer.addChild(new Container());
Container downContainer = sellhouseContainer.addChild(new Container());
// Text, der auf der Karte steht
// Die Preise werden dynamisch dem BoardManager entnommen
upContainer.addChild(new Label("„Grundstück wählen:", new ElementId("label-Text"))); //TODO hier überall die entsprechenden Variablen einfügen
upContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile
upContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
middleContainer.setPreferredSize(new Vector3f(100, 150, 0));
middleContainer.setBackground(new QuadBackgroundComponent(ColorRGBA.Red));
middleContainer.addChild(new Label("Dies ist ein Container", new ElementId("label-Text")));
middleContainer.addChild(new Label("", new ElementId("label-Text")));
middleContainer.addChild(new Label("Hier kann der Slider und die Checkbocen eingefügt werden", new ElementId("label-Text")));
downContainer.addChild(new Label("", new ElementId("label-Text")));// Leerzeile
downContainer.addChild(new Label("Erstattung:", new ElementId("label-Text")));// Leerzeile
downContainer.addChild(new Label("Hier die tätsächliche Erstattung", new ElementId("label-Text")));
downContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.4657f, 0.4735f, 0.4892f, 1.0f)));
// Beenden-Button
Button cancelButton = sellhouseContainer.addChild(new Button("Abbrechen", new ElementId("button"))); //TODO ggf die Buttons Sprachabhängig von den Properties machen
cancelButton.setFontSize(32);
cancelButton.addClickCommands(s -> ifTopDialog(() -> {
app.getGameLogic().playSound(Sound.BUTTON);
close();
}));
// Kaufen-Button
Button confirmButton = sellhouseContainer.addChild(new Button("Bestätigen", new ElementId("button"))); //TODO ggf die Buttons Sprachabhängig von den Properties machen
confirmButton.setFontSize(32);
confirmButton.addClickCommands(s -> ifTopDialog( () -> {
app.getGameLogic().playSound(Sound.BUTTON);
app.getGameLogic().send(new BuyPropertyRequest());
}));
float padding = 10; // Padding around the settingsContainer for the background
backgroundContainer.setPreferredSize(sellhouseContainer.getPreferredSize().addLocal(padding, padding, 0));
// Zentriere das Menü
sellhouseContainer.setLocalTranslation(
(app.getCamera().getWidth() - sellhouseContainer.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + sellhouseContainer.getPreferredSize().y) / 2,
8
);
backgroundContainer.setLocalTranslation(
(app.getCamera().getWidth() - sellhouseContainer.getPreferredSize().x - padding) / 2,
(app.getCamera().getHeight() + sellhouseContainer.getPreferredSize().y+ padding) / 2,
7
);
app.getGuiNode().attachChild(sellhouseContainer);
}
/**
* Schließt das Menü und entfernt die GUI-Elemente.
*/
@Override
public void close() {
app.getGuiNode().detachChild(sellhouseContainer); // Entferne das Menü
app.getGuiNode().detachChild(backgroundContainer); //Entfernt Rand
super.close();
}
@Override
public void escape() {
new SettingsMenu(app).open();
}
}