From ae078024cbb24ce3119986a9c828438ea10387d9 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Fri, 1 Sep 2023 15:51:46 +0900 Subject: [PATCH] angular modulo for wind dir --- .../terrarum/ui/BasicDebugInfoWindow.kt | 38 ++--- .../torvald/terrarum/weather/WeatherMixer.kt | 2 +- .../torvald/terrarum/weather/Weatherbox.kt | 155 ++++++++++++++++-- 3 files changed, 154 insertions(+), 41 deletions(-) diff --git a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt index 48e57847a..0a1055786 100644 --- a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt +++ b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt @@ -13,10 +13,12 @@ import net.torvald.terrarum.Terrarum.mouseTileY import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE import net.torvald.terrarum.controller.TerrarumController import net.torvald.terrarum.gameworld.GameWorld +import net.torvald.terrarum.gameworld.fmod import net.torvald.terrarum.imagefont.TinyAlphNum import net.torvald.terrarum.modulebasegame.IngameRenderer import net.torvald.terrarum.modulebasegame.TerrarumIngame import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory +import net.torvald.terrarum.weather.WeatherDirBox import net.torvald.terrarum.weather.WeatherMixer import net.torvald.terrarum.weather.WeatherStateBox import net.torvald.terrarum.worlddrawer.LightmapRenderer @@ -359,6 +361,10 @@ class BasicDebugInfoWindow : UICanvas() { private val GRAPH_CH = 100 private fun drawWeatherStateBox(batch: SpriteBatch, box: WeatherStateBox, label: String, x: Int, y: Int, ymax: Double = 1.0) { + val ymax = if (box is WeatherDirBox) 4.0 else ymax + fun Float.goff() = if (box is WeatherDirBox) this + 2.0 else this + 0.0 + fun Float.mod() = if (box is WeatherDirBox) this.plus(2f).fmod(4f).minus(2f) else this + val bw = GRAPH_CW * 3 + 1 val bh = GRAPH_CH val xw = GRAPH_CW @@ -411,28 +417,10 @@ class BasicDebugInfoWindow : UICanvas() { // here draws actual data App.shapeRender.inUse { - val pysM1 = (0 until xw).map { + val pys = (-2*xw..xw*3).map { val px = it.toFloat() / xw - bh - (bh * WeatherStateBox.interpolate(px, box.pM2, box.pM1, box.p0, box.p1) / ymax).toFloat() + bh - (bh * box.valueAt(px).goff() / ymax).toFloat() } - val pys0 = (0 until xw).map { - val px = it.toFloat() / xw - bh - (bh * WeatherStateBox.interpolate(px, box.pM1, box.p0, box.p1, box.p2) / ymax).toFloat() - } - val pys1 = (0 until xw).map { - val px = it.toFloat() / xw - bh - (bh * WeatherStateBox.interpolate(px, box.p0, box.p1, box.p2, box.p3) / ymax).toFloat() - } - val pys2 = (0 until xw).map { - val px = it.toFloat() / xw - bh - (bh * WeatherStateBox.interpolate(px, box.p1, box.p2, box.p3, box.p3) / ymax).toFloat() - } - val pys3 = (0 until xw).map { - val px = it.toFloat() / xw - bh - (bh * WeatherStateBox.interpolate(px, box.p2, box.p3, box.p3, box.p3) / ymax).toFloat() - } - val pys = pysM1 + pys0 + pys1 + pys2 + pys3 + box.p3 - // interpolated values it.color = colGraph @@ -453,11 +441,11 @@ class BasicDebugInfoWindow : UICanvas() { // graph points it.color = colGraph - if (box.x < 0.5) it.circle(x + (GRAPH_CW * 0.5f) - xi, App.scr.hf - 1 - (y + bh-(box.p0 * bh / ymax).toFloat()), 2.5f) - it.circle(x + (GRAPH_CW * 1.5f) - xi, App.scr.hf - 1 - (y + bh-(box.p1 * bh / ymax).toFloat()), 2.5f) - it.circle(x + (GRAPH_CW * 2.5f) - xi, App.scr.hf - 1 - (y + bh-(box.p2 * bh / ymax).toFloat()), 2.5f) + if (box.x < 0.5) it.circle(x + (GRAPH_CW * 0.5f) - xi, App.scr.hf - 1 - (y + bh-(box.p0.mod().goff() * bh / ymax).toFloat()), 2.5f) + it.circle(x + (GRAPH_CW * 1.5f) - xi, App.scr.hf - 1 - (y + bh-(box.p1.mod().goff() * bh / ymax).toFloat()), 2.5f) + it.circle(x + (GRAPH_CW * 2.5f) - xi, App.scr.hf - 1 - (y + bh-(box.p2.mod().goff() * bh / ymax).toFloat()), 2.5f) it.color = colGrapi - if (box.x > 0.5) it.circle(x + (GRAPH_CW * 3.5f) - xi, App.scr.hf - 1 - (y + bh-(box.p3 * bh / ymax).toFloat()), 2.5f) + if (box.x > 0.5) it.circle(x + (GRAPH_CW * 3.5f) - xi, App.scr.hf - 1 - (y + bh-(box.p3.mod().goff() * bh / ymax).toFloat()), 2.5f) } @@ -468,7 +456,7 @@ class BasicDebugInfoWindow : UICanvas() { // text batch.color = Color.WHITE - App.fontSmallNumbers.draw(batch, "$ccY$label $ccG${box.get().toDouble().toIntAndFrac(3)}", x.toFloat(), y - 14f) + App.fontSmallNumbers.draw(batch, "$ccY$label $ccG${box.value().toDouble().toIntAndFrac(3)}", x.toFloat(), y - 14f) } private val processorName = App.processor.replace(Regex(""" Processor|( CPU)? @ [0-9.]+GHz"""), "") + if (App.is32BitJVM) " (32-bit)" else "" diff --git a/src/net/torvald/terrarum/weather/WeatherMixer.kt b/src/net/torvald/terrarum/weather/WeatherMixer.kt index baf2a5fd0..54a4a9d58 100644 --- a/src/net/torvald/terrarum/weather/WeatherMixer.kt +++ b/src/net/torvald/terrarum/weather/WeatherMixer.kt @@ -248,7 +248,7 @@ internal object WeatherMixer : RNGConsumer { val currentWindSpeed = weatherbox.windSpeed.getAndUpdate( world.worldTime.timeDelta / WIND_SPEED_TIME_UNIT) { currentWeather.getRandomWindSpeed(takeUniformRand(-1f..1f)) } - val currentWindDir = weatherbox.windDir.getAndUpdate( world.worldTime.timeDelta / WIND_DIR_TIME_UNIT) { RNG.nextFloat() } * 2.0 * Math.PI + val currentWindDir = weatherbox.windDir.getAndUpdate( world.worldTime.timeDelta / WIND_DIR_TIME_UNIT) { RNG.nextFloat() * 4f } * Math.PI * 0.5 if (currentWeather.forceWindVec != null) { diff --git a/src/net/torvald/terrarum/weather/Weatherbox.kt b/src/net/torvald/terrarum/weather/Weatherbox.kt index aeed4a1f3..500ed13e0 100644 --- a/src/net/torvald/terrarum/weather/Weatherbox.kt +++ b/src/net/torvald/terrarum/weather/Weatherbox.kt @@ -1,18 +1,22 @@ package net.torvald.terrarum.weather +import net.torvald.terrarum.floorToInt +import net.torvald.terrarum.gameworld.fmod +import kotlin.math.absoluteValue + class Weatherbox { - val windDir = WeatherStateBox() // 0 .. 1.0 + val windDir = WeatherDirBox() // 0 .. 1.0 val windSpeed = WeatherStateBox() // 0 .. arbitrarily large number } -data class WeatherStateBox( - var x: Float = 0f, - var pM2: Float = 0f, - var pM1: Float = 0f, +open class WeatherStateBox( + var x: Float = 0f, + var pM2:Float = 0f, + var pM1:Float = 0f, var p0: Float = 0f, var p1: Float = 0f, var p2: Float = 0f, @@ -23,11 +27,20 @@ data class WeatherStateBox( // - removing p4 and beyond: for faster response to the changing weather schedule and make the forecasting less accurate like irl ) { - fun get() = interpolate(x, p0, p1, p2, p3) + open fun value() = interpolate(x, p0, p1, p2, p3) + open fun valueAt(x: Float) = when (x.floorToInt()) { + -2 -> interpolate(x + 2, pM2,pM1, p0, p1) + -1 -> interpolate(x + 1, pM1, p0, p1, p2) + 0 -> interpolate(x - 0, p0, p1, p2, p3) + 1 -> interpolate(x - 1, p1, p2, p3, p3) + 2 -> interpolate(x - 2, p2, p3, p3, p3) + 3 -> interpolate(x - 3, p3, p3, p3, p3) + else -> throw IllegalArgumentException() + } - fun getAndUpdate(xdelta: Float, next: () -> Float): Float { + open fun getAndUpdate(xdelta: Float, next: () -> Float): Float { synchronized(WeatherMixer.RNG) { - val y = get() + val y = value() x += xdelta while (x >= 1.0) { x -= 1.0f @@ -46,16 +59,128 @@ data class WeatherStateBox( return y } } + protected fun interpolate(u: Float, p0: Float, p1: Float, p2: Float, p3: Float): Float { + val c1: Float = p1 + val c2: Float = -0.5f * p0 + 0.5f * p2 + val c3: Float = p0 - 2.5f * p1 + 2.0f * p2 - 0.5f * p3 + val c4: Float = -0.5f * p0 + 1.5f * p1 - 1.5f * p2 + 0.5f * p3 + return (((c4 * u + c3) * u + c2) * u + c1) + } companion object { // fixed with T=0.5 - fun interpolate(u: Float, p0: Float, p1: Float, p2: Float, p3: Float): Float { - val c1: Float = p1 - val c2: Float = -0.5f * p0 + 0.5f * p2 - val c3: Float = p0 - 2.5f * p1 + 2.0f * p2 - 0.5f * p3 - val c4: Float = -0.5f * p0 + 1.5f * p1 - 1.5f * p2 + 0.5f * p3 - return (((c4 * u + c3) * u + c2) * u + c1) - } } +} + +/** + * WeatherStateBox with rotational range of -2..2 + */ +class WeatherDirBox( + x: Float = 0f, + pM2:Float = 0f, + pM1:Float = 0f, + p0: Float = 0f, + p1: Float = 0f, + p2: Float = 0f, + p3: Float = 0f, +) : WeatherStateBox(x, pM2, pM1, p0, p1, p2, p3) { + override fun value() = valueAt(x) + + override fun valueAt(x: Float): Float { + var pM2 = pM2 + var pM1 = pM1 + var p0 = p0 + var p1 = p1 + var p2 = p2 + var p3 = p3 + + if (x < -2f) { + if (pM1 - pM2 > 2f) { + pM2 -= 4f + pM1 -= 4f + p0 -= 4f + p1 -= 4f + p2 -= 4f + p3 -= 4f + } + else if (pM1 - pM2 < -2f) { + pM2 += 4f + pM1 += 4f + p0 += 4f + p1 += 4f + p2 += 4f + p3 += 4f + } + } + + if (x < -1f) { + if (pM1 - pM2 > 2f) { + pM1 -= 4f + p0 -= 4f + p1 -= 4f + p2 -= 4f + p3 -= 4f + } + else if (pM1 - pM2 < -2f) { + pM1 += 4f + p0 += 4f + p1 += 4f + p2 += 4f + p3 += 4f + } + } + + if (x < 0f) { + if (p0 - pM1 > 2f) { + p0 -= 4f + p1 -= 4f + p2 -= 4f + p3 -= 4f + } + else if (p0 - pM1 < -2f) { + p0 += 4f + p1 += 4f + p2 += 4f + p3 += 4f + } + } + + if (p1 - p0 > 2f) { + p1 -= 4f + p2 -= 4f + p3 -= 4f + } + else if (p1 - p0 < -2f) { + p1 += 4f + p2 += 4f + p3 += 4f + } + + if (p2 - p1 > 2f) { + p2 -= 4f + p3 -= 4f + } + else if (p2 - p1 < -2f) { + p2 += 4f + p3 += 4f + } + + if (p3 - p2 > 2f) { + p3 -= 4f + } + else if (p3 - p2 < -2f) { + p3 += 4f + } + + return when (x.floorToInt()) { + -2 -> interpolate(x + 2, pM2,pM1, p0, p1) + -1 -> interpolate(x + 1, pM1, p0, p1, p2) + 0 -> interpolate(x - 0, p0, p1, p2, p3) + 1 -> interpolate(x - 1, p1, p2, p3, p3) + 2 -> interpolate(x - 2, p2, p3, p3, p3) + 3 -> interpolate(x - 3, p3, p3, p3, p3) + else -> throw IllegalArgumentException() + }.plus(2f).fmod(4f).minus(2f) + } } \ No newline at end of file