List <Vector2Int> TestTile(List <Vector2Int> pointsInt) { List <Vector2Int> vector2Ints = new List <Vector2Int>(); TilemapStructure objectTileStruct = tileGrid.TilemapType[TilemapType.Object]; TilemapStructure groundTileStruct = tileGrid.TilemapType[TilemapType.Ground]; for (int i = 0; i < pointsInt.Count; i++) { Vector2Int tilePos = new Vector2Int(pointsInt[i].x, pointsInt[i].y); int objectTileType = objectTileStruct.GetTileEnumNumber(tilePos.x, tilePos.y); int groundTileType = groundTileStruct.GetTileEnumNumber(tilePos.x, tilePos.y); if (objectTileType != (int)ObjectTileType.Tree) { for (int j = 0; j < poissonSamp.spawnTileType.Length; j++) { if (groundTileType == (int)poissonSamp.spawnTileType[j]) { vector2Ints.Add(tilePos); } } } } return(vector2Ints); }
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); }
// Create Random Tile public override void Apply(TilemapStructure tilemapStruct) { TilemapStructure groundTileStruct = tilemapStruct.grid.TilemapType[TilemapType.Ground]; TilemapStructure objectTileStruct = tilemapStruct.grid.TilemapType[TilemapType.Object]; var random = new System.Random(tilemapStruct.grid.Seed); for (int x = 0; x < tilemapStruct.Width; x++) { for (int y = 0; y < tilemapStruct.Height; y++) { foreach (SpawnConfigulation spawnThing in spawnConfigulations) { int groundTile = groundTileStruct.GetTileEnumNumber(x, y); // get tile's tileType, from tilePosition ex) 1 water, 2 sand, 4, grass int objectTile = objectTileStruct.GetTileEnumNumber(x, y); // 0 none, 2000 tree, if (spawnThing.dontSpawnTileType.Length != 0) { for (int i = 0; i < spawnThing.dontSpawnTileType.Length; i++) { if (objectTile != (int)spawnThing.dontSpawnTileType[i]) { setTile(x, y, spawnThing, random, tilemapStruct, groundTile); } } } else { setTile(x, y, spawnThing, random, tilemapStruct, groundTile); } } } } }
public override void Apply(TilemapStructure tilemap) { var groundTilemap = tilemap.Grid.Tilemaps[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 tree in TreeSelection) { var groundTile = groundTilemap.GetTile(x, y); if (tree.SpawnOnGrounds.Any(tile => (int)tile == groundTile)) { // Do a random chance check if (random.Next(0, 100) <= tree.SpawnChancePerCell) { tilemap.SetTile(x, y, (int)tree.Tree); } // We don't break here, because other tree selections can still overrule this one. } } } } }
public override void Apply(TilemapStructure tilemap) { _random = new System.Random(tilemap.Grid.Seed); // Re-create the heightmap from our tilemap var heightmap = Noise.GenerateNoiseMap(tilemap.Width, tilemap.Height, tilemap.Grid.Seed, GroundHeightmap.NoiseScale, GroundHeightmap.Octaves, GroundHeightmap.Persistance, GroundHeightmap.Lacunarity, GroundHeightmap.Offset); if (GroundHeightmap.ApplyIslandGradient) { var islandGradient = Noise.GenerateIslandGradientMap(tilemap.Width, tilemap.Height); for (int x = 0, y; x < tilemap.Width; x++) { for (y = 0; y < tilemap.Height; y++) { // Subtract the islandGradient value from the noiseMap value float subtractedValue = heightmap[y * tilemap.Width + x] - islandGradient[y * tilemap.Width + x]; // Apply it into the map, but make sure we clamp it between 0f and 1f heightmap[y * tilemap.Width + x] = Mathf.Clamp01(subtractedValue); } } } // Get all start positions var validStartPositions = TilemapHelper.GetTilesByType(tilemap, StartingTileTypes.Select(a => (int)a)); var amountOfRivers = _random.Next(MinRiverQuota, MaxRiverQuota + 1); var rivers = new List <DownstreamRiver>(); for (int i = 0; i < amountOfRivers; i++) { // Get valid startPoint with respect to distance between existing rivers var startPoint = GetValidStartPosition(validStartPositions, rivers); if (!startPoint.HasValue) { break; } // Build river from start based on heightmap var river = new DownstreamRiver(startPoint.Value); if (river.Build(tilemap, heightmap)) { rivers.Add(river); } } // Set river tiles into tilemap int riverTileId = (int)GroundTileType.River; foreach (var riverPosition in rivers.SelectMany(a => a.RiverPositions)) { tilemap.SetTile(riverPosition.x, riverPosition.y, riverTileId); } }
public void Apply(TilemapStructure tilemap) { var validEnumValues = (GroundTileType[])Enum.GetValues(typeof(GroundTileType)); for (int x = 0; x < tilemap.Width; x++) { for (int y = 0; y < tilemap.Height; y++) { var randomValue = (int)validEnumValues[UnityEngine.Random.Range(0, validEnumValues.Length)]; tilemap.SetTile(x, y, randomValue); } } }
public override void Apply(TilemapStructure tilemap) { TileTypeEnum[] validEnumValues = (TileTypeEnum[])Enum.GetValues(typeof(TileTypeEnum)); for (int x = 0; x < tilemap.Width; x++) { for (int y = 0; y < tilemap.Height; y++) { int randomValue = (int)validEnumValues[UnityEngine.Random.Range(0, validEnumValues.Length)]; tilemap.SetTile(x, y, randomValue); } } }
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 override void Apply(TilemapStructure tilemap) { // Make sure that TileTypes are ordered from small to high height TileTypes = TileTypes.OrderBy(a => a.Height).ToArray(); // Pass along our parameters to generate our noise var noiseMap = Noise.GenerateNoiseMap(tilemap.Width, tilemap.Height, tilemap.Grid.Seed, NoiseScale, Octaves, Persistance, Lacunarity, Offset); if (ApplyIslandGradient) { var islandGradient = Noise.GenerateIslandGradientMap(tilemap.Width, tilemap.Height); for (int x = 0, y; x < tilemap.Width; x++) { for (y = 0; y < tilemap.Height; y++) { // Subtract the islandGradient value from the noiseMap value float subtractedValue = noiseMap[y * tilemap.Width + x] - islandGradient[y * tilemap.Width + x]; // Apply it into the map, but make sure we clamp it between 0f and 1f noiseMap[y * tilemap.Width + x] = Mathf.Clamp01(subtractedValue); } } } for (int x = 0; x < tilemap.Width; x++) { for (int y = 0; y < tilemap.Height; y++) { // Get height at this position var height = noiseMap[y * tilemap.Width + x]; // Loop over our configured tile types for (int i = 0; i < TileTypes.Length; i++) { // If the height is smaller or equal then use this tiletype if (height <= TileTypes[i].Height) { tilemap.SetTile(x, y, (int)TileTypes[i].GroundTile); break; } } } } }
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.GetTileEnumNumber(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.SetTileEnumNumber(x, y, dominantTile); } else { tilemap.SetTileEnumNumber(x, y, replaceTileId); } } } } } } }
public override void Apply(TilemapStructure tilemap) { _random = new System.Random(tilemap.Grid.Seed); var rivers = new List <DrunkenRiver>(); var validStartPositions = TilemapHelper.GetTilesByType(tilemap, StartingTileTypes.Select(a => (int)a)); var amountOfRivers = _random.Next(MinRiverQuota, MaxRiverQuota + 1); for (int i = 0; i < amountOfRivers; i++) { // Get valid startPoint with respect to distance between existing rivers var startPoint = GetValidStartPosition(validStartPositions, rivers); if (!startPoint.HasValue) { break; } // Find valid endPos (closest deep water tile to startPos) var endPos = TilemapHelper.FindClosestTileByType(tilemap, startPoint.Value, (int)GroundTileType.DeepWater); if (!endPos.HasValue) { break; } // Build river from start to end position var river = new DrunkenRiver(_random, RiverDriftChance, startPoint.Value, endPos.Value); if (river.Build()) { rivers.Add(river); } } // Set river tiles into tilemap int riverTileId = (int)GroundTileType.River; foreach (var riverPosition in rivers.SelectMany(a => a.RiverPositions)) { tilemap.SetTile(riverPosition.x, riverPosition.y, riverTileId); } }
public override void Apply(TilemapStructure tilemap) { // Make sure TileType ordered from small to high height tileTypes = tileTypes.OrderBy(a => a.Height).ToArray(); float[] noiseMap = Noise.GenerateNoiseMap(tilemap.Width, tilemap.Height, tilemap.grid.Seed, NoiseScale, Octaves, Persistance, Lacunarity, Offset); if (ApplyIslandGradient) { float[] islandGradient = Noise.GenerateIslandGradientMap(tilemap.Width, tilemap.Height); for (int x = 0, y; x < tilemap.Width; x++) { for (y = 0; y < tilemap.Height; y++) { float subtractedValue = noiseMap[y * tilemap.Width + x] - islandGradient[y * tilemap.Width + x]; // make sure Clamp to 0f~ 1f; noiseMap[y * tilemap.Width + x] = Mathf.Clamp01(subtractedValue); } } } for (int x = 0; x < tilemap.Width; x++) { for (int y = 0; y < tilemap.Height; y++) { float height = noiseMap[y * tilemap.Width + x]; for (int i = 0; i < tileTypes.Length; i++) { if (height <= tileTypes[i].Height) { tilemap.SetTile(x, y, (int)tileTypes[i].tileTypeEnum); break; } } } } }
public override void Apply(TilemapStructure tilemap) { // Make sure TileType ordered from small to high height tileTypes = tileTypes.OrderBy(a => a.Height).ToArray(); var noiseMap = Noise.GenerateNoiseMap(tilemap.Width, tilemap.Height, tilemap.Seed, NoiseScale, Octaves, Persistance, Lacunarity, Offset); for (int x = 0; x < tilemap.Width; x++) { for (int y = 0; y < tilemap.Height; y++) { var height = noiseMap[y * tilemap.Width + x]; for (int i = 0; i < tileTypes.Length; i++) { if (height <= tileTypes[i].Height) { tilemap.SetTile(x, y, (int)tileTypes[i].tileTypeEnum); break; } } } } }
// 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); } } } } } }
void setTile(int x, int y, SpawnConfigulation spawnThing, System.Random random, TilemapStructure tilemapStruct, int groundTile) { if (spawnThing.spawnTileType.Any(tile => (int)tile == groundTile)) // 타일 중 하나라도 groundTile이랑 같다면 { if (random.Next(0, 100) <= spawnThing.SpawnChancePerCell) { tilemapStruct.SetTileEnumNumber(x, y, (int)spawnThing.objectType); } } }
public abstract void Apply(TilemapStructure tilemap);