예제 #1
0
    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);
        }
    }
예제 #3
0
    // 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);
    }