| | |
| | | { |
| | | public int? seed; |
| | | public static int maxWidth = 256; |
| | | public static int maxHeight = 384; |
| | | public static int maxGroundHeight = 256; |
| | | public static int maxDepth = 384; |
| | | public static int groundDepth = 256; |
| | | private float scale; |
| | | private float offsetX; |
| | | private float offsetY; |
| | | Tilemap tilemap; |
| | | public CustomRuleTile forestRuleTile; |
| | | public TileBase borderTile; |
| | | public List<Generateable> generateables; |
| | | private List<Generateable> generateables; |
| | | //public List<TileBase> tiles; |
| | | |
| | | private void Awake() |
| | |
| | | |
| | | SetSettingsFromSeed(seed.Value); |
| | | |
| | | transform.position = new Vector3((maxWidth / 2) * -1, (maxGroundHeight + 1) * -1, transform.position.z); |
| | | // Position adjusted to center horizontally, but align top at y=0 |
| | | transform.position = new Vector3((maxWidth / 2) * -1, -1, transform.position.z); |
| | | |
| | | LoadGenerateablesFromResources(); |
| | | } |
| | |
| | | public IEnumerator GenerateTiles(Action finishedCallback, List<Vector3Int> destroyedTiles) |
| | | { |
| | | // generate ground |
| | | yield return CreateGroundLayer(destroyedTiles); |
| | | |
| | | if (generateables != null) |
| | | { |
| | | yield return GenerateOreClusters(destroyedTiles); |
| | | } |
| | | |
| | | // generate borders |
| | | yield return GenerateBorders(); |
| | | finishedCallback(); |
| | | } |
| | | |
| | | private IEnumerator CreateGroundLayer(List<Vector3Int> destroyedTiles) |
| | | { |
| | | for (int x = 1; x < maxWidth; x++) |
| | | { |
| | | for (int y = 1; y < maxGroundHeight; y++) |
| | | for (int y = -1; y > -groundDepth; y--) |
| | | { |
| | | float xPerlin = ((float)x / maxWidth) * scale + offsetX; |
| | | float yPerlin = ((float)y / maxHeight) * scale + offsetY; |
| | | float yPerlin = ((float)Mathf.Abs(y) / maxDepth) * scale + offsetY; |
| | | float perlinNoise = Mathf.PerlinNoise(xPerlin, yPerlin); |
| | | |
| | | if (perlinNoise <= 0.7f) |
| | |
| | | yield return null; |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (generateables != null) |
| | | private IEnumerator GenerateOreClusters(List<Vector3Int> destroyedTiles) |
| | | { |
| | | foreach (Generateable generateable in generateables) |
| | | { |
| | | foreach (Generateable generateable in generateables) |
| | | // Convert spawn heights to negative values if they aren't already |
| | | int maxY = -Mathf.Abs(generateable.maxSpawnHeight); |
| | | int minY = -Mathf.Abs(generateable.minSpawnHeight); |
| | | Debug.Log($"Generating {generateable.name} between Y: {minY} - {maxY}"); |
| | | for (int x = 0; x < maxWidth; x++) |
| | | { |
| | | for (int x = 0; x < maxWidth; x++) |
| | | for (int y = maxY; y > minY; y--) |
| | | { |
| | | for (int y = generateable.minSpawnHeight; y < generateable.maxSpawnHeight; y++) |
| | | { |
| | | float xPerlin = ((float)x / maxWidth) * (float)generateable.clusterWeight + offsetX; |
| | | float yPerlin = ((float)y / maxHeight) * (float)generateable.clusterWeight + offsetY; |
| | | float perlinNoise = Mathf.PerlinNoise(xPerlin, yPerlin); |
| | | float xPerlin = ((float)x / maxWidth) * (float)generateable.clusterWeight + offsetX; |
| | | float yPerlin = ((float)Mathf.Abs(y) / maxDepth) * (float)generateable.clusterWeight + offsetY; |
| | | float perlinNoise = Mathf.PerlinNoise(xPerlin, yPerlin); |
| | | |
| | | if (perlinNoise <= (1f / (float)generateable.weight)) |
| | | if (perlinNoise <= (1f / (float)generateable.weight)) |
| | | { |
| | | Vector3Int tileSpawnCoord = new Vector3Int(x, y); |
| | | if (!destroyedTiles.Contains(tileSpawnCoord) && tilemap.HasTile(tileSpawnCoord)) |
| | | { |
| | | Vector3Int tileSpawnCoord = new Vector3Int(x, y); |
| | | if (!destroyedTiles.Contains(tileSpawnCoord) && tilemap.HasTile(tileSpawnCoord)) |
| | | // Check potential cluster size before placing |
| | | int clusterSize = CountPotentialClusterSize(x, y, generateable.weight, generateable.clusterWeight); |
| | | if (clusterSize >= generateable.minClusterSize) |
| | | { |
| | | // Check potential cluster size before placing |
| | | int clusterSize = CountPotentialClusterSize(x, y, generateable.weight, generateable.clusterWeight); |
| | | if (clusterSize >= generateable.minClusterSize) |
| | | { |
| | | tilemap.SetTile(tileSpawnCoord, generateable.tile); |
| | | } |
| | | //tilemap.SetTile(tileSpawnCoord, generateable.tile); |
| | | tilemap.SetTile(tileSpawnCoord, generateable.tile); |
| | | } |
| | | //tilemap.SetTile(tileSpawnCoord, generateable.tile); |
| | | } |
| | | |
| | | } |
| | | |
| | | // Update UI every 8 lines |
| | | if ((x % 8) == 0) |
| | | { |
| | | yield return null; |
| | | } |
| | | } |
| | | |
| | | // Update UI every 8 lines |
| | | if ((x % 8) == 0) |
| | | { |
| | | yield return null; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // generate borders |
| | | private IEnumerator GenerateBorders() |
| | | { |
| | | // Vertical borders (going up from underground to sky) |
| | | for (int x = 0; x <= maxWidth; x += maxWidth) |
| | | { |
| | | for (int y = 0; y <= maxHeight; y++) |
| | | for (int y = -groundDepth; y <= maxDepth - groundDepth; y++) |
| | | { |
| | | tilemap.SetTile(new Vector3Int(x, y), borderTile); |
| | | } |
| | | |
| | | } |
| | | yield return null; |
| | | for (int y = 0; y <= maxHeight; y += maxHeight) |
| | | |
| | | // Horizontal borders (at bottom and sky level) |
| | | for (int y = -groundDepth; y <= maxDepth - groundDepth; y += maxDepth) |
| | | { |
| | | for (int x = 1; x <= maxWidth; x++) |
| | | { |
| | | tilemap.SetTile(new Vector3Int(x, y), borderTile); |
| | | } |
| | | |
| | | } |
| | | yield return null; |
| | | finishedCallback(); |
| | | } |
| | | |
| | | private int CountPotentialClusterSize(int startX, int startY, int weight, int clusterWeight) |
| | | { |
| | | int size = 0; |
| | |
| | | if (checked_positions.Contains(neighbor)) continue; |
| | | |
| | | float xPerlin = ((float)neighbor.x / maxWidth) * clusterWeight + offsetX; |
| | | float yPerlin = ((float)neighbor.y / maxHeight) * clusterWeight + offsetY; |
| | | float yPerlin = ((float)Mathf.Abs(neighbor.y) / maxDepth) * clusterWeight + offsetY; |
| | | float perlinNoise = Mathf.PerlinNoise(xPerlin, yPerlin); |
| | | |
| | | if (perlinNoise <= (1f / (float)weight)) |