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:
Leonid Pershin
2026-06-12 07:47:04 +03:00
parent 1f87fb0b74
commit c30e2ce764
70 changed files with 0 additions and 233 deletions
@@ -0,0 +1,115 @@
namespace MrGameEng.AI;
/// <summary>Shape of a <see cref="ResponseCurve"/> mapping a normalized input to a utility.</summary>
public enum CurveType
{
/// <summary>Straight line: <c>y = slope·(x xShift) + yShift</c>.</summary>
Linear,
/// <summary>Power curve: <c>y = slope·(x xShift)^exponent + yShift</c>; the exponent eases in/out.</summary>
Polynomial,
/// <summary>S-shaped logistic centred on <c>xShift</c>; <c>exponent</c> is the steepness.</summary>
Logistic,
/// <summary>Hermite smoothstep over <c>[xShift, xShift + 1/slope]</c>; flat ends, smooth middle.</summary>
SmoothStep,
}
/// <summary>
/// Maps a normalized input in <c>[0,1]</c> to a utility in <c>[0,1]</c> through one of a few
/// shapes. The input is clamped before evaluation and the output is clamped after, so a curve is
/// always safe to feed a raw normalized <see cref="Consideration{TContext}"/> value. Curves are
/// immutable value types — build them once and reuse them across evaluations.
/// </summary>
public readonly struct ResponseCurve
{
/// <summary>The shape applied by <see cref="Evaluate"/>.</summary>
public CurveType Type { get; }
/// <summary>Vertical scale / steepness (the <c>m</c> term). See <see cref="CurveType"/> per shape.</summary>
public float Slope { get; }
/// <summary>Power for <see cref="CurveType.Polynomial"/> and steepness for <see cref="CurveType.Logistic"/>.</summary>
public float Exponent { get; }
/// <summary>Horizontal shift of the curve (the <c>c</c> term): the input value mapped to the origin.</summary>
public float XShift { get; }
/// <summary>Vertical shift of the curve (the <c>b</c> term) added after scaling.</summary>
public float YShift { get; }
/// <summary>
/// Builds a curve from raw parameters. Prefer the named factories
/// (<see cref="Linear"/>, <see cref="Polynomial"/>, <see cref="Logistic"/>, <see cref="SmoothStep"/>)
/// which document the meaning of each term for their shape.
/// </summary>
public ResponseCurve(
CurveType type,
float slope = 1f,
float exponent = 1f,
float xShift = 0f,
float yShift = 0f
)
{
Type = type;
Slope = slope;
Exponent = exponent;
XShift = xShift;
YShift = yShift;
}
/// <summary>The identity curve: <c>y = x</c>. The default when a consideration needs no shaping.</summary>
public static ResponseCurve Identity => new(CurveType.Linear);
/// <summary>Straight line <c>y = slope·(x xShift) + yShift</c>. A negative slope inverts the input.</summary>
public static ResponseCurve Linear(float slope = 1f, float xShift = 0f, float yShift = 0f) =>
new(CurveType.Linear, slope, 1f, xShift, yShift);
/// <summary>
/// Power curve <c>y = slope·(x xShift)^exponent + yShift</c>. An exponent above 1 eases in
/// (slow start), below 1 eases out (fast start). Quadratic is <c>exponent = 2</c>.
/// </summary>
public static ResponseCurve Polynomial(
float exponent,
float slope = 1f,
float xShift = 0f,
float yShift = 0f
) => new(CurveType.Polynomial, slope, exponent, xShift, yShift);
/// <summary>
/// Logistic S-curve centred on <paramref name="midpoint"/>; <paramref name="steepness"/> controls how
/// sharp the transition is (≈10 gives a soft threshold, larger is more switch-like).
/// </summary>
public static ResponseCurve Logistic(float steepness = 10f, float midpoint = 0.5f) =>
new(CurveType.Logistic, 1f, steepness, midpoint);
/// <summary>
/// Hermite smoothstep rising from 0 to 1 over <c>[xShift, xShift + 1/slope]</c>: flat below the
/// start, flat above the end, smooth in between. Default rises across the whole <c>[0,1]</c> range.
/// </summary>
public static ResponseCurve SmoothStep(float slope = 1f, float xShift = 0f) =>
new(CurveType.SmoothStep, slope, 1f, xShift);
/// <summary>Evaluates the curve. <paramref name="x"/> is clamped to <c>[0,1]</c>; the result is clamped to <c>[0,1]</c>.</summary>
public float Evaluate(float x)
{
x = Math.Clamp(x, 0f, 1f);
var y = Type switch
{
CurveType.Linear => Slope * (x - XShift) + YShift,
CurveType.Polynomial => Slope * MathF.Pow(x - XShift, Exponent) + YShift,
CurveType.Logistic => 1f / (1f + MathF.Exp(-Exponent * (x - XShift))) * Slope + YShift,
CurveType.SmoothStep => SmoothStepValue(x),
_ => x,
};
return Math.Clamp(y, 0f, 1f);
}
private float SmoothStepValue(float x)
{
var t = Math.Clamp((x - XShift) * Slope, 0f, 1f);
return t * t * (3f - 2f * t) + YShift;
}
}