132 lines
4.0 KiB
Kotlin
132 lines
4.0 KiB
Kotlin
package ru.dbotthepony.kstarbound.world
|
|
|
|
import ru.dbotthepony.kvector.api.IStruct2i
|
|
import ru.dbotthepony.kvector.vector.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 IChunk {
|
|
val pos: ChunkPos
|
|
|
|
// relative
|
|
fun getCell(x: Int, y: Int): IChunkCell
|
|
fun getCell(pos: IStruct2i) = getCell(pos.component1(), pos.component2())
|
|
|
|
/**
|
|
* Возвращает псевдослучайное 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)
|
|
}
|
|
|
|
// for getting tiles directly, avoiding manual layer specification
|
|
interface ITileChunk : IChunk {
|
|
// relative
|
|
fun getTile(x: Int, y: Int): ITileState
|
|
fun getTile(pos: IStruct2i) = getTile(pos.component1(), pos.component2())
|
|
}
|
|
|
|
class ForegroundView(private val parent: IChunk) : ITileChunk, IChunk by parent {
|
|
override fun getTile(x: Int, y: Int): ITileState {
|
|
return parent.getCell(x, y).foreground
|
|
}
|
|
}
|
|
|
|
class BackgroundView(private val parent: IChunk) : ITileChunk, IChunk by parent {
|
|
override fun getTile(x: Int, y: Int): ITileState {
|
|
return parent.getCell(x, y).background
|
|
}
|
|
}
|
|
|
|
fun IChunk.iterate(fromX: Int = 0, fromY: Int = 0, toX: Int = fromX + CHUNK_SIZE, toY: Int = fromY + CHUNK_SIZE): Iterator<Pair<Vector2i, IChunkCell>> {
|
|
return object : Iterator<Pair<Vector2i, IChunkCell>> {
|
|
private var x = fromX
|
|
private var y = fromY
|
|
|
|
override fun hasNext(): Boolean {
|
|
return x < toX && y < toY
|
|
}
|
|
|
|
override fun next(): Pair<Vector2i, IChunkCell> {
|
|
if (!hasNext())
|
|
throw NoSuchElementException()
|
|
|
|
val tile = getCell(x, y)
|
|
val pos = Vector2i(x, y)
|
|
|
|
x++
|
|
|
|
if (x >= toX) {
|
|
y++
|
|
x = 0
|
|
}
|
|
|
|
return pos to tile
|
|
}
|
|
}
|
|
}
|
|
|
|
fun ITileChunk.iterate(fromX: Int = 0, fromY: Int = 0, toX: Int = fromX + CHUNK_SIZE, toY: Int = fromY + CHUNK_SIZE): Iterator<Pair<Vector2i, ITileState>> {
|
|
return object : Iterator<Pair<Vector2i, ITileState>> {
|
|
private var x = fromX
|
|
private var y = fromY
|
|
|
|
override fun hasNext(): Boolean {
|
|
return x < toX && y < toY
|
|
}
|
|
|
|
override fun next(): Pair<Vector2i, ITileState> {
|
|
if (!hasNext())
|
|
throw NoSuchElementException()
|
|
|
|
val tile = getTile(x, y)
|
|
val pos = Vector2i(x, y)
|
|
|
|
x++
|
|
|
|
if (x >= toX) {
|
|
y++
|
|
x = 0
|
|
}
|
|
|
|
return pos to tile
|
|
}
|
|
}
|
|
}
|