diff --git a/Paths/Assets/Scripts/Algorithms/AStar.cs b/Paths/Assets/Scripts/Algorithms/AStar.cs index 1d9a1ab..1a61c6a 100644 --- a/Paths/Assets/Scripts/Algorithms/AStar.cs +++ b/Paths/Assets/Scripts/Algorithms/AStar.cs @@ -43,10 +43,12 @@ namespace Algorithms { _closedList.Add(current); RecordState(); - List adjacentNodes = this._nodeGrid.GetAdjacentNodesList(current); + Node[] adjacentNodes = this._nodeGrid.GetAdjacentNodesArray(current); + if (true) { + for (int i = 0; i < adjacentNodes.Length; i++) { + Node n = adjacentNodes[i]; + if (n == null) continue; - if (adjacentNodes.Count > 0) { - foreach (Node n in adjacentNodes) { if (!_closedList.Contains(n) && n.Walkable) { if (!_openList.Contains(n)) { n.Parent = current; @@ -58,8 +60,6 @@ namespace Algorithms { } } } - - RecordState(); } } diff --git a/Paths/Assets/Scripts/Algorithms/NodeGrid.cs b/Paths/Assets/Scripts/Algorithms/NodeGrid.cs index cef4137..d98b090 100644 --- a/Paths/Assets/Scripts/Algorithms/NodeGrid.cs +++ b/Paths/Assets/Scripts/Algorithms/NodeGrid.cs @@ -112,5 +112,27 @@ namespace Algorithms { public Node GetRandomNode() { return Grid[Random.Range(0, Width), Random.Range(0, Height)]; } + + public static NodeGrid GetFilledNodeGrid(int width, int height) { + var nodeGrid = new NodeGrid(width, height); + + // Set each Node to a Wall + for (int x = 0; x < width; x++) + for (int y = 0; y < height; y++) + nodeGrid.Grid[x, y].Walkable = false; + + return nodeGrid; + } + + public bool IsEdge(Vector2Int position) { + return position.x == 0 || position.x == Width - 1 || position.y == 0 || position.y == Height - 1; + } + + public void ClearRoom(Rect room) { + for (float x = room.xMin; x < room.xMax; x++) + for (float y = room.yMin; y < room.yMax; y++) { + Grid[(int) x, (int) y].Walkable = true; + } + } } } \ No newline at end of file diff --git a/Paths/Assets/Scripts/GridState.cs b/Paths/Assets/Scripts/GridState.cs index 6c79b1e..0d034a0 100644 --- a/Paths/Assets/Scripts/GridState.cs +++ b/Paths/Assets/Scripts/GridState.cs @@ -7,7 +7,7 @@ public class GridState { public readonly GridNodeType[,] Grid; public readonly float Time; - public GridState(NodeGrid grid, List seen, List expanded, Vector2Int start, + public GridState(NodeGrid grid, IReadOnlyList seen, IReadOnlyList expanded, Vector2Int start, Vector2Int end, Stack path) { this.Time = UnityEngine.Time.realtimeSinceStartup; diff --git a/Paths/Assets/Scripts/LevelGeneration/RandomPlacement.cs b/Paths/Assets/Scripts/LevelGeneration/RandomPlacement.cs index 086976c..2486663 100644 --- a/Paths/Assets/Scripts/LevelGeneration/RandomPlacement.cs +++ b/Paths/Assets/Scripts/LevelGeneration/RandomPlacement.cs @@ -7,6 +7,7 @@ namespace LevelGeneration { public class RandomPlacement : ILevelGenerator { private readonly float _percentFill; private readonly bool _fillTo; + private readonly bool _add; /// @@ -15,25 +16,33 @@ namespace LevelGeneration { /// /// The target percentage to fill the graph to. /// If true, the graph will be filled to the target percentage. If false, it will simply add that percentage. - public RandomPlacement(float percentFill, bool fillTo) { + /// If false, removes walls instead of adding walls. + public RandomPlacement(float percentFill, bool fillTo, bool add) { _percentFill = percentFill; _fillTo = fillTo; + _add = add; } public NodeGrid Generate(NodeGrid nodeGrid) { // Calculate the number of walls to place int wallsLeft = (int) Math.Round(nodeGrid.CellCount * _percentFill); - if (_fillTo) wallsLeft -= nodeGrid.Walls().Count(); + if (_fillTo) wallsLeft -= (_add ? nodeGrid.Walls() : nodeGrid.Empty()).Count(); wallsLeft = Mathf.Clamp(wallsLeft, 0, nodeGrid.CellCount); // Begin adding walls while (wallsLeft > 0) { // Grab a node, skip if already a wall Node node = nodeGrid.GetRandomNode(); - if (!node.Walkable) continue; - // Node is empty, set to a wall - node.Walkable = false; + if (_add) { + if (!node.Walkable) continue; + node.Walkable = false; + } + else { + if (node.Walkable) continue; + node.Walkable = true; + } + wallsLeft--; } diff --git a/Paths/Assets/Scripts/LevelGeneration/RoomCarve.cs b/Paths/Assets/Scripts/LevelGeneration/RoomCarve.cs new file mode 100644 index 0000000..dbb6f5d --- /dev/null +++ b/Paths/Assets/Scripts/LevelGeneration/RoomCarve.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Algorithms; +using UnityEngine; +using Random = UnityEngine.Random; + +namespace LevelGeneration { + public class RoomCarve : ILevelGenerator { + private Vector2Int _roomRange; + private Vector2Int _roomSizeRange; + private int _maxAttempts; + + public RoomCarve(Vector2Int roomRange, Vector2Int roomSizeRange, int maxAttempts) { + _roomRange = roomRange; + _roomSizeRange = roomSizeRange; + _maxAttempts = maxAttempts; + } + + public NodeGrid Generate(NodeGrid nodeGrid) { + int roomCount = Random.Range(_roomRange.x, _roomRange.y); + int attempts = 0; + + // TODO: Update to latest Unity 2020 update to gain access to RectInt.Overlaps (?) + + // Generate rooms + List rooms = new List(); + do { + // Quit after too many attempts failed + if (attempts > _maxAttempts) + break; + + // Get a position and check that it's not on the edge of the grid + Vector2Int pos = nodeGrid.RandomPosition(); + if (nodeGrid.IsEdge(pos)) continue; + + + var size = new Vector2Int( + Math.Min(Random.Range(_roomSizeRange.x, _roomSizeRange.y), nodeGrid.Width - pos.x), + Math.Min(Random.Range(_roomSizeRange.x, _roomSizeRange.y), nodeGrid.Height - pos.y) + ); + var newRoom = new Rect(pos, size); + + // Check that it doesn't overlap with any of the previous rooms + bool skip = rooms.Any(room => room.Overlaps(newRoom)); + + // If it didn't, + if (!skip) + rooms.Add(newRoom); + else + attempts++; + } while (rooms.Count < roomCount); + + // Set all nodes within rooms + foreach (Rect rect in rooms) + nodeGrid.ClearRoom(rect); + + return nodeGrid; + } + } +} \ No newline at end of file diff --git a/Paths/Assets/Scripts/LevelGeneration/RoomCarve.cs.meta b/Paths/Assets/Scripts/LevelGeneration/RoomCarve.cs.meta new file mode 100644 index 0000000..201794f --- /dev/null +++ b/Paths/Assets/Scripts/LevelGeneration/RoomCarve.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8b95ad3163134f988aa423b183d65c1d +timeCreated: 1605336649 \ No newline at end of file