Files
mrgameeng/tests/MrGameEng.Simulation.Tests/Pathfinding/FlowFieldTests.cs
T

102 lines
3.2 KiB
C#

using Microsoft.Xna.Framework;
using Xunit;
namespace MrGameEng.Pathfinding.Tests;
public class FlowFieldTests
{
[Fact]
public void Build_DistancesGrowFromGoal_DirectionsDescend()
{
var grid = new TestGrid(".....", ".###.", ".....");
var builder = new FlowFieldBuilder(grid);
var field = new FlowField();
builder.Build([new Point(0, 0)], field);
Assert.Equal(0f, field.DistanceAt(0, 0));
Assert.True(field.DistanceAt(4, 2) > field.DistanceAt(1, 0));
// Из любой достижимой не-целевой клетки направление ведёт к клетке с меньшей дистанцией.
for (var y = 0; y < grid.Height; y++)
{
for (var x = 0; x < grid.Width; x++)
{
if (
!grid.IsPassable(x, y)
|| !field.IsReachable(x, y)
|| field.DistanceAt(x, y) == 0f
)
{
continue;
}
var direction = field.DirectionAt(x, y);
Assert.NotEqual(Vector2.Zero, direction);
var nx = x + Math.Sign(MathF.Round(direction.X * 10f));
var ny = y + Math.Sign(MathF.Round(direction.Y * 10f));
Assert.True(
field.DistanceAt(nx, ny) < field.DistanceAt(x, y),
$"direction at ({x},{y}) does not descend"
);
}
}
}
[Fact]
public void Build_UnreachablePocket_IsFlagged()
{
var grid = new TestGrid("..#..", "..#..", "..#..");
var builder = new FlowFieldBuilder(grid);
var field = new FlowField();
builder.Build([new Point(0, 1)], field);
Assert.False(field.IsReachable(4, 1));
Assert.Equal(Vector2.Zero, field.DirectionAt(4, 1));
Assert.True(field.IsReachable(1, 2));
}
[Fact]
public void Build_MultipleGoals_EachCellFlowsToNearest()
{
var grid = new TestGrid("..........");
var builder = new FlowFieldBuilder(grid);
var field = new FlowField();
builder.Build([new Point(0, 0), new Point(9, 0)], field);
Assert.True(field.DirectionAt(2, 0).X < 0f); // ближе к левой цели
Assert.True(field.DirectionAt(7, 0).X > 0f); // ближе к правой
Assert.Equal(0f, field.DistanceAt(9, 0));
}
[Fact]
public void Build_Rebuild_OverwritesPreviousField()
{
var grid = new TestGrid(".....");
var builder = new FlowFieldBuilder(grid);
var field = new FlowField();
builder.Build([new Point(0, 0)], field);
Assert.True(field.DirectionAt(4, 0).X < 0f);
builder.Build([new Point(4, 0)], field);
Assert.True(field.DirectionAt(0, 0).X > 0f);
Assert.Equal(0f, field.DistanceAt(4, 0));
}
[Fact]
public void Build_NoValidGoals_EverythingUnreachable()
{
var grid = new TestGrid(".#.");
var builder = new FlowFieldBuilder(grid);
var field = new FlowField();
builder.Build([new Point(1, 0)], field); // цель — стена
Assert.False(field.IsReachable(0, 0));
Assert.False(field.IsReachable(2, 0));
}
}