mirror of
https://github.com/Xevion/Paths.git
synced 2025-12-10 18:07:59 -06:00
overall fixes to classes, final removal of Manager, docs, CustomSlider new keyword, IPathfinding interface Cleanup() func, GridController positioning amendments
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace Algorithms {
|
namespace Algorithms {
|
||||||
@@ -15,7 +14,7 @@ namespace Algorithms {
|
|||||||
public Vector2Int End { get; private set; }
|
public Vector2Int End { get; private set; }
|
||||||
|
|
||||||
public AStar(NodeGrid nodeGrid) {
|
public AStar(NodeGrid nodeGrid) {
|
||||||
this.NodeGrid = nodeGrid;
|
NodeGrid = nodeGrid;
|
||||||
ChangeController = new ChangeController(nodeGrid.RenderNodeTypes());
|
ChangeController = new ChangeController(nodeGrid.RenderNodeTypes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +77,7 @@ namespace Algorithms {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix start position being overriden
|
// Fix start and end position being overriden
|
||||||
ChangeController.RemovePositions(start, 1);
|
ChangeController.RemovePositions(start, 1);
|
||||||
|
|
||||||
// if all good, return path
|
// if all good, return path
|
||||||
@@ -86,7 +85,8 @@ namespace Algorithms {
|
|||||||
if (temp == null) return null;
|
if (temp == null) return null;
|
||||||
do {
|
do {
|
||||||
_path.Push(temp);
|
_path.Push(temp);
|
||||||
ChangeController.AddChange(new Change(temp.Position.x, temp.Position.y, GridNodeType.Path, GridNodeType.Expanded));
|
ChangeController.AddChange(new Change(temp.Position.x, temp.Position.y, GridNodeType.Path,
|
||||||
|
GridNodeType.Expanded));
|
||||||
temp = temp.Parent;
|
temp = temp.Parent;
|
||||||
} while (temp != null && !temp.Equals(startNode));
|
} while (temp != null && !temp.Equals(startNode));
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public class ChangeController {
|
|||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Move the ChangeController's current index forward by index.
|
/// Move the ChangeController's current index forward by a certain number of times.
|
||||||
/// Positive values only, wil only result in forward movement (if any).
|
/// Positive values only, wil only result in forward movement (if any).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="n">The number of times to move forward.</param>
|
/// <param name="n">The number of times to move forward.</param>
|
||||||
@@ -80,7 +80,7 @@ public class ChangeController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Move the ChangeController's current index backward by index.
|
/// Move the ChangeController's current index backward by a certain number of times.
|
||||||
/// Positive values only, will only result in backward movement (if any).
|
/// Positive values only, will only result in backward movement (if any).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="n">The number of times to move backward.</param>
|
/// <param name="n">The number of times to move backward.</param>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
|
||||||
public class CustomSlider: Slider {
|
public class CustomSlider: Slider {
|
||||||
public bool IsPressed { get; private set; }
|
public new bool IsPressed { get; private set; }
|
||||||
|
|
||||||
public override void OnPointerDown(PointerEventData eventData)
|
public override void OnPointerDown(PointerEventData eventData)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -141,9 +141,9 @@ public class GridController : MonoBehaviour {
|
|||||||
public Vector2Int GetGridPosition(Vector3 worldPosition) {
|
public Vector2Int GetGridPosition(Vector3 worldPosition) {
|
||||||
Vector3 localScale = transform.localScale;
|
Vector3 localScale = transform.localScale;
|
||||||
Vector2 gridPosition = (worldPosition + (localScale / 2f)) / new Vector2(localScale.x, localScale.y);
|
Vector2 gridPosition = (worldPosition + (localScale / 2f)) / new Vector2(localScale.x, localScale.y);
|
||||||
return new Vector2Int(
|
return Size - new Vector2Int(
|
||||||
(int) (gridPosition.x * width),
|
(int) (gridPosition.x * width),
|
||||||
(int) (gridPosition.y * height)) - Size - Vector2Int.one;
|
(int) (gridPosition.y * height)) - Vector2Int.one;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -154,9 +154,9 @@ public class GridController : MonoBehaviour {
|
|||||||
public Vector3 GetWorldPosition(Vector2Int gridPosition) {
|
public Vector3 GetWorldPosition(Vector2Int gridPosition) {
|
||||||
Transform ttransform = transform;
|
Transform ttransform = transform;
|
||||||
Vector3 localScale = ttransform.localScale;
|
Vector3 localScale = ttransform.localScale;
|
||||||
Vector2 bottomLeft = ttransform.position - (localScale / 2f);
|
Vector2 topRight = ttransform.position + (localScale / 2f);
|
||||||
var singleSquare = new Vector2(localScale.x / width, localScale.y / height);
|
var singleSquare = new Vector2(localScale.x / width, localScale.y / height);
|
||||||
Vector2 worldPosition = bottomLeft + (singleSquare * gridPosition) + (singleSquare / 2f);
|
Vector2 worldPosition = topRight - (singleSquare * (gridPosition + Vector2Int.one)) + (singleSquare / 2f);
|
||||||
return worldPosition;
|
return worldPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,4 +17,5 @@ public interface IPathfinding {
|
|||||||
Vector2Int Start { get; }
|
Vector2Int Start { get; }
|
||||||
Vector2Int End { get; }
|
Vector2Int End { get; }
|
||||||
ChangeController ChangeController { get; }
|
ChangeController ChangeController { get; }
|
||||||
|
void Cleanup();
|
||||||
}
|
}
|
||||||
@@ -1,180 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Algorithms;
|
|
||||||
using LevelGeneration;
|
|
||||||
using TMPro;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.UI;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The primary controller of the entire application, managing state, events and sending commands
|
|
||||||
/// </summary>
|
|
||||||
public class Manager : MonoBehaviour {
|
|
||||||
private IPathfinding _algorithm;
|
|
||||||
private ChangeController _state;
|
|
||||||
private int _curIndex;
|
|
||||||
private Stack<Node> _path;
|
|
||||||
private float _runtime;
|
|
||||||
|
|
||||||
public float speed;
|
|
||||||
public float clampIncrement;
|
|
||||||
public bool moving = true;
|
|
||||||
|
|
||||||
public Camera mainCamera;
|
|
||||||
public GameObject gridObject;
|
|
||||||
public GridController gridController;
|
|
||||||
public TextMeshPro debugText;
|
|
||||||
public Slider progressSlider;
|
|
||||||
private float? _moveTo;
|
|
||||||
|
|
||||||
private int CurrentIndex {
|
|
||||||
get => (int) _runtime;
|
|
||||||
set => _runtime = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Start() {
|
|
||||||
GeneratePath();
|
|
||||||
Resize();
|
|
||||||
|
|
||||||
progressSlider.onValueChanged.AddListener((value) => MoveToSlider(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Update the animation progress to the slider's (new) position.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="new">The new position on the slider.</param>
|
|
||||||
private void MoveToSlider(float @new) {
|
|
||||||
_runtime = @new * _state.Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void OnDrawGizmos() {
|
|
||||||
if (!Application.isPlaying) return;
|
|
||||||
|
|
||||||
Vector3 mouse = mainCamera.ScreenToWorldPoint(Input.mousePosition);
|
|
||||||
Vector3 localScale = gridObject.transform.localScale;
|
|
||||||
Vector2Int gridPosition = GetGridPosition(mouse, localScale);
|
|
||||||
Vector2Int realGridPosition = gridController.Size - gridPosition - Vector2Int.one;
|
|
||||||
|
|
||||||
var style = new GUIStyle();
|
|
||||||
style.normal.textColor = Color.blue;
|
|
||||||
Gizmos.color = Color.blue;
|
|
||||||
|
|
||||||
Gizmos.DrawWireCube(GetWorldPosition(gridPosition, localScale), localScale / (Vector2) gridController.Size);
|
|
||||||
Handles.Label(mouse, String.Format("{0}{1}",
|
|
||||||
gridPosition,
|
|
||||||
_algorithm.NodeGrid.IsValid(gridPosition)
|
|
||||||
? $"\n{_state.Current[realGridPosition.x, realGridPosition.y]}"
|
|
||||||
: ""
|
|
||||||
), style);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the current time multiplier, based on the latest change in the path.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>A positive non-zero float representing how fast the current frame should be processed.</returns>
|
|
||||||
private float CurrentMultiplier() {
|
|
||||||
if (_state.Index == -1)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
switch (_state.CurrentChange.New) {
|
|
||||||
case GridNodeType.Path:
|
|
||||||
return 1 / 5f;
|
|
||||||
case GridNodeType.Empty:
|
|
||||||
break;
|
|
||||||
case GridNodeType.Wall:
|
|
||||||
break;
|
|
||||||
case GridNodeType.Start:
|
|
||||||
break;
|
|
||||||
case GridNodeType.End:
|
|
||||||
break;
|
|
||||||
case GridNodeType.Seen:
|
|
||||||
break;
|
|
||||||
case GridNodeType.Expanded:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Update() {
|
|
||||||
// Toggle pause with space
|
|
||||||
if (Input.GetKeyDown(KeyCode.Space)) {
|
|
||||||
moving = !moving;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Input.GetKeyDown(KeyCode.G)) {
|
|
||||||
GeneratePath();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increment index if unpaused and not clicking (implying slider may be interacted with)
|
|
||||||
if (moving && !Input.GetMouseButton(0)) {
|
|
||||||
var increment = Time.deltaTime * speed * CurrentMultiplier();
|
|
||||||
if (clampIncrement > 0)
|
|
||||||
increment = Mathf.Clamp(increment, 0, _state.Count * Time.deltaTime / clampIncrement);
|
|
||||||
_runtime += increment;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load next state in grid or update text
|
|
||||||
if (CurrentIndex < _state.Count)
|
|
||||||
LoadNextState();
|
|
||||||
|
|
||||||
// Update progress slider silently
|
|
||||||
progressSlider.SetValueWithoutNotify(_runtime / _state.Count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Generates a new grid and runs pathfinding.
|
|
||||||
/// </summary>
|
|
||||||
private void GeneratePath() {
|
|
||||||
CurrentIndex = 0;
|
|
||||||
var nodeGrid = new NodeGrid(gridController.width, gridController.height);
|
|
||||||
|
|
||||||
// Vector2Int start = nodeGrid.RandomPosition();
|
|
||||||
Vector2Int start = new Vector2Int(3, 6);
|
|
||||||
Vector2Int end = nodeGrid.RandomPosition();
|
|
||||||
|
|
||||||
nodeGrid.ApplyGenerator(new RandomPlacement(0.3f, true, true));
|
|
||||||
|
|
||||||
nodeGrid.GetNode(start).Walkable = true;
|
|
||||||
nodeGrid.GetNode(end).Walkable = true;
|
|
||||||
|
|
||||||
_algorithm = new AStar(nodeGrid);
|
|
||||||
_path = _algorithm.FindPath(start, end);
|
|
||||||
_state = _algorithm.ChangeController;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Loads the appropriate grid state into the shader via the ChangeController instance.
|
|
||||||
/// </summary>
|
|
||||||
private void LoadNextState() {
|
|
||||||
_state.MoveTo(Math.Max(1, CurrentIndex)); // use Math.max to ensure both start/end nodes are always rendered
|
|
||||||
gridController.LoadDirtyGridState(_state.Current, _state.DirtyFlags);
|
|
||||||
|
|
||||||
string pathCount = _path != null ? $"{_path.Count}" : "N/A";
|
|
||||||
debugText.text = $"{_state.CurrentRuntime * 1000.0:F1}ms\n" +
|
|
||||||
$"{this.CurrentIndex:000} / {_state.Count:000}\n" +
|
|
||||||
$"Path: {pathCount} tiles";
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Scales the GridController GameObject to fit within the Camera
|
|
||||||
/// </summary>
|
|
||||||
private void Resize() {
|
|
||||||
float ratioImage = (float) gridController.width / gridController.height;
|
|
||||||
float ratioScreen = mainCamera.aspect;
|
|
||||||
|
|
||||||
var orthographicSize = mainCamera.orthographicSize;
|
|
||||||
var image = new Vector2(gridController.width, gridController.height);
|
|
||||||
var screen = new Vector2(2 * orthographicSize * mainCamera.aspect, orthographicSize * 2);
|
|
||||||
|
|
||||||
gridObject.transform.localScale = ratioScreen > ratioImage
|
|
||||||
? new Vector3(image.x * screen.y / image.y, screen.y, 0.001f)
|
|
||||||
: new Vector3(screen.x, image.y * screen.x / image.x, 0.001f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: ca142250b9964eb1adf66ac7c5cc3e3e
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 300
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Algorithms;
|
using Algorithms;
|
||||||
|
using TMPro;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UI;
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -39,7 +39,9 @@ public class UIController : MonoBehaviour {
|
|||||||
// UI & important App references
|
// UI & important App references
|
||||||
public CustomSlider progressSlider;
|
public CustomSlider progressSlider;
|
||||||
public GridController gridController;
|
public GridController gridController;
|
||||||
public Manager manager;
|
public Camera mainCamera;
|
||||||
|
public TextMeshPro debugText;
|
||||||
|
public GameObject gridObject;
|
||||||
|
|
||||||
// Animation State, Click Management
|
// Animation State, Click Management
|
||||||
private Vector2Int _lastClickLocation;
|
private Vector2Int _lastClickLocation;
|
||||||
@@ -72,13 +74,13 @@ public class UIController : MonoBehaviour {
|
|||||||
_end = _grid.RandomPosition();
|
_end = _grid.RandomPosition();
|
||||||
_runtime = 0;
|
_runtime = 0;
|
||||||
|
|
||||||
manager.Resize();
|
Resize();
|
||||||
progressSlider.onValueChanged.AddListener((value) => MoveToSlider(value));
|
progressSlider.onValueChanged.AddListener((value) => MoveToSlider(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Update() {
|
private void Update() {
|
||||||
if (Input.GetMouseButton(0)) {
|
if (Input.GetMouseButton(0)) {
|
||||||
Vector3 worldMouse = manager.mainCamera.ScreenToWorldPoint(Input.mousePosition);
|
Vector3 worldMouse = mainCamera.ScreenToWorldPoint(Input.mousePosition);
|
||||||
Vector2Int position = gridController.GetGridPosition(worldMouse);
|
Vector2Int position = gridController.GetGridPosition(worldMouse);
|
||||||
|
|
||||||
// Initial click, remember what they clicked
|
// Initial click, remember what they clicked
|
||||||
@@ -224,7 +226,7 @@ public class UIController : MonoBehaviour {
|
|||||||
gridController.LoadDirtyGridState(_state.Current, _state.DirtyFlags);
|
gridController.LoadDirtyGridState(_state.Current, _state.DirtyFlags);
|
||||||
|
|
||||||
string pathCount = _path != null ? $"{_path.Count}" : "N/A";
|
string pathCount = _path != null ? $"{_path.Count}" : "N/A";
|
||||||
manager.debugText.text = $"{_state.CurrentRuntime * 1000.0:F1}ms\n" +
|
debugText.text = $"{_state.CurrentRuntime * 1000.0:F1}ms\n" +
|
||||||
$"{CurrentIndex + 1:000} / {_state.Count:000}\n" +
|
$"{CurrentIndex + 1:000} / {_state.Count:000}\n" +
|
||||||
$"Path: {pathCount} tiles";
|
$"Path: {pathCount} tiles";
|
||||||
}
|
}
|
||||||
@@ -262,8 +264,8 @@ public class UIController : MonoBehaviour {
|
|||||||
public void OnDrawGizmos() {
|
public void OnDrawGizmos() {
|
||||||
if (!Application.isPlaying) return;
|
if (!Application.isPlaying) return;
|
||||||
|
|
||||||
Vector3 mouse = manager.mainCamera.ScreenToWorldPoint(Input.mousePosition);
|
Vector3 mouse = mainCamera.ScreenToWorldPoint(Input.mousePosition);
|
||||||
Vector3 localScale = manager.gridObject.transform.localScale;
|
Vector3 localScale = gridObject.transform.localScale;
|
||||||
Vector2Int gridPosition = gridController.GetGridPosition(mouse);
|
Vector2Int gridPosition = gridController.GetGridPosition(mouse);
|
||||||
|
|
||||||
var style = new GUIStyle();
|
var style = new GUIStyle();
|
||||||
@@ -287,4 +289,20 @@ public class UIController : MonoBehaviour {
|
|||||||
if (_state != null)
|
if (_state != null)
|
||||||
_runtime = @new * _state.Count;
|
_runtime = @new * _state.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Scales the GridController GameObject to fit within the Camera
|
||||||
|
/// </summary>
|
||||||
|
public void Resize() {
|
||||||
|
float ratioImage = (float) gridController.width / gridController.height;
|
||||||
|
float ratioScreen = mainCamera.aspect;
|
||||||
|
|
||||||
|
var orthographicSize = mainCamera.orthographicSize;
|
||||||
|
var image = new Vector2(gridController.width, gridController.height);
|
||||||
|
var screen = new Vector2(2 * orthographicSize * mainCamera.aspect, orthographicSize * 2);
|
||||||
|
|
||||||
|
gridObject.transform.localScale = ratioScreen > ratioImage
|
||||||
|
? new Vector3(image.x * screen.y / image.y, screen.y, 0.001f)
|
||||||
|
: new Vector3(screen.x, image.y * screen.x / image.x, 0.001f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user