175 lines
3.7 KiB
Kotlin
175 lines
3.7 KiB
Kotlin
package ru.dbotthepony.kstarbound.world
|
||
|
||
import ru.dbotthepony.kstarbound.math.roundByAbsoluteValue
|
||
import ru.dbotthepony.kstarbound.world.api.CHUNK_SIZE_BITS
|
||
import ru.dbotthepony.kvector.api.IStruct2d
|
||
import ru.dbotthepony.kvector.api.IStruct2i
|
||
import ru.dbotthepony.kvector.vector.Vector2i
|
||
|
||
private fun circulate(value: Int, bounds: Int): Int {
|
||
require(bounds > 0) { "Bounds must be positive ($bounds given)" }
|
||
|
||
if (value >= bounds) {
|
||
return value % bounds
|
||
} else if (value < 0) {
|
||
return bounds + value % bounds
|
||
}
|
||
|
||
return value
|
||
}
|
||
|
||
/**
|
||
* Сетка чанков идёт как и сетка тайлов.
|
||
*
|
||
* * Вправо у нас положительный X
|
||
* * Влево у нас отрицательный X
|
||
* * Вверх у нас положительный Y
|
||
* * Вниз у нас отрицательный Y
|
||
*/
|
||
class ChunkPos(val x: Int, val y: Int) : Comparable<ChunkPos> {
|
||
constructor(pos: IStruct2i) : this(pos.component1(), pos.component2())
|
||
|
||
val firstBlock get() = Vector2i(tileX, tileY)
|
||
val lastBlock get() = Vector2i(((x + 1) shl CHUNK_SIZE_BITS) - 1, ((y + 1) shl CHUNK_SIZE_BITS) - 1)
|
||
|
||
/**
|
||
* Координата тайла на 0 позиции по оси X внутри чанка в мире
|
||
*/
|
||
val tileX: Int get() = x shl CHUNK_SIZE_BITS
|
||
|
||
/**
|
||
* Координата тайла на 0 позиции по оси Y внутри чанка в мире
|
||
*/
|
||
val tileY: Int get() = y shl CHUNK_SIZE_BITS
|
||
|
||
val top: ChunkPos
|
||
get() {
|
||
return ChunkPos(x, y + 1)
|
||
}
|
||
|
||
val bottom: ChunkPos
|
||
get() {
|
||
return ChunkPos(x, y - 1)
|
||
}
|
||
|
||
val left: ChunkPos
|
||
get() {
|
||
return ChunkPos(x - 1, y)
|
||
}
|
||
|
||
val topLeft: ChunkPos
|
||
get() {
|
||
return ChunkPos(x - 1, y + 1)
|
||
}
|
||
|
||
val topRight: ChunkPos
|
||
get() {
|
||
return ChunkPos(x + 1, y + 1)
|
||
}
|
||
|
||
val bottomLeft: ChunkPos
|
||
get() {
|
||
return ChunkPos(x - 1, y - 1)
|
||
}
|
||
|
||
val bottomRight: ChunkPos
|
||
get() {
|
||
return ChunkPos(x + 1, y - 1)
|
||
}
|
||
|
||
val right: ChunkPos
|
||
get() {
|
||
return ChunkPos(x + 1, y)
|
||
}
|
||
|
||
override fun equals(other: Any?): Boolean {
|
||
if (other is ChunkPos)
|
||
return other.x == x && other.y == y
|
||
|
||
return false
|
||
}
|
||
|
||
override fun hashCode(): Int {
|
||
return (y shl 16) xor x
|
||
}
|
||
|
||
override fun toString(): String {
|
||
return "ChunkPos[$x $y]"
|
||
}
|
||
|
||
override fun compareTo(other: ChunkPos): Int {
|
||
if (x > other.x) {
|
||
return 1
|
||
} else if (x < other.x) {
|
||
return -1
|
||
}
|
||
|
||
return y.compareTo(other.y)
|
||
}
|
||
|
||
fun circular(xWrap: Int): ChunkPos {
|
||
val x = circulate(x, xWrap)
|
||
|
||
if (x == this.x) {
|
||
return this
|
||
}
|
||
|
||
return ChunkPos(x, y)
|
||
}
|
||
|
||
fun toLong(): Long {
|
||
return toLong(x, y)
|
||
}
|
||
|
||
companion object {
|
||
val ZERO = ChunkPos(0, 0)
|
||
|
||
fun toLong(x: Int, y: Int): Long {
|
||
return x.toLong() or (y.toLong() shl 32)
|
||
}
|
||
|
||
fun longFromPosition(x: Int, y: Int): Long {
|
||
return toLong(component(x), component(y))
|
||
}
|
||
|
||
fun fromPosition(input: IStruct2i): ChunkPos {
|
||
val (x, y) = input
|
||
return ChunkPos(component(x), component(y))
|
||
}
|
||
|
||
fun fromPosition(input: IStruct2d): ChunkPos {
|
||
val (x, y) = input
|
||
return fromPosition(x, y)
|
||
}
|
||
|
||
fun fromPosition(x: Int, y: Int): ChunkPos {
|
||
return ChunkPos(component(x), component(y))
|
||
}
|
||
|
||
fun fromPosition(x: Int, y: Int, xWrap: Int): ChunkPos {
|
||
return ChunkPos(circulate(component(x), xWrap), component(y))
|
||
}
|
||
|
||
fun fromPosition(x: Double, y: Double): ChunkPos {
|
||
return ChunkPos(
|
||
component(roundByAbsoluteValue(x)),
|
||
component(roundByAbsoluteValue(y))
|
||
)
|
||
}
|
||
|
||
fun fromPosition(x: Double, y: Double, xWrap: Int): ChunkPos {
|
||
return ChunkPos(
|
||
circulate(component(roundByAbsoluteValue(x)), xWrap),
|
||
component(roundByAbsoluteValue(y))
|
||
)
|
||
}
|
||
|
||
fun component(value: Int): Int {
|
||
if (value < 0) {
|
||
return -((-value) shr CHUNK_SIZE_BITS) - 1
|
||
}
|
||
|
||
return value shr CHUNK_SIZE_BITS
|
||
}
|
||
}
|
||
} |