mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-09 01:54:04 +09:00
angular modulo for wind dir
This commit is contained in:
@@ -13,10 +13,12 @@ import net.torvald.terrarum.Terrarum.mouseTileY
|
|||||||
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
|
||||||
import net.torvald.terrarum.controller.TerrarumController
|
import net.torvald.terrarum.controller.TerrarumController
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
import net.torvald.terrarum.imagefont.TinyAlphNum
|
import net.torvald.terrarum.imagefont.TinyAlphNum
|
||||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory
|
import net.torvald.terrarum.modulebasegame.ui.ItemSlotImageFactory
|
||||||
|
import net.torvald.terrarum.weather.WeatherDirBox
|
||||||
import net.torvald.terrarum.weather.WeatherMixer
|
import net.torvald.terrarum.weather.WeatherMixer
|
||||||
import net.torvald.terrarum.weather.WeatherStateBox
|
import net.torvald.terrarum.weather.WeatherStateBox
|
||||||
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
import net.torvald.terrarum.worlddrawer.LightmapRenderer
|
||||||
@@ -359,6 +361,10 @@ class BasicDebugInfoWindow : UICanvas() {
|
|||||||
private val GRAPH_CH = 100
|
private val GRAPH_CH = 100
|
||||||
|
|
||||||
private fun drawWeatherStateBox(batch: SpriteBatch, box: WeatherStateBox, label: String, x: Int, y: Int, ymax: Double = 1.0) {
|
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 bw = GRAPH_CW * 3 + 1
|
||||||
val bh = GRAPH_CH
|
val bh = GRAPH_CH
|
||||||
val xw = GRAPH_CW
|
val xw = GRAPH_CW
|
||||||
@@ -411,28 +417,10 @@ class BasicDebugInfoWindow : UICanvas() {
|
|||||||
|
|
||||||
// here draws actual data
|
// here draws actual data
|
||||||
App.shapeRender.inUse {
|
App.shapeRender.inUse {
|
||||||
val pysM1 = (0 until xw).map {
|
val pys = (-2*xw..xw*3).map {
|
||||||
val px = it.toFloat() / xw
|
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
|
// interpolated values
|
||||||
it.color = colGraph
|
it.color = colGraph
|
||||||
@@ -453,11 +441,11 @@ class BasicDebugInfoWindow : UICanvas() {
|
|||||||
|
|
||||||
// graph points
|
// graph points
|
||||||
it.color = colGraph
|
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)
|
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 * 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 * 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
|
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
|
// text
|
||||||
batch.color = Color.WHITE
|
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 ""
|
private val processorName = App.processor.replace(Regex(""" Processor|( CPU)? @ [0-9.]+GHz"""), "") + if (App.is32BitJVM) " (32-bit)" else ""
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
val currentWindSpeed = weatherbox.windSpeed.getAndUpdate( world.worldTime.timeDelta / WIND_SPEED_TIME_UNIT) {
|
val currentWindSpeed = weatherbox.windSpeed.getAndUpdate( world.worldTime.timeDelta / WIND_SPEED_TIME_UNIT) {
|
||||||
currentWeather.getRandomWindSpeed(takeUniformRand(-1f..1f))
|
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) {
|
if (currentWeather.forceWindVec != null) {
|
||||||
|
|||||||
@@ -1,18 +1,22 @@
|
|||||||
package net.torvald.terrarum.weather
|
package net.torvald.terrarum.weather
|
||||||
|
|
||||||
|
import net.torvald.terrarum.floorToInt
|
||||||
|
import net.torvald.terrarum.gameworld.fmod
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
|
|
||||||
class Weatherbox {
|
class Weatherbox {
|
||||||
|
|
||||||
val windDir = WeatherStateBox() // 0 .. 1.0
|
val windDir = WeatherDirBox() // 0 .. 1.0
|
||||||
val windSpeed = WeatherStateBox() // 0 .. arbitrarily large number
|
val windSpeed = WeatherStateBox() // 0 .. arbitrarily large number
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
data class WeatherStateBox(
|
open class WeatherStateBox(
|
||||||
var x: Float = 0f,
|
var x: Float = 0f,
|
||||||
var pM2: Float = 0f,
|
var pM2:Float = 0f,
|
||||||
var pM1: Float = 0f,
|
var pM1:Float = 0f,
|
||||||
var p0: Float = 0f,
|
var p0: Float = 0f,
|
||||||
var p1: Float = 0f,
|
var p1: Float = 0f,
|
||||||
var p2: 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
|
// - 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) {
|
synchronized(WeatherMixer.RNG) {
|
||||||
val y = get()
|
val y = value()
|
||||||
x += xdelta
|
x += xdelta
|
||||||
while (x >= 1.0) {
|
while (x >= 1.0) {
|
||||||
x -= 1.0f
|
x -= 1.0f
|
||||||
@@ -46,16 +59,128 @@ data class WeatherStateBox(
|
|||||||
return y
|
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 {
|
companion object {
|
||||||
// fixed with T=0.5
|
// 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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user