From 924c7db5eb7d79720557b2b94cd4e78d955e2ff8 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Mon, 3 Jul 2017 23:42:59 +0900 Subject: [PATCH] dunno why but setting camera position to negative works... --- src/net/torvald/point/Point2d.kt | 3 +- src/net/torvald/terrarum/StateInGameGDX.kt | 33 ++++++--- src/net/torvald/terrarum/gameactors/Hitbox.kt | 6 +- .../gameactors/PlayableActorDelegate.kt | 15 ++++ .../gameactors/PlayerBuilderSigrid.kt | 2 +- .../terrarum/ui/BasicDebugInfoWindow.kt | 10 +-- src/net/torvald/terrarum/ui/UIHandler.kt | 4 +- src/net/torvald/terrarum/ui/UIQuickBar.kt | 1 + .../terrarum/worlddrawer/BlocksDrawer_old.kt | 39 +++++----- .../terrarum/worlddrawer/LightmapRenderer.kt | 71 +++++++++---------- 10 files changed, 112 insertions(+), 72 deletions(-) diff --git a/src/net/torvald/point/Point2d.kt b/src/net/torvald/point/Point2d.kt index 0bdfddfba..9d653f6da 100644 --- a/src/net/torvald/point/Point2d.kt +++ b/src/net/torvald/point/Point2d.kt @@ -7,7 +7,7 @@ import org.dyn4j.geometry.Vector2 /** * Created by minjaesong on 16-01-15. */ -class Point2d(var x: Double, var y: Double) : Cloneable { +data class Point2d(var x: Double, var y: Double) : Cloneable { override fun toString(): String { return "($x, $y)" @@ -53,4 +53,5 @@ class Point2d(var x: Double, var y: Double) : Cloneable { fun length(other: Point2d) = distSqr(other).sqrt() fun distSqr(other: Point2d) = ((this.x - other.x).sqr() + (this.y - other.y).sqr()) + } diff --git a/src/net/torvald/terrarum/StateInGameGDX.kt b/src/net/torvald/terrarum/StateInGameGDX.kt index fd93decd4..d6ff1fef7 100644 --- a/src/net/torvald/terrarum/StateInGameGDX.kt +++ b/src/net/torvald/terrarum/StateInGameGDX.kt @@ -73,7 +73,6 @@ class StateInGameGDX(val batch: SpriteBatch) : Screen { val ZOOM_MIN = 0.5f var worldDrawFrameBuffer = FrameBuffer(Pixmap.Format.RGBA8888, Gdx.graphics.width.div(ZOOM_MIN).ceilInt(), Gdx.graphics.height.div(ZOOM_MIN).ceilInt(), false) - //var backDrawFrameBuffer = FrameBuffer(Pixmap.Format.RGBA8888, Gdx.graphics.width, Gdx.graphics.height, false) //private lateinit var shader12BitCol: Shader // grab LibGDX if you want some shader //private lateinit var shaderBlur: Shader @@ -265,7 +264,11 @@ class StateInGameGDX(val batch: SpriteBatch) : Screen { ) uiAlasesPausing.forEach { addUI(it) } // put them all to the UIContainer uiAliases.forEach { addUI(it) } // put them all to the UIContainer - } + + + + LightmapRenderer.fireRecalculateEvent() + }// END enter /////////////// @@ -379,7 +382,6 @@ class StateInGameGDX(val batch: SpriteBatch) : Screen { // Post-update; ones that needs everything is completed // - LightmapRenderer.renderLightMap() // FeaturesDrawer.render(batch) // // end of post-update // @@ -387,9 +389,11 @@ class StateInGameGDX(val batch: SpriteBatch) : Screen { // now the actual drawing part // worldDrawFrameBuffer.inAction { batch.inUse { + // using custom code; this is obscure and tricky camera.position.set(WorldCamera.gdxCamX, WorldCamera.gdxCamY, 0f) // make camara work camera.update() batch.projectionMatrix = camera.combined + batch.color = Color.WHITE blendNormal() @@ -423,6 +427,7 @@ class StateInGameGDX(val batch: SpriteBatch) : Screen { blendNormal() else blendMul() + LightmapRenderer.fireRecalculateEvent() LightmapRenderer.draw(batch) @@ -806,20 +811,25 @@ class StateInGameGDX(val batch: SpriteBatch) : Screen { } ThreadParallel.startAll() + + playableActorDelegate?.update(delta) } else { actorContainer.forEach { - it.update(delta) + if (it != playableActorDelegate?.actor) { + it.update(delta) - if (it is Pocketed) { - it.inventory.forEach { inventoryEntry -> - inventoryEntry.item.effectWhileInPocket(delta) - if (it.equipped(inventoryEntry.item)) { - inventoryEntry.item.effectWhenEquipped(delta) + if (it is Pocketed) { + it.inventory.forEach { inventoryEntry -> + inventoryEntry.item.effectWhileInPocket(delta) + if (it.equipped(inventoryEntry.item)) { + inventoryEntry.item.effectWhenEquipped(delta) + } } } } } + playableActorDelegate?.update(delta) //AmmoMeterProxy(player!!, uiVitalItem.UI as UIVitalMetre) } } @@ -1085,6 +1095,9 @@ class StateInGameGDX(val batch: SpriteBatch) : Screen { // Set up viewport when window is resized initViewPort(width, height) + + + LightmapRenderer.fireRecalculateEvent() } override fun dispose() { @@ -1098,7 +1111,7 @@ class StateInGameGDX(val batch: SpriteBatch) : Screen { * Camera will be moved so that (newX, newY) would be sit on the top-left edge. */ fun setCameraPosition(newX: Float, newY: Float) { - camera.position.set(newX + TerrarumGDX.HALFW, newY + TerrarumGDX.HALFH, 0f) + camera.position.set(-newX + TerrarumGDX.HALFW, -newY + TerrarumGDX.HALFH, 0f) camera.update() batch.projectionMatrix = camera.combined } diff --git a/src/net/torvald/terrarum/gameactors/Hitbox.kt b/src/net/torvald/terrarum/gameactors/Hitbox.kt index 354529a41..17e45cd4d 100644 --- a/src/net/torvald/terrarum/gameactors/Hitbox.kt +++ b/src/net/torvald/terrarum/gameactors/Hitbox.kt @@ -14,7 +14,7 @@ class Hitbox(x1: Double, y1: Double, width: Double, height: Double) { @Volatile var hitboxStart: Point2d private set - val hitboxEnd: Point2d + inline val hitboxEnd: Point2d get() = Point2d(hitboxStart.x + width, hitboxStart.y + height) var width: Double = 0.0 private set @@ -135,4 +135,8 @@ class Hitbox(x1: Double, y1: Double, width: Double, height: Double) { operator fun minus(other: Hitbox): Vector2 { return Vector2(other.centeredX - this.centeredX, other.centeredY - this.centeredY) } + + override fun equals(other: Any?): Boolean { + return this.hitboxStart == (other as Hitbox).hitboxStart && this.hitboxEnd == (other as Hitbox).hitboxEnd + } } diff --git a/src/net/torvald/terrarum/gameactors/PlayableActorDelegate.kt b/src/net/torvald/terrarum/gameactors/PlayableActorDelegate.kt index fd976bda2..45d0ef606 100644 --- a/src/net/torvald/terrarum/gameactors/PlayableActorDelegate.kt +++ b/src/net/torvald/terrarum/gameactors/PlayableActorDelegate.kt @@ -1,5 +1,7 @@ package net.torvald.terrarum.gameactors +import net.torvald.terrarum.worlddrawer.LightmapRenderer + /** * A wrapper to support instant player changing (or possessing other NPCs maybe) * @@ -13,4 +15,17 @@ class PlayableActorDelegate(val actor: ActorHumanoid) { throw IllegalArgumentException("Player must be 'Controllable'!") } + + fun update(delta: Float) { + //val oldTilewisePos = actor.tilewiseHitbox + + actor.update(delta) + + // fire lightmap recalculate event upon tilewise pos change + //val newTilewisePos = actor.tilewiseHitbox + //if (oldTilewisePos != newTilewisePos) { + // LightmapRenderer.fireRecalculateEvent() + //} + // not going to work: think about stationery tiki torches, global lights, etc + } } \ No newline at end of file diff --git a/src/net/torvald/terrarum/gameactors/PlayerBuilderSigrid.kt b/src/net/torvald/terrarum/gameactors/PlayerBuilderSigrid.kt index 8796cf0f0..4f0dc53c7 100644 --- a/src/net/torvald/terrarum/gameactors/PlayerBuilderSigrid.kt +++ b/src/net/torvald/terrarum/gameactors/PlayerBuilderSigrid.kt @@ -32,7 +32,7 @@ object PlayerBuilderSigrid { p.actorValue[AVKey.SPEEDBUFF] = 1.0 p.actorValue[AVKey.ACCEL] = ActorHumanoid.WALK_ACCEL_BASE p.actorValue[AVKey.ACCELBUFF] = 1.0 - p.actorValue[AVKey.JUMPPOWER] = 9.0 + p.actorValue[AVKey.JUMPPOWER] = 8.0 p.actorValue[AVKey.BASEMASS] = 80.0 p.actorValue[AVKey.SCALEBUFF] = 1.0 // Constant 1.0 for player, meant to be used by random mobs diff --git a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt index bd8b710d8..e158142d2 100644 --- a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt +++ b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt @@ -207,9 +207,9 @@ class BasicDebugInfoWindow : UICanvas { private fun drawHistogram(batch: SpriteBatch, histogram: LightmapRenderer.Histogram, x: Int, y: Int) { val uiColour = Color(0x000000_80.toInt()) - val barR = Color(0xDD0000_FF.toInt()) - val barG = Color(0x00DD00_FF.toInt()) - val barB = Color(0x0000DD_FF.toInt()) + val barR = Color(0xFF0000_FF.toInt()) + val barG = Color(0x00FF00_FF.toInt()) + val barB = Color(0x0000FF_FF.toInt()) val barColour = arrayOf(barR, barG, barB) val w = histogramW.toFloat() val h = histogramH.toFloat() @@ -223,7 +223,7 @@ class BasicDebugInfoWindow : UICanvas { TerrarumGDX.fontSmallNumbers.draw(batch, "255", x.toFloat() + w + 1 - 8*3, y.toFloat() + h + 2) TerrarumGDX.fontSmallNumbers.draw(batch, "Histogramme", x + w / 2 - 5.5f * 8, y.toFloat() + h + 2) - //blendScreen() + blendScreen() for (c in 0..2) { for (i in 0..255) { var histogram_value = if (i == 255) 0 else histogram.get(c)[i] @@ -242,7 +242,7 @@ class BasicDebugInfoWindow : UICanvas { batch.fillRect(bar_x, bar_y, bar_w, bar_h) } } - //blendNormal() + blendNormal() } private fun drawGamepadAxis(batch: SpriteBatch, axisX: Float, axisY: Float, uiX: Int, uiY: Int) { diff --git a/src/net/torvald/terrarum/ui/UIHandler.kt b/src/net/torvald/terrarum/ui/UIHandler.kt index 1a3182f6c..ec7efc631 100644 --- a/src/net/torvald/terrarum/ui/UIHandler.kt +++ b/src/net/torvald/terrarum/ui/UIHandler.kt @@ -18,7 +18,7 @@ import net.torvald.terrarum.gamecontroller.KeyToggler class UIHandler(val UI: UICanvas, val toggleKey: Int? = null, val toggleButton: Int? = null, // UI positions itself? (you must g.flush() yourself after the g.translate(Int, Int)) - var customPositioning: Boolean = false, + var customPositioning: Boolean = false, // mainly used by vital meter val doNotWarnConstant: Boolean = false ) { @@ -141,7 +141,7 @@ class UIHandler(val UI: UICanvas, if (!customPositioning) TerrarumGDX.ingame?.setCameraPosition(posX.toFloat(), posY.toFloat()) batch.color = Color.WHITE - + UI.render(batch) //ingameGraphics.flush() } diff --git a/src/net/torvald/terrarum/ui/UIQuickBar.kt b/src/net/torvald/terrarum/ui/UIQuickBar.kt index cb29c05e4..ec2f405c2 100644 --- a/src/net/torvald/terrarum/ui/UIQuickBar.kt +++ b/src/net/torvald/terrarum/ui/UIQuickBar.kt @@ -34,6 +34,7 @@ class UIQuickBar : UICanvas, MouseControlled { } override fun render(batch: SpriteBatch) { + for (i in 0..SLOT_COUNT - 1) { val image = if (i == selection) ItemSlotImageBuilder.produceLarge(false, i + 1) diff --git a/src/net/torvald/terrarum/worlddrawer/BlocksDrawer_old.kt b/src/net/torvald/terrarum/worlddrawer/BlocksDrawer_old.kt index a68640846..8eae9eb81 100644 --- a/src/net/torvald/terrarum/worlddrawer/BlocksDrawer_old.kt +++ b/src/net/torvald/terrarum/worlddrawer/BlocksDrawer_old.kt @@ -407,14 +407,14 @@ object BlocksDrawer { val for_x_start = x / TILE_SIZE - 1 val for_x_end = for_x_start + (width / TILE_SIZE) + 3 - var zeroTileCounter = 0 - val originalBatchColour = batch.color.cpy() batch.color = color // loop for (y in for_y_start..for_y_end) { - for (x in for_x_start..for_x_end - 1) { + var zeroTileCounter = 0 + + for (x in for_x_start..for_x_end) { val thisTile: Int? if (mode % 3 == WALL) @@ -440,11 +440,13 @@ object BlocksDrawer { LightmapRenderer.getHighestRGB(x - 1, y - 1) ?: 0 >= tileDrawLightThreshold || LightmapRenderer.getHighestRGB(x + 1, y + 1) ?: 0 >= tileDrawLightThreshold || LightmapRenderer.getHighestRGB(x + 1, y - 1) ?: 0 >= tileDrawLightThreshold || - LightmapRenderer.getHighestRGB(x - 1, y + 1) ?: 0 >= tileDrawLightThreshold) { - // blackness + LightmapRenderer.getHighestRGB(x - 1, y + 1) ?: 0 >= tileDrawLightThreshold) + { + // TODO coalesce non-lit black patches if (zeroTileCounter > 0) { - /* unable to do anything */ - + batch.color = Color.BLACK + batch.fillRect(x * TILE_SIZEF, y * TILE_SIZEF, -zeroTileCounter * TILE_SIZEF, TILE_SIZEF) + batch.color = color zeroTileCounter = 0 } @@ -505,17 +507,22 @@ object BlocksDrawer { } // end if (is illuminated) // draw black patch else { - zeroTileCounter++ // unused for now - - batch.color = Color.BLACK - drawTile(batch, mode, x, y, 1, 0) - batch.color = color + zeroTileCounter += 1 // unused for now } } // end if (not an air) } catch (e: NullPointerException) { // do nothing. WARNING: This exception handling may hide erratic behaviour completely. } + + // hit the end of the current scanline + // FIXME bad scanlines bug + if (x == for_x_end) { + batch.color = Color.BLACK + batch.fillRect(x * TILE_SIZEF, y * TILE_SIZEF, -zeroTileCounter * TILE_SIZEF, TILE_SIZEF) + batch.color = color + zeroTileCounter = 0 + } } } @@ -650,14 +657,14 @@ object BlocksDrawer { if (mode == TERRAIN || mode == WALL) batch.draw( tilesTerrain.get(sheetX, sheetY), - (tilewisePosX * TILE_SIZE).toFloat(), - (tilewisePosY * TILE_SIZE).toFloat() + tilewisePosX * TILE_SIZEF, + tilewisePosY * TILE_SIZEF ) else if (mode == WIRE) batch.draw( tilesWire.get(sheetX, sheetY), - (tilewisePosX * TILE_SIZE).toFloat(), - (tilewisePosY * TILE_SIZE).toFloat() + tilewisePosX * TILE_SIZEF, + tilewisePosY * TILE_SIZEF ) else throw IllegalArgumentException() diff --git a/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt b/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt index 1f3861d9b..c4b595462 100644 --- a/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt +++ b/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt @@ -85,7 +85,7 @@ object LightmapRenderer { } } - fun renderLightMap() { + fun fireRecalculateEvent() { for_x_start = WorldCamera.x / TILE_SIZE - 1 // fix for premature lightmap rendering for_y_start = WorldCamera.y / TILE_SIZE - 1 // on topmost/leftmost side @@ -244,6 +244,8 @@ object LightmapRenderer { // O(9n) == O(n) where n is a size of the map // TODO devise multithreading on this + var ambientAccumulator = 0 + var lightLevelThis: Int = 0 val thisTerrain = TerrarumGDX.ingame!!.world.getTileFromTerrain(x, y) val thisWall = TerrarumGDX.ingame!!.world.getTileFromWall(x, y) @@ -281,16 +283,17 @@ object LightmapRenderer { * sample ambient for eight points and apply attenuation for those * maxblend eight values and use it */ - var ambient = 0 - /* + */ambient = ambient maxBlend darkenColoured(getLight(x - 1, y - 1) ?: 0, scaleColour(thisTileOpacity, 1.4142f)) - /* + */ambient = ambient maxBlend darkenColoured(getLight(x + 1, y - 1) ?: 0, scaleColour(thisTileOpacity, 1.4142f)) - /* + */ambient = ambient maxBlend darkenColoured(getLight(x - 1, y + 1) ?: 0, scaleColour(thisTileOpacity, 1.4142f)) - /* + */ambient = ambient maxBlend darkenColoured(getLight(x + 1, y + 1) ?: 0, scaleColour(thisTileOpacity, 1.4142f)) - /* * */ambient = ambient maxBlend darkenColoured(getLight(x , y - 1) ?: 0, thisTileOpacity) - /* * */ambient = ambient maxBlend darkenColoured(getLight(x , y + 1) ?: 0, thisTileOpacity) - /* * */ambient = ambient maxBlend darkenColoured(getLight(x - 1, y ) ?: 0, thisTileOpacity) - /* * */ambient = ambient maxBlend darkenColoured(getLight(x + 1, y ) ?: 0, thisTileOpacity) - return lightLevelThis maxBlend ambient + /* + */ambientAccumulator = ambientAccumulator maxBlend darkenColoured(getLight(x - 1, y - 1) ?: 0, scaleColour(thisTileOpacity, 1.4142f)) + /* + */ambientAccumulator = ambientAccumulator maxBlend darkenColoured(getLight(x + 1, y - 1) ?: 0, scaleColour(thisTileOpacity, 1.4142f)) + /* + */ambientAccumulator = ambientAccumulator maxBlend darkenColoured(getLight(x - 1, y + 1) ?: 0, scaleColour(thisTileOpacity, 1.4142f)) + /* + */ambientAccumulator = ambientAccumulator maxBlend darkenColoured(getLight(x + 1, y + 1) ?: 0, scaleColour(thisTileOpacity, 1.4142f)) + + /* * */ambientAccumulator = ambientAccumulator maxBlend darkenColoured(getLight(x , y - 1) ?: 0, thisTileOpacity) + /* * */ambientAccumulator = ambientAccumulator maxBlend darkenColoured(getLight(x , y + 1) ?: 0, thisTileOpacity) + /* * */ambientAccumulator = ambientAccumulator maxBlend darkenColoured(getLight(x - 1, y ) ?: 0, thisTileOpacity) + /* * */ambientAccumulator = ambientAccumulator maxBlend darkenColoured(getLight(x + 1, y ) ?: 0, thisTileOpacity) + + return lightLevelThis maxBlend ambientAccumulator } else { return lightLevelThis @@ -457,19 +460,15 @@ object LightmapRenderer { // use equation with magic number 8.0 // should draw somewhat exponential curve when you plot the propagation of light in-game - val r = data.r() * (1f - darken.r() * lightScalingMagic) - val g = data.g() * (1f - darken.g() * lightScalingMagic) - val b = data.b() * (1f - darken.b() * lightScalingMagic) - - return constructRGBFromFloat(r.clampZero(), g.clampZero(), b.clampZero()) + return ((data.r() * (1f - darken.r() * lightScalingMagic)).clampZero() * CHANNEL_MAX).round() * MUL_2 + + ((data.g() * (1f - darken.g() * lightScalingMagic)).clampZero() * CHANNEL_MAX).round() * MUL + + ((data.b() * (1f - darken.b() * lightScalingMagic)).clampZero() * CHANNEL_MAX).round() } fun scaleColour(data: Int, scale: Float): RGB10 { - val r = data.r() * scale - val g = data.g() * scale - val b = data.b() * scale - - return constructRGBFromFloat(r.clampOne(), g.clampOne(), b.clampOne()) + return ((data.r() * scale).clampOne() * CHANNEL_MAX).round() * MUL_2 + + ((data.g() * scale).clampOne() * CHANNEL_MAX).round() * MUL + + ((data.b() * scale).clampOne() * CHANNEL_MAX).round() } /** @@ -557,38 +556,38 @@ object LightmapRenderer { * @param rgb2 * @return */ - private inline infix fun RGB10.maxBlend(other: Int): RGB10 { + private infix fun RGB10.maxBlend(other: Int): RGB10 { return (if (this.rawR() > other.rawR()) this.rawR() else other.rawR()) * MUL_2 + (if (this.rawG() > other.rawG()) this.rawG() else other.rawG()) * MUL + (if (this.rawB() > other.rawB()) this.rawB() else other.rawB()) } - private inline infix fun RGB10.linMix(other: Int): RGB10 { + private infix fun RGB10.linMix(other: Int): RGB10 { return ((this.rawR() + other.rawR()) ushr 1) * MUL_2 + ((this.rawG() + other.rawG()) ushr 1) * MUL + ((this.rawB() + other.rawB()) ushr 1) } - private inline infix fun RGB10.colSub(other: Int): RGB10 { + private infix fun RGB10.colSub(other: Int): RGB10 { return ((this.rawR() - other.rawR()).clampChannel()) * MUL_2 + ((this.rawG() - other.rawG()).clampChannel()) * MUL + ((this.rawB() - other.rawB()).clampChannel()) } - private inline infix fun RGB10.colAdd(other: Int): RGB10 { + private infix fun RGB10.colAdd(other: Int): RGB10 { return ((this.rawR() + other.rawR()).clampChannel()) * MUL_2 + ((this.rawG() + other.rawG()).clampChannel()) * MUL + ((this.rawB() + other.rawB()).clampChannel()) } - inline fun RGB10.rawR() = this / MUL_2 - inline fun RGB10.rawG() = this % MUL_2 / MUL - inline fun RGB10.rawB() = this % MUL + fun RGB10.rawR() = this / MUL_2 + fun RGB10.rawG() = this % MUL_2 / MUL + fun RGB10.rawB() = this % MUL /** 0.0 - 1.0 for 0-1023 (0.0 - 0.25 for 0-255) */ - inline fun RGB10.r(): Float = this.rawR() / CHANNEL_MAX_FLOAT - inline fun RGB10.g(): Float = this.rawG() / CHANNEL_MAX_FLOAT - inline fun RGB10.b(): Float = this.rawB() / CHANNEL_MAX_FLOAT + fun RGB10.r(): Float = this.rawR() / CHANNEL_MAX_FLOAT + fun RGB10.g(): Float = this.rawG() / CHANNEL_MAX_FLOAT + fun RGB10.b(): Float = this.rawB() / CHANNEL_MAX_FLOAT /** @@ -631,11 +630,11 @@ object LightmapRenderer { (b * CHANNEL_MAX).round() } - inline fun Int.clampZero() = if (this < 0) 0 else this - inline fun Float.clampZero() = if (this < 0) 0f else this - inline fun Int.clampChannel() = if (this < 0) 0 else if (this > CHANNEL_MAX) CHANNEL_MAX else this - inline fun Float.clampOne() = if (this < 0) 0f else if (this > 1) 1f else this - inline fun Float.clampChannel() = if (this > CHANNEL_MAX_DECIMAL) CHANNEL_MAX_DECIMAL else this + fun Int.clampZero() = if (this < 0) 0 else this + fun Float.clampZero() = if (this < 0) 0f else this + fun Int.clampChannel() = if (this < 0) 0 else if (this > CHANNEL_MAX) CHANNEL_MAX else this + fun Float.clampOne() = if (this < 0) 0f else if (this > 1) 1f else this + fun Float.clampChannel() = if (this > CHANNEL_MAX_DECIMAL) CHANNEL_MAX_DECIMAL else this inline fun getValueFromMap(x: Int, y: Int): Int? = getLight(x, y) fun getHighestRGB(x: Int, y: Int): Int? {