A* adjacents small optimization, new RoomCarving level generation, extend RandomPlacement to allow 'carving', NodeGrid filled grid factory method, IsEdge & ClearRoom

This commit is contained in:
Xevion
2020-11-14 01:43:17 -06:00
parent 3e6507193f
commit 20a378fa89
6 changed files with 106 additions and 11 deletions

View File

@@ -43,10 +43,12 @@ namespace Algorithms {
_closedList.Add(current);
RecordState();
List<Node> 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();
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -7,7 +7,7 @@ public class GridState {
public readonly GridNodeType[,] Grid;
public readonly float Time;
public GridState(NodeGrid grid, List<Node> seen, List<Node> expanded, Vector2Int start,
public GridState(NodeGrid grid, IReadOnlyList<Node> seen, IReadOnlyList<Node> expanded, Vector2Int start,
Vector2Int end, Stack<Node> path) {
this.Time = UnityEngine.Time.realtimeSinceStartup;

View File

@@ -7,6 +7,7 @@ namespace LevelGeneration {
public class RandomPlacement : ILevelGenerator {
private readonly float _percentFill;
private readonly bool _fillTo;
private readonly bool _add;
/// <summary>
@@ -15,25 +16,33 @@ namespace LevelGeneration {
/// </summary>
/// <param name="percentFill">The target percentage to fill the graph to.</param>
/// <param name="fillTo">If true, the graph will be filled to the target percentage. If false, it will simply add that percentage.</param>
public RandomPlacement(float percentFill, bool fillTo) {
/// <param name="add">If false, removes walls instead of adding walls.</param>
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--;
}

View File

@@ -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<Rect> rooms = new List<Rect>();
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;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8b95ad3163134f988aa423b183d65c1d
timeCreated: 1605336649