DEADSOFTWARE

Add biomes and fix mobs physics
[cavedroid.git] / core / src / ru / deadsoftware / cavedroid / game / world / GameWorldGenerator.kt
index dd64c6a04077d02c1cce66c567311749a304e2f1..bc5ffa4cc4afdaf382e2b626844667fb0fe96e3e 100644 (file)
@@ -7,6 +7,13 @@ import kotlin.random.Random
 
 object GameWorldGenerator {
 
+    private const val BIOME_MIN_SIZE = 64
+
+    private enum class Biome {
+        PLAINS,
+        DESERT
+    }
+
     private fun generateHeights(width: Int, min: Int, max: Int, random: Random) = IntArray(width).apply {
         set(0, (min + max) / 2)
         for (x in 1 until width) {
@@ -22,6 +29,68 @@ object GameWorldGenerator {
         }
     }
 
+    private fun generateBiomes(width: Int, random: Random) = buildMap<Int, Biome> {
+        val xSequence = sequence {
+            var lastX = 0
+            var count = 0
+
+            while (lastX < width - BIOME_MIN_SIZE - 1) {
+                yield(lastX)
+
+                lastX = random.nextInt(lastX + BIOME_MIN_SIZE, width)
+                count++
+            }
+        }
+
+        return xSequence.associateWith { Biome.values()[random.nextInt(Biome.values().size)] }
+    }
+
+    private fun plainsBiome(
+        foreMap: Array<IntArray>,
+        backMap: Array<IntArray>,
+        width: Int,
+        height: Int,
+        x: Int,
+        xHeight: Int,
+        random: Random,
+    ) {
+        foreMap[x][xHeight] = GameItems.getBlockId("grass")
+        foreMap[x][height - 1] = GameItems.getBlockId("bedrock")
+        backMap[x][xHeight] = GameItems.getBlockId("grass")
+        backMap[x][height - 1] = GameItems.getBlockId("bedrock")
+
+        for (y in xHeight + 1 until height - 1) {
+            foreMap[x][y] = when {
+                y < xHeight + random.nextInt(5, 8) -> GameItems.getBlockId("dirt")
+                else -> GameItems.getBlockId("stone")
+            }
+            backMap[x][y] = foreMap[x][y]
+        }
+    }
+
+    private fun desertBiome(
+        foreMap: Array<IntArray>,
+        backMap: Array<IntArray>,
+        width: Int,
+        height: Int,
+        x: Int,
+        xHeight: Int,
+        random: Random,
+    ) {
+        foreMap[x][xHeight] = GameItems.getBlockId("sand")
+        foreMap[x][height - 1] = GameItems.getBlockId("bedrock")
+        backMap[x][xHeight] = GameItems.getBlockId("sand")
+        backMap[x][height - 1] = GameItems.getBlockId("bedrock")
+
+        for (y in xHeight + 1 until height - 1) {
+            foreMap[x][y] = when {
+                y < xHeight + random.nextInt(5, 8) -> GameItems.getBlockId("sand")
+                else -> GameItems.getBlockId("stone")
+            }
+            backMap[x][y] = foreMap[x][y]
+        }
+    }
+
     /**
      * Generates world of given width and height with given seed
      * @param width world width
@@ -34,22 +103,19 @@ object GameWorldGenerator {
         val foreMap = Array(width) { IntArray(height) }
         val backMap = Array(width) { IntArray(width) }
         val heightsMap = generateHeights(width, height / 2, height * 3 / 4, random)
+        val biomesMap = generateBiomes(width, random)
+
+        var biome = Biome.PLAINS
 
         for (x in 0 until width) {
             val xHeight = heightsMap[x]
+            biome = biomesMap[x] ?: biome
 
-            foreMap[x][xHeight] = GameItems.getBlockId("grass")
-            foreMap[x][height - 1] = GameItems.getBlockId("bedrock")
-            backMap[x][xHeight] = GameItems.getBlockId("grass")
-            backMap[x][height - 1] = GameItems.getBlockId("bedrock")
-
-            for (y in xHeight + 1 until height - 1) {
-                foreMap[x][y] = when {
-                    y < xHeight + random.nextInt(5, 8) -> GameItems.getBlockId("dirt")
-                    else -> GameItems.getBlockId("stone")
-                }
-                backMap[x][y] = foreMap[x][y]
+            when (biome) {
+                Biome.PLAINS -> plainsBiome(foreMap, backMap, width, height, x, xHeight, random)
+                Biome.DESERT -> desertBiome(foreMap, backMap, width, height, x, xHeight, random)
             }
+
         }
         return Pair(foreMap, backMap)
     }