diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/GameSound.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/GameSound.java index ec54da2..bf5d649 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/GameSound.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/GameSound.java @@ -7,6 +7,10 @@ package pp.monopoly.client; +import java.lang.System.Logger; +import java.lang.System.Logger.Level; +import java.util.prefs.Preferences; + import com.jme3.app.Application; import com.jme3.app.state.AbstractAppState; import com.jme3.app.state.AppStateManager; @@ -14,13 +18,9 @@ import com.jme3.asset.AssetLoadException; import com.jme3.asset.AssetNotFoundException; import com.jme3.audio.AudioData; import com.jme3.audio.AudioNode; + import pp.monopoly.notification.GameEventListener; import pp.monopoly.notification.SoundEvent; - -import java.lang.System.Logger; -import java.lang.System.Logger.Level; -import java.util.prefs.Preferences; - import static pp.util.PreferencesUtils.getPreferences; /** diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/MonopolyApp.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/MonopolyApp.java index cdd2f58..ffe1f4e 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/MonopolyApp.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/MonopolyApp.java @@ -15,6 +15,7 @@ import com.simsilica.lemur.style.BaseStyles; import pp.dialog.DialogBuilder; import pp.dialog.DialogManager; +import pp.graphics.Draw; import pp.monopoly.client.gui.SettingsMenu; import pp.monopoly.client.gui.TestWorld; import pp.monopoly.game.client.ClientGameLogic; @@ -31,24 +32,18 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga private final ActionListener escapeListener = (name, isPressed, tpf) -> handleEscape(isPressed); private final DialogManager dialogManager = new DialogManager(this); private final ExecutorService executor = Executors.newCachedThreadPool(); + private final Draw draw; private SettingsMenu settingsMenu; - - /** - * Path to the styles script for GUI elements. - */ - private static final String STYLES_SCRIPT = "Interface/Lemur/pp-styles.groovy"; //NON-NLS - /** - * Path to the font resource used in the GUI. - */ - private static final String FONT = "Interface/Fonts/Default.fnt"; //NON-NLS - + private TestWorld testWorld; private boolean isSettingsMenuOpen = false; + private boolean inputBlocked = false; public static void main(String[] args) { new MonopolyApp().start(); } public MonopolyApp() { + this.draw = new Draw(assetManager); config = new MonopolyAppConfig(); serverConnection = new NetworkSupport(this); logic = new ClientGameLogic(serverConnection); @@ -67,10 +62,6 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga return logic; } - public ExecutorService getExecutor() { - return executor; - } - private AppSettings makeSettings() { final AppSettings settings = new AppSettings(true); settings.setTitle("Monopoly Game"); @@ -79,29 +70,21 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga return settings; } - public boolean isSettingsMenuOpen() { - return isSettingsMenuOpen; - } - - public void setSettingsMenuOpen(boolean isOpen) { - this.isSettingsMenuOpen = isOpen; - } - @Override public void simpleInitApp() { GuiGlobals.initialize(this); - BaseStyles.loadStyleResources(STYLES_SCRIPT); - GuiGlobals.getInstance().getStyles().setDefaultStyle("pp"); //NON-NLS - final BitmapFont normalFont = assetManager.loadFont(FONT); + BaseStyles.loadGlassStyle(); + GuiGlobals.getInstance().getStyles().setDefaultStyle("glass"); + setupInput(); setupGui(); - // Initialisiere das Startmenü + // Zeige das Startmenü StartMenu.createStartMenu(this); } private void setupGui() { - BitmapFont normalFont = assetManager.loadFont(FONT); + BitmapFont normalFont = assetManager.loadFont("Interface/Fonts/Default.fnt"); topText = new BitmapText(normalFont); topText.setLocalTranslation(10, settings.getHeight() - 10, 0); guiNode.attachChild(topText); @@ -116,16 +99,40 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga private void handleEscape(boolean isPressed) { if (isPressed) { - if (isSettingsMenuOpen && settingsMenu != null) { + if (settingsMenu != null && isSettingsMenuOpen) { + // Schließe das SettingsMenu + System.out.println("Schließe SettingsMenu..."); settingsMenu.close(); + settingsMenu = null; setSettingsMenuOpen(false); } else { + // Öffne das SettingsMenu + System.out.println("Öffne SettingsMenu..."); settingsMenu = new SettingsMenu(this); settingsMenu.open(); setSettingsMenuOpen(true); } } } + + + + private void blockInputs() { + if (!inputBlocked) { + System.out.println("Blockiere Eingaben..."); + inputManager.setCursorVisible(true); // Cursor sichtbar machen + inputManager.clearMappings(); // Alle Mappings entfernen + inputBlocked = true; + } + } + + public void unblockInputs() { + if (inputBlocked) { + System.out.println("Aktiviere Eingaben..."); + setupInput(); // Standard-Eingaben neu registrieren + inputBlocked = false; + } + } public void setInfoText(String text) { topText.setText(text); @@ -147,6 +154,14 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga return dialogManager; } + public Draw getDraw() { + return draw; + } + + public ExecutorService getExecutor() { + return executor; + } + public void closeApp() { stop(); } @@ -160,20 +175,25 @@ public class MonopolyApp extends SimpleApplication implements MonopolyClient, Ga .open(); } - /** - * Wechselt zur TestWorld. - */ - public void startTestWorld() { - guiNode.detachAllChildren(); // GUI entfernen - stop(); // MonopolyApp anhalten - TestWorld.startTestWorld(); // TestWorld starten + public void setSettingsMenuOpen(boolean isOpen) { + this.isSettingsMenuOpen = isOpen; + } + + @Override + public void simpleUpdate(float tpf) { + if (testWorld != null) { + testWorld.update(tpf); // Aktualisiere die Kamera in der TestWorld + } + } + + public void startTestWorld() { + guiNode.detachAllChildren(); // Entferne GUI + testWorld = new TestWorld(this); // Erstelle eine Instanz von TestWorld + testWorld.initializeScene(); // Initialisiere die Szene } - /** - * Kehrt zum Hauptmenü zurück. - */ public void returnToMenu() { - guiNode.detachAllChildren(); - StartMenu.createStartMenu(this); + guiNode.detachAllChildren(); // Entferne die GUI + StartMenu.createStartMenu(this); // Zeige das Startmenü erneut } } diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CameraController.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CameraController.java new file mode 100644 index 0000000..605bea3 --- /dev/null +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CameraController.java @@ -0,0 +1,55 @@ +package pp.monopoly.client.gui; + +import com.jme3.math.FastMath; +import com.jme3.math.Vector3f; +import com.jme3.renderer.Camera; + +/** + * CameraController steuert die Bewegung der Kamera in einem Kreis um eine Zielposition. + */ +public class CameraController { + + private final Camera camera; // Die Kamera, die gesteuert wird + private final Vector3f target; // Zielpunkt, den die Kamera fokussieren soll + private final float radius; // Radius des Kreises + private final float height; // Höhe der Kamera über dem Zielpunkt + private final float speed; // Geschwindigkeit der Bewegung in Radiant pro Sekunde + private float angle = 0; // Aktueller Winkel der Kamera in Radiant + + /** + * Erstellt einen neuen CameraController. + * + * @param camera Die Kamera, die gesteuert wird + * @param target Der Punkt, auf den die Kamera ausgerichtet wird + * @param radius Der Radius des Kreises, auf dem sich die Kamera bewegt + * @param height Die Höhe der Kamera über dem Zielpunkt + * @param speed Die Geschwindigkeit der Bewegung in Radiant pro Sekunde + */ + public CameraController(Camera camera, Vector3f target, float radius, float height, float speed) { + this.camera = camera; + this.target = target; + this.radius = radius; + this.height = height; + this.speed = speed; + } + + /** + * Aktualisiert die Kameraposition basierend auf der verstrichenen Zeit. + * + * @param tpf Zeit pro Frame + */ + public void update(float tpf) { + angle += speed * tpf; // Winkel basierend auf Geschwindigkeit und Zeit erhöhen + if (angle > FastMath.TWO_PI) { + angle -= FastMath.TWO_PI; // Zurücksetzen, um Überlauf zu vermeiden + } + + // Berechne die neue Kameraposition auf der Kreisbahn + float x = FastMath.cos(angle) * radius; + float z = FastMath.sin(angle) * radius; + + // Setze die neue Position der Kamera + camera.setLocation(new Vector3f(x, height, z)); + camera.lookAt(target, Vector3f.UNIT_Y); // Kamera bleibt auf das Ziel fokussiert + } +} diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CreateGameMenu.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CreateGameMenu.java index c6ae9bc..5472da4 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CreateGameMenu.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/CreateGameMenu.java @@ -23,6 +23,11 @@ public class CreateGameMenu { private final Container menuContainer; private Geometry background; + /** + * Konstruktor für das CreateGameMenu. + * + * @param app Die Hauptanwendung (MonopolyApp) + */ public CreateGameMenu(MonopolyApp app) { this.app = app; @@ -43,12 +48,12 @@ public class CreateGameMenu { inputContainer.setLocalTranslation(20, 0, 0); // Abstand vom Rand inputContainer.addChild(new Label("Server-Adresse:")); - TextField playerNameField = inputContainer.addChild(new TextField("localhost")); - playerNameField.setPreferredWidth(400); // Breite des Textfelds + TextField serverAddressField = inputContainer.addChild(new TextField("localhost")); + serverAddressField.setPreferredWidth(400); // Breite des Textfelds inputContainer.addChild(new Label("Port:")); - TextField serverAddressField = inputContainer.addChild(new TextField("42069")); - serverAddressField.setPreferredWidth(400); // Breite des Textfelds + TextField portField = inputContainer.addChild(new TextField("42069")); + portField.setPreferredWidth(400); // Breite des Textfelds // Button-Container Container buttonContainer = menuContainer.addChild(new Container(new SpringGridLayout(Axis.X, Axis.Y))); @@ -64,15 +69,14 @@ public class CreateGameMenu { Button hostButton = buttonContainer.addChild(new Button("Spiel hosten")); hostButton.setPreferredSize(new Vector3f(120, 40, 0)); hostButton.addClickCommands(source -> { - closeCreateGameMenu(); // Schließt das Menü - app.startTestWorld(); // Startet die Testwelt in der Hauptanwendung -}); - + closeCreateGameMenu(); // Schließt das Menü + app.startTestWorld(); // Starte die TestWorld im selben Fenster + }); // "Beitreten"-Button Button joinButton = buttonContainer.addChild(new Button("Beitreten")); joinButton.setPreferredSize(new Vector3f(120, 40, 0)); - // joinButton.addClickCommands(source -> joinGame()); // Placeholder for joining logic + // Placeholder für die Beitrittslogik // Zentrierung des Containers menuContainer.setLocalTranslation( @@ -103,27 +107,15 @@ public class CreateGameMenu { * Geht zum Startmenü zurück, wenn "Abbrechen" angeklickt wird. */ private void goBackToStartMenu() { - app.getGuiNode().detachChild(menuContainer); - app.getGuiNode().detachChild(background); // Entfernt das Hintergrundbild - StartMenu.createStartMenu(app); - } - /* - * Link zwischen createGame und TestWorld - */ - - private void startTestWorld() { - // Entfernt das Menü - app.getGuiNode().detachChild(menuContainer); - app.getGuiNode().detachChild(background); - - // Startet die Testszene - TestWorld.startTestWorld(); + closeCreateGameMenu(); // Schließt das Menü + StartMenu.createStartMenu(app); // Zeige das Startmenü } + /** + * Entfernt das CreateGameMenu und dessen Hintergrund. + */ private void closeCreateGameMenu() { app.getGuiNode().detachChild(menuContainer); // Entfernt den Menü-Container - app.getGuiNode().detachChild(background); // Entfernt das Hintergrundbild + app.getGuiNode().detachChild(background); // Entfernt das Hintergrundbild } - - -} \ No newline at end of file +} diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/GameBoardSynchronizer.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/GameBoardSynchronizer.java index fe5e774..637f7ab 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/GameBoardSynchronizer.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/GameBoardSynchronizer.java @@ -21,7 +21,6 @@ import pp.monopoly.game.server.PlayerColor; import pp.monopoly.model.Board; import pp.monopoly.model.Figure; import pp.monopoly.model.Rotation; - import static pp.util.FloatMath.HALF_PI; import static pp.util.FloatMath.PI; @@ -62,7 +61,6 @@ class GameBoardSynchronizer extends BoardSynchronizer { * @param ship the battleship to be represented * @return the node containing the graphical representation of the battleship */ - @Override public Spatial visit(Figure figure) { final Node node = new Node(FIGURE); node.attachChild(createBox(figure)); diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/MapView.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/MapView.java index 638e402..f93c1d5 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/MapView.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/MapView.java @@ -55,7 +55,7 @@ class MapView { mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha); Geometry background = new Geometry("MapBackground", new Quad(board.getWidth() * FIELD_SIZE, board.getHeight() * FIELD_SIZE)); background.setMaterial(mat); - background.setLocalTranslation(0f, 0f, BACKGROUND_DEPTH); + background.setLocalTranslation(0f, 1f, BACKGROUND_DEPTH); background.setCullHint(CullHint.Never); mapNode.attachChild(background); } diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/MapViewSynchronizer.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/MapViewSynchronizer.java index d7c3ff9..4853356 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/MapViewSynchronizer.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/MapViewSynchronizer.java @@ -38,7 +38,7 @@ class MapViewSynchronizer extends BoardSynchronizer { view.getNode().detachAllChildren(); // Entfernt alle visuellen Elemente vom Knoten } - @Override + public Spatial visit(Figure figure) { return figure.accept(this); } diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/ParticleEffectFactory.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/ParticleEffectFactory.java index f1e18bf..790400c 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/ParticleEffectFactory.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/ParticleEffectFactory.java @@ -1,12 +1,7 @@ package pp.monopoly.client.gui; -import com.jme3.effect.ParticleEmitter; import com.jme3.effect.ParticleMesh.Type; -import com.jme3.effect.shapes.EmitterSphereShape; -import com.jme3.material.Material; -import com.jme3.math.ColorRGBA; -import com.jme3.math.FastMath; -import com.jme3.math.Vector3f; + import pp.monopoly.client.MonopolyApp; /** diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/SettingsMenu.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/SettingsMenu.java index 1424bd4..6997c45 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/SettingsMenu.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/SettingsMenu.java @@ -88,8 +88,13 @@ public class SettingsMenu extends Dialog { */ @Override public void close() { - app.getGuiNode().detachChild(settingsContainer); - app.getGuiNode().detachChild(overlayBackground); - app.setSettingsMenuOpen(false); + System.out.println("Schließe SettingsMenu..."); // Debugging-Ausgabe + app.getGuiNode().detachChild(settingsContainer); // Entferne das Menü + app.getGuiNode().detachChild(overlayBackground); // Entferne das Overlay + app.setSettingsMenuOpen(false); // Menü als geschlossen markieren + app.unblockInputs(); // Eingaben wieder aktivieren + System.out.println("SettingsMenu geschlossen."); // Debugging-Ausgabe } + + } diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/TestWorld.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/TestWorld.java index b0a82fc..34fb5dc 100644 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/TestWorld.java +++ b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/TestWorld.java @@ -1,39 +1,78 @@ package pp.monopoly.client.gui; -import com.jme3.app.SimpleApplication; import com.jme3.material.Material; import com.jme3.math.Vector3f; import com.jme3.scene.Geometry; import com.jme3.scene.shape.Box; import com.jme3.texture.Texture; +import pp.monopoly.client.MonopolyApp; + /** * TestWorld zeigt eine einfache Szene mit einem texturierten Quadrat. + * Die Kamera wird durch den CameraController gesteuert. */ -public class TestWorld extends SimpleApplication { +public class TestWorld { - @Override - public void simpleInitApp() { + private final MonopolyApp app; + private CameraController cameraController; // Steuert die Kamera + + /** + * Konstruktor für TestWorld. + * + * @param app Die Hauptanwendung (MonopolyApp) + */ + public TestWorld(MonopolyApp app) { + this.app = app; + } + + /** + * Initialisiert die Szene und startet die Kamerabewegung. + */ + public void initializeScene() { + app.getGuiNode().detachAllChildren(); // Entferne GUI + app.getRootNode().detachAllChildren(); // Entferne andere Szenenobjekte + + createBoard(); // Erstelle das Spielfeld + + // Erstelle den CameraController + cameraController = new CameraController( + app.getCamera(), // Die Kamera der App + Vector3f.ZERO, // Fokus auf die Mitte des Spielfelds + 5, // Radius des Kreises + 3, // Höhe der Kamera + 0.5f // Geschwindigkeit der Bewegung + ); + + // Deaktiviere den Maus-Cursor + app.enqueue(() -> app.getInputManager().setCursorVisible(false)); + } + + /** + * Aktualisiert die Kameraposition. + * + * @param tpf Zeit pro Frame + */ + public void update(float tpf) { + if (cameraController != null) { + cameraController.update(tpf); + } + } + + /** + * Erstelle das Spielfeld. + */ + private void createBoard() { // Erstelle ein Quadrat Box box = new Box(1, 0.01f, 1); // Dünnes Quadrat für die Textur Geometry geom = new Geometry("Box", box); // Setze das Material mit Textur - Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); - Texture texture = assetManager.loadTexture("Pictures/board.png"); // Ersetze durch den Pfad zum gewünschten Bild + Material mat = new Material(app.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md"); + Texture texture = app.getAssetManager().loadTexture("Pictures/board.png"); mat.setTexture("ColorMap", texture); geom.setMaterial(mat); - // Füge das Quadrat zur Szene hinzu - rootNode.attachChild(geom); - - // Setze die Kameraposition, um das Quadrat zu fokussieren - cam.setLocation(new Vector3f(0, 0, 3)); // Kamera auf der Z-Achse, nah am Quadrat - cam.lookAt(geom.getLocalTranslation(), Vector3f.UNIT_Y); - } - - public static void startTestWorld() { - TestWorld testWorldApp = new TestWorld(); - testWorldApp.start(); + app.getRootNode().attachChild(geom); } } diff --git a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/TestWorldWithMenu.java b/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/TestWorldWithMenu.java deleted file mode 100644 index 8240049..0000000 --- a/Projekte/monopoly/client/src/main/java/pp/monopoly/client/gui/TestWorldWithMenu.java +++ /dev/null @@ -1,80 +0,0 @@ -package pp.monopoly.client.gui; - -import com.jme3.app.SimpleApplication; -import com.jme3.material.Material; -import com.jme3.math.Vector3f; -import com.jme3.scene.Geometry; -import com.jme3.scene.shape.Box; -import com.jme3.texture.Texture; -import com.jme3.system.JmeCanvasContext; -import com.jme3.system.AppSettings; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; - -public class TestWorldWithMenu extends SimpleApplication { - - public static void createAndShowGUI() { - // Create JFrame - JFrame frame = new JFrame("Test World with Menu"); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setLayout(new BorderLayout()); - frame.setSize(800, 600); - - // Create Menu Bar - JMenuBar menuBar = new JMenuBar(); - JMenu fileMenu = new JMenu("File"); - JMenuItem exitItem = new JMenuItem(new AbstractAction("Exit") { - @Override - public void actionPerformed(ActionEvent e) { - System.exit(0); - } - }); - fileMenu.add(exitItem); - menuBar.add(fileMenu); - frame.setJMenuBar(menuBar); - - // Create Canvas for jMonkey - AppSettings settings = new AppSettings(true); - settings.setWidth(800); - settings.setHeight(600); - - TestWorldWithMenu app = new TestWorldWithMenu(); - app.setSettings(settings); - app.createCanvas(); // Create a canvas for embedding - JmeCanvasContext ctx = (JmeCanvasContext) app.getContext(); - ctx.setSystemListener(app); - Canvas canvas = ctx.getCanvas(); - canvas.setSize(800, 600); - - // Add the canvas to JFrame - frame.add(canvas, BorderLayout.CENTER); - - // Show the frame - frame.setVisible(true); - - // Start the jMonkeyEngine application - app.startCanvas(); - } - - @Override - public void simpleInitApp() { - // Erstelle ein Quadrat - Box box = new Box(1, 0.01f, 1); // Dünnes Quadrat für die Textur - Geometry geom = new Geometry("Box", box); - - // Setze das Material mit Textur - Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); - Texture texture = assetManager.loadTexture("Pictures/board.png"); // Replace with the path to your image - mat.setTexture("ColorMap", texture); - geom.setMaterial(mat); - - // Füge das Quadrat zur Szene hinzu - rootNode.attachChild(geom); - - // Setze die Kameraposition, um das Quadrat zu fokussieren - cam.setLocation(new Vector3f(0, 0, 3)); // Kamera auf der Z-Achse, nah am Quadrat - cam.lookAt(geom.getLocalTranslation(), Vector3f.UNIT_Y); - } -}