CI / build-test (push) Failing after 1m8s
Add MrGameEng.AI utility-AI module; format codebase with CSharpier New MrGameEng.AI module (ResponseCurve, Consideration, UtilityAction, UtilityAi selector, Blackboard) plus CSharpier formatting applied across the whole engine. Documents the CSharpier convention in CLAUDE.md. @
99 lines
3.0 KiB
C#
99 lines
3.0 KiB
C#
using Microsoft.Xna.Framework;
|
|
using MrGameEng.Graphics;
|
|
using Xunit;
|
|
|
|
namespace MrGameEng.Graphics.Tests;
|
|
|
|
public class CameraMathTests
|
|
{
|
|
private static void AssertVector(Vector2 expected, Vector2 actual, float tolerance = 0.001f)
|
|
{
|
|
Assert.InRange(actual.X, expected.X - tolerance, expected.X + tolerance);
|
|
Assert.InRange(actual.Y, expected.Y - tolerance, expected.Y + tolerance);
|
|
}
|
|
|
|
[Fact]
|
|
public void CameraPosition_MapsToScreenCenter()
|
|
{
|
|
var camera = new Camera(new Vector2(500f, 300f), zoom: 2f, rotation: 0.7f);
|
|
|
|
var state = CameraMath.Compute(camera, 800, 600, ViewportMapping.Identity);
|
|
|
|
AssertVector(new Vector2(400f, 300f), state.WorldToScreen(camera.Position));
|
|
}
|
|
|
|
[Fact]
|
|
public void ScreenToWorld_RoundTripsWithWorldToScreen()
|
|
{
|
|
var camera = new Camera(new Vector2(123f, -45f), zoom: 1.5f, rotation: 0.3f);
|
|
var state = CameraMath.Compute(
|
|
camera,
|
|
1280,
|
|
720,
|
|
new ViewportMapping(new Vector2(0f, 60f), 1.5f)
|
|
);
|
|
|
|
var screen = new Vector2(200f, 500f);
|
|
var world = state.ScreenToWorld(screen);
|
|
|
|
AssertVector(screen, state.WorldToScreen(world));
|
|
}
|
|
|
|
[Fact]
|
|
public void Zoom_ShrinksCullRect()
|
|
{
|
|
var camera = new Camera(Vector2.Zero, zoom: 2f);
|
|
|
|
var state = CameraMath.Compute(camera, 800, 600, ViewportMapping.Identity);
|
|
|
|
Assert.Equal(400f, state.CullRect.Width, 1);
|
|
Assert.Equal(300f, state.CullRect.Height, 1);
|
|
AssertVector(Vector2.Zero, state.CullRect.Center);
|
|
}
|
|
|
|
[Fact]
|
|
public void Rotation_ExpandsCullRectToCoverRotatedView()
|
|
{
|
|
var straight = CameraMath.Compute(
|
|
new Camera(Vector2.Zero),
|
|
800,
|
|
600,
|
|
ViewportMapping.Identity
|
|
);
|
|
var rotated = CameraMath.Compute(
|
|
new Camera(Vector2.Zero, rotation: MathF.PI / 4f),
|
|
800,
|
|
600,
|
|
ViewportMapping.Identity
|
|
);
|
|
|
|
Assert.True(rotated.CullRect.Width > straight.CullRect.Width);
|
|
Assert.True(rotated.CullRect.Height > straight.CullRect.Height);
|
|
}
|
|
|
|
[Fact]
|
|
public void Bounds_ClampCameraToWorldEdges()
|
|
{
|
|
var bounds = new RectF(0f, 0f, 2000f, 1000f);
|
|
var camera = new Camera(new Vector2(-500f, 500f), bounds: bounds);
|
|
|
|
var state = CameraMath.Compute(camera, 800, 600, ViewportMapping.Identity);
|
|
|
|
// Camera should be clamped so the view's left edge sits at the world's left edge.
|
|
AssertVector(new Vector2(0f, 200f), state.ScreenToWorld(Vector2.Zero));
|
|
}
|
|
|
|
[Fact]
|
|
public void Mapping_CentersVirtualResolutionInWiderWindow()
|
|
{
|
|
var mapping = CameraMath.ComputeMapping(1920, 1080, 640, 360);
|
|
|
|
Assert.Equal(3f, mapping.Scale);
|
|
Assert.Equal(Vector2.Zero, mapping.Offset);
|
|
|
|
var letterboxed = CameraMath.ComputeMapping(1920, 1200, 640, 360);
|
|
Assert.Equal(3f, letterboxed.Scale);
|
|
Assert.Equal(new Vector2(0f, 60f), letterboxed.Offset);
|
|
}
|
|
}
|