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)); } }
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(); }
//Функция установки тайлов 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; }
// 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); }
// 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); }
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); }
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); }
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); }
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); }
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(); }
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); }
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); }