feat(app): Phase B.2 — ChaseCamera (third-person follow camera)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
631fd3c9bb
commit
84d7d06008
2 changed files with 130 additions and 0 deletions
66
src/AcDream.App/Rendering/ChaseCamera.cs
Normal file
66
src/AcDream.App/Rendering/ChaseCamera.cs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace AcDream.App.Rendering;
|
||||
|
||||
/// <summary>
|
||||
/// Third-person chase camera that follows behind and above a player
|
||||
/// character. Implements <see cref="ICamera"/> so it plugs into the
|
||||
/// existing renderer pipeline.
|
||||
/// </summary>
|
||||
public sealed class ChaseCamera : ICamera
|
||||
{
|
||||
public Vector3 Position { get; private set; }
|
||||
public float Aspect { get; set; } = 16f / 9f;
|
||||
public float FovY { get; set; } = MathF.PI / 3f;
|
||||
|
||||
/// <summary>Distance behind the player.</summary>
|
||||
public float Distance { get; set; } = 8f;
|
||||
|
||||
/// <summary>Camera pitch above horizontal (radians). Positive = look down.</summary>
|
||||
public float Pitch { get; set; } = 0.35f; // ~20 degrees
|
||||
|
||||
/// <summary>Vertical offset from the player's feet to the look-at point (eye height).</summary>
|
||||
public float EyeHeight { get; set; } = 1.5f;
|
||||
|
||||
private const float PitchMin = 0.05f;
|
||||
private const float PitchMax = 1.4f; // ~80 degrees
|
||||
|
||||
private float _playerYaw;
|
||||
private Vector3 _lookAt;
|
||||
|
||||
public Matrix4x4 View =>
|
||||
Matrix4x4.CreateLookAt(Position, _lookAt, Vector3.UnitZ);
|
||||
|
||||
public Matrix4x4 Projection =>
|
||||
Matrix4x4.CreatePerspectiveFieldOfView(FovY, Aspect, 1f, 5000f);
|
||||
|
||||
/// <summary>
|
||||
/// Update the camera position to follow the player.
|
||||
/// </summary>
|
||||
public void Update(Vector3 playerPosition, float playerYaw)
|
||||
{
|
||||
_playerYaw = playerYaw;
|
||||
_lookAt = playerPosition + new Vector3(0f, 0f, EyeHeight);
|
||||
|
||||
// Camera offset: behind the player (-forward direction) and above.
|
||||
float forwardX = MathF.Cos(playerYaw);
|
||||
float forwardY = MathF.Sin(playerYaw);
|
||||
|
||||
float horizontalDist = Distance * MathF.Cos(Pitch);
|
||||
float verticalDist = Distance * MathF.Sin(Pitch);
|
||||
|
||||
Position = new Vector3(
|
||||
playerPosition.X - forwardX * horizontalDist,
|
||||
playerPosition.Y - forwardY * horizontalDist,
|
||||
playerPosition.Z + EyeHeight + verticalDist);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjust pitch by a delta (from mouse Y movement).
|
||||
/// </summary>
|
||||
public void AdjustPitch(float delta)
|
||||
{
|
||||
Pitch = Math.Clamp(Pitch + delta, PitchMin, PitchMax);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue