Compare commits
	
		
			15 Commits
		
	
	
		
			0a34751825
			...
			d18cea435c
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					d18cea435c | ||
| 
						 | 
					1543f0dcea | ||
| 
						 | 
					ae181e4eff | ||
| 
						 | 
					fa96324c15 | ||
| 
						 | 
					9f559fe0d7 | ||
| 
						 | 
					cf6ee535b8 | ||
| 
						 | 
					be89bf1a27 | ||
| 
						 | 
					6f2027c2fb | ||
| 
						 | 
					6e99f17787 | ||
| 
						 | 
					b7e2e3213a | ||
| 
						 | 
					3ea6452d6d | ||
| 
						 | 
					fd3c141967 | ||
| 
						 | 
					b3d2dfed08 | ||
| 
						 | 
					5306208107 | ||
| 
						 | 
					2a7cbeed89 | 
@@ -8,6 +8,7 @@ import com.jme3.effect.ParticleMesh;
 | 
			
		||||
import com.jme3.effect.shapes.EmitterSphereShape;
 | 
			
		||||
import com.jme3.light.AmbientLight;
 | 
			
		||||
import com.jme3.light.DirectionalLight;
 | 
			
		||||
import com.jme3.light.PointLight;
 | 
			
		||||
import com.jme3.material.Material;
 | 
			
		||||
import com.jme3.math.ColorRGBA;
 | 
			
		||||
import com.jme3.math.FastMath;
 | 
			
		||||
@@ -19,6 +20,8 @@ import com.jme3.scene.Geometry;
 | 
			
		||||
import com.jme3.scene.Node;
 | 
			
		||||
import com.jme3.scene.Spatial;
 | 
			
		||||
import com.jme3.scene.shape.Box;
 | 
			
		||||
import com.jme3.scene.shape.Cylinder;
 | 
			
		||||
import com.jme3.scene.shape.Sphere;
 | 
			
		||||
import com.jme3.shadow.DirectionalLightShadowRenderer;
 | 
			
		||||
import com.jme3.shadow.EdgeFilteringMode;
 | 
			
		||||
import com.jme3.texture.Texture;
 | 
			
		||||
@@ -26,6 +29,8 @@ import com.jme3.util.SkyFactory;
 | 
			
		||||
import com.jme3.util.TangentBinormalGenerator;
 | 
			
		||||
 | 
			
		||||
import pp.monopoly.client.gui.BobTheBuilder;
 | 
			
		||||
import pp.monopoly.client.gui.CameraController;
 | 
			
		||||
import pp.monopoly.client.gui.CameraInputHandler;
 | 
			
		||||
import pp.monopoly.client.gui.Toolbar;
 | 
			
		||||
import pp.monopoly.model.Board;
 | 
			
		||||
import pp.monopoly.client.gui.FigureControl;
 | 
			
		||||
@@ -74,6 +79,15 @@ public class BoardAppState extends MonopolyAppState {
 | 
			
		||||
 | 
			
		||||
    private Vector3f currentTarget = new Vector3f(-10f,0,-10f);
 | 
			
		||||
 | 
			
		||||
    private float modelHeight = -5f;
 | 
			
		||||
    private final float targetHeight = 0f; 
 | 
			
		||||
    private final float animationSpeed = 0.01389f; 
 | 
			
		||||
    private Node modelNode;
 | 
			
		||||
    private boolean startAnimation = false; 
 | 
			
		||||
    private CameraController cameraController;
 | 
			
		||||
    private CameraInputHandler cameraInputHandler;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initializes the state by setting up the sky, lights, and other visual components.
 | 
			
		||||
     * This method is called when the state is first attached to the state manager.
 | 
			
		||||
@@ -84,12 +98,16 @@ public class BoardAppState extends MonopolyAppState {
 | 
			
		||||
    @Override
 | 
			
		||||
    public void initialize(AppStateManager stateManager, Application application) {
 | 
			
		||||
        super.initialize(stateManager, application);
 | 
			
		||||
 | 
			
		||||
        // Initialisiere den CameraController zuerst
 | 
			
		||||
        cameraController = new CameraController(getApp().getCamera(), 25, 40);
 | 
			
		||||
 | 
			
		||||
        // Danach den CameraInputHandler mit dem initialisierten CameraController
 | 
			
		||||
        cameraInputHandler = new CameraInputHandler(cameraController, getApp().getInputManager());
 | 
			
		||||
 | 
			
		||||
        popUpManager = new PopUpManager(getApp());
 | 
			
		||||
        viewNode.attachChild(sceneNode);
 | 
			
		||||
 | 
			
		||||
        //TODO remove this only for camera testing
 | 
			
		||||
        adjustCamera();
 | 
			
		||||
        
 | 
			
		||||
        setupLights();
 | 
			
		||||
        setupSky();
 | 
			
		||||
    }
 | 
			
		||||
@@ -114,30 +132,6 @@ public class BoardAppState extends MonopolyAppState {
 | 
			
		||||
        }
 | 
			
		||||
        getApp().getRootNode().attachChild(viewNode);
 | 
			
		||||
    }
 | 
			
		||||
    //TODO remove this only for camera testing
 | 
			
		||||
    private static final float ABOVE_SEA_LEVEL = 10f;
 | 
			
		||||
    private static final float INCLINATION = 2.5f;
 | 
			
		||||
    private float cameraAngle;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Adjusts the camera position and orientation to create a circular motion around
 | 
			
		||||
     * the center of the map. This provides a dynamic view of the sea and surrounding environment.
 | 
			
		||||
     */
 | 
			
		||||
    private void adjustCamera() {
 | 
			
		||||
        final Board board = getGameLogic().getBoard();
 | 
			
		||||
        final float mx = 0.5f * board.getWidth();
 | 
			
		||||
        final float my = 0.5f * board.getHeight();
 | 
			
		||||
        final float radius = 2f * sqrt(mx * mx + my + my);
 | 
			
		||||
        final float cos = radius * cos(cameraAngle);
 | 
			
		||||
        final float sin = radius * sin(cameraAngle);
 | 
			
		||||
        final float x = mx - cos;
 | 
			
		||||
        final float y = my - sin;
 | 
			
		||||
        final Camera camera = getApp().getCamera();
 | 
			
		||||
        camera.setLocation(new Vector3f(0,10,0));
 | 
			
		||||
        camera.lookAt(new Vector3f(getCurrentTarget()),
 | 
			
		||||
                                    Vector3f.UNIT_Y);
 | 
			
		||||
        camera.update();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
@@ -154,18 +148,7 @@ public class BoardAppState extends MonopolyAppState {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the state each frame, moving the camera to simulate it circling around the map.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tpf the time per frame (seconds)
 | 
			
		||||
     */
 | 
			
		||||
    @Override
 | 
			
		||||
    public void update(float tpf) {
 | 
			
		||||
        super.update(tpf);
 | 
			
		||||
        //TODO remove this only for camera testing
 | 
			
		||||
        cameraAngle += TWO_PI * 0.05f * tpf;
 | 
			
		||||
        // adjustCamera();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets up the lighting for the scene, including directional and ambient lights.
 | 
			
		||||
@@ -198,8 +181,8 @@ public class BoardAppState extends MonopolyAppState {
 | 
			
		||||
        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 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);
 | 
			
		||||
@@ -229,18 +212,20 @@ public class BoardAppState extends MonopolyAppState {
 | 
			
		||||
        sceneNode.attachChild(createCardDeck());
 | 
			
		||||
        sceneNode.attachChild(seaGeo);
 | 
			
		||||
 | 
			
		||||
        addModelToCenter(sceneNode);
 | 
			
		||||
    
 | 
			
		||||
        // Schneefall hinzufügen
 | 
			
		||||
        addSnowEffect(sceneNode);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Node createCardDeck() {
 | 
			
		||||
        Node cardDeck = new Node("cardDeck");
 | 
			
		||||
        Spatial card = getApp().getAssetManager().loadModel("models/Kartendecks/Ereigniskarten_Deck.j3o");
 | 
			
		||||
        Spatial card = getApp().getAssetManager().loadModel("models/Kartendecks/Ereigniskarten.j3o");
 | 
			
		||||
        card.setLocalTranslation(5.5f, 0, 2.7f);
 | 
			
		||||
        card.setLocalScale(4.1f);
 | 
			
		||||
        card.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.QUARTER_PI, Vector3f.UNIT_Y));
 | 
			
		||||
 | 
			
		||||
        Spatial card2 = getApp().getAssetManager().loadModel("models/Kartendecks/Gemeinschaftskarten_Deck.j3o");
 | 
			
		||||
        Spatial card2 = getApp().getAssetManager().loadModel("models/Kartendecks/Gemeinschaftskarten.j3o");
 | 
			
		||||
        card2.setLocalTranslation(-1.4f, 0, -3.8f);
 | 
			
		||||
        card2.setLocalScale(4.1f);
 | 
			
		||||
        card2.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.QUARTER_PI , Vector3f.UNIT_Y));
 | 
			
		||||
@@ -282,4 +267,87 @@ public class BoardAppState extends MonopolyAppState {
 | 
			
		||||
        // Emitter zur Szene hinzufügen
 | 
			
		||||
        parentNode.attachChild(snowEmitter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void addModelToCenter(Node parentNode) {
 | 
			
		||||
        AssetManager assetManager = getApp().getAssetManager();
 | 
			
		||||
    
 | 
			
		||||
        Material material = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
 | 
			
		||||
        material.setColor("Diffuse", ColorRGBA.White);
 | 
			
		||||
        material.setBoolean("UseMaterialColors", true);
 | 
			
		||||
    
 | 
			
		||||
        Sphere lowerSphereLeft = new Sphere(32, 32, 0.5f);
 | 
			
		||||
        Geometry lowerSphereLeftGeom = new Geometry("LowerSphereLeft", lowerSphereLeft);
 | 
			
		||||
        lowerSphereLeftGeom.setMaterial(material);
 | 
			
		||||
        lowerSphereLeftGeom.setLocalTranslation(-0.6f - 4f, 0.5f, 0.3f - 5f);
 | 
			
		||||
 | 
			
		||||
        Sphere lowerSphereRight = new Sphere(32, 32, 0.5f);
 | 
			
		||||
        Geometry lowerSphereRightGeom = new Geometry("LowerSphereRight", lowerSphereRight);
 | 
			
		||||
        lowerSphereRightGeom.setMaterial(material);
 | 
			
		||||
        lowerSphereRightGeom.setLocalTranslation(0.6f - 4f, 0.5f, 0.3f - 5f);
 | 
			
		||||
 | 
			
		||||
        Cylinder cylinder = new Cylinder(16, 16, 0.4f, 2f, true);
 | 
			
		||||
        Geometry cylinderGeom = new Geometry("Cylinder", cylinder);
 | 
			
		||||
        cylinderGeom.setMaterial(material);
 | 
			
		||||
        cylinderGeom.setLocalTranslation(0f - 4f, 1.5f, 0f - 5f);
 | 
			
		||||
        cylinderGeom.rotate(FastMath.HALF_PI, 0, 0);
 | 
			
		||||
 | 
			
		||||
        Sphere upperSphere = new Sphere(32, 32, 0.4f);
 | 
			
		||||
        Geometry upperSphereGeom = new Geometry("UpperSphere", upperSphere);
 | 
			
		||||
        upperSphereGeom.setMaterial(material);
 | 
			
		||||
        upperSphereGeom.setLocalTranslation(0f - 4f, 2.5f, 0f - 5f);
 | 
			
		||||
 | 
			
		||||
        this.modelNode = new Node("3DModel");
 | 
			
		||||
        this.modelNode.attachChild(lowerSphereLeftGeom);
 | 
			
		||||
        this.modelNode.attachChild(lowerSphereRightGeom);
 | 
			
		||||
        this.modelNode.attachChild(cylinderGeom);
 | 
			
		||||
        this.modelNode.attachChild(upperSphereGeom);
 | 
			
		||||
 | 
			
		||||
        this.modelNode.setLocalTranslation(0, modelHeight, 0);
 | 
			
		||||
        parentNode.attachChild(this.modelNode);
 | 
			
		||||
 | 
			
		||||
        PointLight lightLeft = new PointLight();
 | 
			
		||||
        lightLeft.setColor(ColorRGBA.Blue);
 | 
			
		||||
        lightLeft.setPosition(new Vector3f(-0.6f - 4f, 0f, 0.3f - 5f));
 | 
			
		||||
        lightLeft.setRadius(2f);
 | 
			
		||||
        parentNode.addLight(lightLeft);
 | 
			
		||||
 | 
			
		||||
        PointLight lightRight = new PointLight();
 | 
			
		||||
        lightRight.setColor(ColorRGBA.Blue);
 | 
			
		||||
        lightRight.setPosition(new Vector3f(0.6f - 4f, 0f, 0.3f - 5f));
 | 
			
		||||
        lightRight.setRadius(2f);
 | 
			
		||||
        parentNode.addLight(lightRight);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    public void update(float tpf) {
 | 
			
		||||
        super.update(tpf);
 | 
			
		||||
        if (startAnimation && modelHeight < targetHeight) {
 | 
			
		||||
            modelHeight += animationSpeed * tpf; // Geschwindigkeit basierend auf Zeit pro Frame
 | 
			
		||||
            if (modelHeight > targetHeight) {
 | 
			
		||||
                modelHeight = targetHeight; // Zielhöhe nicht überschreiten
 | 
			
		||||
                startAnimation = false; // Animation beenden
 | 
			
		||||
            }
 | 
			
		||||
            updateModelHeight(); // Aktualisiere die Position des Modells
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    private void updateModelHeight() {
 | 
			
		||||
        if (modelNode == null) {
 | 
			
		||||
            modelNode = (Node) sceneNode.getChild("3DModel");
 | 
			
		||||
        }
 | 
			
		||||
        if (modelNode != null) {
 | 
			
		||||
            modelNode.setLocalTranslation(0, modelHeight, 0); // Aktualisiere die Y-Position
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void onRollDicePressed() {
 | 
			
		||||
        System.out.println("onRollDicePressed called");
 | 
			
		||||
        if (!startAnimation) {
 | 
			
		||||
            startAnimation = true;
 | 
			
		||||
            modelHeight = -5f; // Reset der Höhe
 | 
			
		||||
            updateModelHeight(); // Stelle sicher, dass das Modell an der Startposition ist
 | 
			
		||||
            System.out.println("Animation started, startAnimation set to: " + startAnimation);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -3,64 +3,57 @@ package pp.monopoly.client.gui;
 | 
			
		||||
import com.jme3.math.Vector3f;
 | 
			
		||||
import com.jme3.renderer.Camera;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Controls the movement of the camera within the scene.
 | 
			
		||||
 */
 | 
			
		||||
public class CameraController {
 | 
			
		||||
    public enum CameraMode {
 | 
			
		||||
        FOCUS_CURRENT_PLAYER,
 | 
			
		||||
        FOCUS_SELF,
 | 
			
		||||
        FREECAM
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private final Camera camera;
 | 
			
		||||
    private final float height = 25;    // Height of the camera above the game board
 | 
			
		||||
    private CameraMode currentMode = CameraMode.FOCUS_CURRENT_PLAYER;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor for the CameraController.
 | 
			
		||||
     *
 | 
			
		||||
     * @param camera The camera to be controlled
 | 
			
		||||
     */
 | 
			
		||||
    public CameraController(Camera camera) {
 | 
			
		||||
    private final float height;  // Höhe der Kamera
 | 
			
		||||
    private final float offset;  // Versatz zur Spielfeldseite
 | 
			
		||||
 | 
			
		||||
    public CameraController(Camera camera, float height, float offset) {
 | 
			
		||||
        this.camera = camera;
 | 
			
		||||
        setPosition(0);
 | 
			
		||||
        camera.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);
 | 
			
		||||
        this.height = height;
 | 
			
		||||
        this.offset = offset;
 | 
			
		||||
        setMode(currentMode);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setMode(CameraMode mode) {
 | 
			
		||||
        this.currentMode = mode;
 | 
			
		||||
        updatePosition(0); // Standardmäßig das Startfeld fokussieren
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the camera's position and orientation.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tpf Time per frame
 | 
			
		||||
     */
 | 
			
		||||
    public void update(float tpf) {
 | 
			
		||||
        if (currentMode != CameraMode.FREECAM) {
 | 
			
		||||
            camera.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the camera's position based on the field ID.
 | 
			
		||||
     *
 | 
			
		||||
     * @param fieldID The ID of the field to which the camera should move
 | 
			
		||||
     */
 | 
			
		||||
    public void setPosition(int fieldID) {
 | 
			
		||||
        camera.setLocation(fieldIdToVector(fieldID));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the camera's position using specific coordinates.
 | 
			
		||||
     *
 | 
			
		||||
     * @param x The X-coordinate of the new camera position
 | 
			
		||||
     * @param y The Y-coordinate of the new camera position
 | 
			
		||||
     */
 | 
			
		||||
    public void setPosition(float x, float y) {
 | 
			
		||||
        camera.setLocation(new Vector3f(x, height, y));
 | 
			
		||||
    public void updatePosition(int fieldID) {
 | 
			
		||||
        Vector3f newPosition = fieldIdToVector(fieldID);
 | 
			
		||||
        camera.setLocation(newPosition);
 | 
			
		||||
        if (currentMode != CameraMode.FREECAM) {
 | 
			
		||||
            camera.lookAt(Vector3f.ZERO, Vector3f.UNIT_Y);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Maps a field ID to its corresponding position in the game world.
 | 
			
		||||
     *
 | 
			
		||||
     * @param fieldID The ID of the field
 | 
			
		||||
     * @return The position of the field as a {@link Vector3f}
 | 
			
		||||
     * @throws IllegalArgumentException If the field ID is invalid
 | 
			
		||||
     */
 | 
			
		||||
    private Vector3f fieldIdToVector(int fieldID) {
 | 
			
		||||
        if (fieldID <= 10) return new Vector3f(30, height, 0);
 | 
			
		||||
        if (fieldID <= 20) return new Vector3f(0, height, 30);
 | 
			
		||||
        if (fieldID <= 30) return new Vector3f(-30, height, 0);
 | 
			
		||||
        if (fieldID <= 40) return new Vector3f(0, height, -30);
 | 
			
		||||
        else throw new IllegalArgumentException();
 | 
			
		||||
        switch (currentMode) {
 | 
			
		||||
            case FOCUS_CURRENT_PLAYER:
 | 
			
		||||
                if (fieldID <= 10) return new Vector3f(offset, height, 0);
 | 
			
		||||
                if (fieldID <= 20) return new Vector3f(0, height, offset);
 | 
			
		||||
                if (fieldID <= 30) return new Vector3f(-offset, height, 0);
 | 
			
		||||
                return new Vector3f(0, height, -offset);
 | 
			
		||||
            case FOCUS_SELF:
 | 
			
		||||
                return new Vector3f(0, height, fieldID <= 20 ? offset : -offset);
 | 
			
		||||
            case FREECAM:
 | 
			
		||||
            default:
 | 
			
		||||
                return new Vector3f(0, height, 0); 
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,60 +1,31 @@
 | 
			
		||||
//package pp.monopoly.client.gui;
 | 
			
		||||
//
 | 
			
		||||
//import com.jme3.input.InputManager;
 | 
			
		||||
//import com.jme3.input.KeyInput;
 | 
			
		||||
//import com.jme3.input.controls.ActionListener;
 | 
			
		||||
//import com.jme3.input.controls.KeyTrigger;
 | 
			
		||||
//
 | 
			
		||||
///**
 | 
			
		||||
// * Handhabt die Eingaben für die Kamera.
 | 
			
		||||
// */
 | 
			
		||||
//public class CameraInputHandler {
 | 
			
		||||
//
 | 
			
		||||
//    private CameraController cameraController; // Kamera-Controller
 | 
			
		||||
//
 | 
			
		||||
//    /**
 | 
			
		||||
//     * Konstruktor für den CameraInputHandler.
 | 
			
		||||
//     *
 | 
			
		||||
//     * @param cameraController Der Kamera-Controller, der gesteuert werden soll.
 | 
			
		||||
//     * @param inputManager     Der InputManager, um Eingaben zu registrieren.
 | 
			
		||||
//     */
 | 
			
		||||
//    public CameraInputHandler(CameraController cameraController, InputManager inputManager) {
 | 
			
		||||
//        if (cameraController == null || inputManager == null) {
 | 
			
		||||
//            throw new IllegalArgumentException("CameraController und InputManager dürfen nicht null sein");
 | 
			
		||||
//        }
 | 
			
		||||
//        this.cameraController = cameraController;
 | 
			
		||||
//
 | 
			
		||||
//        // Mappings für Kamerasteuerung
 | 
			
		||||
//        inputManager.addMapping("FocusCurrentPlayer", new KeyTrigger(KeyInput.KEY_1)); // Modus 1
 | 
			
		||||
//        inputManager.addMapping("FocusSelf", new KeyTrigger(KeyInput.KEY_2));         // Modus 2
 | 
			
		||||
//        inputManager.addMapping("FreeCam", new KeyTrigger(KeyInput.KEY_3));          // Modus 3
 | 
			
		||||
//
 | 
			
		||||
//        // Listener für die Kameramodi
 | 
			
		||||
//        inputManager.addListener(actionListener, "FocusCurrentPlayer", "FocusSelf", "FreeCam");
 | 
			
		||||
//    }
 | 
			
		||||
//
 | 
			
		||||
//    /**
 | 
			
		||||
//     * ActionListener für die Kamerasteuerung.
 | 
			
		||||
//     */
 | 
			
		||||
//    private final ActionListener actionListener = (name, isPressed, tpf) -> {
 | 
			
		||||
//        if (!isPressed) return;
 | 
			
		||||
//
 | 
			
		||||
//        // Umschalten der Kamera-Modi basierend auf der Eingabe
 | 
			
		||||
//        switch (name) {
 | 
			
		||||
//            case "FocusCurrentPlayer" -> {
 | 
			
		||||
//                cameraController.setMode(CameraController.CameraMode.FOCUS_CURRENT_PLAYER);
 | 
			
		||||
//                System.out.println("Kameramodus: Fokus auf aktuellen Spieler");
 | 
			
		||||
//            }
 | 
			
		||||
//            case "FocusSelf" -> {
 | 
			
		||||
//                cameraController.setMode(CameraController.CameraMode.FOCUS_SELF);
 | 
			
		||||
//                System.out.println("Kameramodus: Fokus auf eigene Figur");
 | 
			
		||||
//            }
 | 
			
		||||
//            case "FreeCam" -> {
 | 
			
		||||
//                cameraController.setMode(CameraController.CameraMode.FREECAM);
 | 
			
		||||
//                System.out.println("Kameramodus: Freie Kamera");
 | 
			
		||||
//            }
 | 
			
		||||
//            default -> System.err.println("Unbekannter Kameramodus: " + name);
 | 
			
		||||
//        }
 | 
			
		||||
//    };
 | 
			
		||||
//}
 | 
			
		||||
//
 | 
			
		||||
package pp.monopoly.client.gui;
 | 
			
		||||
 | 
			
		||||
import com.jme3.input.InputManager;
 | 
			
		||||
import com.jme3.input.KeyInput;
 | 
			
		||||
import com.jme3.input.controls.ActionListener;
 | 
			
		||||
import com.jme3.input.controls.KeyTrigger;
 | 
			
		||||
 | 
			
		||||
public class CameraInputHandler {
 | 
			
		||||
    private CameraController cameraController;
 | 
			
		||||
 | 
			
		||||
    public CameraInputHandler(CameraController cameraController, InputManager inputManager) {
 | 
			
		||||
        this.cameraController = cameraController;
 | 
			
		||||
 | 
			
		||||
        // Tasten für die verschiedenen Kameramodi registrieren
 | 
			
		||||
        inputManager.addMapping("FocusCurrentPlayer", new KeyTrigger(KeyInput.KEY_1));
 | 
			
		||||
        inputManager.addMapping("FocusSelf", new KeyTrigger(KeyInput.KEY_2));
 | 
			
		||||
        inputManager.addMapping("FreeCam", new KeyTrigger(KeyInput.KEY_3));
 | 
			
		||||
 | 
			
		||||
        inputManager.addListener(actionListener, "FocusCurrentPlayer", "FocusSelf", "FreeCam");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private final ActionListener actionListener = (name, isPressed, tpf) -> {
 | 
			
		||||
        if (!isPressed) return;
 | 
			
		||||
 | 
			
		||||
        switch (name) {
 | 
			
		||||
            case "FocusCurrentPlayer" -> cameraController.setMode(CameraController.CameraMode.FOCUS_CURRENT_PLAYER);
 | 
			
		||||
            case "FocusSelf" -> cameraController.setMode(CameraController.CameraMode.FOCUS_SELF);
 | 
			
		||||
            case "FreeCam" -> cameraController.setMode(CameraController.CameraMode.FREECAM);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
@@ -20,6 +20,7 @@ import com.simsilica.lemur.event.MouseEventControl;
 | 
			
		||||
import com.simsilica.lemur.event.MouseListener;
 | 
			
		||||
import com.simsilica.lemur.style.ElementId;
 | 
			
		||||
import pp.dialog.Dialog;
 | 
			
		||||
import pp.monopoly.client.BoardAppState;
 | 
			
		||||
import pp.monopoly.client.MonopolyApp;
 | 
			
		||||
import pp.monopoly.client.gui.popups.Bankrupt;
 | 
			
		||||
import pp.monopoly.game.server.Player;
 | 
			
		||||
@@ -101,6 +102,7 @@ public class Toolbar extends Dialog implements GameEventListener {
 | 
			
		||||
        setupBorders(container);
 | 
			
		||||
        setupSpacer(container);
 | 
			
		||||
        setupPlayerInfoSection(container);
 | 
			
		||||
        setupSpacer(container);
 | 
			
		||||
        setupDiceSection(container);
 | 
			
		||||
        setupActionMenu(container);
 | 
			
		||||
 | 
			
		||||
@@ -289,8 +291,14 @@ public class Toolbar extends Dialog implements GameEventListener {
 | 
			
		||||
        startDiceAnimation();
 | 
			
		||||
        app.getGameLogic().send(new RollDice());
 | 
			
		||||
        app.getGameLogic().playSound(Sound.BUTTON);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Animation in BoardAppState starten
 | 
			
		||||
        BoardAppState boardAppState = app.getStateManager().getState(BoardAppState.class);
 | 
			
		||||
        if (boardAppState != null) {
 | 
			
		||||
            boardAppState.onRollDicePressed(); // Animation starten
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private Button createTradeButton() {
 | 
			
		||||
@@ -307,6 +315,7 @@ public class Toolbar extends Dialog implements GameEventListener {
 | 
			
		||||
 | 
			
		||||
        tradeButton.addClickCommands(s -> ifTopDialog(() -> {
 | 
			
		||||
            new ChoosePartner(app).open();
 | 
			
		||||
            
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        return tradeButton;
 | 
			
		||||
 
 | 
			
		||||
@@ -73,7 +73,7 @@ public class Bankrupt extends Dialog implements PopupDialog {
 | 
			
		||||
    private void createBankruptContainer() {
 | 
			
		||||
        bankruptContainer = new Container();
 | 
			
		||||
        bankruptContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f)));
 | 
			
		||||
        bankruptContainer.setPreferredSize(new Vector3f(550, 250, 10));
 | 
			
		||||
        bankruptContainer.setPreferredSize(new Vector3f(550, 350, 10));
 | 
			
		||||
 | 
			
		||||
        // Title
 | 
			
		||||
        Label title = bankruptContainer.addChild(new Label("Vorsicht!", new ElementId("warning-title")));
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
package pp.monopoly.client.gui.popups;
 | 
			
		||||
 | 
			
		||||
import com.jme3.math.ColorRGBA;
 | 
			
		||||
import com.jme3.math.Vector3f;
 | 
			
		||||
import com.simsilica.lemur.Button;
 | 
			
		||||
import com.simsilica.lemur.Container;
 | 
			
		||||
import com.simsilica.lemur.Label;
 | 
			
		||||
@@ -41,6 +42,7 @@ public class BuildingPropertyCard extends Dialog implements PopupDialog {
 | 
			
		||||
        buildingPropertyContainer = new Container();
 | 
			
		||||
        buildingPropertyContainer.setBackground(new QuadBackgroundComponent(field.getColor().getColor()));
 | 
			
		||||
        addContentToContainer(buildingPropertyContainer, field);
 | 
			
		||||
        buildingPropertyContainer.setPreferredSize(new Vector3f(360,420,1));
 | 
			
		||||
 | 
			
		||||
        // Create the background container
 | 
			
		||||
        backgroundContainer = new Container();
 | 
			
		||||
@@ -50,6 +52,9 @@ public class BuildingPropertyCard extends Dialog implements PopupDialog {
 | 
			
		||||
        float padding = 10f;
 | 
			
		||||
        backgroundContainer.setPreferredSize(buildingPropertyContainer.getPreferredSize().addLocal(padding, padding, 0));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        System.out.println(backgroundContainer.getPreferredSize());
 | 
			
		||||
 | 
			
		||||
        // Position the containers
 | 
			
		||||
        centerContainers(padding);
 | 
			
		||||
    }
 | 
			
		||||
@@ -64,7 +69,7 @@ public class BuildingPropertyCard extends Dialog implements PopupDialog {
 | 
			
		||||
        // Title
 | 
			
		||||
        Label title = container.addChild(new Label(field.getName(), new ElementId("label-Bold")));
 | 
			
		||||
        title.setBackground(new QuadBackgroundComponent(field.getColor().getColor()));
 | 
			
		||||
        title.setFontSize(48);
 | 
			
		||||
        title.setFontSize(38);
 | 
			
		||||
 | 
			
		||||
        // Property details
 | 
			
		||||
        Container propertyValuesContainer = container.addChild(new Container());
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,6 @@ import com.simsilica.lemur.Button;
 | 
			
		||||
import com.simsilica.lemur.Container;
 | 
			
		||||
import com.simsilica.lemur.Label;
 | 
			
		||||
import com.simsilica.lemur.Selector;
 | 
			
		||||
import com.simsilica.lemur.TextField;
 | 
			
		||||
import com.simsilica.lemur.component.QuadBackgroundComponent;
 | 
			
		||||
import com.simsilica.lemur.component.SpringGridLayout;
 | 
			
		||||
import com.simsilica.lemur.core.VersionedList;
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ 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.Button;
 | 
			
		||||
@@ -72,6 +73,7 @@ public class FoodFieldCard extends Dialog implements PopupDialog {
 | 
			
		||||
    private void createBackgroundContainer() {
 | 
			
		||||
        backgroundContainer = new Container();
 | 
			
		||||
        backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Light gray background
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -82,6 +84,7 @@ public class FoodFieldCard extends Dialog implements PopupDialog {
 | 
			
		||||
    private void createFoodFieldContainer(FoodField field) {
 | 
			
		||||
        foodFieldContainer = new Container();
 | 
			
		||||
        foodFieldContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.1f, 0.1f, 0.1f, 0.9f)));
 | 
			
		||||
        foodFieldContainer.setPreferredSize(new Vector3f(360,420,1));
 | 
			
		||||
 | 
			
		||||
        // Title
 | 
			
		||||
        Label title = foodFieldContainer.addChild(new Label(field.getName(), new ElementId("label-Bold")));
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
package pp.monopoly.client.gui.popups;
 | 
			
		||||
 | 
			
		||||
import com.jme3.math.ColorRGBA;
 | 
			
		||||
import com.jme3.math.Vector3f;
 | 
			
		||||
import com.simsilica.lemur.Button;
 | 
			
		||||
import com.simsilica.lemur.Container;
 | 
			
		||||
import com.simsilica.lemur.Label;
 | 
			
		||||
@@ -52,6 +53,7 @@ public class GateFieldCard extends Dialog implements PopupDialog {
 | 
			
		||||
    private void createBackgroundContainer() {
 | 
			
		||||
        backgroundContainer = new Container();
 | 
			
		||||
        backgroundContainer.setBackground(new QuadBackgroundComponent(new ColorRGBA(0.8657f, 0.8735f, 0.8892f, 1.0f))); // Light gray background
 | 
			
		||||
        gateFieldContainer.setPreferredSize(new Vector3f(360,420,1));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,6 @@ import com.simsilica.lemur.Button;
 | 
			
		||||
import com.simsilica.lemur.Container;
 | 
			
		||||
import com.simsilica.lemur.Label;
 | 
			
		||||
import com.simsilica.lemur.Selector;
 | 
			
		||||
import com.simsilica.lemur.TextField;
 | 
			
		||||
import com.simsilica.lemur.component.QuadBackgroundComponent;
 | 
			
		||||
import com.simsilica.lemur.component.SpringGridLayout;
 | 
			
		||||
import com.simsilica.lemur.core.VersionedList;
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,6 @@ import com.simsilica.lemur.Button;
 | 
			
		||||
import com.simsilica.lemur.Container;
 | 
			
		||||
import com.simsilica.lemur.Label;
 | 
			
		||||
import com.simsilica.lemur.Selector;
 | 
			
		||||
import com.simsilica.lemur.TextField;
 | 
			
		||||
import com.simsilica.lemur.component.QuadBackgroundComponent;
 | 
			
		||||
import com.simsilica.lemur.component.SpringGridLayout;
 | 
			
		||||
import com.simsilica.lemur.core.VersionedList;
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,6 @@ import com.simsilica.lemur.Button;
 | 
			
		||||
import com.simsilica.lemur.Container;
 | 
			
		||||
import com.simsilica.lemur.Label;
 | 
			
		||||
import com.simsilica.lemur.Selector;
 | 
			
		||||
import com.simsilica.lemur.TextField;
 | 
			
		||||
import com.simsilica.lemur.component.QuadBackgroundComponent;
 | 
			
		||||
import com.simsilica.lemur.component.SpringGridLayout;
 | 
			
		||||
import com.simsilica.lemur.core.VersionedList;
 | 
			
		||||
 
 | 
			
		||||
| 
		 After Width: | Height: | Size: 304 KiB  | 
| 
		 After Width: | Height: | Size: 94 KiB  | 
| 
		 Before Width: | Height: | Size: 518 KiB  | 
| 
		 Before Width: | Height: | Size: 55 KiB  | 
| 
		 Before Width: | Height: | Size: 552 KiB  | 
| 
		 Before Width: | Height: | Size: 100 KiB  | 
| 
		 Before Width: | Height: | Size: 24 MiB  | 
| 
		 Before Width: | Height: | Size: 66 KiB  | 
| 
		 Before Width: | Height: | Size: 200 KiB  | 
| 
		 Before Width: | Height: | Size: 6.7 MiB  | 
| 
		 Before Width: | Height: | Size: 31 MiB  | 
| 
		 Before Width: | Height: | Size: 18 MiB  | 
| 
		 Before Width: | Height: | Size: 209 KiB  | 
| 
		 Before Width: | Height: | Size: 41 KiB  |