DEADSOFTWARE

Closes #5: Reimplement world generator in kotlin
authorfredboy <fredboy@protonmail.com>
Tue, 16 Jun 2020 11:31:44 +0000 (18:31 +0700)
committerfredboy <fredboy@protonmail.com>
Tue, 16 Jun 2020 13:16:17 +0000 (20:16 +0700)
core/src/ru/deadsoftware/cavedroid/game/GameWorld.java
core/src/ru/deadsoftware/cavedroid/game/GameWorldGenerator.kt [new file with mode: 0644]
core/src/ru/deadsoftware/cavedroid/game/WorldGen.java [deleted file]

index cbf970ced1a84251183cca22cbd9877844ae374a..3bf4981d76d5b5914679f3ed82d2f81adcf979b7 100644 (file)
@@ -1,6 +1,8 @@
 package ru.deadsoftware.cavedroid.game;
 
 import com.badlogic.gdx.utils.Disposable;
+import com.badlogic.gdx.utils.TimeUtils;
+import kotlin.Pair;
 import ru.deadsoftware.cavedroid.game.mobs.FallingGravel;
 import ru.deadsoftware.cavedroid.game.mobs.FallingSand;
 import ru.deadsoftware.cavedroid.game.mobs.MobsController;
@@ -43,10 +45,9 @@ public class GameWorld implements Disposable {
         if (isNewGame) {
             mWidth = DEFAULT_WIDTH;
             mHeight = DEFAULT_HEIGHT;
-            WorldGen.genWorld(mWidth, mHeight);
-            mForeMap = WorldGen.getForeMap();
-            mBackMap = WorldGen.getBackMap();
-            WorldGen.clear();
+            Pair<int[][], int[][]> maps = GameWorldGeneratorKt.generate(mWidth, mHeight, TimeUtils.millis());
+            mForeMap = maps.getFirst();
+            mBackMap = maps.getSecond();
             mMobsController.getPlayer().respawn(this);
         } else {
             mForeMap = foreMap;
diff --git a/core/src/ru/deadsoftware/cavedroid/game/GameWorldGenerator.kt b/core/src/ru/deadsoftware/cavedroid/game/GameWorldGenerator.kt
new file mode 100644 (file)
index 0000000..c157a4e
--- /dev/null
@@ -0,0 +1,52 @@
+package ru.deadsoftware.cavedroid.game
+
+import com.badlogic.gdx.utils.TimeUtils
+import kotlin.math.abs
+import kotlin.random.Random
+
+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) {
+        val previous = get(x - 1)
+        var d = random.nextInt(-5, 6).let { if (it !in -4..4) it / abs(it) else 0 }
+
+        if (previous + d !in min..max) { d = -d }
+        if (lastIndex - x < abs(get(0) - previous) * 3) {
+            d = get(0).compareTo(previous).let { if (it != 0) it / abs(it) else 0 }
+        }
+
+        set(x, get(x - 1) + d)
+    }
+}
+
+/**
+ * Generates world of given width and height with given seed
+ * @param width world width
+ * @param height world height
+ * @param seed seed for random number generator
+ * @return pair of foreground and background layers
+ */
+fun generate(width: Int, height: Int, seed: Long = TimeUtils.millis()): Pair<Array<IntArray>, Array<IntArray>> {
+    val random = Random(seed)
+    val foreMap = Array(width) { IntArray(height) }
+    val backMap = Array(width) { IntArray(width) }
+    val heightsMap = generateHeights(width, height / 2, height * 3 / 4, random)
+
+    for (x in 0 until width) {
+        val xHeight = heightsMap[x]
+
+        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]
+        }
+    }
+    return Pair(foreMap, backMap)
+}
diff --git a/core/src/ru/deadsoftware/cavedroid/game/WorldGen.java b/core/src/ru/deadsoftware/cavedroid/game/WorldGen.java
deleted file mode 100644 (file)
index cc02aea..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-package ru.deadsoftware.cavedroid.game;
-
-import com.badlogic.gdx.math.RandomXS128;
-import com.badlogic.gdx.utils.TimeUtils;
-
-import javax.annotation.CheckForNull;
-
-class WorldGen {
-
-    @CheckForNull
-    private static RandomXS128 rand;
-    private static long seed;
-
-    @CheckForNull
-    private static int[][] foreMap, backMap;
-    @CheckForNull
-    private static int[] hMap;
-    @CheckForNull
-    private static int[] bMap; //biomes, 0-plains, 1-desert
-
-    public static long getSeed() {
-        return seed;
-    }
-
-    static int[] genLandscape(int width, int mid, int min, int max) {
-        int[] res = new int[width];
-        bMap = new int[width];
-        int t;
-        res[0] = mid;
-        for (int i = 1; i < width; i++) {
-            t = rand.nextInt(7) - 3;
-            if (t > -3 && t < 3) {
-                t = 0;
-            } else {
-                t /= Math.abs(t);
-            }
-            if (i > width - (max - min)) {
-                if (res[i - 1] + t < res[0]) {
-                    t = Math.abs(t);
-                } else if (res[i - 1] + t > res[0]) {
-                    t = -Math.abs(t);
-                }
-            }
-            res[i] = res[i - 1] + t;
-            if (res[i] < min) {
-                res[i] = min;
-            }
-            if (res[i] > max) {
-                res[i] = max;
-            }
-            bMap[i] = 0;
-//            if (i >= width / 2) {
-//                bMap[i] = 1;
-//                if (res[i] < 60) res[i] = 60;
-//            } else {
-//                bMap[i] = 0;
-//            }
-        }
-        if (res[0] < res[width - 1]) {
-            res[width - 1] = res[0];
-        }
-        return res;
-    }
-
-    private static void genCactus(int x, int y) {
-        assert foreMap != null;
-        foreMap[x][y] = 59;
-        foreMap[x][y - 1] = 59;
-        foreMap[x][y - 2] = 59;
-    }
-
-    private static void genOak(int x, int y) {
-        assert foreMap != null && backMap != null;
-        backMap[x][y] = 15;
-        backMap[x][y - 1] = 15;
-        backMap[x][y - 2] = 15;
-        backMap[x][y - 3] = 15;
-        backMap[x][y - 4] = 16;
-        backMap[x][y - 5] = 16;
-        backMap[x - 1][y - 3] = 16;
-        backMap[x - 1][y - 4] = 16;
-        backMap[x + 1][y - 3] = 16;
-        backMap[x + 1][y - 4] = 16;
-        foreMap[x][y - 3] = 16;
-        foreMap[x][y - 4] = 16;
-        foreMap[x][y - 5] = 16;
-        foreMap[x - 1][y - 3] = 16;
-        foreMap[x - 1][y - 4] = 16;
-        foreMap[x + 1][y - 3] = 16;
-        foreMap[x + 1][y - 4] = 16;
-    }
-
-    static void genWorld(int width, int height) {
-        genWorld(width, height, TimeUtils.millis());
-    }
-
-    static void genWorld(int width, int height, long worldseed) {
-        int dirtH;
-        seed = worldseed;
-        rand = new RandomXS128(seed);
-        foreMap = new int[width][height];
-        backMap = new int[width][height];
-        hMap = genLandscape(width, height / 4, height / 8, height / 2);
-        for (int x = 0; x < width; x++) {
-            dirtH = 4 + rand.nextInt(2);
-            for (int y = height - hMap[x]; y < height; y++) {
-                if (y == height - hMap[x]) {
-                    switch (bMap[x]) {
-                        case 0:
-                            foreMap[x][y] = 2;
-                            backMap[x][y] = 2;
-                            break;
-                        case 1:
-                            foreMap[x][y] = 10;
-                            backMap[x][y] = 10;
-                            break;
-                    }
-                } else if (y < height - hMap[x] + dirtH) {
-                    switch (bMap[x]) {
-                        case 0:
-                            foreMap[x][y] = 3;
-                            backMap[x][y] = 3;
-                            break;
-                        case 1:
-                            foreMap[x][y] = 10;
-                            backMap[x][y] = 10;
-                            break;
-                    }
-                } else if (bMap[x] == 1 && y < height - hMap[x] + dirtH + 3) {
-                    foreMap[x][y] = 21;
-                    backMap[x][y] = 21;
-                } else if (y < height - 1) {
-                    foreMap[x][y] = 1;
-                    backMap[x][y] = 1;
-                } else {
-                    foreMap[x][y] = 7;
-                    backMap[x][y] = 7;
-                }
-            }
-            for (int y = height - 60; y < height - 1; y++) {
-                if (foreMap[x][y] == 0 && bMap[x] != 1) {
-                    foreMap[x][y] = 8;
-                    if (bMap[x] == 0) {
-                        if (y == height - 60) {
-                            backMap[x][y] = 2;
-                        } else {
-                            backMap[x][y] = 3;
-                        }
-                    }
-                    if (y == height - hMap[x] - 1) {
-                        foreMap[x][y + 1] = 3;
-                        backMap[x][y + 1] = 3;
-                    }
-                }
-            }
-            if (x > 2 && x < width - 2) {
-                if (foreMap[x][height - hMap[x] - 1] == 0 && foreMap[x][height - hMap[x]] == 2) {
-                    switch (rand.nextInt(50)) {
-                        case 0:
-                            genOak(x, height - hMap[x] - 1);
-                            break;
-                        case 1:
-                            foreMap[x][height - hMap[x] - 1] = 26;
-                            break;
-                        case 2:
-                            foreMap[x][height - hMap[x] - 1] = 29;
-                            break;
-                        case 3:
-                            foreMap[x][height - hMap[x] - 1] = 30;
-                            break;
-                        case 4:
-                            foreMap[x][height - hMap[x] - 1] = 31;
-                            break;
-                        case 5:
-                            foreMap[x][height - hMap[x] - 1] = 32;
-                            break;
-                    }
-                }
-                if (foreMap[x][height - hMap[x] - 1] == 0 && foreMap[x][height - hMap[x]] == 10) {
-                    switch (rand.nextInt(20)) {
-                        case 0:
-                            genCactus(x, height - hMap[x] - 1);
-                            break;
-                        case 1:
-                            foreMap[x][height - hMap[x] - 1] = 27;
-                            break;
-                    }
-                }
-            }
-        }
-    }
-
-    static int[][] getForeMap() {
-        assert foreMap != null;
-        return foreMap;
-    }
-
-    static int[][] getBackMap() {
-        assert backMap != null;
-        return backMap;
-    }
-
-    static void clear() {
-        hMap = null;
-        bMap = null;
-    }
-}