From: fredboy Date: Tue, 16 Jun 2020 11:31:44 +0000 (+0700) Subject: Closes #5: Reimplement world generator in kotlin X-Git-Tag: alpha0.4~5 X-Git-Url: http://deadsoftware.ru/gitweb?a=commitdiff_plain;h=16b10981ea5bc34da1a8d63c70acf03faef8fc92;p=cavedroid.git Closes #5: Reimplement world generator in kotlin --- diff --git a/core/src/ru/deadsoftware/cavedroid/game/GameWorld.java b/core/src/ru/deadsoftware/cavedroid/game/GameWorld.java index cbf970c..3bf4981 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/GameWorld.java +++ b/core/src/ru/deadsoftware/cavedroid/game/GameWorld.java @@ -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 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 index 0000000..c157a4e --- /dev/null +++ b/core/src/ru/deadsoftware/cavedroid/game/GameWorldGenerator.kt @@ -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> { + 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 index cc02aea..0000000 --- a/core/src/ru/deadsoftware/cavedroid/game/WorldGen.java +++ /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; - } -}