Add celluar automica map generator.

This commit is contained in:
Duan Tao 2018-12-19 19:47:36 +08:00
parent a1a2b89949
commit c18b64f10f
3 changed files with 81 additions and 4 deletions

View File

@ -74,8 +74,12 @@ class HexMath {
return hexesToReturn
}
fun getDistance(origin: Vector2, destination: Vector2): Int { // Yes, this is a dumb implementation. But I can't be arsed to think of a better one right now, other stuff to do.
return max(abs(origin.x-destination.x),abs(origin.y-destination.y) ).toInt()
fun getDistance(origin: Vector2, destination: Vector2): Int {
val relative_x = origin.x-destination.x
val relative_y = origin.y-destination.y
if (relative_x * relative_y >= 0)
return max(abs(relative_x),abs(relative_y)).toInt()
else
return (abs(relative_x) + abs(relative_y)).toInt()
}
}

View File

@ -11,6 +11,79 @@ import java.util.*
import kotlin.collections.HashMap
import kotlin.math.ceil
class CelluarAutomataRandomMapGenerator:SeedRandomMapGenerator() {
internal val landProb = 0.55f
internal val numSmooth = 4
override fun generateMap(distance: Int): HashMap<String, TileInfo> {
val mapVectors = HexMath().getVectorsInDistance(Vector2.Zero, distance)
val landscape = HashMap<Vector2, TerrainType>()
//init
for (vector in mapVectors)
landscape[vector] = generateInitTerrain(vector, distance)
//smooth
for (loop in 0..numSmooth) {
for (vector in mapVectors) {
if (HexMath().getDistance(Vector2.Zero, vector) < distance) {
val neighborLands = HexMath().getAdjacentVectors(vector).count {landscape[it] == TerrainType.Land}
if (landscape[vector] == TerrainType.Land) {
if (neighborLands < 3)
landscape[vector] = TerrainType.Water
} else {
if (neighborLands > 3)
landscape[vector] = TerrainType.Land
}
}
else {
landscape[vector] = TerrainType.Water
}
}
}
val map = HashMap<Vector2, TileInfo>()
for (vector in mapVectors)
map[vector] = generateTile(vector,landscape[vector]!!)
divideIntoAreas(6, 0f, map)
val mapToReturn = HashMap<String, TileInfo>()
for(tile in map) {
tile.value.setTransients()
mapToReturn[tile.key.toString()] = tile.value
}
setWaterTiles(mapToReturn)
for(tile in mapToReturn.values) randomizeTile(tile,mapToReturn)
return mapToReturn
}
private fun generateInitTerrain(vector: Vector2, distance: Int): TerrainType {
var type = TerrainType.Land
if (HexMath().getDistance(Vector2.Zero, vector) > 0.9f * distance)
type = if (Random().nextDouble() < 0.1) TerrainType.Land else TerrainType.Water
else if (HexMath().getDistance(Vector2.Zero, vector) > 0.85f * distance)
type = if (Random().nextDouble() < 0.2) TerrainType.Land else TerrainType.Water
else
type = if (Random().nextDouble() < landProb) TerrainType.Land else TerrainType.Water
return type
}
private fun generateTile(vector: Vector2, type: TerrainType): TileInfo {
val tile=TileInfo()
tile.position=vector
if (type == TerrainType.Land)
tile.baseTerrain = ""
else
tile.baseTerrain = "Ocean"
return tile
}
}
class PerlinNoiseRandomMapGenerator:SeedRandomMapGenerator(){
override fun generateMap(distance: Int): HashMap<String, TileInfo> {
val map = HashMap<Vector2, TileInfo>()

View File

@ -35,7 +35,7 @@ class TileMap {
val map:HashMap<String,TileInfo>
if(mapType==NewGameScreen.NewGameParameters.MapType.WithWater)
map = PerlinNoiseRandomMapGenerator().generateMap(distance)
map = CelluarAutomataRandomMapGenerator().generateMap(distance)
else map = SeedRandomMapGenerator().generateMap(distance,0f)