Skip to content

Instantly share code, notes, and snippets.

@veiset
Last active May 27, 2022 21:02
Show Gist options
  • Save veiset/49fe3d224b10a75131ce7597ef65eb52 to your computer and use it in GitHub Desktop.
Save veiset/49fe3d224b10a75131ce7597ef65eb52 to your computer and use it in GitHub Desktop.
package org.veiset.tsar.world
import com.badlogic.gdx.math.Vector2
import org.veiset.tsar.engine2.utils.component1
import org.veiset.tsar.engine2.utils.component2
import org.veiset.tsar.engine2.utils.x
import org.veiset.tsar.world.icon.WorldIcon
import kotlin.math.absoluteValue
import kotlin.math.cos
import kotlin.math.pow
import kotlin.math.sin
import kotlin.math.sqrt
import kotlin.random.Random
data class Universe(
val seed: Long,
val numberOfTiers: Int = 25,
val removeRandomConnections: Boolean = true,
val chanceToConnect: Float = 1f,
val chanceToConnectSameTier: Float = 0.1f
) {
private val random = Random(seed)
val worlds: List<List<World>> = (0..numberOfTiers).map(::generateTier)
init {
worlds.forEachIndexed { tierIndex, tier: List<World> ->
if (worlds.size - 1 > tierIndex) {
val nextTier = worlds[tierIndex + 1]
connectEverything(tier, nextTier)
if (tierIndex > 2) {
if (removeRandomConnections) {
removeRandomConnections(tier, tierIndex)
}
addRandomNeighbourConnections(tier)
}
}
}
}
private fun connectEverything(tier: List<World>, nextTier: List<World>) {
tier.map { world ->
world.connections = nextTier
.filter { world.withinReach(it) && random.nextFloat() <= chanceToConnect }
}
}
private fun removeRandomConnections(tier: List<World>, tierIndex: Int) {
tier.shuffled(random).take(tierIndex).map {
it.connections = it.connections.shuffled(random).subList(0, (0..1).random(random))
}
}
private fun addRandomNeighbourConnections(tier: List<World>) {
tier.mapIndexed { mapIndex, world ->
val n1 = if (mapIndex - 1 < 0) tier[tier.size - 1] else tier[mapIndex - 1]
val n2 = if (mapIndex + 1 > tier.size - 1) tier[0] else tier[mapIndex + 1]
if (chanceToConnectSameTier > random.nextFloat()) {
n1.connections += world
world.connections += n1
}
if (chanceToConnectSameTier > random.nextFloat()) {
n2.connections += world
world.connections += n2
}
}
}
private fun generateTier(tier: Int): List<World> {
val maxWorlds = if (tier > 2) tier * 3 + 1 else tier * 2 + 1
val angle = 100f / maxWorlds
val halfAngle = (angle / 2.0)
return (0..(maxWorlds - 1))
.map { index ->
val rn = if (random.nextBoolean()) -1 else 1
val noise = random.nextFloat()
val randomAngle = noise * halfAngle * 0.9 * rn
val radAngle = Math.toRadians((360f / 100f) * (index * angle + randomAngle)).toFloat()
val position = Vector2(tier * cos(radAngle), tier * -sin(radAngle))
World(
tier = tier,
index = index,
size = angle,
position = position,
seed = random.nextLong(),
iconSize = 40
)
}
}
fun worldAtPosition(click: Vector2, radius: Float, size: Float): World? {
val xtier = ((click.x / radius).absoluteValue + 0.5) // optimize checking
val ytier = ((click.y / radius).absoluteValue + 0.5) // optimize checking
val tier = sqrt(xtier.pow(2) + ytier.pow(2)).toInt()
return worlds.getOrNull(tier)?.firstOrNull { it.atPosition(click, radius, size) }
}
}
data class World(
val tier: Int,
val index: Int,
val size: Float,
val position: Vector2,
val seed: Long,
val iconSize: Int = 40,
var cleared: Boolean = false,
val mapSize: Pair<Int, Int> = Pair(60, 40)
) {
var connections: List<World> = emptyList()
val icon = WorldIcon(seed, iconSize)
val monsters: Int = 10 + tier + (Random(seed).nextFloat() * 10 * tier).toInt()
fun withinReach(world: World): Boolean {
val targetPosition = world.size * world.index
val pos = index * size
val reach = size / 2f
if (pos + reach > targetPosition && pos - reach < targetPosition) {
return true
}
if (pos - reach < 0 && 100 - reach < targetPosition) {
return true
}
if (pos + reach > 100 && 100 - pos + reach > targetPosition) {
return true
}
return false
}
fun atPosition(click: Vector2, scale: Float, iconSize: Float): Boolean {
val (x, y) = (this.position.x * scale x this.position.y * scale)
val offset = iconSize / 2
return click.x in (x - offset..x + offset) && click.y in (y - offset..y + offset)
}
}

Visualisation:

https://imgur.com/Ot6UWzh

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment