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); }
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; }
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); }
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); }
/// <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(); }