MainMenu Background Map scaled to Screen and minor MapGen fixes (#7000)

* MapGenerator fixes

* MainMenu Background Map scaled to Screen

* MainMenu Background Map scaled to Screen - groupSize as public const
This commit is contained in:
SomeTroglodyte 2022-06-02 07:57:33 +02:00 committed by GitHub
parent 56f11ccdca
commit cdeabd044d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 90 additions and 36 deletions

View File

@ -10,7 +10,6 @@ import com.unciv.logic.GameInfo
import com.unciv.logic.GameStarter
import com.unciv.logic.map.MapParameters
import com.unciv.logic.map.MapShape
import com.unciv.logic.map.MapSize
import com.unciv.logic.map.MapSizeNew
import com.unciv.logic.map.MapType
import com.unciv.logic.map.mapgenerator.MapGenerator
@ -23,6 +22,7 @@ import com.unciv.ui.civilopedia.CivilopediaScreen
import com.unciv.ui.crashhandling.launchCrashHandling
import com.unciv.ui.crashhandling.postCrashHandlingRunnable
import com.unciv.ui.images.ImageGetter
import com.unciv.ui.map.TileGroupMap
import com.unciv.ui.newgamescreen.NewGameScreen
import com.unciv.ui.pickerscreens.ModManagementScreen
import com.unciv.ui.popup.*
@ -31,6 +31,8 @@ import com.unciv.ui.saves.QuickSave
import com.unciv.ui.utils.*
import com.unciv.ui.utils.UncivTooltip.Companion.addTooltip
import com.unciv.ui.worldscreen.mainmenu.WorldScreenMenuPopup
import kotlin.math.min
class MainMenuScreen: BaseScreen() {
private val backgroundTable = Table().apply { background= ImageGetter.getBackground(Color.WHITE) }
@ -76,16 +78,29 @@ class MainMenuScreen: BaseScreen() {
ImageGetter.ruleset = RulesetCache.getVanillaRuleset()
launchCrashHandling("ShowMapBackground") {
val newMap = MapGenerator(RulesetCache.getVanillaRuleset())
var scale = 1f
var mapWidth = stage.width / TileGroupMap.groupHorizontalAdvance
var mapHeight = stage.height / TileGroupMap.groupSize
if (mapWidth * mapHeight > 3000f) { // 3000 as max estimated number of tiles is arbitrary (we had typically 721 before)
scale = mapWidth * mapHeight / 3000f
mapWidth /= scale
mapHeight /= scale
scale = min(scale, 20f)
}
val mapRuleset = RulesetCache.getVanillaRuleset()
val newMap = MapGenerator(mapRuleset)
.generateMap(MapParameters().apply {
shape = MapShape.rectangular
mapSize = MapSizeNew(MapSize.Small)
mapSize = MapSizeNew(mapWidth.toInt() + 1, mapHeight.toInt() + 1)
type = MapType.default
waterThreshold = -0.055f // Gives the same level as when waterThreshold was unused in MapType.default
})
postCrashHandlingRunnable { // for GL context
ImageGetter.setNewRuleset(RulesetCache.getVanillaRuleset())
ImageGetter.setNewRuleset(mapRuleset)
val mapHolder = EditorMapHolder(this@MainMenuScreen, newMap) {}
mapHolder.setScale(scale)
backgroundTable.addAction(Actions.sequence(
Actions.fadeOut(0f),
Actions.run {

View File

@ -25,6 +25,7 @@ import kotlin.math.max
import kotlin.math.pow
import kotlin.math.roundToInt
import kotlin.math.sign
import kotlin.math.ulp
import kotlin.random.Random
@ -45,13 +46,26 @@ class MapGenerator(val ruleset: Ruleset) {
/** builds a [TerrainOccursRange] for [terrain] from a [unique] (type [UniqueType.TileGenerationConditions]) */
constructor(terrain: Terrain, unique: Unique)
: this(terrain,
unique.params[0].toFloat(), unique.params[1].toFloat(),
unique.params[2].toFloat(), unique.params[3].toFloat())
/** checks if both [temperature] and [humidity] satisfy their ranges (>From, <=To) */
unique.params[0].toFloatMakeInclusive(-1f), unique.params[1].toFloat(),
unique.params[2].toFloatMakeInclusive(0f), unique.params[3].toFloat())
/** Checks if both [temperature] and [humidity] satisfy their ranges (>From, <=To)
* Note the lowest allowed limit has been made inclusive (temp -1 nudged down by 1 [Float.ulp], humidity at 0)
*/
// Yes this does implicit conversions Float/Double
fun matches(temperature: Double, humidity: Double) =
tempFrom < temperature && temperature <= tempTo &&
humidFrom < humidity && humidity <= humidTo
companion object {
/** A [toFloat] that also nudges the value slightly down if it matches [limit] to make the resulting range inclusive on the lower end */
private fun String.toFloatMakeInclusive(limit: Float): Float {
val result = toFloat()
if (result != limit) return result
return result - result.ulp
}
}
}
private fun Terrain.getGenerationConditions() =
getMatchingUniques(UniqueType.TileGenerationConditions)
@ -463,11 +477,15 @@ class MapGenerator(val ruleset: Ruleset) {
// List is OK here as it's only sequentially scanned
val limitsMap: List<TerrainOccursRange> =
ruleset.terrains.values.flatMap {
it.getGenerationConditions()
}
ruleset.terrains.values.filter { it.type == TerrainType.Land }
.flatMap { it.getGenerationConditions() }
val noTerrainUniques = limitsMap.isEmpty()
val elevationTerrains = arrayOf(Constants.mountain, Constants.hill)
val elevationTerrains = ruleset.terrains.values.asSequence()
.filter {
it.hasUnique(UniqueType.OccursInChains)
}.mapTo(mutableSetOf()) { it.name }
if (elevationTerrains.isEmpty())
elevationTerrains.add(Constants.mountain)
for (tile in tileMap.values.asSequence()) {
if (tile.isWater || tile.baseTerrain in elevationTerrains)
@ -526,6 +544,7 @@ class MapGenerator(val ruleset: Ruleset) {
}
}
}
/**
* [MapParameters.rareFeaturesRichness] is the probability of spawning a rare feature
*/
@ -600,16 +619,21 @@ class MapGenerationRandomness {
/**
* Generates a perlin noise channel combining multiple octaves
*
* [nOctaves] is the number of octaves
* [persistence] is the scaling factor of octave amplitudes
* [lacunarity] is the scaling factor of octave frequencies
* [scale] is the distance the noise is observed from
* @param tile Source for x / x coordinates.
* @param seed Misnomer: actually the z value the Perlin cloud is 'cut' on.
* @param nOctaves is the number of octaves.
* @param persistence is the scaling factor of octave amplitudes.
* @param lacunarity is the scaling factor of octave frequencies.
* @param scale is the distance the noise is observed from.
*/
fun getPerlinNoise(tile: TileInfo, seed: Double,
nOctaves: Int = 6,
persistence: Double = 0.5,
lacunarity: Double = 2.0,
scale: Double = 10.0): Double {
fun getPerlinNoise(
tile: TileInfo,
seed: Double,
nOctaves: Int = 6,
persistence: Double = 0.5,
lacunarity: Double = 2.0,
scale: Double = 10.0
): Double {
val worldCoords = HexMath.hex2WorldCoords(tile.position)
return Perlin.noise3d(worldCoords.x.toDouble(), worldCoords.y.toDouble(), seed, nOctaves, persistence, lacunarity, scale)
}

View File

@ -25,6 +25,21 @@ class TileGroupMap<T: TileGroup>(
worldWrap: Boolean = false,
tileGroupsToUnwrap: Set<T>? = null
): Group() {
companion object {
/** Vertical size of a hex in world coordinates, or the distance between the centers of any two opposing edges
* (the hex is oriented so it has corners to the left and right of the center and its upper and lower bounds are horizontal edges) */
const val groupSize = 50f
/** Length of the diagonal of a hex, or distance between two opposing corners */
const val groupSizeDiagonal = groupSize * 1.1547005f // groupSize * sqrt(4/3)
/** Horizontal displacement per hex, meaning the increase in overall map size (in world coordinates) when adding a column.
* On the hex, this can be visualized as the horizontal distance between the leftmost corner and the
* line connecting the two corners at 2 and 4 o'clock. */
const val groupHorizontalAdvance = groupSizeDiagonal * 3 / 4
//TODO magic numbers that **seem** like they might depend on these values can be found in
// TileGroupMap.getPositionalVector, TileGroup.updateArrows, TileGroup.updateRoadImages
// and other places. I can't understand them so I'm leaving cleanup of hardcoding to someone else.
}
/** If the [act] method should be performed. If this is false, every child within this [TileGroupMap] will not get their [act] method called
* and thus not perform any [com.badlogic.gdx.scenes.scene2d.Action]s.
* Most children here already do not do anything in their [act] methods. However, even iterating through all of them */
@ -34,7 +49,6 @@ class TileGroupMap<T: TileGroup>(
private var topY = -Float.MAX_VALUE
private var bottomX = Float.MAX_VALUE
private var bottomY = Float.MAX_VALUE
private val groupSize = 50
private val mirrorTileGroups = HashMap<TileInfo, Pair<T, T>>()
init {
@ -54,8 +68,8 @@ class TileGroupMap<T: TileGroup>(
HexMath.hex2WorldCoords(tileGroup.tileInfo.position)
}
tileGroup.setPosition(positionalVector.x * 0.8f * groupSize.toFloat(),
positionalVector.y * 0.8f * groupSize.toFloat())
tileGroup.setPosition(positionalVector.x * 0.8f * groupSize,
positionalVector.y * 0.8f * groupSize)
topX =
if (worldWrap)
@ -82,12 +96,12 @@ class TileGroupMap<T: TileGroup>(
for (mirrorTiles in mirrorTileGroups.values){
val positionalVector = HexMath.hex2WorldCoords(mirrorTiles.first.tileInfo.position)
mirrorTiles.first.setPosition(positionalVector.x * 0.8f * groupSize.toFloat(),
positionalVector.y * 0.8f * groupSize.toFloat())
mirrorTiles.first.setPosition(positionalVector.x * 0.8f * groupSize,
positionalVector.y * 0.8f * groupSize)
mirrorTiles.first.moveBy(-bottomX - bottomX * 2, -bottomY )
mirrorTiles.second.setPosition(positionalVector.x * 0.8f * groupSize.toFloat(),
positionalVector.y * 0.8f * groupSize.toFloat())
mirrorTiles.second.setPosition(positionalVector.x * 0.8f * groupSize,
positionalVector.y * 0.8f * groupSize)
mirrorTiles.second.moveBy(-bottomX + bottomX * 2, -bottomY)
}
}
@ -157,21 +171,22 @@ class TileGroupMap<T: TileGroup>(
* Returns the positional coordinates of the TileGroupMap center.
*/
fun getPositionalVector(stageCoords: Vector2): Vector2 {
val trueGroupSize = 0.8f * groupSize.toFloat()
val trueGroupSize = 0.8f * groupSize
return Vector2(bottomX, bottomY)
.add(stageCoords)
.sub(groupSize.toFloat() / 2f, groupSize.toFloat() / 2f)
.sub(groupSize / 2f, groupSize / 2f)
.scl(1f / trueGroupSize)
}
fun getMirrorTiles(): HashMap<TileInfo, Pair<T, T>> = mirrorTileGroups
override fun act(delta: Float) {
if(shouldAct) {
super.act(delta)
}
}
// For debugging purposes
override fun draw(batch: Batch?, parentAlpha: Float) { super.draw(batch, parentAlpha) }
@Suppress("RedundantOverride")
override fun act(delta: Float) {
if(shouldAct) {
super.act(delta)
}
}
override fun draw(batch: Batch?, parentAlpha: Float) { super.draw(batch, parentAlpha) }
}