rework dimensions and orientation into Placement, optimise requirements to work on previous candidates, use vec3 for positions

This commit is contained in:
2022-11-24 11:34:11 +01:00
parent f13ba4cd95
commit 3e51410ade
36 changed files with 268 additions and 275 deletions

View File

@@ -1,55 +0,0 @@
using System.Collections.Generic;
using UnityEngine;
namespace EscapeRoomEngine.Engine.Runtime
{
public struct Dimensions
{
public int width;
public int length;
public int x;
public int z;
public Vector2Int Position
{
get => new(x, z);
set
{
x = value.x;
z = value.y;
}
}
public Vector2Int Size
{
get => new(width, length);
set
{
width = value.x;
length = value.y;
}
}
public int Area => width * length;
public HashSet<Vector2Int> EveryPosition
{
get
{
var positions = new HashSet<Vector2Int>();
for (var zIter = 0; zIter < length; zIter++)
{
for (var xIter = 0; xIter < width; xIter++)
{
positions.Add(new Vector2Int(xIter, zIter));
}
}
return positions;
}
}
public override string ToString() => $"({width}, {length}) at ({x}, {z})";
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: b70ad3679d5c48768c1d132f56dba4dd
timeCreated: 1667222427

View File

@@ -56,7 +56,7 @@ namespace EscapeRoomEngine.Engine.Runtime
Logger.Log("Generating room...", LogType.RoomGeneration);
// get the last entrance from the newest room or create a spawn passage with no entrance door for where the player will start
var entrance = NumberOfRooms > 0 ? _rooms.Last().exit : new Passage(new DoorModule(null, theme.spawnDoor), true);
var entrance = NumberOfRooms > 0 ? _rooms.Last().exit : new Passage(new DoorModule(null, theme.spawnDoor));
var room = new Room(entrance);
_rooms.Add(room);

View File

@@ -45,7 +45,7 @@ namespace EscapeRoomEngine.Engine.Runtime
#region Puzzles
[BoxGroup("Puzzles")] [MinMaxSlider(0, 10)]
[BoxGroup("Puzzles")] [MinMaxSlider(0, 24)]
public Vector2Int puzzleCount;
[BoxGroup("Puzzles")]

View File

@@ -10,37 +10,27 @@ using Object = UnityEngine.Object;
namespace EscapeRoomEngine.Engine.Runtime.Modules
{
public enum Orientation
{
North = 0, East = 90, South = 180, West = 270
}
public class Module
{
public static HashSet<Orientation> EveryOrientation => new(new[]
{
Orientation.North, Orientation.East, Orientation.South, Orientation.West
});
public readonly List<Module> relatedModules = new();
public ModuleState State { get; private set; }
internal Orientation Orientation => srPlacement.orientation;
/// <summary>
/// Get the space relative (<i>SR</i>) position of this module.
/// </summary>
internal Vector2Int SrPosition => srDimensions.Position;
internal Vector3Int SrPosition => srPlacement.position;
/// <summary>
/// Get the room relative (<i>RR</i>) position of this module.
/// </summary>
internal Vector2Int RrPosition => space.ToRoomRelative(SrPosition);
internal Vector3Int RrPosition => space?.ToRoomRelative(SrPosition) ?? SrPosition;
internal readonly ModuleDescription description;
internal Orientation orientation;
/// <summary>
/// The space relative (<i>SR</i>) dimensions of this module.
/// The space relative (<i>SR</i>) placement of this module.
/// </summary>
protected Dimensions srDimensions;
public Placement srPlacement;
protected readonly Space space;
@@ -58,49 +48,55 @@ namespace EscapeRoomEngine.Engine.Runtime.Modules
internal bool CheckRequirements()
{
return PreconditionRequirement.CheckPreconditions(this, space) &&
PlacementRequirement.TryPlacing(this, space) &&
OrientationRequirement.TryOrienting(this, space);
PlacementRequirement.TryPlacing(this, space);
}
/// <summary>
/// Place this module with a position relative to the room.
/// </summary>
/// <param name="rrPosition">The room relative (<i>RR</i>) position of this module. Must be inside the space dimensions.</param>
/// <param name="orientation">The orientation of this module.</param>
/// <exception cref="EngineException">If the position is not inside the space dimensions.</exception>
internal void PlaceRoomRelative(Vector2Int rrPosition) => Place(space.ToSpaceRelative(rrPosition));
internal void PlaceRoomRelative(Vector3Int rrPosition, Orientation orientation) =>
Place(new Placement
{
position = space.ToSpaceRelative(rrPosition),
size = description.modulePrefab.size,
orientation = orientation
});
/// <summary>
/// Place this module with a position relative to the space it is in.
/// </summary>
/// <param name="srPosition">The space relative (<i>SR</i>) position of this module. Must be inside the space dimensions.</param>
/// <param name="placement">The space relative (<i>SR</i>) placement of this module. Must be inside the space dimensions.</param>
/// <exception cref="EngineException">If the position is not inside the space dimensions.</exception>
internal void Place(Vector2Int srPosition) {
if (space != null && !srPosition.IsInsideRelative(space.rrDimensions))
internal void Place(Placement placement) {
if (space != null && !placement.position.IsInsideRelative(space.rrPlacement))
{
throw new EngineException($"Trying to place {this} at {srPosition}, which is outside space dimensions {space.rrDimensions}.");
throw new EngineException($"Trying to place {this} at {placement.position} which is outside space dimensions {space.rrPlacement}.");
}
srPlacement = placement;
srDimensions.Position = srPosition;
Logger.Log($"{this} has been placed at {srPosition} (SR)", LogType.ModulePlacement);
Logger.Log($"{this} has been placed at {placement.position} (SR)", LogType.ModulePlacement);
}
/// <summary>
/// Convert a position relative to this module to one relative to its space.
/// <example>The module relative position <c>(0, 1)</c> should always be in front of the module, wherever it faces.</example>
/// <example>The module relative position <c>(0, 0, 1)</c> should always be in front of the module, wherever it faces.</example>
/// </summary>
/// <param name="mrPosition">The module relative (<i>MR</i>) position that should be converted to a space relative (<i>SR</i>) position.</param>
/// <returns></returns>
internal Vector2Int ToSpaceRelative(Vector2Int mrPosition)
internal Vector3Int ToSpaceRelative(Vector3Int mrPosition)
{
return srDimensions.Position + orientation switch
// ReSharper disable once ArrangeRedundantParentheses
return srPlacement.position + (Orientation switch
{
Orientation.North => mrPosition,
Orientation.East => new Vector2Int(mrPosition.y, -mrPosition.x),
Orientation.East => new Vector3Int(mrPosition.z, 0, -mrPosition.x),
Orientation.South => -mrPosition,
Orientation.West => new Vector2Int(-mrPosition.y, mrPosition.x),
Orientation.West => new Vector3Int(-mrPosition.z, 0, mrPosition.x),
_ => throw new ArgumentOutOfRangeException()
};
});
}
internal virtual void InstantiateModule(Transform parent)
@@ -108,8 +104,8 @@ namespace EscapeRoomEngine.Engine.Runtime.Modules
Logger.Log($"Instantiating {this}", LogType.ModuleInstantiation);
State = Object.Instantiate(description.modulePrefab, parent, false);
State.transform.localPosition = new Vector3(srDimensions.x + .5f, 0, srDimensions.z + .5f);
State.transform.Rotate(Vector3.up, (float)orientation);
State.transform.localPosition = new Vector3(SrPosition.x + .5f, 0, SrPosition.z + .5f);
State.transform.Rotate(Vector3.up, Orientation.Angle());
State.name = ToString();
State.SetModule(this);
}

View File

@@ -14,8 +14,6 @@ namespace EscapeRoomEngine.Engine.Runtime.Modules
public List<PreconditionRequirement> preconditionRequirements = new();
[BoxGroup("Requirements")]
public List<PlacementRequirement> placementRequirements = new();
[BoxGroup("Requirements")]
public List<OrientationRequirement> orientationRequirements = new();
internal bool HasType(ModuleType type)
{

View File

@@ -0,0 +1,19 @@
using System.Collections.Generic;
namespace EscapeRoomEngine.Engine.Runtime
{
public enum Orientation
{
North = 0, East = 90, South = 180, West = 270
}
public static class OrientationExtensions
{
public static HashSet<Orientation> EveryOrientation() => new(new[]
{
Orientation.North, Orientation.East, Orientation.South, Orientation.West
});
public static float Angle(this Orientation orientation) => (float)orientation;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 892800b15ed4409582647cfc5659b820
timeCreated: 1669115056

View File

@@ -1,5 +1,4 @@
using EscapeRoomEngine.Engine.Runtime.Modules;
using UnityEngine;
using Logger = EscapeRoomEngine.Engine.Runtime.Utilities.Logger;
using LogType = EscapeRoomEngine.Engine.Runtime.Utilities.LogType;
@@ -7,31 +6,12 @@ namespace EscapeRoomEngine.Engine.Runtime
{
public class Passage
{
internal DoorModule fromOut, toIn;
/// <summary>
/// The room relative (<i>RR</i>) position of this passage.
/// </summary>
internal Vector2Int rrPosition;
internal readonly DoorModule fromOut;
internal DoorModule toIn;
internal Passage(DoorModule from, bool spawnPassage = false)
internal Passage(DoorModule from)
{
if (spawnPassage)
{
fromOut = from;
rrPosition = Vector2Int.zero;
}
else
{
ConnectFrom(from);
}
}
internal void ConnectFrom(DoorModule door)
{
fromOut = door;
rrPosition = fromOut.RrPosition;
Logger.Log($"Connected passage from {door} at {rrPosition} (RR)", LogType.PassageConnection);
fromOut = from;
}
internal void ConnectTo(DoorModule door)
@@ -39,10 +19,9 @@ namespace EscapeRoomEngine.Engine.Runtime
toIn = door;
// to make sure the origin of the player doesn't move, the two doors must be placed in the same location in the same orientation
toIn.PlaceRoomRelative(rrPosition);
toIn.orientation = fromOut.orientation;
toIn.PlaceRoomRelative(fromOut.RrPosition, fromOut.Orientation);
Logger.Log($"Connected passage to {door} at {rrPosition} (RR)", LogType.PassageConnection);
Logger.Log($"Connected passage from {fromOut} to {toIn} at {toIn.RrPosition} (RR)", LogType.PassageConnection);
}
}
}

View File

@@ -0,0 +1,47 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace EscapeRoomEngine.Engine.Runtime
{
public struct Placement
{
public Vector3Int position;
public Vector2Int size;
public Orientation orientation;
/// <summary>
/// Create a set with every possible combination of position and orientation given the dimensions.
///
/// <remarks>
/// The size of all placements will be (1, 1).
/// </remarks>
/// </summary>
public List<Placement> EveryPlacement
{
get
{
var placements = new List<Placement>();
for (var zIter = 0; zIter < size.y; zIter++)
{
for (var xIter = 0; xIter < size.x; xIter++)
{
placements.AddRange(OrientationExtensions.EveryOrientation().Select(o => new Placement
{
position = new Vector3Int(xIter, 0, zIter),
size = Vector2Int.one,
orientation = o
}));
}
}
return placements;
}
}
public string PositionAndOrientation() => $"{{({position.x}, {position.z}), {orientation}}}";
public override string ToString() => $"{{{position}, {size}, {orientation}}}";
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fd604a23d14e49aeb740a8108bd35111
timeCreated: 1669114833

View File

@@ -5,26 +5,29 @@ using UnityEngine;
namespace EscapeRoomEngine.Engine.Runtime.Requirements
{
[CreateAssetMenu(menuName = "Requirements/Face Space Center")]
public class FaceSpaceCenter : OrientationRequirement
public class FaceSpaceCenter : PlacementRequirement
{
protected override IEnumerable<Orientation> GenerateCandidates(Module module, Space space)
protected override List<Placement> FilterCandidates(List<Placement> candidates, Module module, Space space)
{
var orientation = new HashSet<Orientation>(1);
float width = space.rrDimensions.width;
float length = space.rrDimensions.length;
var xRel = module.SrPosition.x / (width - 1);
var zRel = module.SrPosition.y / (length - 1);
if (zRel > xRel)
{
orientation.Add(zRel > 1 - xRel ? Orientation.South : Orientation.East);
}
else
{
orientation.Add(zRel > 1 - xRel ? Orientation.West : Orientation.North);
}
float width = space.rrPlacement.size.x - 1;
float length = space.rrPlacement.size.y - 1;
return orientation;
candidates.RemoveAll(candidate =>
{
var xRel = candidate.position.x / width;
var zRel = candidate.position.z / length;
return candidate.orientation !=
(zRel > xRel
? zRel > 1 - xRel
? Orientation.South
: Orientation.East
: zRel > 1 - xRel
? Orientation.West
: Orientation.North);
});
return candidates;
}
}
}

View File

@@ -1,6 +1,5 @@
using System.Collections.Generic;
using EscapeRoomEngine.Engine.Runtime.Modules;
using NaughtyAttributes;
using UnityEngine;
namespace EscapeRoomEngine.Engine.Runtime.Requirements
@@ -8,21 +7,11 @@ namespace EscapeRoomEngine.Engine.Runtime.Requirements
[CreateAssetMenu(menuName = "Requirements/No Overlap")]
public class NoOverlap : PlacementRequirement
{
[InfoBox("A module relative position will be oriented with the module (e.g. (0, 1) is always in front of the module).")]
[Label("Reserved Positions (Module Relative)")]
public List<Vector2Int> mrReservedPositions;
protected override IEnumerable<Vector2Int> GenerateCandidates(Module module, Space space)
protected override List<Placement> FilterCandidates(List<Placement> candidates, Module module, Space space)
{
var candidates = space.rrDimensions.EveryPosition;
space.AllModules.ForEach(m =>
space.AllModules.ForEach(other =>
{
candidates.Remove(m.SrPosition);
m.description.placementRequirements
.FindAll(r => r is NoOverlap)
.ForEach(r => ((NoOverlap)r).mrReservedPositions
.ForEach(p => candidates.Remove(m.ToSpaceRelative(p))));
candidates.RemoveAll(candidate => candidate.position.Equals(other.SrPosition));
});
return candidates;

View File

@@ -1,40 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using EscapeRoomEngine.Engine.Runtime.Modules;
using EscapeRoomEngine.Engine.Runtime.Utilities;
namespace EscapeRoomEngine.Engine.Runtime.Requirements
{
public abstract class OrientationRequirement : Requirement<Orientation>
{
protected abstract override IEnumerable<Orientation> GenerateCandidates(Module module, Space space);
public static bool TryOrienting(Module module, Space space)
{
if (module.description.orientationRequirements.Count == 0)
{
// don't evaluate requirements if there are none
return true;
}
var orientationCandidates = Candidates(
Module.EveryOrientation,
module.description.orientationRequirements,
module, space);
Logger.Log($"orientation candidates: {string.Join(",", orientationCandidates.ToList().ConvertAll(c => c.ToString()))}", LogType.RequirementResolution);
if (orientationCandidates.Count > 0)
{
module.orientation = orientationCandidates.RandomElement();
return true;
}
// ReSharper disable once RedundantIfElseBlock
else
{
Logger.Log("Could not find suitable orientation for module", LogType.RequirementResolution);
return false;
}
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 0704ea5393394baf921f68d2dcbdfaec
timeCreated: 1667878220

View File

@@ -7,22 +7,18 @@ namespace EscapeRoomEngine.Engine.Runtime.Requirements
[CreateAssetMenu(menuName = "Requirements/Place Along Space Edges")]
public class PlaceAlongSpaceEdges : PlacementRequirement
{
protected override IEnumerable<Vector2Int> GenerateCandidates(Module module, Space space)
protected override List<Placement> FilterCandidates(List<Placement> candidates, Module module, Space space)
{
var edgePositions = new HashSet<Vector2Int>();
var right = space.rrPlacement.size.x - 1;
var top = space.rrPlacement.size.y - 1;
for (var x = 0; x < space.rrDimensions.width; x++)
candidates.RemoveAll(candidate =>
{
edgePositions.Add(new Vector2Int(x, 0));
edgePositions.Add(new Vector2Int(x, space.rrDimensions.length - 1));
}
for (var z = 0; z < space.rrDimensions.length; z++)
{
edgePositions.Add(new Vector2Int(0, z));
edgePositions.Add(new Vector2Int(space.rrDimensions.width - 1, z));
}
var position = candidate.position;
return position.x > 0 && position.x < right && position.z > 0 && position.z < top;
});
return edgePositions;
return candidates;
}
}
}

View File

@@ -7,9 +7,9 @@ namespace EscapeRoomEngine.Engine.Runtime.Requirements
[CreateAssetMenu(menuName = "Requirements/Place Anywhere")]
public class PlaceAnywhere : PlacementRequirement
{
protected override IEnumerable<Vector2Int> GenerateCandidates(Module module, Space space)
protected override List<Placement> FilterCandidates(List<Placement> candidates, Module module, Space space)
{
return space.rrDimensions.EveryPosition;
return candidates;
}
}
}

View File

@@ -2,15 +2,12 @@
using System.Linq;
using EscapeRoomEngine.Engine.Runtime.Modules;
using EscapeRoomEngine.Engine.Runtime.Utilities;
using UnityEngine;
using Logger = EscapeRoomEngine.Engine.Runtime.Utilities.Logger;
using LogType = EscapeRoomEngine.Engine.Runtime.Utilities.LogType;
namespace EscapeRoomEngine.Engine.Runtime.Requirements
{
public abstract class PlacementRequirement : Requirement<Vector2Int>
public abstract class PlacementRequirement : Requirement<Placement>
{
protected abstract override IEnumerable<Vector2Int> GenerateCandidates(Module module, Space space);
protected abstract override List<Placement> FilterCandidates(List<Placement> candidates, Module module, Space space);
public static bool TryPlacing(Module module, Space space)
{
@@ -21,11 +18,11 @@ namespace EscapeRoomEngine.Engine.Runtime.Requirements
}
var placementCandidates = Candidates(
space.rrDimensions.EveryPosition,
space.rrPlacement.EveryPlacement,
module.description.placementRequirements,
module, space);
Logger.Log($"placement candidates: {string.Join(", ", placementCandidates.ToList().ConvertAll(c => c.ToString()))}", LogType.RequirementResolution);
Logger.Log($"placement candidates: {string.Join(", ", placementCandidates.ToList().ConvertAll(c => c.PositionAndOrientation()))}", LogType.RequirementResolution);
if (placementCandidates.Count > 0)
{

View File

@@ -7,9 +7,9 @@ namespace EscapeRoomEngine.Engine.Runtime.Requirements
{
public abstract class PreconditionRequirement : Requirement<bool>
{
protected static readonly HashSet<bool> TrueSet = new(new[] { true }), FalseSet = new(new[] { false });
private static readonly List<bool> TrueSet = new(new[] { true });
protected abstract override IEnumerable<bool> GenerateCandidates(Module module, Space space);
protected abstract override List<bool> FilterCandidates(List<bool> candidates, Module module, Space space);
public static bool CheckPreconditions(Module module, Space space)
{

View File

@@ -12,12 +12,12 @@ namespace EscapeRoomEngine.Engine.Runtime.Requirements
[Required]
public ModuleDescription relatedModule;
protected override IEnumerable<bool> GenerateCandidates(Module module, Space space)
protected override List<bool> FilterCandidates(List<bool> candidates, Module module, Space space)
{
var newModule = Module.CreateModuleByType(space, relatedModule);
module.relatedModules.Add(newModule);
return new []{ space.StageModuleWithRequirements(newModule) };
return new List<bool> { space.StageModuleWithRequirements(newModule) };
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using EscapeRoomEngine.Engine.Runtime.Modules;
using UnityEngine;
@@ -6,22 +7,15 @@ namespace EscapeRoomEngine.Engine.Runtime.Requirements
{
public abstract class Requirement<T> : ScriptableObject
{
protected abstract IEnumerable<T> GenerateCandidates(Module module, Space space);
protected abstract List<T> FilterCandidates(List<T> candidates, Module module, Space space);
public void Restrict(HashSet<T> candidates, Module module, Space space) =>
candidates.IntersectWith(GenerateCandidates(module, space));
public static HashSet<T> Candidates(
HashSet<T> initialCandidates,
protected static List<T> Candidates(
List<T> candidates,
IEnumerable<Requirement<T>> requirements,
Module module, Space space)
{
foreach (var requirement in requirements)
{
requirement.Restrict(initialCandidates, module, space);
}
return initialCandidates;
return requirements.Aggregate(candidates,
(current, requirement) => requirement.FilterCandidates(current, module, space));
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using EscapeRoomEngine.Engine.Runtime.Modules;
using EscapeRoomEngine.Engine.Runtime.Utilities;
using UnityEngine;
using Logger = EscapeRoomEngine.Engine.Runtime.Utilities.Logger;
using LogType = EscapeRoomEngine.Engine.Runtime.Utilities.LogType;
@@ -13,7 +14,7 @@ namespace EscapeRoomEngine.Engine.Runtime
/// <summary>
/// The room relative (<i>RR</i>) dimensions of this space.
/// </summary>
internal readonly Dimensions rrDimensions;
internal readonly Placement rrPlacement;
internal readonly Room room;
/// <summary>
@@ -42,10 +43,10 @@ namespace EscapeRoomEngine.Engine.Runtime
internal Space(Room room, Passage entrance)
{
this.room = room;
rrDimensions = GenerateSpaceDimensions(
rrPlacement = GenerateSpaceDimensions(
entrance,
Engine.DefaultEngine.theme.minRoomSize,
Engine.DefaultEngine.theme.playSpace);
Engine.DefaultEngine.theme.minRoomSize.ProjectAtFloor(),
Engine.DefaultEngine.theme.playSpace.ProjectAtFloor());
// connect the space to its passage
entrance.ConnectTo(new DoorModule(this,
@@ -94,20 +95,20 @@ namespace EscapeRoomEngine.Engine.Runtime
{
_spaceObject = new GameObject($"Space {name}");
_spaceObject.transform.SetParent(parent, false);
_spaceObject.transform.localPosition = new Vector3(rrDimensions.x, 0, rrDimensions.z);
_spaceObject.transform.localPosition = new Vector3(rrPlacement.position.x, 0, rrPlacement.position.z);
// build the space floor out of tiles
_spaceTiles = new GameObject($"Space Geometry");
_spaceTiles.transform.SetParent(_spaceObject.transform, false);
_spaceTiles.isStatic = true;
for (var z = 0; z < rrDimensions.length; z++)
for (var z = 0; z < rrPlacement.size.y; z++)
{
for (var x = 0; x < rrDimensions.width; x++)
for (var x = 0; x < rrPlacement.size.x; x++)
{
var left = x == 0;
var right = x == rrDimensions.width - 1;
var right = x == rrPlacement.size.x - 1;
var bottom = z == 0;
var top = z == rrDimensions.length - 1;
var top = z == rrPlacement.size.y - 1;
TileLocation location;
if (bottom)
@@ -131,40 +132,40 @@ namespace EscapeRoomEngine.Engine.Runtime
/// Convert a position relative to this space to one relative to the room.
/// </summary>
/// <param name="srPosition">The space relative (<i>SR</i>) position that should be converted to a room relative (<i>RR</i>) position.</param>
internal Vector2Int ToRoomRelative(Vector2Int srPosition) => srPosition + rrDimensions.Position;
internal Vector3Int ToRoomRelative(Vector3Int srPosition) => srPosition + rrPlacement.position;
/// <summary>
/// Convert a position relative to the room to one relative to this space.
/// </summary>
/// <param name="rrPosition">The room relative (<i>RR</i>) position that should be converted to a space relative (<i>SR</i>) position.</param>
internal Vector2Int ToSpaceRelative(Vector2Int rrPosition) => rrPosition - rrDimensions.Position;
internal Vector3Int ToSpaceRelative(Vector3Int rrPosition) => rrPosition - rrPlacement.position;
/// <summary>
/// Generate space dimensions that fit the required size constraints and cover the position of the entrance.
/// </summary>
/// <returns>The generated room relative (<i>RR</i>) dimensions.</returns>
private static Dimensions GenerateSpaceDimensions(Passage entrance, Vector2Int minSize, Vector2Int availableSpace)
/// <returns>A room relative (<i>RR</i>) placement with the generated dimensions. Always faces North.</returns>
private static Placement GenerateSpaceDimensions(Passage entrance, Vector3Int minSize, Vector3Int availableSpace)
{
var xMin = -1;
var xMax = -1;
var zMin = -1;
var zMax = -1;
var position = entrance.rrPosition;
var door = entrance.fromOut;
var position = door.RrPosition;
// fix the side the door is facing away from
switch (door.orientation)
switch (door.Orientation)
{
case Orientation.North:
zMin = position.y;
zMax = Utilities.Utilities.RandomInclusive(zMin + minSize.y, availableSpace.y);
zMin = position.z;
zMax = Utilities.Utilities.RandomInclusive(zMin + minSize.z, availableSpace.z);
break;
case Orientation.East:
xMin = position.x;
xMax = Utilities.Utilities.RandomInclusive(xMin + minSize.x, availableSpace.x);
break;
case Orientation.South:
zMax = position.y + 1;
zMin = Utilities.Utilities.RandomInclusive(0, zMax - minSize.y);
zMax = position.z + 1;
zMin = Utilities.Utilities.RandomInclusive(0, zMax - minSize.z);
break;
case Orientation.West:
xMax = position.x + 1;
@@ -180,16 +181,14 @@ namespace EscapeRoomEngine.Engine.Runtime
if(xMax == -1)
xMax = Utilities.Utilities.RandomInclusive(Math.Max(position.x + 1, xMin + minSize.x), availableSpace.x);
if(zMin == -1)
zMin = Utilities.Utilities.RandomInclusive(0, Math.Min(position.y, availableSpace.y - minSize.y));
zMin = Utilities.Utilities.RandomInclusive(0, Math.Min(position.z, availableSpace.z - minSize.z));
if(zMax == -1)
zMax = Utilities.Utilities.RandomInclusive(Math.Max(position.y + 1, zMin + minSize.y), availableSpace.y);
zMax = Utilities.Utilities.RandomInclusive(Math.Max(position.z + 1, zMin + minSize.z), availableSpace.z);
var dimensions = new Dimensions
var dimensions = new Placement
{
width = xMax - xMin,
length = zMax - zMin,
x = xMin,
z = zMin
position = new Vector3Int(xMin, 0, zMin),
size = new Vector2Int(xMax - xMin, zMax - zMin)
};
Logger.Log($"Generated space dimensions {dimensions} from entrance position {position}", LogType.RoomGeneration);

View File

@@ -9,13 +9,13 @@ namespace EscapeRoomEngine.Engine.Runtime.Utilities
#region Math
/// <summary>
/// Returns whether a position relative to some dimensions is inside those dimensions.
/// Returns whether a position relative to some placement is inside its dimensions.
/// </summary>
/// <param name="position">The position to check, relative to the dimensions.</param>
/// <param name="dimensions">The dimensions to check the position against.</param>
public static bool IsInsideRelative(this Vector2Int position, Dimensions dimensions)
/// <param name="position">The position to check, relative to the placement.</param>
/// <param name="placement">The placement to check the position against.</param>
public static bool IsInsideRelative(this Vector3Int position, Placement placement)
{
return position.x >= 0 && position.y >= 0 && position.x < dimensions.width && position.y < dimensions.length;
return position.x >= 0 && position.z >= 0 && position.x < placement.size.x && position.z < placement.size.y;
}
#endregion
@@ -29,4 +29,12 @@ namespace EscapeRoomEngine.Engine.Runtime.Utilities
#endregion
}
public static class Vector2IntExtensions
{
public static Vector3Int ProjectAtFloor(this Vector2Int vector) => vector.ProjectAtHeight(0);
public static Vector3Int ProjectAtHeight(this Vector2Int vector, int height) =>
new Vector3Int(vector.x, height, vector.y);
}
}