private void InitializeNodes() { for (int x = 0; x < grid.width; x++) { for (int y = 0; y < grid.height; y++) { Node node = grid.GetNode(x, y); node.Gcost = int.MaxValue; node.Hcost = 0; node.CalculateFcost(); node.previousNode = null; } } }
public Stack <Vector3Int> Algorithm(Vector3Int start, Vector3Int goal, NodeGrid grid) { _CurrentNode = grid.GetNode(start); _OpenList = new HashSet <Node>(); _ClosedList = new HashSet <Node>(); _OpenList.Add(_CurrentNode); Stack <Vector3Int> path = null; while (_OpenList.Count > 0 && path == null) { List <Node> neighbors = grid.FindNeighbors(_CurrentNode.Position); ExamineNeighbors(neighbors, _CurrentNode, goal, grid); UpdateCurrentTile(ref _CurrentNode); path = GeneratePath(_CurrentNode, start, goal); } AStarDebug.Instance?.CreateTiles(_OpenList, _ClosedList, grid, start, goal, path); return(path); }
public bool DirectionIsOpen(Coord direction, bool cutCorners = false) { if (direction.x == 0 && direction.y == 0 && direction.z == 0) { return(true); } if (direction.IsDirection) { return(directionOpen[direction.ToDirectionIndex]); } if (DirectionIsOpen(new Coord(direction.x, 0, 0)) && DirectionIsOpen(new Coord(0, direction.y, 0)) && DirectionIsOpen(new Coord(0, 0, direction.z))) { return(true); } if (cutCorners) { Coord x = new Coord(direction.x, 0, 0); Coord y = new Coord(0, direction.y, 0); Coord z = new Coord(0, 0, direction.z); return(DirectionIsOpen(x) && NodeGrid.GetNode(position + x).DirectionIsOpen(y + z) || DirectionIsOpen(y) && NodeGrid.GetNode(position + y).DirectionIsOpen(x + z) || DirectionIsOpen(z) && NodeGrid.GetNode(position + z).DirectionIsOpen(x + y)); } return(false); }
public GameObject SpawnObjectFromGrid(GameObject obj, int x, int z, Vector3 positionOffset = default(Vector3), Quaternion rotationOffset = default(Quaternion)) { if (grid.GetNode(x, z) == null) { Debug.LogError("Node coordinates are outside of bounds"); return(null); } return(Instantiate(obj, grid.values[x, z].pos + positionOffset, Quaternion.identity * rotationOffset)); }
public bool IsPossibleToMove() { bool isOutside; nextNode = nodeGrid.GetNode(snake[0].occupiedNode.x + NodeGrid.offsets[currentDirection].x, snake[0].occupiedNode.z + NodeGrid.offsets[currentDirection].z, out isOutside); if (isOutside) { Debug.Log("Is outside"); return(false); } if (IsEatingYourself()) { Debug.Log("Eat yourself"); return(false); } return(true); }
public static Coord[] FindPath(Coord startPos, IList <Coord> goalPositions) { bool singleTarget = goalPositions.Count == 1; bool success = false; HashSet <Node> goals = new HashSet <Node>(goalPositions.Select(NodeGrid.GetNode)); Node startNode = NodeGrid.GetNode(startPos); Node goalNode = NodeGrid.GetNode(goalPositions[0]); if (startNode != null && goalNode != null && goalNode.IsWalkable && goalNode != startNode) { Heap <Node> open = new Heap <Node>(NodeGrid.GridCount); HashSet <Node> closed = new HashSet <Node>(); open.Add(startNode); while (open.Count > 0) { Node current = open.RemoveFirst(); closed.Add(current); if (singleTarget && current == goalNode || !singleTarget && goals.Contains(current) /*current == goalNode*/) { goalNode = current; success = true; break; } foreach (Node neighbor in NodeGrid.GetNeighbors(current)) { if (!neighbor.IsWalkable || closed.Contains(neighbor)) { continue; } int newMovementCost = current.gCost + GetDistance(current, neighbor); if (newMovementCost < neighbor.gCost || !open.Contains(neighbor)) { neighbor.gCost = newMovementCost; neighbor.hCost = GetDistance(neighbor, goalNode); neighbor.parent = current; if (!open.Contains(neighbor)) { open.Add(neighbor); } else { open.UpdateItem(neighbor); } } } } } Coord[] waypoints = null; if (success) { waypoints = RetracePath(startNode, goalNode); } return(waypoints == null || waypoints.Length == 0 ? null : waypoints); }
public static List <Vector2> FindPath(Vector3 startPosition, Vector3 targetPosition, ref NodeGrid ground) { List <Vector2> path = new List <Vector2>(); Node current = null; Node start = ground.GetNode(new Vector2Int(Mathf.RoundToInt(startPosition.x), Mathf.RoundToInt(startPosition.y))); Node target = ground.GetNode(new Vector2Int(Mathf.RoundToInt(targetPosition.x - .1f), Mathf.RoundToInt(targetPosition.y))); // If the target is not reachable, return empty path if (!start.walkable || !target.walkable) { return(path); } List <Node> open = new List <Node>(); List <Node> closed = new List <Node>(); open.Add(start); start.costs = WhatCosts(start, start, target); // First loop while (current != target && open.Count > 0) { // Get the lowest F cost current = open[0]; foreach (Node node in open) { if (node.costs.z < current.costs.z) // F cost { current = node; } } open.Remove(current); closed.Add(current); // Foreach Neighbours for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { Node neighbour = ground.GetNode(current.position + new Vector2((float)i / ground.getAccuracy(), (float)j / ground.getAccuracy())); if (neighbour.walkable && !IsInList(neighbour, closed)) // Skip the unwalkable and closed nodes (includes the current one) { if (!IsInList(neighbour, open) || WhatCosts(current, neighbour, target).z < neighbour.costs.z) { neighbour.costs = WhatCosts(current, neighbour, target); neighbour.parent = current; if (!IsInList(neighbour, open)) { open.Add(neighbour); } } } } } } // Draw back the path while (current != null) { path.Add(current.position); current = current.parent; } path.Reverse(); return(path); }
public static List <Node> PathFind(Point start, Point end) { HashSet <Node> path = new HashSet <Node>(); //Open List HashSet <Node> closed = new HashSet <Node>(); //Closed List Point center = new Point((((start.X + end.X) / 2) / 4) * 4, (((start.Y + end.Y) / 2) / 4) * 4); NodeGrid grid = WorldData.GetNodeGrid(center); Node st = grid.GetNode(start); Node ed = grid.GetNode(end); Node current = st; if (ed == null || st == null) { return(null); } path.Add(st); bool atend = false; if (showPath) { lock (WorldData.currentRegions) WorldData.tempRender.Clear(); } do { List <Node> surrounding = grid.GetSurroundingNodes(current); if (surrounding == null) { break; } //Move from surrounding list to the open path for (int i = 0; i < surrounding.Count; i++) { if (surrounding[i].IsOpen && !closed.Contains(surrounding[i])) { if (!path.Contains(surrounding[i])) { path.Add(surrounding[i]); surrounding[i].ParentNode = current; } else { int newG = surrounding[i].CalculateDistFromStart(current); if (newG < surrounding[i].DistanceFromStart) { surrounding[i].DistanceEstimate(current, ed); surrounding[i].ParentNode = current; } } } } //Finds best F value from surrounding nodes int bestTotal = int.MaxValue; Node bestNode = null; foreach (Node nd in path) { int dist = nd.DistanceEstimate(current, ed); if (dist < bestTotal) { bestNode = nd; bestTotal = dist; } } if (bestNode == null) { break; } path.Remove(bestNode); closed.Add(bestNode); current = bestNode; //If close enough, end the search for the end point if (Math.Abs(ed.Location.X - bestNode.Location.X) < 4 && Math.Abs(ed.Location.Y - bestNode.Location.Y) < 4) { atend = true; } } while (!atend); List <Node> routedPath = new List <Node>() { current }; while (true) { if (current == st) { break; } else { current = current.ParentNode; routedPath.Add(current); } } routedPath.Reverse(); if (showPath) { lock (WorldData.currentRegions) { foreach (Node nd in path) { WorldData.tempRender.Add(new World.Objects.WorldObjectBase(nd.Location.X, nd.Location.Y, TextureManager.TextureNames.button, 1, 1)); } foreach (Node nd in routedPath) { WorldData.tempRender.Add(new World.Objects.WorldObjectBase(nd.Location.X, nd.Location.Y, TextureManager.TextureNames.textBox, 1, 1)); } } } return(routedPath); }
private void Update() { if (Input.GetMouseButton(0)) { Vector3 worldMouse = mainCamera.ScreenToWorldPoint(Input.mousePosition); Vector2Int position = gridController.GetGridPosition(worldMouse); // Initial click, remember what they clicked if (Input.GetMouseButtonDown(0)) { if (progressSlider.IsPressed) { _modify = ClickType.ProgressBar; } else if (position == _start) { _modify = ClickType.Start; } else if (position == _end) { _modify = ClickType.End; } else { Node node = _grid.GetNode(position); _modify = node.Walkable ? ClickType.Add : ClickType.Remove; node.Walkable = !node.Walkable; if (_animationState == AnimationState.Paused) { _animationState = AnimationState.Stopped; } else if (_animationState == AnimationState.Started) { _animationState = AnimationState.Reloading; } } _lastClickLocation = position; } else { // If still holding down the button & the latest movement is over a new grid if (_lastClickLocation != position) { _lastClickLocation = position; if (_grid.IsValid(position)) { Node node = _grid.GetNode(position); switch (_modify) { // regular clicking toggles walls // Note: Wall toggling instantly reloads, but only real start/end node movement reloads. case ClickType.Add: node.Walkable = false; if (EditShouldReload) { _animationState = AnimationState.Reloading; } break; case ClickType.Remove: node.Walkable = true; if (EditShouldReload) { _animationState = AnimationState.Reloading; } break; case ClickType.Start: if (node.Walkable) { _start = position; if (EditShouldReload) { _animationState = AnimationState.Reloading; } } break; case ClickType.End: if (node.Walkable) { _end = position; if (EditShouldReload) { _animationState = AnimationState.Reloading; } } break; case ClickType.ProgressBar: break; default: throw new ArgumentOutOfRangeException(); } } } } } // Handle user start/stopping if (Input.GetKeyDown(KeyCode.Space)) { switch (_animationState) { case AnimationState.Stopped: _animationState = AnimationState.Reloading; break; case AnimationState.Paused: _animationState = AnimationState.Started; break; case AnimationState.Started: // Restart if already on final frame, else simply pause if (CurrentIndex >= _state.Count) { _runtime = 0; } else { _animationState = AnimationState.Paused; } break; case AnimationState.Reloading: break; default: throw new ArgumentOutOfRangeException(); } } switch (_animationState) { case AnimationState.Reloading: // Reloading seizes while the mouse button is depressed if (!Input.GetMouseButton(0)) { GeneratePath(); LoadNextState(); _animationState = AnimationState.Started; } else { gridController.LoadGridState(_grid.RenderNodeTypes(_start, _end)); } progressSlider.SetValueWithoutNotify(_runtime / _state.Count); break; case AnimationState.Started: // Calculate how much to move forward if (!progressSlider.IsPressed) { var increment = Time.deltaTime * speed * CurrentMultiplier(); if (clampIncrement > 0) { increment = Mathf.Clamp(increment, 0, _state.Count * Time.deltaTime / clampIncrement); } _runtime += increment; } progressSlider.SetValueWithoutNotify(_runtime / _state.Count); if (_runtime < _state.Count) { LoadNextState(); } break; case AnimationState.Stopped: // Render editable grid when fully stopped gridController.LoadGridState(_grid.RenderNodeTypes(_start, _end)); break; case AnimationState.Paused: if (_runtime < _state.Count) { LoadNextState(); } break; default: throw new ArgumentOutOfRangeException(); } if (_animationState != _previousAnimationState) { Debug.Log($"Animation State {_previousAnimationState} -> {_animationState}"); _previousAnimationState = _animationState; } }
public override void OnInspectorGUI() { NodeGrid grid = (NodeGrid)target; if (!init) { width = grid.Width; height = grid.Height; } grid.NodePrefab = EditorGUILayout.ObjectField("Node Prefab", grid.NodePrefab, typeof(GameObject), false) as GameObject; grid.PathBaseMaterial = EditorGUILayout.ObjectField("Base Material", grid.PathBaseMaterial, typeof(Material), false) as Material; grid.PathNotTraversableMaterial = EditorGUILayout.ObjectField("Not Traversable Material", grid.PathNotTraversableMaterial, typeof(Material), false) as Material; grid.PathCheckedMaterial = EditorGUILayout.ObjectField("Checked Material", grid.PathCheckedMaterial, typeof(Material), false) as Material; grid.PathGoalMaterial = EditorGUILayout.ObjectField("Goal Material", grid.PathGoalMaterial, typeof(Material), false) as Material; grid.PathFinalMaterial = EditorGUILayout.ObjectField("Final Path Material", grid.PathFinalMaterial, typeof(Material), false) as Material; grid.PathStartMaterial = EditorGUILayout.ObjectField("Start Material", grid.PathStartMaterial, typeof(Material), false) as Material; width = Mathf.Max(EditorGUILayout.DelayedIntField("X Dimension:", width), 1); height = Mathf.Max(EditorGUILayout.DelayedIntField("Y Dimension:", height), 1); if (width != grid.Width || height != grid.Height) { grid.AlterSize(width, height); EditorUtility.SetDirty(target); } EditorGUILayout.BeginHorizontal(); { grid.StartX = EditorGUILayout.IntField("Start Node:", grid.StartX); grid.StartY = EditorGUILayout.IntField(grid.StartY); } EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); { grid.EndX = EditorGUILayout.IntField("End Node:", grid.EndX); grid.EndY = EditorGUILayout.IntField(grid.EndY); } EditorGUILayout.EndHorizontal(); // Draw all the traversability check boxes traversabilityPosition = EditorGUILayout.BeginScrollView(traversabilityPosition); { EditorGUILayout.LabelField("Traversability"); EditorGUILayout.BeginVertical(); { for (int i = 0; i < grid.Height; i++) { EditorGUILayout.BeginHorizontal(); { for (int j = 0; j < grid.Width; j++) { grid.GetNode(j, i).Traversable = EditorGUILayout.Toggle(grid.GetNode(j, i).Traversable); } } EditorGUILayout.EndHorizontal(); } } EditorGUILayout.EndVertical(); } EditorGUILayout.EndScrollView(); // Draw all the text boxes for travel cost travelCostPosition = EditorGUILayout.BeginScrollView(travelCostPosition); { EditorGUILayout.LabelField("Travel Cost"); EditorGUILayout.BeginVertical(); { for (int i = 0; i < grid.Height; i++) { EditorGUILayout.BeginHorizontal(); { for (int j = 0; j < grid.Width; j++) { if (grid.GetNode(j, i).Traversable) { grid.GetNode(j, i).TravelCost = EditorGUILayout.IntField(grid.GetNode(j, i).TravelCost); } else { GUI.enabled = false; grid.GetNode(j, i).TravelCost = EditorGUILayout.IntField(grid.GetNode(j, i).TravelCost); GUI.enabled = true; } } } EditorGUILayout.EndHorizontal(); } } EditorGUILayout.EndVertical(); } EditorGUILayout.EndScrollView(); if (GUI.changed) { EditorUtility.SetDirty(target); } }