public Tile[,] CreateTerrainTilesData(float tileLength) { Tile[,] tileData = new Tile[width, height]; Queue <Tile> borderTiles = new Queue <Tile>(); List <Tile> waterTiles = new List <Tile>(); List <Tile> landTiles = new List <Tile>(); Queue <Tile> lakeTiles = new Queue <Tile>(); Queue <Tile> beachTiles = new Queue <Tile>(); Queue <Tile> coastTiles = new Queue <Tile>(); List <Tile> locations = new List <Tile>(); List <Tile>[] regions = new List <Tile> [9]; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { // Calculate actual center position in scene Vector2 center = new Vector2((-(width - 1) * 0.5f + i) * tileLength, (-(height - 1) * 0.5f + j) * tileLength); // Create a tile class Tile newTile = new Tile(i, j, center, tileLength); // Set property values of each tile // 1) Assign borders if (i == 0 || i == width - 1 || j == 0 || j == height - 1) { newTile.border = true; borderTiles.Enqueue(newTile); } // 2) Assign water and land newTile.water = !inside(newTile.Position); newTile.land = !newTile.water; if (!newTile.water) { newTile.DistanceToWater = int.MaxValue; landTiles.Add(newTile); } else { waterTiles.Add(newTile); } // Store in 2d array tileData[i, j] = newTile; } } // Store neighbor/adjacent tiles for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { tileData[i, j].Neighbors = GetNeighborTiles(tileData[i, j], tileData); } } AssignOceanTiles(borderTiles); AssignLakeTiles(waterTiles, lakeTiles); AssignBeachAndCoast(landTiles, beachTiles, locations); // Elevations AssignElevations(beachTiles); RedistributeElevations(locations); // Moistures AssignMoisture(lakeTiles, locations); RedistributeMoisture(locations); AssignBiome(landTiles); // ================================ // Assign distance to water landTiles.ForEach(lt => { if (lt.coast) { lt.DistanceToWater = 1; coastTiles.Enqueue(lt); } }); while (coastTiles.Count > 0) { Tile t = coastTiles.Dequeue(); foreach (Tile n in t.Neighbors) { if (!n.land) { continue; } int newD = t.DistanceToWater + 1; if (newD < n.DistanceToWater) { n.DistanceToWater = newD; coastTiles.Enqueue(n); } } } // Assign region foreach (Tile lt in landTiles) { AssignRegion(lt); if (regions[(int)lt.RegionNum] == null) { regions[(int)lt.RegionNum] = new List <Tile>(); } regions[(int)lt.RegionNum].Add(lt); } // Find a spawn region for player and theater // The region with the most land tiles excluding the middle region Region spawnRegion = Region.Northwest; for (int i = 0; i < regions.Length; i++) { if ((Region)i == Region.Middle) { continue; } int landTilesCount = regions[i].Count; //Debug.Log("Region " + ((Region)i).ToString() + " has " + landTilesCount + " land tiles"); if (landTilesCount > regions[(int)spawnRegion].Count) { spawnRegion = (Region)i; } } Debug.Log("Spawn region is " + spawnRegion.ToString()); // Determine spawn center of the theater // It needs to be at the farthest distance from water Tile potentialSpawnTile = null; foreach (Tile rt in regions[(int)spawnRegion]) { if (potentialSpawnTile == null || rt.DistanceToWater > potentialSpawnTile.DistanceToWater) { potentialSpawnTile = rt; if (rt.DistanceToWater == 7) { break; } } } potentialSpawnTile.isSpawnCenter = true; for (int i = -4; i <= 4; i++) { for (int j = -4; j <= 4; j++) { Vector2Int pos = new Vector2Int(potentialSpawnTile.Position.x + i, potentialSpawnTile.Position.y + j); tileData[pos.x, pos.y].hasBuilding = true; } } Debug.Log("Potential spawn tile is " + potentialSpawnTile.Position + " with " + potentialSpawnTile.DistanceToWater + " units of distance to nearest water."); // Spawn items List <Tile> watermelonTileList = new List <Tile>(); List <Tile> starbucksTileList = new List <Tile>(); List <Tile> sofaTileList = new List <Tile>(); for (int i = 0; i < regions.Length; i++) { if ((Region)i == spawnRegion) { continue; } SpawnItemEquipment(regions[i], ItemEquipment.Sofa, 0.2f, sofaTileList); SpawnItemEquipment(regions[i], ItemEquipment.Hammer, 0.3f); SpawnItemEquipment(regions[i], ItemEquipment.Starbucks, 0.4f, starbucksTileList); SpawnItemEquipment(regions[i], ItemEquipment.Watermelon, 0.6f, watermelonTileList); if (i == regions.Length - 1) { if (watermelonTileList.Count == 0) { SpawnItemEquipment(regions[i], ItemEquipment.Watermelon, 1f, watermelonTileList); } if (starbucksTileList.Count == 0) { SpawnItemEquipment(regions[i], ItemEquipment.Starbucks, 1f, starbucksTileList); } if (sofaTileList.Count == 0) { SpawnItemEquipment(regions[i], ItemEquipment.Sofa, 1f, sofaTileList); } } } // Spawn enemies foreach (Tile watermelonTile in watermelonTileList) { SpawnEnemiesAroundItem(watermelonTile, 0.2f); } foreach (Tile starbucksTile in starbucksTileList) { SpawnEnemiesAroundItem(starbucksTile, 0.3f); } foreach (Tile sofaTile in sofaTileList) { SpawnEnemiesAroundItem(sofaTile, 0.3f); } // Trees foreach (Tile t in locations) { if (t.hasBuilding || t.hasItemEquipment) { continue; } List <Vector2> trees = new PoissonDiscSampling(poissonRadius, new Vector2(tileLength, tileLength), GetRejectionSamples(t.Biome)).SamplingPoints; List <Tile> lakeNeighbors = new List <Tile>(); t.Neighbors.ForEach(nb => { if (nb.lake) { lakeNeighbors.Add(nb); } }); if (lakeNeighbors.Count > 0) { foreach (Tile lake in lakeNeighbors) { for (int i = 0; i < trees.Count; i++) { Vector2 newTreeCenter = t.Center + trees[i]; if (lake.IsWithinTile(newTreeCenter)) { trees.RemoveAt(i); } } } } t.Trees = trees; } // Rocks foreach (Tile t in locations) { if (t.hasBuilding || t.hasItemEquipment) { continue; } if (t.Biome != Biome.DESERT && t.Biome != Biome.TEMPERATE_DESERT) { continue; } t.Rocks = new List <Vector2>(); // First rock if (RandomSelect_Percentage(0.1f)) { t.Rocks.Add(new Vector2(UnityEngine.Random.Range(-t.Length / 2f, t.Length / 2f), UnityEngine.Random.Range(-t.Length / 2f, t.Length / 2f))); } // Second rock if (RandomSelect_Percentage(0.05f)) { t.Rocks.Add(new Vector2(UnityEngine.Random.Range(-t.Length / 2f, t.Length / 2f), UnityEngine.Random.Range(-t.Length / 2f, t.Length / 2f))); } } return(tileData); }