convert game playing..
This commit is contained in:
@@ -1,15 +1,18 @@
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using BumpCombat.Constants;
|
||||
using BumpCombat.Core;
|
||||
using BumpCombat.Enemies;
|
||||
using BumpCombat.Player;
|
||||
using BumpCombat.Progression;
|
||||
using BumpCombat.Spawning;
|
||||
using BumpCombat.Stage;
|
||||
using BumpCombat.UI;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.TestTools;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace BumpCombat.PlayModeTests
|
||||
{
|
||||
@@ -298,6 +301,142 @@ namespace BumpCombat.PlayModeTests
|
||||
}
|
||||
}
|
||||
|
||||
[UnityTest]
|
||||
public IEnumerator RoomScaleComparison_UsesMatchedCameraAndMinimapForOriginalAndExpanded()
|
||||
{
|
||||
const int referenceSeed = 20260922;
|
||||
RunConstants constants = GameplayConstants.Current.Run;
|
||||
RoomScaleComparisonMode previousMode = constants.Stage1FirstCombatRoomScaleComparison;
|
||||
UnityEngine.Random.State previousRandomState = UnityEngine.Random.state;
|
||||
float previousTimeScale = Time.timeScale;
|
||||
bool previousProductionMode = RunManager.ForceProductionModeForTests;
|
||||
string captureDirectory = System.Environment.GetEnvironmentVariable(
|
||||
"BUMPCOMBAT_COMPARISON_CAPTURE_DIRECTORY");
|
||||
|
||||
try
|
||||
{
|
||||
constants.Stage1FirstCombatRoomScaleComparison = RoomScaleComparisonMode.Original;
|
||||
yield return LoadAndStartRun();
|
||||
|
||||
StageManager stageManager = Object.FindAnyObjectByType<StageManager>();
|
||||
Camera camera = Camera.main;
|
||||
Assert.That(stageManager, Is.Not.Null);
|
||||
Assert.That(camera, Is.Not.Null);
|
||||
|
||||
RoomScaleComparisonMode[] modes =
|
||||
{
|
||||
RoomScaleComparisonMode.Original,
|
||||
RoomScaleComparisonMode.Expanded,
|
||||
};
|
||||
for (int modeIndex = 0; modeIndex < modes.Length; modeIndex++)
|
||||
{
|
||||
RoomScaleComparisonMode mode = modes[modeIndex];
|
||||
constants.Stage1FirstCombatRoomScaleComparison = mode;
|
||||
stageManager.StartRun(referenceSeed);
|
||||
yield return new WaitForSecondsRealtime(0.4f);
|
||||
|
||||
StageNode firstCombat = FindFirstCombat(stageManager.CurrentPlan);
|
||||
Assert.That(firstCombat, Is.Not.Null);
|
||||
Assert.That(firstCombat.PresetId,
|
||||
Is.EqualTo(mode == RoomScaleComparisonMode.Expanded
|
||||
? LevelPresetCatalog.S1AComparisonExpandedPresetId
|
||||
: "GRAVE_S1_COMBAT_A"));
|
||||
|
||||
StageDirection entryDirection = GetEntryDirection(
|
||||
stageManager.CurrentPlan.StartNode,
|
||||
firstCombat);
|
||||
|
||||
// Reset immediately before the same room activation so the
|
||||
// encounter's UnityEngine.Random group rolls match A/B.
|
||||
UnityEngine.Random.InitState(referenceSeed);
|
||||
stageManager.RequestZoneTransition(firstCombat.Id, entryDirection);
|
||||
float deadline = Time.realtimeSinceStartup + 4f;
|
||||
while (stageManager.CurrentZone == null
|
||||
|| stageManager.CurrentZone.NodeId != firstCombat.Id
|
||||
|| stageManager.IsTransitioning)
|
||||
{
|
||||
Assert.That(Time.realtimeSinceStartup, Is.LessThan(deadline),
|
||||
"The comparison fixture did not reach the first combat room.");
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// CoTransitionZone sets CurrentZone before its doorway
|
||||
// hold. Wait for ActivateZone and encounter spawn to
|
||||
// finish before inspecting or capturing the room.
|
||||
yield return new WaitForSecondsRealtime(0.4f);
|
||||
|
||||
ZoneInstance zone = stageManager.CurrentZone;
|
||||
Assert.That(stageManager.IsTransitioning, Is.False);
|
||||
AssertReferenceEncounter(
|
||||
zone,
|
||||
mode == RoomScaleComparisonMode.Expanded ? 6 : 3,
|
||||
mode == RoomScaleComparisonMode.Expanded ? 4 : 2);
|
||||
float expectedOrtho = mode == RoomScaleComparisonMode.Expanded
|
||||
? constants.StageComparisonCameraViewHalfExtents.y
|
||||
: constants.StageComparisonOriginalCameraViewHalfExtents.y;
|
||||
Assert.That(zone.Preset.GridWidth,
|
||||
Is.EqualTo(mode == RoomScaleComparisonMode.Expanded ? 36 : 18));
|
||||
Assert.That(zone.Preset.GridHeight,
|
||||
Is.EqualTo(mode == RoomScaleComparisonMode.Expanded ? 24 : 12));
|
||||
|
||||
PlayerController comparisonPlayer =
|
||||
Object.FindAnyObjectByType<PlayerController>();
|
||||
Vector2 returnPosition = comparisonPlayer.transform.position;
|
||||
Vector2 explorationPosition = returnPosition;
|
||||
bool foundUnseenCell = false;
|
||||
for (int y = 0; y < zone.Preset.GridHeight && !foundUnseenCell; y++)
|
||||
{
|
||||
for (int x = 0; x < zone.Preset.GridWidth; x++)
|
||||
{
|
||||
if (zone.GetRuntimeCell(x, y) == PresetCellType.Empty
|
||||
|| zone.IsCellVisible(x, y))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
explorationPosition = zone.Preset.CellToWorldPosition(
|
||||
zone.ZoneCenter,
|
||||
new Vector2Int(x, y));
|
||||
foundUnseenCell = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.That(foundUnseenCell, Is.True,
|
||||
"The comparison room must have an unseen terrain cell.");
|
||||
Assert.That(comparisonPlayer.TryReposition(explorationPosition), Is.True);
|
||||
zone.UpdateVisibility(explorationPosition);
|
||||
yield return null;
|
||||
Assert.That(comparisonPlayer.TryReposition(returnPosition), Is.True);
|
||||
zone.UpdateVisibility(returnPosition);
|
||||
yield return null;
|
||||
|
||||
camera.Render();
|
||||
Assert.That(camera.orthographicSize, Is.EqualTo(expectedOrtho).Within(0.01f));
|
||||
AssertPixelPerfectReference(
|
||||
camera,
|
||||
mode == RoomScaleComparisonMode.Expanded ? 480 : 320,
|
||||
mode == RoomScaleComparisonMode.Expanded ? 270 : 180);
|
||||
AssertMinimapTerrainMatches(zone);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(captureDirectory))
|
||||
{
|
||||
CaptureWorldOnlyCamera(
|
||||
camera,
|
||||
captureDirectory,
|
||||
mode == RoomScaleComparisonMode.Expanded ? "expanded" : "original");
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
constants.Stage1FirstCombatRoomScaleComparison = previousMode;
|
||||
UnityEngine.Random.state = previousRandomState;
|
||||
Time.timeScale = previousTimeScale;
|
||||
RunManager.ForceProductionModeForTests = previousProductionMode;
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerator DestroyActiveEnemies()
|
||||
{
|
||||
EnemyController[] enemies = Object.FindObjectsByType<EnemyController>(
|
||||
@@ -313,6 +452,184 @@ namespace BumpCombat.PlayModeTests
|
||||
yield return null;
|
||||
}
|
||||
|
||||
private static StageNode FindFirstCombat(StagePlan plan)
|
||||
{
|
||||
StageNode entrance = plan.StartNode;
|
||||
for (int i = 0; i < plan.Nodes.Count; i++)
|
||||
{
|
||||
StageNode node = plan.Nodes[i];
|
||||
if (node.NodeType != StageNodeType.Combat)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int direction = 0; direction < 4; direction++)
|
||||
{
|
||||
if (entrance.GetConnection((StageDirection)direction) == node.Id)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static StageDirection GetEntryDirection(StageNode entrance, StageNode target)
|
||||
{
|
||||
for (int direction = 0; direction < 4; direction++)
|
||||
{
|
||||
StageDirection sourceDirection = (StageDirection)direction;
|
||||
if (entrance.GetConnection(sourceDirection) == target.Id)
|
||||
{
|
||||
return sourceDirection.Opposite();
|
||||
}
|
||||
}
|
||||
|
||||
return StageDirection.West;
|
||||
}
|
||||
|
||||
private static void AssertPixelPerfectReference(
|
||||
Camera camera,
|
||||
int expectedWidth,
|
||||
int expectedHeight)
|
||||
{
|
||||
Component pixelPerfect = camera.GetComponent(
|
||||
"UnityEngine.Rendering.Universal.PixelPerfectCamera");
|
||||
Assert.That(pixelPerfect, Is.Not.Null);
|
||||
PropertyInfo referenceWidth = pixelPerfect.GetType().GetProperty("refResolutionX");
|
||||
PropertyInfo referenceHeight = pixelPerfect.GetType().GetProperty("refResolutionY");
|
||||
Assert.That(referenceWidth.GetValue(pixelPerfect), Is.EqualTo(expectedWidth));
|
||||
Assert.That(referenceHeight.GetValue(pixelPerfect), Is.EqualTo(expectedHeight));
|
||||
}
|
||||
|
||||
private static void AssertMinimapTerrainMatches(ZoneInstance zone)
|
||||
{
|
||||
RunHUD hud = Object.FindAnyObjectByType<RunHUD>();
|
||||
Assert.That(hud, Is.Not.Null);
|
||||
FieldInfo terrainField = typeof(RunHUD).GetField(
|
||||
"minimapTerrainRoot",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
RectTransform terrainRoot = terrainField?.GetValue(hud) as RectTransform;
|
||||
Assert.That(terrainRoot, Is.Not.Null);
|
||||
|
||||
int visibleCellCount = 0;
|
||||
for (int y = 0; y < zone.Preset.GridHeight; y++)
|
||||
{
|
||||
for (int x = 0; x < zone.Preset.GridWidth; x++)
|
||||
{
|
||||
if (zone.GetRuntimeCell(x, y) != PresetCellType.Empty)
|
||||
{
|
||||
visibleCellCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assert.That(terrainRoot.childCount, Is.EqualTo(visibleCellCount));
|
||||
Assert.That(zone.VisibilityRevision, Is.GreaterThan(0));
|
||||
|
||||
int darkCellCount = 0;
|
||||
int dimCellCount = 0;
|
||||
for (int y = 0; y < zone.Preset.GridHeight; y++)
|
||||
{
|
||||
for (int x = 0; x < zone.Preset.GridWidth; x++)
|
||||
{
|
||||
if (zone.GetRuntimeCell(x, y) == PresetCellType.Empty)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Image cell = terrainRoot.Find($"Terrain {x},{y}")?.GetComponent<Image>();
|
||||
Assert.That(cell, Is.Not.Null);
|
||||
Color32 color = cell.color;
|
||||
if (zone.IsCellVisible(x, y))
|
||||
{
|
||||
Assert.That(color, Is.Not.EqualTo(new Color32(2, 4, 5, 255)));
|
||||
}
|
||||
else if (zone.IsCellExplored(x, y))
|
||||
{
|
||||
dimCellCount++;
|
||||
Assert.That(color.a, Is.EqualTo(255));
|
||||
}
|
||||
else
|
||||
{
|
||||
darkCellCount++;
|
||||
Assert.That(color, Is.EqualTo(new Color32(2, 4, 5, 255)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assert.That(dimCellCount, Is.GreaterThan(0));
|
||||
Assert.That(darkCellCount, Is.GreaterThan(0));
|
||||
}
|
||||
|
||||
private static void AssertReferenceEncounter(
|
||||
ZoneInstance zone,
|
||||
int expectedBatCount,
|
||||
int expectedSkeletonCount)
|
||||
{
|
||||
int batCount = 0;
|
||||
int skeletonCount = 0;
|
||||
for (int i = 0; i < zone.SpawnedEnemies.Count; i++)
|
||||
{
|
||||
EnemyController enemy = zone.SpawnedEnemies[i];
|
||||
if (enemy == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (enemy.name.StartsWith("Bat", System.StringComparison.Ordinal))
|
||||
{
|
||||
batCount++;
|
||||
}
|
||||
else if (enemy.name.StartsWith("Skeleton", System.StringComparison.Ordinal))
|
||||
{
|
||||
skeletonCount++;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.That(batCount, Is.EqualTo(expectedBatCount));
|
||||
Assert.That(skeletonCount, Is.EqualTo(expectedSkeletonCount));
|
||||
}
|
||||
|
||||
private static void CaptureWorldOnlyCamera(
|
||||
Camera camera,
|
||||
string directory,
|
||||
string variant)
|
||||
{
|
||||
System.IO.Directory.CreateDirectory(directory);
|
||||
RenderTexture previousTarget = camera.targetTexture;
|
||||
RenderTexture previousActive = RenderTexture.active;
|
||||
RenderTexture target = new(640, 360, 24, RenderTextureFormat.ARGB32);
|
||||
Texture2D snapshot = null;
|
||||
try
|
||||
{
|
||||
target.Create();
|
||||
camera.targetTexture = target;
|
||||
camera.Render();
|
||||
RenderTexture.active = target;
|
||||
snapshot = new Texture2D(640, 360, TextureFormat.RGB24, false);
|
||||
snapshot.ReadPixels(new Rect(0f, 0f, 640f, 360f), 0, 0);
|
||||
snapshot.Apply();
|
||||
string path = System.IO.Path.Combine(
|
||||
directory,
|
||||
$"s1a-{variant}-world.png");
|
||||
System.IO.File.WriteAllBytes(path, snapshot.EncodeToPNG());
|
||||
}
|
||||
finally
|
||||
{
|
||||
camera.targetTexture = previousTarget;
|
||||
RenderTexture.active = previousActive;
|
||||
if (snapshot != null)
|
||||
{
|
||||
Object.Destroy(snapshot);
|
||||
}
|
||||
|
||||
target.Release();
|
||||
Object.Destroy(target);
|
||||
}
|
||||
}
|
||||
|
||||
private static EnemyController FindRangedPrefab(SpawnDirector director)
|
||||
{
|
||||
FieldInfo field = typeof(SpawnDirector).GetField(
|
||||
|
||||
Reference in New Issue
Block a user