mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-12 03:24:06 +09:00
CIELab and CIELch colour util
Former-commit-id: f8b0413223c2c968e4627e7c251220d32e2c6bf5 Former-commit-id: 2bce3479a8ad95ac06fbbd6c35cf73967a49568d
This commit is contained in:
99
src/net/torvald/colourutil/CIELabUtil.kt
Normal file
99
src/net/torvald/colourutil/CIELabUtil.kt
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
package net.torvald.colourutil
|
||||||
|
|
||||||
|
import com.jme3.math.FastMath
|
||||||
|
import org.newdawn.slick.Color
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RGB in this code is always sRGB.
|
||||||
|
* reference: http://www.brucelindbloom.com/index.html?Equations.html
|
||||||
|
*
|
||||||
|
* Created by minjaesong on 16-09-01.
|
||||||
|
*/
|
||||||
|
object CIELabUtil {
|
||||||
|
fun Color.brighterLab(scale: Float): Color {
|
||||||
|
val brighten = scale + 1f
|
||||||
|
|
||||||
|
val lab = this.toLab()
|
||||||
|
lab.L *= brighten
|
||||||
|
return lab.toRGB()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Color.darkerLab(scale: Float): Color {
|
||||||
|
val darken = 1f - scale
|
||||||
|
|
||||||
|
val lab = this.toLab()
|
||||||
|
lab.L *= darken
|
||||||
|
return lab.toRGB()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sweet Lab linear gradient */
|
||||||
|
fun getGradient(scale: Float, fromCol: Color, toCol: Color): Color {
|
||||||
|
val from = fromCol.toLab()
|
||||||
|
val to = toCol.toLab()
|
||||||
|
val newL = FastMath.interpolateLinear(scale, from.L, to.L)
|
||||||
|
val newA = FastMath.interpolateLinear(scale, from.a, to.a)
|
||||||
|
val newB = FastMath.interpolateLinear(scale, from.b, to.b)
|
||||||
|
val newAlpha = FastMath.interpolateLinear(scale, from.alpha, to.alpha)
|
||||||
|
|
||||||
|
return CIELab(newL, newA, newB, newAlpha).toRGB()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Color.toLab() = this.toXYZ().toLab()
|
||||||
|
private fun CIELab.toRGB() = this.toXYZ().toRGB()
|
||||||
|
|
||||||
|
fun Color.toXYZ(): CIEXYZ {
|
||||||
|
val x = 0.4124564f * r + 0.3575761f * g + 0.1804375f * b
|
||||||
|
val y = 0.2126729f * r + 0.7151522f * g + 0.0721750f * b
|
||||||
|
val z = 0.0193339f * r + 0.1191920f * g + 0.9503041f * b
|
||||||
|
|
||||||
|
return CIEXYZ(x, y, z, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun CIEXYZ.toRGB(): Color {
|
||||||
|
val r = 3.2404542f * x + -1.5371385f * y + -0.4985314f * z
|
||||||
|
val g = -0.9692660f * x + 1.8760108f * y + 0.0415560f * z
|
||||||
|
val b = 0.0556434f * x + -0.2040259f * y + 1.0572252f * z
|
||||||
|
|
||||||
|
return Color(r, g, b, alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun CIEXYZ.toLab(): CIELab {
|
||||||
|
val x = pivotXYZ(x / whitePoint.x)
|
||||||
|
val y = pivotXYZ(y / whitePoint.y)
|
||||||
|
val z = pivotXYZ(z / whitePoint.z)
|
||||||
|
|
||||||
|
val L = Math.max(0f, 116 * y - 16)
|
||||||
|
val a = 500 * (x - y)
|
||||||
|
val b = 200 * (y - z)
|
||||||
|
|
||||||
|
return CIELab(L, a, b, alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun CIELab.toXYZ(): CIEXYZ {
|
||||||
|
val y = L.plus(16).div(116f)
|
||||||
|
val x = a / 500f + y
|
||||||
|
val z = y - b / 200f
|
||||||
|
|
||||||
|
val x3 = x.cube()
|
||||||
|
val z3 = z.cube()
|
||||||
|
|
||||||
|
return CIEXYZ(
|
||||||
|
whitePoint.x * if (x3 > epsilon) x3 else (x - 16f / 116f) / 7.787f,
|
||||||
|
whitePoint.y * if (L > kappa * epsilon) (L.plus(16f) / 116f).cube() else L / kappa,
|
||||||
|
whitePoint.z * if (z3 > epsilon) z3 else (z - 16f / 116f) / 7.787f,
|
||||||
|
alpha
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun pivotXYZ(n: Float) = if (n > epsilon) n.cbrt() else (kappa * n + 16f) / 116f
|
||||||
|
|
||||||
|
val epsilon = 0.008856f
|
||||||
|
val kappa = 903.3f
|
||||||
|
val whitePoint = CIEXYZ(95.047f, 100f, 108.883f)
|
||||||
|
|
||||||
|
private fun Float.cbrt() = FastMath.pow(this, 1f / 3f)
|
||||||
|
private fun Float.cube() = this * this * this
|
||||||
|
}
|
||||||
|
|
||||||
|
data class CIEXYZ(var x: Float = 0f, var y: Float = 0f, var z: Float = 0f, val alpha: Float = 1f)
|
||||||
|
data class CIELab(var L: Float = 0f, var a: Float = 0f, var b: Float = 0f, val alpha: Float = 1f)
|
||||||
65
src/net/torvald/colourutil/CIELchUtil.kt
Normal file
65
src/net/torvald/colourutil/CIELchUtil.kt
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package net.torvald.colourutil
|
||||||
|
|
||||||
|
import com.jme3.math.FastMath
|
||||||
|
import net.torvald.colourutil.CIELabUtil.toLab
|
||||||
|
import net.torvald.colourutil.CIELabUtil.toRGB
|
||||||
|
import net.torvald.colourutil.CIELabUtil.toXYZ
|
||||||
|
import org.newdawn.slick.Color
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RGB in this code is always sRGB.
|
||||||
|
* reference: http://www.brucelindbloom.com/index.html?Equations.html
|
||||||
|
*
|
||||||
|
* Created by minjaesong on 16-09-01.
|
||||||
|
*/
|
||||||
|
|
||||||
|
object CIELchUtil {
|
||||||
|
|
||||||
|
/** Sweet Lch linear gradient */
|
||||||
|
fun getGradient(scale: Float, fromCol: Color, toCol: Color): Color {
|
||||||
|
val from = fromCol.toLch()
|
||||||
|
val to = toCol.toLch()
|
||||||
|
val newL = FastMath.interpolateLinear(scale, from.L, to.L)
|
||||||
|
val newC = FastMath.interpolateLinear(scale, from.c, to.c)
|
||||||
|
val newAlpha = FastMath.interpolateLinear(scale, from.alpha, to.alpha)
|
||||||
|
val newH: Float
|
||||||
|
|
||||||
|
if ((from.h - to.h).abs() == FastMath.PI) // exact opposite colour
|
||||||
|
return CIELabUtil.getGradient(scale, fromCol, toCol)
|
||||||
|
else if ((from.h - to.h).abs() > FastMath.PI) // reflex angle
|
||||||
|
newH = FastMath.interpolateLinear(scale, from.h, to.h + FastMath.TWO_PI)
|
||||||
|
else
|
||||||
|
newH = FastMath.interpolateLinear(scale, from.h, to.h)
|
||||||
|
|
||||||
|
return CIELch(newL, newC, newH, newAlpha).toRGB()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun CIELab.toLch(): CIELch {
|
||||||
|
val c = (a.sqr() + b.sqr()).sqrt()
|
||||||
|
val h = FastMath.atan2(b, a)
|
||||||
|
|
||||||
|
return CIELch(L, c, h, alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun CIELch.toLab(): CIELab {
|
||||||
|
val a = c * FastMath.cos(h)
|
||||||
|
val b = c * FastMath.sin(h)
|
||||||
|
|
||||||
|
return CIELab(L, a, b, alpha)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Color.toLch() = this.toXYZ().toLab().toLch()
|
||||||
|
private fun CIELch.toRGB() = this.toLab().toXYZ().toRGB()
|
||||||
|
|
||||||
|
private fun Float.sqr() = this * this
|
||||||
|
private fun Float.sqrt() = Math.sqrt(this.toDouble()).toFloat()
|
||||||
|
|
||||||
|
private fun Float.abs() = FastMath.abs(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param L : Luminosity in 0.0 - 1.0
|
||||||
|
* @param c : Chroma (saturation) in 0.0 - 1.0
|
||||||
|
* @param h : Hue in radian (-pi to pi)
|
||||||
|
*/
|
||||||
|
data class CIELch(var L: Float = 0f, var c: Float = 0f, var h: Float = 0f, var alpha: Float = 1f)
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.torvald.colourutil
|
package net.torvald.colourutil
|
||||||
|
|
||||||
|
import com.jme3.math.FastMath
|
||||||
import org.newdawn.slick.Color
|
import org.newdawn.slick.Color
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -7,4 +8,16 @@ import org.newdawn.slick.Color
|
|||||||
*/
|
*/
|
||||||
object ColourUtil {
|
object ColourUtil {
|
||||||
fun toSlickColor(r: Int, g: Int, b: Int) = Color(r.shl(16) or g.shl(8) or b)
|
fun toSlickColor(r: Int, g: Int, b: Int) = Color(r.shl(16) or g.shl(8) or b)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use CIELabUtil.getGradient for natural-looking colour
|
||||||
|
*/
|
||||||
|
fun getGradient(scale: Float, fromCol: Color, toCol: Color): Color {
|
||||||
|
val r = FastMath.interpolateLinear(scale, fromCol.r, toCol.r)
|
||||||
|
val g = FastMath.interpolateLinear(scale, fromCol.g, toCol.g)
|
||||||
|
val b = FastMath.interpolateLinear(scale, fromCol.b, toCol.b)
|
||||||
|
val a = FastMath.interpolateLinear(scale, fromCol.a, toCol.a)
|
||||||
|
|
||||||
|
return Color(r, g, b, a)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package net.torvald.colourutil
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by minjaesong on 16-03-10.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @param h : Hue 0-359
|
|
||||||
* @param s : Saturation 0-1
|
|
||||||
* @param v : Value (brightness in Adobe Photoshop(TM)) 0-1
|
|
||||||
*/
|
|
||||||
data class HSV(
|
|
||||||
var h: Float,
|
|
||||||
var s: Float,
|
|
||||||
var v: Float
|
|
||||||
)
|
|
||||||
@@ -4,6 +4,8 @@ import com.jme3.math.FastMath
|
|||||||
import org.newdawn.slick.Color
|
import org.newdawn.slick.Color
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* OBSOLETE; use CIELchUtil for natural-looking colour
|
||||||
|
*
|
||||||
* Created by minjaesong on 16-01-16.
|
* Created by minjaesong on 16-01-16.
|
||||||
*/
|
*/
|
||||||
object HSVUtil {
|
object HSVUtil {
|
||||||
@@ -20,7 +22,7 @@ object HSVUtil {
|
|||||||
* *
|
* *
|
||||||
* @link http://www.rapidtables.com/convert/color/hsv-to-rgb.htm
|
* @link http://www.rapidtables.com/convert/color/hsv-to-rgb.htm
|
||||||
*/
|
*/
|
||||||
fun toRGB(H: Float, S: Float, V: Float): Color {
|
fun toRGB(H: Float, S: Float, V: Float, alpha: Float = 1f): Color {
|
||||||
var H = H
|
var H = H
|
||||||
H %= 360f
|
H %= 360f
|
||||||
|
|
||||||
@@ -64,12 +66,11 @@ object HSVUtil {
|
|||||||
B_prime = X
|
B_prime = X
|
||||||
}
|
}
|
||||||
|
|
||||||
return Color(
|
return Color(R_prime + m, G_prime + m, B_prime + m, alpha)
|
||||||
R_prime + m, G_prime + m, B_prime + m)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toRGB(hsv: HSV): Color {
|
fun toRGB(hsv: HSV): Color {
|
||||||
return toRGB(hsv.h, hsv.s, hsv.v)
|
return toRGB(hsv.h * 360, hsv.s, hsv.v, hsv.alpha)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fromRGB(color: Color): HSV {
|
fun fromRGB(color: Color): HSV {
|
||||||
@@ -104,7 +105,14 @@ object HSVUtil {
|
|||||||
h *= 60f
|
h *= 60f
|
||||||
if (h < 0) h += 360f
|
if (h < 0) h += 360f
|
||||||
|
|
||||||
return HSV(h, s, v)
|
return HSV(h.div(360f), s, v, color.a)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param h : Hue in 0.0 - 1.0 (360 deg)
|
||||||
|
* @param s : Saturation in 0.0 - 1.0
|
||||||
|
* @param v : Value in 0.0 - 1.0
|
||||||
|
*/
|
||||||
|
data class HSV(var h: Float = 0f, var s: Float = 0f, var v: Float = 0f, var alpha: Float = 1f)
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ constructor() : BasicGameState() {
|
|||||||
// determine whether the inactive actor should be re-active
|
// determine whether the inactive actor should be re-active
|
||||||
wakeDormantActors()
|
wakeDormantActors()
|
||||||
// determine whether the actor should be active or dormant
|
// determine whether the actor should be active or dormant
|
||||||
InactivateDistantActors()
|
KillOrKnockdownActors()
|
||||||
updateActors(gc, delta)
|
updateActors(gc, delta)
|
||||||
// TODO thread pool(?)
|
// TODO thread pool(?)
|
||||||
CollisionSolver.process()
|
CollisionSolver.process()
|
||||||
@@ -424,17 +424,21 @@ constructor() : BasicGameState() {
|
|||||||
* If the actor must be dormant, the target actor will be put to the list specifically for them.
|
* If the actor must be dormant, the target actor will be put to the list specifically for them.
|
||||||
* if the actor is not to be dormant, it will be just ignored.
|
* if the actor is not to be dormant, it will be just ignored.
|
||||||
*/
|
*/
|
||||||
fun InactivateDistantActors() {
|
fun KillOrKnockdownActors() {
|
||||||
var actorContainerSize = actorContainer.size
|
var actorContainerSize = actorContainer.size
|
||||||
var i = 0
|
var i = 0
|
||||||
while (i < actorContainerSize) { // loop through actorContainer
|
while (i < actorContainerSize) { // loop through actorContainer
|
||||||
val actor = actorContainer[i]
|
val actor = actorContainer[i]
|
||||||
val actorIndex = i
|
val actorIndex = i
|
||||||
if (actor is Visible && !actor.inUpdateRange()) {
|
// kill actors flagged to despawn
|
||||||
// inactive instead of delete, if not flagged to delete
|
if (actor.flagDespawn) {
|
||||||
if (!actor.flagDespawn)
|
actorContainer.removeAt(actorIndex)
|
||||||
actorContainerInactive.add(actor) // naïve add; duplicates are checked when the actor is re-activated
|
actorContainerSize -= 1
|
||||||
|
i-- // array removed 1 elem, so we also decrement counter by 1
|
||||||
|
}
|
||||||
|
// inactivate distant actors
|
||||||
|
else if (actor is Visible && !actor.inUpdateRange()) {
|
||||||
|
actorContainerInactive.add(actor) // naïve add; duplicates are checked when the actor is re-activated
|
||||||
actorContainer.removeAt(actorIndex)
|
actorContainer.removeAt(actorIndex)
|
||||||
actorContainerSize -= 1
|
actorContainerSize -= 1
|
||||||
i-- // array removed 1 elem, so we also decrement counter by 1
|
i-- // array removed 1 elem, so we also decrement counter by 1
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ constructor(gamename: String) : StateBasedGame(gamename) {
|
|||||||
gc.graphics.clear() // clean up any 'dust' in the buffer
|
gc.graphics.clear() // clean up any 'dust' in the buffer
|
||||||
|
|
||||||
//addState(StateSplash())
|
//addState(StateSplash())
|
||||||
addState(StateMonitorCheck())
|
//addState(StateMonitorCheck())
|
||||||
//addState(StateFontTester())
|
//addState(StateFontTester())
|
||||||
ingame = StateInGame()
|
ingame = StateInGame()
|
||||||
addState(ingame)
|
addState(ingame)
|
||||||
|
|||||||
@@ -186,9 +186,9 @@ open class ActorWithBody : Actor(), Visible {
|
|||||||
|
|
||||||
@Transient internal val BASE_FRICTION = 0.3
|
@Transient internal val BASE_FRICTION = 0.3
|
||||||
|
|
||||||
@Transient val KINEMATIC = 1 // does not be budged by external forces
|
@Transient val KINEMATIC = 1 // does not displaced by external forces
|
||||||
@Transient val DYNAMIC = 2
|
@Transient val DYNAMIC = 2 // displaced by external forces
|
||||||
@Transient val STATIC = 3 // does not be budged by external forces, target of collision
|
@Transient val STATIC = 3 // does not displaced by external forces, target of collision
|
||||||
var collisionType = DYNAMIC
|
var collisionType = DYNAMIC
|
||||||
|
|
||||||
@Transient private val CCD_TICK = 1.0 / 16.0
|
@Transient private val CCD_TICK = 1.0 / 16.0
|
||||||
@@ -214,7 +214,11 @@ open class ActorWithBody : Actor(), Visible {
|
|||||||
internal var walledLeft = false
|
internal var walledLeft = false
|
||||||
internal var walledRight = false
|
internal var walledRight = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* true: This actor had just made collision
|
||||||
|
*/
|
||||||
var ccdCollided = false
|
var ccdCollided = false
|
||||||
|
private set
|
||||||
|
|
||||||
var isWalkingH = false
|
var isWalkingH = false
|
||||||
var isWalkingV = false
|
var isWalkingV = false
|
||||||
@@ -945,6 +949,8 @@ open class ActorWithBody : Actor(), Visible {
|
|||||||
assertPrinted = true
|
assertPrinted = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun flagDespawn() { flagDespawn = true }
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
@Transient private val TSIZE = MapDrawer.TILE_SIZE
|
@Transient private val TSIZE = MapDrawer.TILE_SIZE
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package net.torvald.terrarum.gameactors
|
package net.torvald.terrarum.gameactors
|
||||||
|
|
||||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
import net.torvald.colourutil.CIELabUtil.brighterLab
|
||||||
import org.dyn4j.geometry.Vector2
|
import org.dyn4j.geometry.Vector2
|
||||||
import org.newdawn.slick.Color
|
import org.newdawn.slick.Color
|
||||||
import org.newdawn.slick.GameContainer
|
import org.newdawn.slick.GameContainer
|
||||||
@@ -34,18 +34,28 @@ open class ProjectileSimple(
|
|||||||
|
|
||||||
damage = bulletDatabase[type][0] as Int
|
damage = bulletDatabase[type][0] as Int
|
||||||
displayColour = bulletDatabase[type][1] as Color
|
displayColour = bulletDatabase[type][1] as Color
|
||||||
|
|
||||||
|
collisionType = KINEMATIC
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun update(gc: GameContainer, delta: Int) {
|
override fun update(gc: GameContainer, delta: Int) {
|
||||||
// hit something and despawn! (use ```flagDespawn = true```)
|
// hit something and despawn
|
||||||
|
if (ccdCollided) flagDespawn()
|
||||||
|
|
||||||
super.update(gc, delta)
|
super.update(gc, delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun drawBody(gc: GameContainer, g: Graphics) {
|
override fun drawBody(gc: GameContainer, g: Graphics) {
|
||||||
// draw trail of solid colour (Terraria style maybe?)
|
// draw trail of solid colour (Terraria style maybe?)
|
||||||
|
g.lineWidth = 3f
|
||||||
|
g.drawGradientLine(
|
||||||
|
nextHitbox.centeredX.toFloat(),
|
||||||
|
nextHitbox.centeredY.toFloat(),
|
||||||
|
displayColour,
|
||||||
|
hitbox.centeredX.toFloat(),
|
||||||
|
hitbox.centeredY.toFloat(),
|
||||||
|
displayColour.brighterLab(0.8f)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package net.torvald.terrarum.weather
|
|||||||
|
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.JsonFetcher
|
import net.torvald.JsonFetcher
|
||||||
|
import net.torvald.colourutil.CIELchUtil
|
||||||
import net.torvald.colourutil.ColourUtil
|
import net.torvald.colourutil.ColourUtil
|
||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
@@ -108,11 +109,8 @@ object WeatherMixer {
|
|||||||
// interpolate R, G and B
|
// interpolate R, G and B
|
||||||
val scale = (timeInSec % dataPointDistance).toFloat() / dataPointDistance // [0.0, 1.0]
|
val scale = (timeInSec % dataPointDistance).toFloat() / dataPointDistance // [0.0, 1.0]
|
||||||
|
|
||||||
val r = interpolateLinear(scale, colourThis.red, colourNext.red)
|
//val newCol = ColourUtil.getGradient(scale, colourThis, colourNext)
|
||||||
val g = interpolateLinear(scale, colourThis.green, colourNext.green)
|
val newCol = CIELchUtil.getGradient(scale, colourThis, colourNext)
|
||||||
val b = interpolateLinear(scale, colourThis.blue, colourNext.blue)
|
|
||||||
|
|
||||||
val newCol = ColourUtil.toSlickColor(r, g, b)
|
|
||||||
|
|
||||||
/* // very nice monitor code
|
/* // very nice monitor code
|
||||||
// 65 -> 66 | 300 | 19623 | RGB8(255, 0, 255) -[41%]-> RGB8(193, 97, 23) | * `230`40`160`
|
// 65 -> 66 | 300 | 19623 | RGB8(255, 0, 255) -[41%]-> RGB8(193, 97, 23) | * `230`40`160`
|
||||||
@@ -127,19 +125,6 @@ object WeatherMixer {
|
|||||||
|
|
||||||
fun Color.toStringRGB() = "RGB8(${this.red}, ${this.green}, ${this.blue})"
|
fun Color.toStringRGB() = "RGB8(${this.red}, ${this.green}, ${this.blue})"
|
||||||
|
|
||||||
fun interpolateLinear(scale: Float, startValue: Int, endValue: Int): Int {
|
|
||||||
if (startValue == endValue) {
|
|
||||||
return startValue
|
|
||||||
}
|
|
||||||
if (scale <= 0f) {
|
|
||||||
return startValue
|
|
||||||
}
|
|
||||||
if (scale >= 1f) {
|
|
||||||
return endValue
|
|
||||||
}
|
|
||||||
return Math.round((1f - scale) * startValue + scale * endValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getWeatherList(classification: String) = weatherList[classification]!!
|
fun getWeatherList(classification: String) = weatherList[classification]!!
|
||||||
fun getRandomWeather(classification: String) =
|
fun getRandomWeather(classification: String) =
|
||||||
getWeatherList(classification)[HQRNG().nextInt(getWeatherList(classification).size)]
|
getWeatherList(classification)[HQRNG().nextInt(getWeatherList(classification).size)]
|
||||||
|
|||||||
Reference in New Issue
Block a user