Ejemplo n.º 1
0
    private bool CanAppendTile(VoxelTile existingTile, VoxelTile tileToAppend, Direction direction)
    {
        if (existingTile == null)
        {
            return(true);
        }

        if (direction == Direction.Right)
        {
            return(Enumerable.SequenceEqual(existingTile.ColorsRight, tileToAppend.ColorsLeft));
        }
        else if (direction == Direction.Left)
        {
            return(Enumerable.SequenceEqual(existingTile.ColorsLeft, tileToAppend.ColorsRight));
        }
        else if (direction == Direction.Forward)
        {
            return(Enumerable.SequenceEqual(existingTile.ColorsForward, tileToAppend.ColorsBack));
        }
        else if (direction == Direction.Back)
        {
            return(Enumerable.SequenceEqual(existingTile.ColorsBack, tileToAppend.ColorsForward));
        }
        else
        {
            throw new ArgumentException("Wrong direction value, should be Vector3.left/right/back/forward",
                                        nameof(direction));
        }
    }
Ejemplo n.º 2
0
    private void Generate()
    {
        possibleTiles = new List <VoxelTile> [MapSize.x, MapSize.y];

        int maxAttempts = 10;
        int attempts    = 0;

        while (attempts++ < maxAttempts)
        {
            for (int x = 0; x < MapSize.x; x++)
            {
                for (int y = 0; y < MapSize.y; y++)
                {
                    possibleTiles[x, y] = new List <VoxelTile>(TilePrefabs);
                }
            }

            VoxelTile tileInCenter = GetRandomTile(TilePrefabs);
            possibleTiles[MapSize.x / 2, MapSize.y / 2] = new List <VoxelTile> {
                tileInCenter
            };

            recalcPossibleTilesQueue.Clear();
            EnqueueNeighboursToRecalc(new Vector2Int(MapSize.x / 2, MapSize.y / 2));

            bool success = GenerateAllPossibleTiles();

            if (success)
            {
                break;
            }
        }

        PlaceAllTiles();
    }
Ejemplo n.º 3
0
    //Функция установки тайлов
    private void PlaseTail(int x, int y)
    {
        List <VoxelTile> availableTiles = new List <VoxelTile> (); //список тайлов которые мы можем поставить

        foreach (VoxelTile tilePrefab in TilePrefabs)
        {
            if (CanAppendTile(existingTile: spawnedTiles[x - 1, y], tileToAppend : tilePrefab, Vector3.left) &&
                CanAppendTile(existingTile: spawnedTiles[x + 1, y], tileToAppend : tilePrefab, Vector3.right) &&
                CanAppendTile(existingTile: spawnedTiles[x, y - 1], tileToAppend : tilePrefab, Vector3.back) &&
                CanAppendTile(existingTile: spawnedTiles[x, y + 1], tileToAppend : tilePrefab, Vector3.forward))
            {
                availableTiles.Add(tilePrefab);
            }
        }
        if (availableTiles.Count == 0)
        {
            return;
        }

        VoxelTile selectedTiles = GetRandomTile(availableTiles);  //выбираем рандомный тайл из списка доступных
        Vector3   position      = new Vector3(x, y: 0, z: y) * selectedTiles.VoxelSize * selectedTiles.TileSizexz;

        spawnedTiles[x, y] = Instantiate(selectedTiles, position, selectedTiles.transform.rotation);  //устанавливаем выбраный тайл в нужнную клетку
        localseed         += (localseed + localseed) * 7 / 3;
    }
Ejemplo n.º 4
0
    //  Places a tile at a given location
    private void PlaceTile(int x, int y)
    {
        //  We add a list of tiles that are available (which we can put in this place)
        List <VoxelTile> availableTiles = new List <VoxelTile>();

        foreach (VoxelTile tilePrefab in TilePrefabs)
        {
            if (CanAppendTile(existingTile: spawnedTiles[x - 1, y], tileToAppend: tilePrefab, Vector3.left) &&
                CanAppendTile(existingTile: spawnedTiles[x - 1, y], tileToAppend: tilePrefab, Vector3.right) &&
                CanAppendTile(existingTile: spawnedTiles[x - 1, y], tileToAppend: tilePrefab, Vector3.back) &&
                CanAppendTile(existingTile: spawnedTiles[x - 1, y], tileToAppend: tilePrefab, Vector3.forward))
            {
                availableTiles.Add(tilePrefab);
            }
        }

        if (availableTiles.Count == 0)
        {
            return;
        }

        //  Choose a random tile from those that suit us
        //  Variable for saving a randomly selected tile from the available ones
        VoxelTile selectedTile = availableTiles[Random.Range(0, availableTiles.Count)];

        spawnedTiles[x, y] = Instantiate(selectedTile, position: new Vector3(x, y: 0, z: y) * 4.0f, Quaternion.identity);
    }
Ejemplo n.º 5
0
    //  Places a tile at a given location
    private void PlaceTile(int x, int y)
    {
        //  We add a list of tiles that are available (which we can put in this place)
        List <VoxelTile> availableTiles = new List <VoxelTile>();

        foreach (VoxelTile tilePrefab in TilePrefabs)
        {
            if (CanAppendTile(existingTile: spawnedTiles[x - 1, y], tileToAppend: tilePrefab, Direction.Left) &&
                CanAppendTile(existingTile: spawnedTiles[x - 1, y], tileToAppend: tilePrefab, Direction.Right) &&
                CanAppendTile(existingTile: spawnedTiles[x - 1, y], tileToAppend: tilePrefab, Direction.Back) &&
                CanAppendTile(existingTile: spawnedTiles[x - 1, y], tileToAppend: tilePrefab, Direction.Forward))
            {
                availableTiles.Add(tilePrefab);
            }
        }

        if (availableTiles.Count == 0)
        {
            return;
        }

        //  Choose a random tile from those that suit us
        //  Variable for saving a randomly selected tile from the available ones
        VoxelTile selectedTile = GetRandomTile(availableTiles);
        Vector3   position     = selectedTile.VoxelSize * selectedTile.TileSideVoxels * new Vector3(x, y: 0, z: y);

        spawnedTiles[x, y] = Instantiate(selectedTile, position, selectedTile.transform.rotation);
    }
Ejemplo n.º 6
0
    private void PlaceTile(int x, int y)
    {
        if (possibleTiles[x, y].Count == 0)
        {
            return;
        }

        VoxelTile selectedTile = GetRandomTile(possibleTiles[x, y]);
        Vector3   position     = selectedTile.VoxelSize * selectedTile.TileSideVoxels * new Vector3(x, 0, y);

        spawnedTiles[x, y] = Instantiate(selectedTile, position, selectedTile.transform.rotation);
    }
Ejemplo n.º 7
0
    private void PlaceTail(int x, int y)
    {
        if (possibleTiles[x, y].Count == 0)
        {
            return;
        }

        VoxelTile selectedTiles = GetRandomTile(possibleTiles[x, y]);                                              //выбираем рандомный тайл из списка доступных
        Vector3   position      = new Vector3(x, y: 0, z: y) * selectedTiles.VoxelSize * selectedTiles.TileSizexz; //задаём координаты

        spawnedTiles[x, y] = Instantiate(selectedTiles, position, selectedTiles.transform.rotation);               //устанавливаем выбраный тайл в нужнную клетку
    }
    private void PlaceTile(int x, int y)
    {
        List<VoxelTile> availableTiles = new List<VoxelTile>();

        foreach (VoxelTile tilePrefab in TilePrefabs)
        {
            if (CanAppendTile(spawnedTiles[x - 1, y], tilePrefab, Direction.Left) &&
                CanAppendTile(spawnedTiles[x + 1, y], tilePrefab, Direction.Right) &&
                CanAppendTile(spawnedTiles[x, y - 1], tilePrefab, Direction.Back) &&
                CanAppendTile(spawnedTiles[x, y + 1], tilePrefab, Direction.Forward))
            {
                availableTiles.Add(tilePrefab);
            }
        }

        if (availableTiles.Count == 0) return;

        VoxelTile selectedTile = GetRandomTile(availableTiles);
        Vector3 position = selectedTile.VoxelSize * selectedTile.TileSideVoxels * new Vector3(x, 0, y);
        spawnedTiles[x, y] = Instantiate(selectedTile, position, selectedTile.transform.rotation);
    }
Ejemplo n.º 9
0
    private bool IsTilePossible(VoxelTile tile, Vector2Int position)
    {
        bool isAllRightImpossible = possibleTiles[position.x - 1, position.y]
                                    .All(rightTile => !CanAppendTile(tile, rightTile, Direction.Right));

        if (isAllRightImpossible)
        {
            return(false);
        }

        bool isAllLeftImpossible = possibleTiles[position.x + 1, position.y]
                                   .All(leftTile => !CanAppendTile(tile, leftTile, Direction.Left));

        if (isAllLeftImpossible)
        {
            return(false);
        }

        bool isAllForwardImpossible = possibleTiles[position.x, position.y - 1]
                                      .All(fwdTile => !CanAppendTile(tile, fwdTile, Direction.Forward));

        if (isAllForwardImpossible)
        {
            return(false);
        }

        bool isAllBackImpossible = possibleTiles[position.x, position.y + 1]
                                   .All(backTile => !CanAppendTile(tile, backTile, Direction.Back));

        if (isAllBackImpossible)
        {
            return(false);
        }

        return(true);
    }
Ejemplo n.º 10
0
    private bool IsTilePossible(VoxelTile tile, Vector2Int position)
    {
        bool isAllRightTileImpossible = possibleTiles[position.x - 1, position.y]
                                        .All(rightTile => !CanAppendTile(existingTile: tile, tileToAppend: rightTile, Vector3.right));

        if (isAllRightTileImpossible)
        {
            return(false);
        }

        bool isAllLeftTileImpossible = possibleTiles[position.x + 1, position.y]
                                       .All(leftTile => !CanAppendTile(existingTile: tile, tileToAppend: leftTile, Vector3.left));

        if (isAllLeftTileImpossible)
        {
            return(false);
        }

        bool isAllForwardTileImpossible = possibleTiles[position.x, position.y - 1]
                                          .All(forwardTile => !CanAppendTile(existingTile: tile, tileToAppend: forwardTile, Vector3.forward));

        if (isAllForwardTileImpossible)
        {
            return(false);
        }

        bool isAllBackTileImpossible = possibleTiles[position.x, position.y + 1]
                                       .All(backTile => !CanAppendTile(existingTile: tile, tileToAppend: backTile, Vector3.back));

        if (isAllBackTileImpossible)
        {
            return(false);
        }

        return(true);
    }
Ejemplo n.º 11
0
    public void Generate()
    {
        possibleTiles = new List <VoxelTile> [MapSize.x, MapSize.y];

        int maxAttempts = 10;
        int attempts    = 0;

        while (attempts++ < maxAttempts)
        {
            for (int x = 0; x < MapSize.x; x++)
            {
                for (int y = 0; y < MapSize.y; y++)
                {
                    possibleTiles[x, y] = new List <VoxelTile>(TilePrefabs);
                }
            }
            GenerateFirstTiles();

            VoxelTile tileInCenter = GetRandomTile(TilePrefabs);// берём рандомный тайл
            possibleTiles[MapSize.x / 2, MapSize.y / 2] = new List <VoxelTile> {
                tileInCenter
            };                                                                                 //ставим его в центр

            recalcPossibleTilesQueue.Clear();
            EnqueueNeigboursToRecalc(new Vector2Int(MapSize.x / 2, MapSize.y / 2));

            bool success = GenerateAllPossibleTiles();

            if (success)
            {
                break;
            }
        }

        PlaseAllTiles();
    }
Ejemplo n.º 12
0
    private bool GenerateAllPossibleTiles()
    {
        int maxIterations = MapSize.x * MapSize.y;
        int iterations    = 0;
        int backtracks    = 0;

        while (iterations++ < maxIterations)
        {
            int maxInnerIterations = 500;
            int innerIterations    = 0;

            while (recalcPossibleTilesQueue.Count > 0 && innerIterations++ < maxInnerIterations)
            {
                Vector2Int position = recalcPossibleTilesQueue.Dequeue();
                if (position.x == 0 || position.y == 0 ||
                    position.x == MapSize.x - 1 || position.y == MapSize.y - 1)
                {
                    continue;
                }

                List <VoxelTile> possibleTilesHere = possibleTiles[position.x, position.y];

                int countRemoved = possibleTilesHere.RemoveAll(t => !IsTilePossible(t, position));

                if (countRemoved > 0)
                {
                    EnqueueNeighboursToRecalc(position);
                }

                if (possibleTilesHere.Count == 0)
                {
                    possibleTilesHere.AddRange(TilePrefabs);
                    possibleTiles[position.x + 1, position.y] = new List <VoxelTile>(TilePrefabs);
                    possibleTiles[position.x - 1, position.y] = new List <VoxelTile>(TilePrefabs);
                    possibleTiles[position.x, position.y + 1] = new List <VoxelTile>(TilePrefabs);
                    possibleTiles[position.x, position.y - 1] = new List <VoxelTile>(TilePrefabs);

                    EnqueueNeighboursToRecalc(position);

                    backtracks++;
                }
            }
            if (innerIterations == maxInnerIterations)
            {
                break;
            }

            List <VoxelTile> maxCountTile         = possibleTiles[1, 1];
            Vector2Int       maxCountTilePosition = new Vector2Int(1, 1);

            for (int x = 1; x < MapSize.x - 1; x++)
            {
                for (int y = 1; y < MapSize.y - 1; y++)
                {
                    if (possibleTiles[x, y].Count > maxCountTile.Count)
                    {
                        maxCountTile         = possibleTiles[x, y];
                        maxCountTilePosition = new Vector2Int(x, y);
                    }
                }
            }

            if (maxCountTile.Count == 1)
            {
                Debug.Log($"Generated for {iterations} iterations, with {backtracks} backtracks");
                return(true);
            }

            VoxelTile tileToCollapse = GetRandomTile(maxCountTile);
            possibleTiles[maxCountTilePosition.x, maxCountTilePosition.y] = new List <VoxelTile> {
                tileToCollapse
            };
            EnqueueNeighboursToRecalc(maxCountTilePosition);
        }

        Debug.Log($"Failed, run out of iterations with {backtracks} backtracks");
        return(false);
    }
Ejemplo n.º 13
0
    private bool GenerateAllPossibleTiles()
    {
        int backtracks = 0;

        int maxIterations = MapSize.x * MapSize.y;
        int iterations    = 0;

        while (iterations++ < maxIterations)
        {
            int maxInnerIterations = 500;
            int innerIterations    = 0;
            while (recalcPossibleTilesQueue.Count > 0 && innerIterations++ < maxInnerIterations)
            {
                Vector2Int position = recalcPossibleTilesQueue.Dequeue();
                if (position.x == 0 ||
                    position.y == 0 ||
                    position.x == MapSize.x - 1 ||
                    position.y == MapSize.y - 1)
                {
                    continue;
                }

                List <VoxelTile> possibleTilesHere = possibleTiles[position.x, position.y];

                int countRemoved = possibleTilesHere.RemoveAll(match: t => !IsTilePossible(t, position));

                if (countRemoved > 0)
                {
                    EnqueueNeigboursToRecalc(position);
                }

                if (possibleTilesHere.Count == 0)
                {
                    // Зашли в тупик, в этих координатах невозможен ни один тайл. Попробуем ещё раз разрешим все тайлы
                    // в этих и соседних координатах и посмотрим устаканится ли всё
                    possibleTilesHere.AddRange(TilePrefabs);
                    possibleTiles[position.x + 1, position.y] = new List <VoxelTile>(TilePrefabs);
                    possibleTiles[position.x - 1, position.y] = new List <VoxelTile>(TilePrefabs);
                    possibleTiles[position.x, position.y + 1] = new List <VoxelTile>(TilePrefabs);
                    possibleTiles[position.x, position.y - 1] = new List <VoxelTile>(TilePrefabs);

                    EnqueueNeigboursToRecalc(position);

                    backtracks++;
                }
            }
            if (innerIterations == maxInnerIterations)
            {
                break;
            }

            List <VoxelTile> maxCountTile         = possibleTiles[1, 1];
            Vector2Int       maxCountTilePosition = new Vector2Int(x: 1, y: 1);

            for (int x = 1; x < MapSize.x - 1; x++)
            {
                for (int y = 1; y < MapSize.y - 1; y++)
                {
                    if (possibleTiles[x, y].Count > maxCountTile.Count)
                    {
                        maxCountTile         = possibleTiles[x, y];
                        maxCountTilePosition = new Vector2Int(x, y);
                    }
                }
            }

            if (maxCountTile.Count == 1)
            {
                Debug.Log(message: $"Generated for {iterations} iterations, with {backtracks} backtracks");
                return(true);
            }

            VoxelTile tileToCollapse = GetRandomTile(maxCountTile);
            possibleTiles[maxCountTilePosition.x, maxCountTilePosition.y] = new List <VoxelTile> {
                tileToCollapse
            };
            EnqueueNeigboursToRecalc(maxCountTilePosition);
        }

        Debug.Log(message: $"Failed, run out of iterations with {backtracks} backtracks");
        return(false);
    }