mirror of
https://github.com/Xevion/Paths.git
synced 2025-12-06 03:15:50 -06:00
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:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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--;
|
||||
}
|
||||
|
||||
|
||||
61
Paths/Assets/Scripts/LevelGeneration/RoomCarve.cs
Normal file
61
Paths/Assets/Scripts/LevelGeneration/RoomCarve.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Paths/Assets/Scripts/LevelGeneration/RoomCarve.cs.meta
Normal file
3
Paths/Assets/Scripts/LevelGeneration/RoomCarve.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b95ad3163134f988aa423b183d65c1d
|
||||
timeCreated: 1605336649
|
||||
Reference in New Issue
Block a user