diff --git a/core/src/ru/deadsoftware/cavedroid/game/world/GameWorldGenerator.kt b/core/src/ru/deadsoftware/cavedroid/game/world/GameWorldGenerator.kt
index 8776254f7dca8d6a1d3b3212aff95335bdb22733..004a56b01a945ec581dd084a5e26c390da3de190 100644 (file)
package ru.deadsoftware.cavedroid.game.world
package ru.deadsoftware.cavedroid.game.world
-import ru.deadsoftware.cavedroid.game.GameItems
+import com.google.common.primitives.Ints.min
+import ru.deadsoftware.cavedroid.game.GameItemsHolder
+import ru.deadsoftware.cavedroid.game.model.block.Block
import ru.deadsoftware.cavedroid.game.model.world.Biome
import ru.deadsoftware.cavedroid.game.model.world.generator.WorldGeneratorConfig
import kotlin.math.abs
import ru.deadsoftware.cavedroid.game.model.world.Biome
import ru.deadsoftware.cavedroid.game.model.world.generator.WorldGeneratorConfig
import kotlin.math.abs
class GameWorldGenerator(
private val config: WorldGeneratorConfig,
class GameWorldGenerator(
private val config: WorldGeneratorConfig,
+ private val gameItemsHolder: GameItemsHolder,
) {
private val random = Random(config.seed)
) {
private val random = Random(config.seed)
- private val foreMap by lazy { Array(config.width) { IntArray(config.height) } }
- private val backMap by lazy { Array(config.width) { IntArray(config.height) } }
+ private val foreMap by lazy { Array(config.width) { Array(config.height) { gameItemsHolder.fallbackBlock } } }
+ private val backMap by lazy { Array(config.width) { Array(config.height) { gameItemsHolder.fallbackBlock } } }
private val heights by lazy { generateHeights() }
private val biomesMap by lazy { generateBiomes() }
private val heights by lazy { generateHeights() }
private val biomesMap by lazy { generateBiomes() }
+ private val plainsPlants = listOf("dandelion", "rose", "tallgrass")
+ private val mushrooms = listOf("mushroom_brown", "mushroom_red",)
+
private fun generateHeights(): IntArray {
val surfaceHeightRange = config.minSurfaceHeight .. config.maxSurfaceHeight
val result = IntArray(config.width)
private fun generateHeights(): IntArray {
val surfaceHeightRange = config.minSurfaceHeight .. config.maxSurfaceHeight
val result = IntArray(config.width)
- result[0] = (config.minSurfaceHeight + config.maxSurfaceHeight) / 2
+ result[0] = surfaceHeightRange.random(random)
for (x in 1 ..< config.width) {
val previous = result[x - 1]
for (x in 1 ..< config.width) {
val previous = result[x - 1]
return xSequence.associateWith { config.biomes.random(random) }
}
return xSequence.associateWith { config.biomes.random(random) }
}
+ private fun winterBiome(x: Int) {
+ assert(x in 0 ..< config.width) { "x not in range of world width" }
+
+ val surfaceHeight = heights[x]
+
+ val grass = gameItemsHolder.getBlock("grass_snowed")
+ val bedrock = gameItemsHolder.getBlock("bedrock")
+ val dirt = gameItemsHolder.getBlock("dirt")
+ val stone = gameItemsHolder.getBlock("stone")
+ val snow = gameItemsHolder.getBlock("snow")
+
+ foreMap[x][surfaceHeight] = grass
+ foreMap[x][config.height - 1] = bedrock
+ backMap[x][surfaceHeight] = grass
+ backMap[x][config.height - 1] = bedrock
+
+ if (surfaceHeight - 1 < config.seaLevel) {
+ foreMap[x][surfaceHeight - 1] = snow
+ }
+
+ for (y in min(surfaceHeight + 1, config.seaLevel) ..< config.height - 1) {
+ if (y <= surfaceHeight) {
+ backMap[x][y] = dirt
+ continue
+ }
+
+ foreMap[x][y] = when {
+ y < surfaceHeight + random.nextInt(5, 8) -> dirt
+ else -> stone
+ }
+ backMap[x][y] = foreMap[x][y]
+ }
+
+ val plant = random.nextInt(100)
+ if (surfaceHeight < config.seaLevel) {
+ if (plant < 10) {
+ generateSpruce(x)
+ }
+ }
+ }
+
private fun plainsBiome(x: Int) {
assert(x in 0 ..< config.width) { "x not in range of world width" }
val surfaceHeight = heights[x]
private fun plainsBiome(x: Int) {
assert(x in 0 ..< config.width) { "x not in range of world width" }
val surfaceHeight = heights[x]
- val grassId = GameItems.getBlockId("grass")
- val bedrockId = GameItems.getBlockId("bedrock")
- val dirtId = GameItems.getBlockId("dirt")
- val stoneId = GameItems.getBlockId("stone")
+ val grass = gameItemsHolder.getBlock("grass")
+ val bedrock = gameItemsHolder.getBlock("bedrock")
+ val dirt = gameItemsHolder.getBlock("dirt")
+ val stone = gameItemsHolder.getBlock("stone")
+
+ foreMap[x][surfaceHeight] = grass
+ foreMap[x][config.height - 1] = bedrock
+ backMap[x][surfaceHeight] = grass
+ backMap[x][config.height - 1] = bedrock
- foreMap[x][surfaceHeight] = grassId
- foreMap[x][config.height - 1] = bedrockId
- backMap[x][surfaceHeight] = grassId
- backMap[x][config.height - 1] = bedrockId
+ for (y in min(surfaceHeight + 1, config.seaLevel) ..< config.height - 1) {
+ if (y <= surfaceHeight) {
+ backMap[x][y] = dirt
+ continue
+ }
- for (y in surfaceHeight + 1 ..< config.height - 1) {
foreMap[x][y] = when {
foreMap[x][y] = when {
- y < surfaceHeight + random.nextInt(5, 8) -> dirtId
- else -> stoneId
+ y < surfaceHeight + random.nextInt(5, 8) -> dirt
+ else -> stone
}
backMap[x][y] = foreMap[x][y]
}
}
backMap[x][y] = foreMap[x][y]
}
+
+ val plant = random.nextInt(100)
+ if (surfaceHeight < config.seaLevel) {
+ if (plant < 10) {
+ generateOak(x)
+ } else if (plant < 40) {
+ generateTallGrass(x)
+ }
+ }
}
private fun desertBiome(x: Int) {
}
private fun desertBiome(x: Int) {
val surfaceHeight = heights[x]
val surfaceHeight = heights[x]
- val sandId = GameItems.getBlockId("sand")
- val bedrockId = GameItems.getBlockId("bedrock")
- val sandstoneId = GameItems.getBlockId("sandstone")
- val stoneId = GameItems.getBlockId("stone")
+ val sand = gameItemsHolder.getBlock("sand")
+ val bedrock = gameItemsHolder.getBlock("bedrock")
+ val sandstone = gameItemsHolder.getBlock("sandstone")
+ val stone = gameItemsHolder.getBlock("stone")
- foreMap[x][surfaceHeight] = sandId
- foreMap[x][config.height - 1] = bedrockId
- backMap[x][surfaceHeight] = sandId
- backMap[x][config.height - 1] = bedrockId
+ foreMap[x][surfaceHeight] = sand
+ foreMap[x][config.height - 1] = bedrock
+ backMap[x][surfaceHeight] = sand
+ backMap[x][config.height - 1] = bedrock
+
+ for (y in min(surfaceHeight + 1, config.seaLevel) ..< config.height - 1) {
+ if (y <= surfaceHeight) {
+ backMap[x][y] = sand
+ continue
+ }
- for (y in surfaceHeight + 1 ..< config.height - 1) {
foreMap[x][y] = when {
foreMap[x][y] = when {
- y < surfaceHeight + random.nextInt(5, 8) -> sandId
- y < surfaceHeight + random.nextInt(0, 2) -> sandstoneId
- else -> stoneId
+ y < surfaceHeight + random.nextInt(5, 8) -> sand
+ y < surfaceHeight + random.nextInt(0, 2) -> sandstone
+ else -> stone
}
backMap[x][y] = foreMap[x][y]
}
}
backMap[x][y] = foreMap[x][y]
}
- if (surfaceHeight < config.seaLevel && random.nextInt(100) < 5) {
- generateCactus(x)
+ val plant = random.nextInt(100)
+ if (surfaceHeight < config.seaLevel) {
+ if (plant < 5) {
+ generateCactus(x)
+ } else if (plant < 10) {
+ generateDeadBush(x)
+ }
}
}
private fun fillWater() {
}
}
private fun fillWater() {
- val waterId = GameItems.getBlockId("water")
+ val water = gameItemsHolder.getBlock("water")
for (x in 0 ..< config.width) {
for (y in config.seaLevel ..< config.height) {
for (x in 0 ..< config.width) {
for (y in config.seaLevel ..< config.height) {
- if (foreMap[x][y] != 0) {
+ if (foreMap[x][y] != gameItemsHolder.fallbackBlock) {
break
}
break
}
- foreMap[x][y] = waterId
+ foreMap[x][y] = water
}
}
}
private fun generateCactus(x: Int) {
}
}
}
private fun generateCactus(x: Int) {
- val cactusId = GameItems.getBlockId("cactus")
- val cactusHeight = random.nextInt(5)
+ val cactus = gameItemsHolder.getBlock("cactus")
+ val cactusHeight = random.nextInt(3)
val h = heights[x] - 1
for (y in h downTo max(0, h - cactusHeight)) {
val h = heights[x] - 1
for (y in h downTo max(0, h - cactusHeight)) {
- foreMap[x][y] = cactusId
+ foreMap[x][y] = cactus
+ }
+ }
+
+ private fun generateOak(x: Int) {
+ val log = gameItemsHolder.getBlock("log_oak")
+ val leaves = gameItemsHolder.getBlock("leaves_oak")
+ val h = heights[x] - 1
+ val treeH = random.nextInt(5, 7)
+ val height = max(0, h - treeH)
+
+ val top = height - 1
+ if (top >= 0) {
+ foreMap[x][top] = leaves
+ backMap[x][top] = leaves
+ }
+
+ for (x1 in max(0, x - 1) .. min(config.width - 1, x + 1)) {
+ for (y in height .. height + treeH - 4) {
+ foreMap[x1][y] = leaves
+ backMap[x1][y] = leaves
+ }
+ if (random.nextInt(15) < 3) {
+ foreMap[x1][heights[x1] - 1] = gameItemsHolder.getBlock(mushrooms.random(random))
+ }
+ }
+
+ for (y in h downTo height) {
+ backMap[x][y] = log
+ }
+ }
+
+ private fun generateSpruce(x: Int) {
+ val log = gameItemsHolder.getBlock("log_spruce")
+ val leaves = gameItemsHolder.getBlock("leaves_spruce")
+ val h = heights[x] - 1
+ val treeH = random.nextInt(7, 9)
+ val height = max(0, h - treeH)
+
+ val top = height - 1
+ if (top >= 0) {
+ foreMap[x][top] = leaves
+ backMap[x][top] = leaves
+ }
+
+ for (x1 in max(0, x - 1) .. min(config.width - 1, x + 1)) {
+ val y = height
+ foreMap[x1][y] = leaves
+ backMap[x1][y] = leaves
+ }
+
+ for (y in 1..2) {
+ for (x1 in max(0, x - y) .. min(config.width - 1, x + y)) {
+ foreMap[x1][height + 1 + y] = leaves
+ backMap[x1][height + 1 + y] = leaves
+ }
+ }
+
+ for (y in h downTo height) {
+ backMap[x][y] = log
+ }
+ }
+
+ private fun generateTallGrass(x: Int) {
+ val tallGrass = gameItemsHolder.getBlock(plainsPlants.random(random))
+ val h = heights[x] - 1
+ if (h > 0) {
+ foreMap[x][h] = tallGrass
+ }
+ }
+
+ private fun generateDeadBush(x: Int) {
+ val bush = gameItemsHolder.getBlock("deadbush")
+ val h = heights[x] - 1
+ if (h > 0) {
+ foreMap[x][h] = bush
+ }
+ }
+
+ private fun generateOres(x : Int) {
+ val stone = gameItemsHolder.getBlock("stone")
+ val coal = gameItemsHolder.getBlock("coal_ore")
+ val iron = gameItemsHolder.getBlock("iron_ore")
+ val gold = gameItemsHolder.getBlock("gold_ore")
+ val diamond = gameItemsHolder.getBlock("diamond_ore")
+ val lapis = gameItemsHolder.getBlock("lapis_ore")
+
+ for (y in heights[x] ..< config.height) {
+ val res = random.nextInt(10000)
+
+ val h = config.height - y
+ val block = when {
+ res in 0..<25 && h < 16 -> diamond
+ res in 25 ..< 50 && h < 32 -> gold
+ res in 50 ..< 250 && h < 64 -> iron
+ res in 250 ..< 450 && h < 128 -> coal
+ res in 450 ..< (450 + (25 - (abs(h - 16) * (25 / 16)))) -> lapis
+ else -> null
+ }
+
+ if (block != null && foreMap[x][y] == stone) {
+ foreMap[x][y] = block
+ }
}
}
/**
* Generate world
*/
}
}
/**
* Generate world
*/
- fun generate(): Pair<Array<IntArray>, Array<IntArray>> {
+ fun generate(): Pair<Array<Array<Block>>, Array<Array<Block>>> {
var biome = Biome.PLAINS
for (x in 0 until config.width) {
var biome = Biome.PLAINS
for (x in 0 until config.width) {
- val xHeight = heights[x]
biome = biomesMap[x] ?: biome
when (biome) {
Biome.PLAINS -> plainsBiome(x)
Biome.DESERT -> desertBiome(x)
biome = biomesMap[x] ?: biome
when (biome) {
Biome.PLAINS -> plainsBiome(x)
Biome.DESERT -> desertBiome(x)
+ Biome.WINTER -> winterBiome(x)
}
}
+
+ generateOres(x)
}
fillWater()
}
fillWater()