Remove obsolete project files for MrGameEng.AI, MrGameEng.Assets, MrGameEng.Atlases, and MrGameEng.Collisions modules. Introduce new AssetManager and related classes for asset loading and management, including support for texture atlases and mod definitions. Enhance mod loading capabilities with DefDatabase and LanguageManager for JSON-based definitions and localization. Implement a shelf packing algorithm for efficient texture atlas creation.
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
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));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user