Files
Luis Gonzalez e851d5f8e9 Co-Op Layer
2026-06-01 10:48:18 -07:00

88 lines
3.1 KiB
C#

using NUnit.Framework;
using ProjectM.Simulation;
using Unity.Mathematics;
namespace ProjectM.Tests
{
/// <summary>
/// Pure-function tests for <see cref="PlayerSpawnMath.SpawnOffset"/> (no ECS world), mirroring
/// StatMathTests. Pins the M4 co-op deterministic spawn spread: stable, distinct per-NetworkId ring
/// positions so players never stack on connect.
/// </summary>
public class PlayerSpawnRingTests
{
const float R = 2.5f;
const int Slots = 4;
const float Eps = 1e-4f;
[Test]
public void Deterministic_SameInputs_SameOffset()
{
var a = PlayerSpawnMath.SpawnOffset(2, R, Slots);
var b = PlayerSpawnMath.SpawnOffset(2, R, Slots);
Assert.AreEqual(a.x, b.x, Eps);
Assert.AreEqual(a.y, b.y, Eps);
Assert.AreEqual(a.z, b.z, Eps);
}
[Test]
public void FirstFour_Land_On_Cardinal_Ring_Slots()
{
// NetworkIds start at 1; slots=4 -> 0, 90, 180, 270 degrees on a ring of radius R.
AssertXz(PlayerSpawnMath.SpawnOffset(1, R, Slots), R, 0f);
AssertXz(PlayerSpawnMath.SpawnOffset(2, R, Slots), 0f, R);
AssertXz(PlayerSpawnMath.SpawnOffset(3, R, Slots), -R, 0f);
AssertXz(PlayerSpawnMath.SpawnOffset(4, R, Slots), 0f, -R);
}
[Test]
public void Distinct_NetworkIds_Give_Distinct_Positions()
{
var seen = new System.Collections.Generic.List<float3>();
for (int id = 1; id <= 8; id++)
{
var p = PlayerSpawnMath.SpawnOffset(id, R, Slots);
foreach (var q in seen)
Assert.Greater(math.distance(p, q), 1e-3f, $"id {id} collides with an earlier slot");
seen.Add(p);
}
}
[Test]
public void FifthPlayer_Spills_To_Outer_Ring()
{
// idx 4 with slots 4 -> ring 1, slot 0 -> radius doubled, angle 0.
AssertXz(PlayerSpawnMath.SpawnOffset(5, R, Slots), 2f * R, 0f);
}
[Test]
public void NonPositiveRadius_Returns_Zero()
{
Assert.AreEqual(0f, math.length(PlayerSpawnMath.SpawnOffset(3, 0f, Slots)), Eps);
Assert.AreEqual(0f, math.length(PlayerSpawnMath.SpawnOffset(3, -1f, Slots)), Eps);
}
[Test]
public void DegenerateSlots_DoNotThrow_AndStayDistinct()
{
// slots < 1 is clamped to 1 (every player on its own concentric ring).
var a = PlayerSpawnMath.SpawnOffset(1, R, 0);
var b = PlayerSpawnMath.SpawnOffset(2, R, 0);
Assert.Greater(math.distance(a, b), 1e-3f);
}
[Test]
public void Offset_Is_Planar_NoVerticalComponent()
{
for (int id = 1; id <= 6; id++)
Assert.AreEqual(0f, PlayerSpawnMath.SpawnOffset(id, R, Slots).y, Eps);
}
static void AssertXz(float3 p, float x, float z)
{
Assert.AreEqual(x, p.x, Eps);
Assert.AreEqual(z, p.z, Eps);
}
}
}