mirror of
https://github.com/Xevion/Paths.git
synced 2025-12-06 11:15:48 -06:00
fix off by one Random.Range generation (??), improve docs, GetAdjacentNodesArray
This commit is contained in:
2
Paths/Assembly-CSharp-Editor.csproj.DotSettings
Normal file
2
Paths/Assembly-CSharp-Editor.csproj.DotSettings
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=assets_005Ceditor/@EntryIndexedValue">False</s:Boolean></wpf:ResourceDictionary>
|
||||||
@@ -1,32 +1,34 @@
|
|||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
/// <summary>
|
namespace Editor {
|
||||||
/// Prevents script compilation and reload while in play mode.
|
/// <summary>
|
||||||
/// The editor will show a the spinning reload icon if there are unapplied changes but will not actually
|
/// Prevents script compilation and reload while in play mode.
|
||||||
/// apply them until playmode is exited.
|
/// The editor will show a the spinning reload icon if there are unapplied changes but will not actually
|
||||||
/// Note: Script compile errors will not be shown while in play mode.
|
/// apply them until playmode is exited.
|
||||||
/// Derived from the instructions here:
|
/// Note: Script compile errors will not be shown while in play mode.
|
||||||
/// https://support.unity3d.com/hc/en-us/articles/210452343-How-to-stop-automatic-assembly-compilation-from-script
|
/// Derived from the instructions here:
|
||||||
/// </summary>
|
/// https://support.unity3d.com/hc/en-us/articles/210452343-How-to-stop-automatic-assembly-compilation-from-script
|
||||||
[InitializeOnLoad]
|
/// </summary>
|
||||||
public class DisableScriptReload {
|
[InitializeOnLoad]
|
||||||
static DisableScriptReload() {
|
public class DisableScriptReload {
|
||||||
EditorApplication.playModeStateChanged
|
static DisableScriptReload() {
|
||||||
+= OnPlayModeStateChanged;
|
EditorApplication.playModeStateChanged
|
||||||
}
|
+= OnPlayModeStateChanged;
|
||||||
|
}
|
||||||
|
|
||||||
static void OnPlayModeStateChanged(PlayModeStateChange stateChange) {
|
static void OnPlayModeStateChanged(PlayModeStateChange stateChange) {
|
||||||
switch (stateChange) {
|
switch (stateChange) {
|
||||||
case (PlayModeStateChange.EnteredPlayMode): {
|
case (PlayModeStateChange.EnteredPlayMode): {
|
||||||
EditorApplication.LockReloadAssemblies();
|
EditorApplication.LockReloadAssemblies();
|
||||||
Debug.Log("Assembly Reload locked as entering play mode");
|
Debug.Log("Assembly Reload locked as entering play mode");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (PlayModeStateChange.ExitingPlayMode): {
|
case (PlayModeStateChange.ExitingPlayMode): {
|
||||||
Debug.Log("Assembly Reload unlocked as exiting play mode");
|
Debug.Log("Assembly Reload unlocked as exiting play mode");
|
||||||
EditorApplication.UnlockReloadAssemblies();
|
EditorApplication.UnlockReloadAssemblies();
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace Algorithms {
|
|||||||
_closedList.Add(current);
|
_closedList.Add(current);
|
||||||
RecordState();
|
RecordState();
|
||||||
|
|
||||||
List<Node> adjacentNodes = this._nodeGrid.GetAdjacentNodes(current);
|
List<Node> adjacentNodes = this._nodeGrid.GetAdjacentNodesList(current);
|
||||||
|
|
||||||
if (adjacentNodes.Count > 0) {
|
if (adjacentNodes.Count > 0) {
|
||||||
foreach (Node n in adjacentNodes) {
|
foreach (Node n in adjacentNodes) {
|
||||||
|
|||||||
@@ -20,10 +20,11 @@ namespace Algorithms {
|
|||||||
"The height of the grid must be a positive non-zero integer.");
|
"The height of the grid must be a positive non-zero integer.");
|
||||||
|
|
||||||
grid = new List<List<Node>>(width);
|
grid = new List<List<Node>>(width);
|
||||||
|
|
||||||
// Fill grid with width*height nodes, zero-indexed
|
// Fill grid with width*height nodes, zero-indexed
|
||||||
foreach (int x in Enumerable.Range(0, width - 1)) {
|
for (int x = 0; x < width; x++) {
|
||||||
List<Node> list = new List<Node>(height);
|
List<Node> list = new List<Node>(height);
|
||||||
foreach (int y in Enumerable.Range(0, height - 1))
|
for (int y = 0; y < height; y++)
|
||||||
list.Add(new Node(new Vector2Int(x, y), true));
|
list.Add(new Node(new Vector2Int(x, y), true));
|
||||||
|
|
||||||
grid.Add(list);
|
grid.Add(list);
|
||||||
@@ -40,7 +41,7 @@ namespace Algorithms {
|
|||||||
Width = this.grid.Count;
|
Width = this.grid.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Node> GetAdjacentNodes(Node node) {
|
public List<Node> GetAdjacentNodesList(Node node) {
|
||||||
List<Node> temp = new List<Node>();
|
List<Node> temp = new List<Node>();
|
||||||
|
|
||||||
int col = node.Position.x;
|
int col = node.Position.x;
|
||||||
@@ -53,7 +54,25 @@ namespace Algorithms {
|
|||||||
|
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Node[] GetAdjacentNodesArray(Node node) {
|
||||||
|
int col = node.Position.x;
|
||||||
|
int row = node.Position.y;
|
||||||
|
|
||||||
|
return new Node[] {
|
||||||
|
row + 1 < Height ? grid[col][row + 1] : null,
|
||||||
|
row - 1 >= 0 ? grid[col][row - 1] : null,
|
||||||
|
col - 1 >= 0 ? grid[col - 1][row] : null,
|
||||||
|
col + 1 < Width ? grid[col + 1][row] : null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests whether a coordinate is valid on the NodeGrid
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">The X (column) coordinate</param>
|
||||||
|
/// <param name="y">The Y (row) coordinate</param>
|
||||||
|
/// <returns></returns>
|
||||||
public bool IsValid(int x, int y) {
|
public bool IsValid(int x, int y) {
|
||||||
return x > 0 && x < Width && y > 0 && y < Height;
|
return x > 0 && x < Width && y > 0 && y < Height;
|
||||||
}
|
}
|
||||||
@@ -81,8 +100,8 @@ namespace Algorithms {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void AddRandomWall() {
|
public void AddRandomWall() {
|
||||||
while (true) {
|
while (true) {
|
||||||
int x = Random.Range(0, Width - 1);
|
int x = Random.Range(0, Width);
|
||||||
int y = Random.Range(0, Height - 1);
|
int y = Random.Range(0, Height);
|
||||||
|
|
||||||
if (grid[x][y].Walkable) {
|
if (grid[x][y].Walkable) {
|
||||||
grid[x][y].Walkable = false;
|
grid[x][y].Walkable = false;
|
||||||
@@ -104,7 +123,7 @@ namespace Algorithms {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>a valid Vector2Int position within the grid</returns>
|
/// <returns>a valid Vector2Int position within the grid</returns>
|
||||||
public Vector2Int RandomPosition() {
|
public Vector2Int RandomPosition() {
|
||||||
return new Vector2Int(Random.Range(0, Width - 1), Random.Range(0, Height - 1));
|
return new Vector2Int(Random.Range(0, Width), Random.Range(0, Height));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -127,13 +146,13 @@ namespace Algorithms {
|
|||||||
public IEnumerable<Node> Empty() {
|
public IEnumerable<Node> Empty() {
|
||||||
return this.Iterator().Where(node => node.Walkable);
|
return this.Iterator().Where(node => node.Walkable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a random valid node on the grid.
|
/// Returns a random valid node on the grid.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>A Node object.</returns>
|
/// <returns>A Node object.</returns>
|
||||||
public Node GetRandomNode() {
|
public Node GetRandomNode() {
|
||||||
return grid[Random.Range(0, Width - 1)][Random.Range(0, Height - 1)];
|
return grid[Random.Range(0, Width)][Random.Range(0, Height)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,11 @@
|
|||||||
using Algorithms;
|
using Algorithms;
|
||||||
|
|
||||||
public interface ILevelGenerator {
|
public interface ILevelGenerator {
|
||||||
|
/// <summary>
|
||||||
|
/// Applies the LevelGenerator's algorithm.
|
||||||
|
/// A empty NodeGrid is recommended, as the algorithm may perform in unexpected ways, possibly even fail.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="nodeGrid">A NodeGrid object.</param>
|
||||||
|
/// <returns>A modified NodeGrid object.</returns>
|
||||||
NodeGrid Generate(NodeGrid nodeGrid);
|
NodeGrid Generate(NodeGrid nodeGrid);
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,9 @@ namespace LevelGeneration {
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A simple level generator implementing the Drunkard Walk algorithm.
|
/// A simple level generator implementing the Drunkard Walk algorithm.
|
||||||
|
/// This implementation simply starts 'walks' a certain number of times.
|
||||||
|
/// Each walk chooses a node, and then repeatedly chooses an adjacent node randomly.
|
||||||
|
/// Each move clears (or adds) walls.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="walks">The number of independent walks that will be started.</param>
|
/// <param name="walks">The number of independent walks that will be started.</param>
|
||||||
/// <param name="walkLength">The maximum number of nodes to be added/cleared</param>
|
/// <param name="walkLength">The maximum number of nodes to be added/cleared</param>
|
||||||
@@ -24,16 +27,10 @@ namespace LevelGeneration {
|
|||||||
_continueBias = continueBias;
|
_continueBias = continueBias;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="nodeGrid"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public NodeGrid Generate(NodeGrid nodeGrid) {
|
public NodeGrid Generate(NodeGrid nodeGrid) {
|
||||||
for (int unused = 0; unused < _walks; unused++) {
|
for (int unused = 0; unused < _walks; unused++) {
|
||||||
Node node = nodeGrid.GetRandomNode();
|
Node node = nodeGrid.GetRandomNode();
|
||||||
|
Node[] nodes = nodeGrid.GetAdjacentNodesArray(node);
|
||||||
nodeGrid.GetAdjacentNodes(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodeGrid;
|
return nodeGrid;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using Algorithms;
|
using Algorithms;
|
||||||
using TMPro;
|
using TMPro;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@@ -12,7 +11,7 @@ public class Manager : MonoBehaviour {
|
|||||||
private IPathfinding _algorithm;
|
private IPathfinding _algorithm;
|
||||||
private List<GridState> _states;
|
private List<GridState> _states;
|
||||||
private int _curIndex;
|
private int _curIndex;
|
||||||
private Stack<Node> path;
|
private Stack<Node> _path;
|
||||||
private float _lastStart;
|
private float _lastStart;
|
||||||
private float _runtime;
|
private float _runtime;
|
||||||
|
|
||||||
@@ -30,10 +29,10 @@ public class Manager : MonoBehaviour {
|
|||||||
GeneratePath();
|
GeneratePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnDrawGizmos() {
|
// public void OnDrawGizmos() {
|
||||||
float size = (float) (10.0 / gridController.size);
|
// float size = (float) (10.0 / gridController.size);
|
||||||
Gizmos.DrawWireCube(transform.position, new Vector3(size, size, size));
|
// Gizmos.DrawWireCube(transform.position, new Vector3(size, size, size));
|
||||||
}
|
// }
|
||||||
|
|
||||||
public void Update() {
|
public void Update() {
|
||||||
_runtime += Time.deltaTime * speed;
|
_runtime += Time.deltaTime * speed;
|
||||||
@@ -56,8 +55,8 @@ public class Manager : MonoBehaviour {
|
|||||||
var nodeGrid = new NodeGrid(gridController.size, gridController.size);
|
var nodeGrid = new NodeGrid(gridController.size, gridController.size);
|
||||||
_algorithm = new AStar(nodeGrid);
|
_algorithm = new AStar(nodeGrid);
|
||||||
|
|
||||||
// Vector2 start = nodeGrid.RandomPosition();
|
Vector2Int start = nodeGrid.RandomPosition();
|
||||||
Vector2Int start = new Vector2Int(30, 30);
|
// Vector2Int start = new Vector2Int(30, 30);
|
||||||
Vector2Int end = nodeGrid.RandomPosition();
|
Vector2Int end = nodeGrid.RandomPosition();
|
||||||
|
|
||||||
|
|
||||||
@@ -68,7 +67,7 @@ public class Manager : MonoBehaviour {
|
|||||||
nodeGrid.GetNode(start).Walkable = true;
|
nodeGrid.GetNode(start).Walkable = true;
|
||||||
nodeGrid.GetNode(end).Walkable = true;
|
nodeGrid.GetNode(end).Walkable = true;
|
||||||
|
|
||||||
path = _algorithm.FindPath(start, end);
|
_path = _algorithm.FindPath(start, end);
|
||||||
|
|
||||||
_states = _algorithm.GetStates();
|
_states = _algorithm.GetStates();
|
||||||
|
|
||||||
@@ -80,7 +79,7 @@ public class Manager : MonoBehaviour {
|
|||||||
gridController.LoadGridState(state);
|
gridController.LoadGridState(state);
|
||||||
|
|
||||||
float change = state.Time - _lastStart;
|
float change = state.Time - _lastStart;
|
||||||
string pathCount = path != null ? $"{path.Count}" : "N/A";
|
string pathCount = _path != null ? $"{_path.Count}" : "N/A";
|
||||||
debugText.text =
|
debugText.text =
|
||||||
$"{change * 1000.0:F1}ms\n{this.CurrentIndex:000} / {this._states.Count:000}\nPath: {pathCount} tiles";
|
$"{change * 1000.0:F1}ms\n{this.CurrentIndex:000} / {this._states.Count:000}\nPath: {pathCount} tiles";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user