55 lines
1.5 KiB
Kotlin
55 lines
1.5 KiB
Kotlin
package ru.dbotthepony.kstarbound.util
|
|
|
|
import ru.dbotthepony.kommons.math.linearInterpolation
|
|
import ru.dbotthepony.kstarbound.math.Interpolator
|
|
import java.util.random.RandomGenerator
|
|
|
|
data class PeriodicFunction(
|
|
val period: Double = 1.0,
|
|
val min: Double = 0.0,
|
|
val max: Double = 1.0,
|
|
val periodVariance: Double = 0.0,
|
|
val magnitudeVariance: Double = 0.0
|
|
) {
|
|
private var timer = 0.0
|
|
private var timerMax = 1.0
|
|
|
|
private var base = 0.0
|
|
private var target = 0.0
|
|
private var isDescending = false
|
|
|
|
private val halfPeriod = period * 0.5
|
|
private val halfVariance = periodVariance * 0.5
|
|
|
|
fun update(delta: Double, random: RandomGenerator) {
|
|
timer -= delta
|
|
|
|
// original code here explicitly ignore deltas bigger than max period time
|
|
// we, however, do not, if period time is big enough
|
|
while (timer <= 0.0) {
|
|
base = target
|
|
target = (if (isDescending) min else max) + if (magnitudeVariance == 0.0) 0.0 else random.nextDouble(-magnitudeVariance, magnitudeVariance)
|
|
isDescending = !isDescending
|
|
timerMax = (halfPeriod + if (halfVariance == 0.0) 0.0 else random.nextDouble(-halfVariance, halfVariance)).coerceAtLeast(0.01)
|
|
timer += timerMax
|
|
|
|
if (timerMax <= 0.05 && timer <= 0.0) {
|
|
timer = 0.0
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
fun value(interpolator: Interpolator): Double {
|
|
return interpolator.interpolate(1.0 - timer / timerMax, base, target)
|
|
}
|
|
|
|
fun value(): Double {
|
|
return value(::linearInterpolation)
|
|
}
|
|
|
|
fun sinValue(): Double {
|
|
return value(Interpolator.Sin)
|
|
}
|
|
}
|