Пример #1
0
    private static List <PathNode> GetNeighbourList(PathNode currentNode)
    {
        List <PathNode> neighbourList        = new List <PathNode>();
        Direction       currentNodeDirection = gridElements.GetTile(currentNode.GetCell()).ToDirection();

        if (currentNodeDirection != Direction.NULL && currentNodeDirection != Direction.All)
        {
            Vector2Int cellFaced = currentNode.GetCell() + currentNodeDirection.ToOffset();
            if (grid.CellIsValid(cellFaced))
            {
                neighbourList.Add(grid.GetTile(cellFaced));
            }
        }
        else
        {
            //Left
            if (grid.CellIsValid(currentNode.X - 1, currentNode.Y))
            {
                neighbourList.Add(grid.GetTile(currentNode.X - 1, currentNode.Y));
            }

            // Right
            if (grid.CellIsValid(currentNode.X + 1, currentNode.Y))
            {
                neighbourList.Add(grid.GetTile(currentNode.X + 1, currentNode.Y));
            }

            // Up
            if (grid.CellIsValid(currentNode.X, currentNode.Y - 1))
            {
                neighbourList.Add(grid.GetTile(currentNode.X, currentNode.Y - 1));
            }

            // Down
            if (grid.CellIsValid(currentNode.X, currentNode.Y + 1))
            {
                neighbourList.Add(grid.GetTile(currentNode.X, currentNode.Y + 1));
            }
        }

        if (!includeNullElements)
        {
            neighbourList = neighbourList.Where(p => gridElements.GetTile(p.GetCell()) != Element.NULL).ToList();
        }

        return(neighbourList);
    }
Пример #2
0
        private IEnumerator GenerateNodes(int num, Action <List <Vector2Int> > callback)
        {
            if (num <= 0)
            {
                Debug.LogWarning($"Can't generate {num} nodes");
                yield break;
            }

            int attempts    = 0;
            int maxAttempts = num * 2;

            List <Vector2Int> nodesAlreadyFound = new List <Vector2Int>();
            Vector2Int        cell = Vector2Int.zero;

            System.Random rnd = new System.Random(System.DateTime.Now.Millisecond);

            Status = LevelGenerationStatus.Nodes;
            yield return(null);

            for (int i = 0; i < num && attempts < maxAttempts; i++, attempts++)
            {
                cell = new Vector2Int(rnd.Next(0, newLevel.Width), rnd.Next(0, newLevel.Height));
                if (newLevel.GetTile(cell).IsNodeType() || nodesAlreadyFound.Contains(cell))
                {
                    i--;
                    continue;
                }
                nodesAlreadyFound.Add(cell);
                newLevel.SetTile(cell, Element.Node);
                genProgression = Mathf.Max((float)i / num, (float)attempts / maxAttempts);
                yield return(null);
            }
            Debug.Log($"Generated {nodesAlreadyFound.Count}/{num} nodes in {attempts}/{maxAttempts} attempts");

            callback?.Invoke(nodesAlreadyFound);
            yield break;
        }
Пример #3
0
        private bool IsNullTileReadyToVisible(int x, int y)
        {
            if (!grid.CellIsValid(x, y))
            {
                return(false);
            }

            if (LevelManager.Main.Grid.GetTile(x, y) != Element.NULL || grid.GetTile(x, y) != TileVisibility.Invisible)
            {
                return(grid.GetTile(x, y) != TileVisibility.ReadyToVisible);
            }

            if (showDebugLog.HasFlag(LevelFogDebug.ReadyToVisible_Logic))
            {
                Debug.Log($"Is Tile {x},{y} ReadyToVisible?");
            }

            bool isReadyToVisible = true;

            Element        type;
            TileVisibility visibility;

            List <Vector2Int> neighbours = grid.GatherNeighbourCells(x, y, 1, true, true);
            Vector2Int        neighbour;

            for (int i = 0; i < neighbours.Count && isReadyToVisible; i++)
            {
                neighbour = neighbours[i];

                if (!LevelManager.Main.Grid.CellIsValid(neighbour.x, neighbour.y))
                {
                    continue;
                }

                if (!grid.CellIsValid(neighbour.x, neighbour.y))
                {
                    continue;
                }

                type             = LevelManager.Main.Grid.GetTile(neighbour.x, neighbour.y);
                visibility       = grid.GetTile(neighbour.x, neighbour.y);
                isReadyToVisible = visibility == TileVisibility.Visible || type == Element.NULL;
                if (showDebugLog.HasFlag(LevelFogDebug.ReadyToVisible_Logic))
                {
                    Debug.Log($"Checked neighbour {x},{y} ({visibility}) => {isReadyToVisible}");
                }
            }

            if (isReadyToVisible)
            {
                grid.SetTile(x, y, TileVisibility.ReadyToVisible);
            }

            return(isReadyToVisible);
        }
Пример #4
0
    public static List <PathNode> FindPath(Vector2Int startCell, Vector2Int endCell)
    {
        PathNode startNode = grid.GetTile(startCell.x, startCell.y);
        PathNode endNode   = grid.GetTile(endCell.x, endCell.y);

        if (startNode == null)
        {
            Debug.LogError($"Can't find path because start node on cell {startCell} is null");
            return(null);
        }
        if (endNode == null)
        {
            Debug.LogError($"Can't find path because end node on cell {endCell} is null");
            return(null);
        }

        openList = new List <PathNode>()
        {
            startNode
        };
        closedList = new List <PathNode>();

        for (int x = 0; x < grid.Width; x++)
        {
            for (int y = 0; y < grid.Height; y++)
            {
                PathNode pathNode = grid.GetTile(x, y);
                pathNode.gCost        = int.MaxValue;
                pathNode.previousNode = null;
            }
        }

        startNode.gCost = 0;
        startNode.hCost = CalculateDistanceCost(startNode, endNode);

        while (openList.Count > 0)
        {
            PathNode currentNode;

            if (searchBestPath)
            {
                currentNode = GetLowestFCostNode(openList);
            }
            else
            {
                currentNode = openList[new System.Random().Next(0, openList.Count - 1)];
            }

            if (currentNode == endNode)
            {
                // Reached final node
                return(CalculatePath(endNode));
            }

            openList.Remove(currentNode);
            closedList.Add(currentNode);

            foreach (PathNode neighbourNode in GetNeighbourList(currentNode))
            {
                if (closedList.Contains(neighbourNode))
                {
                    continue;
                }

                int tentativeGCost = currentNode.gCost + CalculateDistanceCost(currentNode, neighbourNode);
                if (tentativeGCost < neighbourNode.gCost)
                {
                    neighbourNode.previousNode = currentNode;
                    neighbourNode.gCost        = tentativeGCost;
                    neighbourNode.hCost        = CalculateDistanceCost(neighbourNode, endNode);

                    if (!openList.Contains(neighbourNode))
                    {
                        openList.Add(neighbourNode);
                    }
                }
            }
        }

        // No Path
        return(null);
    }
Пример #5
0
        /// <summary>
        /// Load a new level
        /// </summary>
        /// <param name="newLevel">New level.</param>
        public void LoadLevel(GridXY <Element> newLevel)
        {
            if (newLevel == null || newLevel.Size == 0)
            {
                Debug.LogWarning("The new level grid is not valid");
                return;
            }

            Debug.Log($"0. Loading level {newLevel.Width}x{newLevel.Height}...");
            ClearLevel();

            Debug.Log($"1. Initializing level...");
            Grid.CreateGridXY(newLevel.Width, newLevel.Height, 1, Vector3.zero, true, Element.NULL, Element.NULL);

            Debug.Log("Level is not playable!");
            LvlState = LevelState.NotPlayable;
            OnLevelNotPlayable?.Invoke(this, null);

            Debug.Log("2. Generating level...");
            StartCell = Vector2Int.one * -1;
            EndCell   = Vector2Int.one * -1;

            bool hasStart = false;
            bool hasEnd   = Grid.Size == 1;

            Element type;

            for (int x = 0; x < Grid.Width; x++)
            {
                for (int y = 0; y < Grid.Height; y++)
                {
                    type = newLevel.GetTile(x, y);
                    if (showDebugLog)
                    {
                        Debug.Log($"Setted Tile {x},{y} ({type})");
                    }
                    Grid.SetTile(x, y, type);
                    if (type == Element.Start)
                    {
                        StartCell = new Vector2Int(x, y);
                        hasStart  = true;
                    }
                    else
                    {
                        if (type == Element.End)
                        {
                            EndCell = new Vector2Int(x, y);
                            hasEnd  = true;
                        }
                    }
                }
            }

            Debug.Log("Level is ready!");
            LvlState = LevelState.Ready;
            OnLevelReady?.Invoke(this, new OnLevelReadyEventArgs {
                width = Grid.Width, height = Grid.Height
            });

            if (!hasStart || !hasEnd)
            {
                Debug.LogWarning($"Level has {(!hasStart ? "NO": "")} Start and {(!hasEnd ? "NO" : "")} End");
                return;
            }

            LevelNavigation.SetUp(Grid.Width, Grid.Height, false, true, Grid);

            Debug.Log("Level is playable!");
            LvlState = LevelState.Playable;
            OnLevelPlayable?.Invoke(this, new OnLevelPlayableEventArgs {
                startX = StartCell.x, startY = StartCell.y, endX = EndCell.x, endY = EndCell.y
            });
            OnLevelStart?.Invoke();
        }