Initial project

This commit is contained in:
2026-01-11 21:39:58 -06:00
commit 3bb1a9316b
8 changed files with 296 additions and 0 deletions

View File

@@ -0,0 +1,168 @@
using Godot;
public partial class PlayerCamera : Camera3D
{
[ExportCategory("Camera Movement")]
[Export] public float CameraPanSpeed { get; set; } = 20f;
[Export] public float CameraZoomSpeed { get; set; } = 20f;
[Export] public float CameraZoomMin { get; set; } = 10f;
[Export] public float CameraZoomMax { get; set; } = 50f;
[ExportCategory("Edge Scrolling")]
[Export] public float EdgeScrollMargin { get; set; } = 20f;
[Export] public float EdgeScrollSpeed { get; set; } = 15f;
[ExportCategory("Rotation")]
[Export] public float YawSensitivity { get; set; } = 0.5f;
[Export] public float PitchSensitivity { get; set; } = 0.18f;
[Export] public float StepDegreeMax { get; set; } = 3f;
[Export] public float PitchDegreeMin { get; set; } = 10f;
[Export] public float PitchDegreeMax { get; set; } = 80f;
[Export] public bool CaptureMiddleButton { get; set; } = false;
Vector3 origin = Vector3.Zero;
float orbitDistance = 25f;
float currentHeight = 20f;
float orbitRadius = 20f;
bool isMiddleMouseRotating = false;
float yaw = 0f;
float pitch = 0f;
public override void _Ready()
{
var pitchMin = Mathf.DegToRad(PitchDegreeMin);
var pitchMax = Mathf.DegToRad(PitchDegreeMax);
pitch = Mathf.Clamp(pitch, pitchMin, pitchMax);
UpdateCameraPosition();
}
public override void _Process(double delta)
{
var movement = Vector3.Zero;
// Keyboard Input
if (Input.IsActionPressed("camera_pan_right"))
{
movement.X += 1f;
}
if (Input.IsActionPressed("camera_pan_left"))
{
movement.X -= 1f;
}
if (Input.IsActionPressed("camera_pan_up"))
{
movement.Z += 1f;
}
if (Input.IsActionPressed("camera_pan_down"))
{
movement.Z -= 1f;
}
// Edge Scrolling
var mousePosition = GetViewport().GetMousePosition();
var viewportSize = GetViewport().GetVisibleRect().Size;
if (mousePosition.X < EdgeScrollMargin)
{
movement.X -= 1f;
}
if (mousePosition.X > viewportSize.X - EdgeScrollMargin)
{
movement.X += 1f;
}
if (mousePosition.Y < EdgeScrollMargin)
{
movement.Z -= 1f;
}
if (mousePosition.Y > viewportSize.Y - EdgeScrollMargin)
{
movement.Z += 1f;
}
// Rotating
if (movement.Length() > 0f)
{
movement = movement.Normalized().Rotated(Vector3.Up, yaw);
origin += movement * CameraPanSpeed * (float)delta;
UpdateCameraPosition();
}
}
public override void _UnhandledInput(InputEvent @event)
{
if (@event is InputEventMouseButton mouseButtonEvent)
{
if (mouseButtonEvent.Pressed)
{
var delta = (float)GetProcessDeltaTime();
if (mouseButtonEvent.ButtonIndex is MouseButton.WheelUp)
{
orbitDistance = Mathf.Max(CameraZoomMin, orbitDistance - CameraZoomSpeed * delta);
}
else if (mouseButtonEvent.ButtonIndex is MouseButton.WheelDown)
{
orbitDistance = Mathf.Min(CameraZoomMax, orbitDistance + CameraZoomSpeed * delta);
}
UpdateCameraPosition();
}
if (mouseButtonEvent.ButtonIndex is MouseButton.Middle)
{
isMiddleMouseRotating = mouseButtonEvent.Pressed;
if (CaptureMiddleButton)
{
Input.MouseMode = mouseButtonEvent.Pressed
? Input.MouseModeEnum.Captured
: Input.MouseModeEnum.Visible;
}
}
}
else if (@event is InputEventMouseMotion mouseMotionEvent && isMiddleMouseRotating)
{
var viewportSize = GetViewport().GetVisibleRect().Size;
var viewMin = (float)Mathf.Min(viewportSize.X, viewportSize.Y);
var delta = (float)GetProcessDeltaTime() * 60f;
// px => normalized fraction of screen -> radians, scaled by dt
var dx = (mouseMotionEvent.Relative.X / viewMin) * YawSensitivity * Mathf.Tau * delta;
var dy = (mouseMotionEvent.Relative.Y / viewMin) * PitchSensitivity * Mathf.Tau * delta;
// Safety cap per event
var maxStep = Mathf.DegToRad(StepDegreeMax);
dx = Mathf.Clamp(dx, -maxStep, maxStep);
dy = Mathf.Clamp(dy, -maxStep, maxStep);
yaw -= dx;
pitch += dy;
var pitchMin = Mathf.DegToRad(PitchDegreeMin);
var pitchMax = Mathf.DegToRad(PitchDegreeMax);
pitch = Mathf.Clamp(pitch, pitchMax, pitchMax);
UpdateCameraPosition();
}
}
void UpdateCameraPosition()
{
var direction = new Vector3(
x: Mathf.Sin(yaw) * Mathf.Cos(pitch),
y: Mathf.Sin(pitch),
z: Mathf.Cos(yaw) * Mathf.Cos(pitch)
).Normalized();
Position = origin + direction * orbitDistance;
LookAt(origin, Vector3.Up);
currentHeight = orbitDistance * Mathf.Sin(pitch);
orbitRadius = orbitDistance * Mathf.Cos(pitch);
}
}