195 lines
5.7 KiB
Kotlin
195 lines
5.7 KiB
Kotlin
package ru.dbotthepony.kstarbound.world
|
|
|
|
import ru.dbotthepony.kstarbound.defs.tile.MaterialModifier
|
|
import ru.dbotthepony.kstarbound.defs.tile.TileDefinition
|
|
import ru.dbotthepony.kvector.vector.nint.Vector2i
|
|
|
|
const val CHUNK_SHIFT = 5
|
|
const val CHUNK_SIZE = 1 shl CHUNK_SHIFT // 32
|
|
|
|
const val CHUNK_SIZE_FF = CHUNK_SIZE - 1
|
|
const val CHUNK_SIZEf = CHUNK_SIZE.toFloat()
|
|
const val CHUNK_SIZEd = CHUNK_SIZE.toDouble()
|
|
|
|
interface ITileState {
|
|
val material: TileDefinition?
|
|
val modifier: MaterialModifier?
|
|
val color: Int
|
|
val hueShift: Float
|
|
val modifierHueShift: Float
|
|
}
|
|
|
|
interface IMutableTileState : ITileState {
|
|
override var material: TileDefinition?
|
|
override var modifier: MaterialModifier?
|
|
override var color: Int
|
|
override var hueShift: Float
|
|
override var modifierHueShift: Float
|
|
|
|
/**
|
|
* Выставляет hue shift как байтовое значение в диапазоне 0 .. 255
|
|
*/
|
|
fun setHueShift(value: Int) {
|
|
if (value < 0) {
|
|
hueShift = 0f
|
|
} else if (value > 255) {
|
|
hueShift = 360f
|
|
} else {
|
|
hueShift = (value / 255f) * 360f
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Выставляет hue shift как байтовое значение в диапазоне 0 .. 255
|
|
*/
|
|
fun setModifierHueShift(value: Int) {
|
|
if (value < 0) {
|
|
modifierHueShift = 0f
|
|
} else if (value > 255) {
|
|
modifierHueShift = 360f
|
|
} else {
|
|
modifierHueShift = (value / 255f) * 360f
|
|
}
|
|
}
|
|
}
|
|
|
|
interface ITileMap {
|
|
/**
|
|
* Относительная проверка находится ли координата вне границ чанка
|
|
*/
|
|
fun isOutside(x: Int, y: Int): Boolean {
|
|
return x !in 0 until CHUNK_SIZE || y !in 0 until CHUNK_SIZE
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Предоставляет интерфейс для доступа к тайлам в чанке
|
|
*/
|
|
interface ITileGetter : ITileMap {
|
|
/**
|
|
* Возвращает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
|
*/
|
|
operator fun get(x: Int, y: Int): ITileState
|
|
|
|
/**
|
|
* Возвращает тайл по ОТНОСИТЕЛЬНЫМ координатам внутри чанка
|
|
*/
|
|
operator fun get(pos: Vector2i) = get(pos.x, pos.y)
|
|
|
|
/**
|
|
* Возвращает итератор пар <Vector2i, Тайл?>
|
|
*
|
|
* Вектор имеет ОТНОСИТЕЛЬНЫЕ значения внутри самого чанка
|
|
*/
|
|
val posToTile: Iterator<Pair<Vector2i, ITileState>> get() {
|
|
return object : Iterator<Pair<Vector2i, ITileState>> {
|
|
private var x = 0
|
|
private var y = 0
|
|
|
|
private fun idx() = x + CHUNK_SIZE * y
|
|
|
|
override fun hasNext(): Boolean {
|
|
return idx() < CHUNK_SIZE * CHUNK_SIZE
|
|
}
|
|
|
|
override fun next(): Pair<Vector2i, ITileState> {
|
|
if (!hasNext()) {
|
|
throw IllegalStateException("Already iterated everything!")
|
|
}
|
|
|
|
val tile = this@ITileGetter[x, y]
|
|
val pos = Vector2i(x, y)
|
|
|
|
x++
|
|
|
|
if (x >= CHUNK_SIZE) {
|
|
y++
|
|
x = 0
|
|
}
|
|
|
|
return pos to tile
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Интерфейс предоставляет из себя описание класса, который имеет координаты чанка
|
|
*/
|
|
interface IChunkPositionable : ITileMap {
|
|
val pos: ChunkPos
|
|
|
|
/**
|
|
* Возвращает псевдослучайное Long для заданной позиции
|
|
*
|
|
* Для использования в рендерах и прочих вещах, которым нужно стабильное число на основе своей позиции
|
|
*/
|
|
fun randomLongFor(x: Int, y: Int): Long {
|
|
var long = (x or (pos.x shl CHUNK_SHIFT)) * 738548L + (y or (pos.y shl CHUNK_SHIFT)) * 2191293543L
|
|
long = long xor 8339437585692L
|
|
long = (long ushr 4) or (long shl 52)
|
|
long *= 7848344324L
|
|
long = (long ushr 12) or (long shl 44)
|
|
return long
|
|
}
|
|
|
|
/**
|
|
* Возвращает псевдослучайное нормализированное Double для заданной позиции
|
|
*
|
|
* Для использования в рендерах и прочих вещах, которым нужно стабильное число на основе своей позиции
|
|
*/
|
|
fun randomDoubleFor(x: Int, y: Int): Double {
|
|
return (randomLongFor(x, y) / 9.223372036854776E18) / 2.0 + 0.5
|
|
}
|
|
|
|
/**
|
|
* Возвращает псевдослучайное Long для заданной позиции
|
|
*
|
|
* Для использования в рендерах и прочих вещах, которым нужно стабильное число на основе своей позиции
|
|
*/
|
|
fun randomLongFor(pos: Vector2i) = randomLongFor(pos.x, pos.y)
|
|
|
|
/**
|
|
* Возвращает псевдослучайное нормализированное Double для заданной позиции
|
|
*
|
|
* Для использования в рендерах и прочих вещах, которым нужно стабильное число на основе своей позиции
|
|
*/
|
|
fun randomDoubleFor(pos: Vector2i) = randomDoubleFor(pos.x, pos.y)
|
|
}
|
|
|
|
interface ITileChunk : ITileGetter, IChunkPositionable
|
|
|
|
interface IMutableTileChunk : ITileChunk {
|
|
override fun get(x: Int, y: Int): IMutableTileState
|
|
override fun get(pos: Vector2i): IMutableTileState {
|
|
return get(pos.x, pos.y)
|
|
}
|
|
}
|
|
|
|
object EmptyTileState : IMutableTileState {
|
|
override var material: TileDefinition?
|
|
get() = null
|
|
set(value) {}
|
|
override var modifier: MaterialModifier?
|
|
get() = null
|
|
set(value) {}
|
|
override var color: Int
|
|
get() = 0
|
|
set(value) {}
|
|
override var hueShift: Float
|
|
get() = 0f
|
|
set(value) {}
|
|
override var modifierHueShift: Float
|
|
get() = 0f
|
|
set(value) {}
|
|
}
|
|
|
|
object EmptyTileChunk : IMutableTileChunk {
|
|
override val pos: ChunkPos
|
|
get() = ChunkPos.ZERO
|
|
|
|
override fun get(x: Int, y: Int): IMutableTileState {
|
|
return EmptyTileState
|
|
}
|
|
}
|