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;
         }
     }
 }
Example #2
0
    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);
    }
Example #3
0
    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);
    }
Example #4
0
    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));
    }
Example #5
0
    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);
    }
Example #6
0
    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);
    }
Example #8
0
        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);
        }
Example #9
0
    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;
        }
    }
Example #10
0
    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);
        }
    }