public static Vector2Int?FindClosestTileByType(TilemapStructure tilemap, Vector2Int startPos, int tileType) { float smallestDistance = float.MaxValue; Vector2Int?smallestDistancePosition = null; for (int x = 0; x < tilemap.Width; x++) { for (int y = 0; y < tilemap.Height; y++) { if (tilemap.GetTile(x, y) == tileType) { // Here we check the distance between the start position and the current tile float distance = ((startPos.x - x) * (startPos.x - x) + (startPos.y - y) * (startPos.y - y)); // If this distance is smaller, than the smallest one we have so far encountered // Then let's update it if (distance < smallestDistance) { smallestDistance = distance; smallestDistancePosition = new Vector2Int(x, y); } } } } return(smallestDistancePosition); }
public bool Build(TilemapStructure tilemap, float[] heightmap) { Vector2Int currentPos = RiverPositions.First(); // The target tile we want the river to attempt to reach int waterTileId = (int)GroundTileType.DeepWater; bool done = false; int attempt = 0; while (!done) { // Check how many attempts we have done so far if (attempt >= _maxAttempts) { break; } attempt++; // Get the height of the current position var height = heightmap[currentPos.y * tilemap.Width + currentPos.x]; // Find the neighbor with the lowest height that isn't already a part of the river // Here we use a dirty trick to create a nullable struct, so FirstOrDefault can properly return null // Incase we cannot get to a water tile var lowestHeightNeighbor = tilemap.Get4Neighbors(currentPos.x, currentPos.y) .Select(a => new KeyValuePair <Vector2Int, float>(a.Key, heightmap[a.Key.y * tilemap.Width + a.Key.x])) .OrderBy(a => a.Value) .Select(a => new KeyValuePair <Vector2Int, float>?(a)) .FirstOrDefault(a => !RiverPositions.Contains(a.Value.Key)); // If the lowest neighbor is null if (lowestHeightNeighbor == null) { // Can't go deeper downwards, we made a lake. done = true; break; } // Add the current pos to the river positions currentPos = lowestHeightNeighbor.Value.Key; RiverPositions.Add(lowestHeightNeighbor.Value.Key); // Check if we are done, by checking if the current pos tile is a water tile done = tilemap.GetTile(lowestHeightNeighbor.Value.Key.x, lowestHeightNeighbor.Value.Key.y) == waterTileId; } return(done); }
public override void Apply(TilemapStructure tilemap) { int targetTileId = (int)TargetTile; int replaceTileId = (int)ReplacedBy; for (int i = 0; i < Repetitions; i++) { for (int x = 0; x < tilemap.Width; x++) { for (int y = 0; y < tilemap.Height; y++) { // Check if the current tile is our target tile var tile = tilemap.GetTile(x, y); if (tile == targetTileId) { // Retrieve all 8 neighbors of our current tile var neighbors = tilemap.GetNeighbors(x, y); // Count all the neighbors that are of type target tile int targetTilesCount = neighbors.Count(a => a.Value == targetTileId); // If the min alive count is not reached, we replace the tile if (targetTilesCount < MinAlive) { if (ReplaceByDominantTile) { // Group tiles on tiletype, then order them in descending order based on group size // Select the group's key which is the tiletype because thats what we grouped on // And select the first one (first group's key), because that's the dominant tile type var dominantTile = neighbors .GroupBy(a => a.Value) .OrderByDescending(a => a.Count()) .Select(a => a.Key) .First(); tilemap.SetTile(x, y, dominantTile); } else { tilemap.SetTile(x, y, replaceTileId); } } } } } } }
public static List <Vector2Int> GetTilesByType(TilemapStructure tilemap, IEnumerable <int> enumerable) { // Best to ToList() the IEnumerable because they will otherwise cause multiple enumerations. var tileTypes = enumerable.ToList(); var validTilePositions = new List <Vector2Int>(); for (int x = 0; x < tilemap.Width; x++) { for (int y = 0; y < tilemap.Height; y++) { var tileType = tilemap.GetTile(x, y); // Here we use Any to check if any of the tile types match the current tile if (tileTypes.Any(a => a == tileType)) { validTilePositions.Add(new Vector2Int(x, y)); } } } return(validTilePositions); }
/// <summary> /// 모래 타일, 물 타일, 풀 타일 뭐 등등 그 중에 풀 타일을 골라 /// 10x10 그리드에 각 셀 하나하나 그 타일의 8개의 이웃타일에게 얼마나 많이 같은 타입이 있는지 세고 /// 그 숫자를 통해 타일들을 같은 타입으로 두냐 아니냐를 선택한다. /// </summary> /// <param name="tilemap"></param> public override void Apply(TilemapStructure tilemap) { int targetTileId = (int)TargetTile; int replaceTileId = (int)ReplaceBy; for (int i = 0; i < Reptitions; i++) { for (int x = 0; x < tilemap.Width; x++) { for (int y = 0; y < tilemap.Height; y++) { var tile = tilemap.GetTile(x, y); if (tile == targetTileId) { var neighbors = tilemap.GetNeighbors(x, y); int targetTilesCount = neighbors.Count(a => a.Value == targetTileId); // 만약 minAlive 숫자가 도달하지 못하면 타일을 교체한다 if (targetTilesCount < minAlive) { if (ReplaceByDominantTile) { int dominantTile = neighbors .GroupBy(a => a.Value) .OrderByDescending(a => a.Count()) .Select(a => a.Key) .First(); tilemap.SetTile(x, y, dominantTile); } else { tilemap.SetTile(x, y, replaceTileId); } } } } } } }
// Create Random Tile public override void Apply(TilemapStructure tilemap) { TilemapStructure groundTilemap = tilemap.grid.TilemapType[TilemapType.Ground]; var random = new System.Random(tilemap.grid.Seed); for (int x = 0; x < tilemap.Width; x++) { for (int y = 0; y < tilemap.Height; y++) { foreach (var spawnThing in spawnConfigulations) { int groundTile = groundTilemap.GetTile(x, y); if (spawnThing.spawnTileType.Any(tile => (int)tile == groundTile)) // 타일 중 하나라도 groundTile이랑 같다면 { if (random.Next(0, 100) <= spawnThing.SpawnChancePerCell) { tilemap.SetTile(x, y, (int)spawnThing.objectType); } } } } } }