예제 #1
0
    public static Vector2[] pathfind(Vector2 startPos, Vector2 targetPos, float distance = 0f)
    {
        // Get platform
        var plat = Instance.GetPlatformInPosition(startPos);

        GroundPlatform.Tile?end   = instance.GetNearestTile(plat, targetPos);
        GroundPlatform.Tile?start = instance.GetNearestTile(plat, startPos);

        float          d    = (startPos - targetPos).sqrMagnitude;
        float          sqr  = distance * distance;
        List <Vector2> path = new List <Vector2>();

        if (end.Value.pos == start.Value.pos && end.HasValue)
        {
            if (d > sqr)
            {
                path.Add(TileToWorldPos(end.Value.pos));
            }
            else
            {
                return(null);
            }
        }

        int iteration = 0;

        GroundPlatform.Tile current = start.Value;

        while (current.pos != end.Value.pos && d > sqr)
        {
            byte dir = 0;
            if (current.directions.ContainsKey(end.Value.pos))
            {
                dir = current.directions[end.Value.pos];
                GroundPlatform.Tile?next = null;
                switch (dir)
                {
                case 0:
                    next = plat.GetTile(current.pos + Vector2Int.right);
                    break;

                case 1:
                    next = plat.GetTile(current.pos + Vector2Int.down);
                    break;

                case 2:
                    next = plat.GetTile(current.pos + Vector2Int.left);
                    break;

                case 3:
                    next = plat.GetTile(current.pos + Vector2Int.up);
                    break;

                default:
                    break;
                }

                if (next.HasValue)
                {
                    current = next.Value;
                    path.Add(TileToWorldPos(current.pos));
                }
                else
                {
                    Debug.LogError("Pathfinding failed because of corrupted direction data at " + current.pos + " with direction " + dir);
                    return(null);
                }
            }
            else
            {
                Debug.LogError("Pathfinding failed because of incomplete ground platform generation.");
                return(null);
            }

            d = (targetPos - TileToWorldPos(current.pos)).sqrMagnitude;

            iteration++;
            if (iteration > 10000)
            {
                string s = "";
                for (int i = 0; i < path.Count; i++)
                {
                    s += path[i].ToString() + '\n';
                }

                Debug.Log(s);

                Debug.LogError("Infinite loop in pathfinding!");
                return(null);
            }
        }

        // Get closer from the tile center if needed
        //d = (current.pos - targetPos).magnitude;
        //if (d > distance && path.Count > 0)
        //{
        //    path[path.Count - 1] = current.pos + (current.pos - targetPos).normalized * (d - distance);
        //}

        path.Reverse();

        string pathString = "";

        for (int i = 0; i < path.Count; i++)
        {
            pathString += path[i].ToString();
        }

        if (path.Count > 1)
        {
            d = (startPos - path[path.Count - 1]).magnitude;
            if ((start.Value.type == 0 ||
                 start.Value.type == 7 ||
                 start.Value.type == 5 ||
                 start.Value.type == 10) &&
                d > instance.tileSize)    // Don't skip turns
            {
                path.Add(TileToWorldPos(start.Value.pos));
            }
        }


        // Debug.Log("Path: " + pathString);

        return(path.ToArray());
    }
예제 #2
0
    public void LoadSector(Sector sector)
    {
        searchQueue.Clear();
        for (int i = 0; i < AIData.entities.Count; i++)
        {
            searchQueue.Enqueue(AIData.entities[i]);
        }

        Vector2 center = new Vector2(sector.bounds.x + sector.bounds.w / 2, sector.bounds.y - sector.bounds.h / 2);

        if (sector.platform) // Old data
        {
            BuildTiles(sector.platform, center);
        }
        else if (sector.platformData.Length > 0)
        {
            GameObject[] prefabs = new GameObject[prefabNames.Length];
            for (int i = 0; i < prefabNames.Length; i++)
            {
                prefabs[i] = ResourceManager.GetAsset <GameObject>(prefabNames[i]);
            }

            tileSize = prefabs[0].GetComponent <SpriteRenderer>().bounds.size.x;

            var cols = sector.bounds.w / (int)tileSize;
            var rows = sector.bounds.h / (int)tileSize;

            Offset = new Vector2
            {
                x = center.x - tileSize * (cols - 1) / 2F,
                y = center.y + tileSize * (rows - 1) / 2F
            };

            Size = new Vector2Int
            {
                x = cols,
                y = rows
            };

            directionMap = new short[cols, rows];
            for (int i = 0; i < cols; i++)
            {
                for (int j = 0; j < rows; j++)
                {
                    directionMap[i, j] = -1;
                }
            }

            // Assemble platforms from tile prefabs
            sector.platforms = new GroundPlatform[sector.platformData.Length];
            for (int i = 0; i < sector.platformData.Length; i++)
            {
                var plat = new GroundPlatform(sector.platformData[i], prefabs, this);
                sector.platforms[i] = plat;
            }

            groundPlatforms = sector.platforms;

            // Create the direction map
            for (int i = 0; i < groundPlatforms.Length; i++)
            {
                for (int j = 0; j < groundPlatforms[i].tiles.Count; j++)
                {
                    GroundPlatform.Tile t = groundPlatforms[i].tiles[j];
                    if (t.pos.x >= cols || t.pos.y >= rows || t.pos.x < 0 || t.pos.y < 0)
                    {
                        Debug.LogWarning($"Invalid tile position: { t.pos } Bounds: {cols}, {rows}");
                        continue;
                    }
                    directionMap[t.pos.x, t.pos.y] = GroundPlatform.GetPlatformOpenings(t);
                }
            }


            // Direction map debug
            string str = "";
            for (int j = 0; j < rows; j++)
            {
                for (int i = 0; i < cols; i++)
                {
                    str += directionMap[i, j].ToString().PadLeft(2, '0') + ' ';
                }
                str += '\n';
            }
        }
    }