List <Vector2Int> GetCellsWithinRange() { cellPositionsInRange.Clear(); Vector2Int playerPosition = gameObject.GetComponent <GridPosition2d>().GridPosition; Vector2Int offset = new Vector2Int(); int Range = movementPointsPerTurn; for (int x = Range; x >= -Range; x--) { for (int y = Range; y >= -Range; y--) { if ((Mathf.Abs(x) + Mathf.Abs(y) > Range) == false)// Check if movement is out of player's range without diagonal movement. { offset.x = x; offset.y = y; if (GridUtilities.IsGridCellOccupied(ParentGrid, playerPosition + offset) == false) { cellPositionsInRange.Add(playerPosition + offset); } } } } return(cellPositionsInRange); }
// Not intended for use on each frame because of 'new' allocations. bool MoveToGridPosition(Vector2Int gridPosition) { Debug.Assert(ParentGrid); // As this is a 2D project, the cell Z position is irrelevant. The IsGridCellOccupied check is in 2D. Vector3Int cellPosition3d = new Vector3Int(gridPosition.x, gridPosition.y, -3); Vector3 worldCellPosition = ParentGrid.CellToWorld(cellPosition3d); if (GridUtilities.IsGridCellOccupied(ParentGrid, gridPosition)) { Debug.LogError("Attempted to move \"" + gameObject.name + "\" to occupied grid position: " + gridPosition.ToString()); return(false); } else { gameObject.transform.position = worldCellPosition - Vector3.forward; return(true); } }
// Returns empty queue if there is no valid path. e.g. out of range or blocked. // Uses breadth-first search as we have a small amount of cells and need to guarantee an optimal path. // TODO: Consider caching a path to each cell that is queried, and returning it if it is present and valid. // TODO: Consider moving the allocations out to the class level. This would make the class messier but decrease garbage accumulation. public Queue <Vector2Int> GetPathToCell(Vector2Int targetCellPosition) { Queue <Vector2Int> pathQueue = new Queue <Vector2Int>(); Vector2Int playerPosition = GetComponent <GridPosition2d>().GridPosition; // Position is out of range or blocked, early return. if (cellPositionsInRange.Contains(targetCellPosition) == false) { return(pathQueue); } Queue <SearchCell> unsearchedCellQueue = new Queue <SearchCell>(); List <Vector2Int> searchedCells = new List <Vector2Int>(); Vector2Int searchDirection = new Vector2Int(); bool hasFoundPath = false; SearchCell foundTargetCell = null; // Start search at our current position. unsearchedCellQueue.Enqueue(new SearchCell(playerPosition, null)); while (unsearchedCellQueue.Count > 0 && hasFoundPath == false) { SearchCell searchingCell = unsearchedCellQueue.Dequeue(); // Search in x direction for (int x = -1; x <= 1; x++) { // Search in y direction for (int y = -1; y <= 1; y++) { // This check disables searching diagonally. if ((Mathf.Abs(x) + Mathf.Abs(y) > 1) == false) { searchDirection.x = x; searchDirection.y = y; SearchCell nextCell = new SearchCell(playerPosition + searchDirection, searchingCell) { Position = searchingCell.Position + searchDirection, SearchedFrom = searchingCell }; // Don't re-search searched cells. if (searchedCells.Contains(searchingCell.Position + searchDirection) == false) { searchedCells.Add(nextCell.Position); if (GridUtilities.IsGridCellOccupied(ParentGrid, nextCell.Position) == false) { unsearchedCellQueue.Enqueue(nextCell); if (nextCell.Position == targetCellPosition) { foundTargetCell = nextCell; hasFoundPath = true; } } } } } } } if (hasFoundPath) { while (foundTargetCell.Position != playerPosition) { pathQueue.Enqueue(foundTargetCell.Position); foundTargetCell = foundTargetCell.SearchedFrom; } } // Final range check. if (pathQueue.Count > movementPointsPerTurn) { pathQueue.Clear(); } return(pathQueue); }