//function called to find path, give start and end position of path to be found
    void FindPath(TileVec2 StartPos, TileVec2 EndPos)
    {
        List <TileVec2>    openSet   = new List <TileVec2>();    //all possible positions worth searching.
        HashSet <TileVec2> closedSet = new HashSet <TileVec2>(); //closed set of evaluated and discarded positions

        openSet.Add(startPos);                                   //add start pos as first tile in open set

        //whilst we still have values in openset
        while (openSet.Count > 0)
        {
            TileVec2 currentTile = openSet[0];
            for (int i = 0; i < openSet.Count; i++)
            {
                if (openSet[i].fCost < currentTile.fCost || openSet[i].fCost == currentTile.fCost && openSet[i].hCost < currentTile.hCost)
                {
                    currentTile = openSet[i]; //current tile is equal to next best candidate in list
                }
            }

            openSet.Remove(currentTile); //remove tile we currently evaluating
            closedSet.Add(currentTile);  //move it to closed set

            //if we at end position
            if (currentTile.xPos == EndPos.xPos)
            {
                if (currentTile.yPos == EndPos.yPos)
                {
                    //go draw path to show user
                    RetracePath(startPos, currentTile);
                    return;
                }
            }

            //go look at our neighbours and calculate their costs and add to open list.
            foreach (TileVec2 neighbour in MazeGrid.GetNeighbours(currentTile))
            {
                //unless they out bounds or already in closed list
                if (!neighbour.isFloor || closedSet.Contains(neighbour))
                {
                    continue;
                }

                int newMovCostToNeighbour = currentTile.gCost + GetDistance(currentTile, neighbour);

                if (newMovCostToNeighbour < neighbour.gCost || !openSet.Contains(neighbour))
                {
                    neighbour.gCost = newMovCostToNeighbour;
                    neighbour.hCost = GetDistance(neighbour, EndPos);

                    neighbour.parent = currentTile;

                    if (!openSet.Contains(neighbour))
                    {
                        openSet.Add(neighbour);
                    }
                }
            }
        }
    }
    //retrace path
    //keep looking at next tiles parent until we back at start tile
    //along the way instaniate a tile to show user calculated path
    void RetracePath(TileVec2 startNode, TileVec2 currentTile)
    {
        resetPathHolder();
        while (currentTile != startNode)
        {
            GameObject tile = Instantiate(pathTile, new Vector3(currentTile.xPos, 0.05f, currentTile.yPos), flatTile) as GameObject;
            tile.transform.parent = pathHolder.transform;

            currentTile = currentTile.parent;
        }
    }
    //function used to calculate distance between tiles

    //we use a value of 10 from tile to tile vertically and horizontally, then a value of 14 fo diagonal movements due to pythagoras 1^2 + 1^2 = sqrt(2) or 1.4ish
    //but use ints and scale to 10 and 14, as ints cheaper then floats

    int GetDistance(TileVec2 tileA, TileVec2 tileB)
    {
        int xDist = Mathf.Abs(tileA.xPos - tileB.xPos);
        int yDist = Mathf.Abs(tileA.yPos - tileB.yPos);

        if (xDist > yDist)
        {
            return(14 * yDist + 10 * (xDist - yDist));
        }
        return(14 * xDist + 10 * (yDist - xDist));
    }
Exemple #4
0
    //void OnDrawGizmos()
    //{
    //    Gizmos.DrawWireCube(transform.position, new Vector3(columns, 1, rows));
    //
    //    if (MazeGrid != null)
    //    {
    //        foreach (TileVec2 n in MazeGrid)
    //        {
    //            Gizmos.color = (n.isFloor) ? Color.white : Color.red;
    //            Vector3 worldPos = new Vector3(n.xPos, 0, n.yPos);
    //            Gizmos.DrawCube(worldPos, Vector3.one * 0.5f);
    //        }
    //    }
    //
    //}

    //this will be used for pathfinding
    void CreateGrid()
    {
        MazeGrid = new TileVec2[columns, rows];
        for (int x = 0; x < columns; x++)
        {
            for (int y = 0; y < rows; y++)
            {
                //check each pos in maze
                bool floor = FloorTiles[x, y];
                //set grid to position and see if floor tile there
                MazeGrid[x, y] = new TileVec2(floor, x, y);
            }
        }
    }
    void setStartEndTiles(bool start)
    {
        //do a raycast to see where user clicked on screen and if it hit a tile store position and place start/end tile at that positiom
        Ray        ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;

        if (Physics.Raycast(ray, out hit))
        {
            //if left click to place start tile
            if (start)
            {
                GameObject tile = Instantiate(startTile, hit.transform.position + aboveMaze, flatTile) as GameObject;
                tile.transform.parent = pathHolder.transform;
                tile.name             = "startTile";

                //set our starttile boolean to true so we know we have a start tile in the world
                blnStartTile = true;
                startPos     = new TileVec2(true, (int)hit.transform.position.x, (int)hit.transform.position.z);
            }
            //if right click to place end tile
            else
            {
                //if start tile exists, go to place the end tile
                if (blnStartTile)
                {
                    GameObject tile = Instantiate(endTile, hit.transform.position + aboveMaze, flatTile) as GameObject;
                    tile.name             = "endTile";
                    tile.transform.parent = pathHolder.transform;
                    //set our endtile boolean to true so we know we have a end tile in the world
                    //blnEndTile = true;


                    TileVec2 endPos = new TileVec2(true, (int)hit.transform.position.x, (int)hit.transform.position.z);



                    //now we have a start/end tile, go find path between them
                    FindPath(startPos, endPos);
                }
            }
        }
    }
Exemple #6
0
    //check all tiles around given tile
    public List <TileVec2> GetNeighbours(TileVec2 Tile)
    {
        List <TileVec2> neighbours = new List <TileVec2>();

        for (int x = -1; x <= 1; x++)
        {
            for (int y = -1; y <= 1; y++)
            {
                if (x == 0 && y == 0)
                {
                    continue;                   //dont check self
                }
                int xCheck = Tile.xPos + x;
                int yCheck = Tile.yPos + y;
                //check we not out of bounds of grid
                if (xCheck >= 0 && xCheck < columns && yCheck >= 0 && yCheck < rows)
                {
                    neighbours.Add(MazeGrid[xCheck, yCheck]);
                }
            }
        }
        return(neighbours);
    }