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> { return object : Iterator> { private var x = fromX private var y = fromY override fun hasNext(): Boolean { return x < toX && y < toY } override fun next(): Pair { 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> { return object : Iterator> { private var x = fromX private var y = fromY override fun hasNext(): Boolean { return x < toX && y < toY } override fun next(): Pair { 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 } } }