95 lines
4.0 KiB
Java
95 lines
4.0 KiB
Java
package de.blight.game.control;
|
|
|
|
import com.jme3.input.InputManager;
|
|
import com.jme3.input.MouseInput;
|
|
import com.jme3.input.controls.AnalogListener;
|
|
import com.jme3.input.controls.MouseAxisTrigger;
|
|
import com.jme3.math.*;
|
|
import com.jme3.renderer.Camera;
|
|
import com.jme3.scene.Spatial;
|
|
|
|
/**
|
|
* Third-Person-Kamera:
|
|
* - Mausbewegung → Kamera um den Charakter drehen (immer, kein Klick nötig)
|
|
* - Y-Achse invertiert → Maus hoch = Kamera runter (oldschool)
|
|
* - Mausrad → Zoom (Abstand)
|
|
*/
|
|
public class ThirdPersonCamera {
|
|
|
|
private static final float MOUSE_SENSITIVITY = 1.8f;
|
|
private static final float BASE_DISTANCE = 5f;
|
|
private static final float MIN_DISTANCE = BASE_DISTANCE - 3f;
|
|
private static final float MAX_DISTANCE = BASE_DISTANCE + 3f;
|
|
private static final float MIN_VERTICAL_ANGLE = 0.08f; // Kamera immer leicht über Schulter
|
|
private static final float MAX_VERTICAL_ANGLE = FastMath.HALF_PI - 0.1f;
|
|
private static final float TARGET_HEIGHT = 1.0f;
|
|
|
|
private final Camera cam;
|
|
private final InputManager inputManager;
|
|
|
|
private Spatial target;
|
|
|
|
private float yaw = 0f;
|
|
private float pitch = 0.4f;
|
|
private float distance = BASE_DISTANCE;
|
|
private boolean paused = false;
|
|
|
|
public ThirdPersonCamera(Camera cam, InputManager inputManager) {
|
|
this.cam = cam;
|
|
this.inputManager = inputManager;
|
|
registerMappings();
|
|
}
|
|
|
|
public void setTarget(Spatial target) {
|
|
this.target = target;
|
|
}
|
|
|
|
public void setPaused(boolean paused) { this.paused = paused; }
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
private void registerMappings() {
|
|
inputManager.addMapping("ZoomIn", new MouseAxisTrigger(MouseInput.AXIS_WHEEL, false));
|
|
inputManager.addMapping("ZoomOut", new MouseAxisTrigger(MouseInput.AXIS_WHEEL, true));
|
|
inputManager.addMapping("MouseX", new MouseAxisTrigger(MouseInput.AXIS_X, false));
|
|
inputManager.addMapping("MouseXNeg", new MouseAxisTrigger(MouseInput.AXIS_X, true));
|
|
inputManager.addMapping("MouseY", new MouseAxisTrigger(MouseInput.AXIS_Y, false));
|
|
inputManager.addMapping("MouseYNeg", new MouseAxisTrigger(MouseInput.AXIS_Y, true));
|
|
|
|
AnalogListener analogListener = (name, value, tpf) -> {
|
|
if (paused) return;
|
|
switch (name) {
|
|
// Horizontale Rotation
|
|
case "MouseX" -> yaw -= value * MOUSE_SENSITIVITY;
|
|
case "MouseXNeg" -> yaw += value * MOUSE_SENSITIVITY;
|
|
// Vertikale Rotation — Y invertiert: Maus hoch → Kamera runter
|
|
case "MouseY" -> pitch = FastMath.clamp(pitch - value * MOUSE_SENSITIVITY, MIN_VERTICAL_ANGLE, MAX_VERTICAL_ANGLE);
|
|
case "MouseYNeg" -> pitch = FastMath.clamp(pitch + value * MOUSE_SENSITIVITY, MIN_VERTICAL_ANGLE, MAX_VERTICAL_ANGLE);
|
|
// Zoom
|
|
case "ZoomIn" -> distance = FastMath.clamp(distance - value * 0.5f, MIN_DISTANCE, MAX_DISTANCE);
|
|
case "ZoomOut" -> distance = FastMath.clamp(distance + value * 0.5f, MIN_DISTANCE, MAX_DISTANCE);
|
|
}
|
|
};
|
|
inputManager.addListener(analogListener,
|
|
"MouseX", "MouseXNeg", "MouseY", "MouseYNeg", "ZoomIn", "ZoomOut");
|
|
}
|
|
|
|
public void update(float tpf) {
|
|
if (target == null || paused) return;
|
|
|
|
Vector3f pivot = target.getWorldTranslation().add(0, TARGET_HEIGHT, 0);
|
|
|
|
// Sphärische Koordinaten → kartesisch
|
|
float x = distance * FastMath.cos(pitch) * FastMath.sin(yaw);
|
|
float y = distance * FastMath.sin(pitch);
|
|
float z = distance * FastMath.cos(pitch) * FastMath.cos(yaw);
|
|
|
|
Vector3f camPos = pivot.add(x, y, z);
|
|
cam.setLocation(camPos);
|
|
cam.lookAt(pivot, Vector3f.UNIT_Y);
|
|
}
|
|
|
|
/** Aktueller Yaw-Winkel (für CharacterControl nutzbar). */
|
|
public float getYaw() { return yaw; }
|
|
}
|