diff --git a/src/net/torvald/terrarum/gameactors/AVKey.kt b/src/net/torvald/terrarum/gameactors/AVKey.kt index af9887730..f1ee740eb 100644 --- a/src/net/torvald/terrarum/gameactors/AVKey.kt +++ b/src/net/torvald/terrarum/gameactors/AVKey.kt @@ -58,6 +58,10 @@ object AVKey { const val LUMG = "luminositygreen" const val LUMB = "luminosityblue" const val LUMA = "luminosityuv" + const val OPAR = "opacityred" + const val OPAG = "opacitygreen" + const val OPAB = "opacityblue" + const val OPAA = "opacityuv" const val DRAGCOEFF = "dragcoeff" const val FALLDAMPENMULT = "falldampenmult" diff --git a/src/net/torvald/terrarum/gameactors/Luminous.kt b/src/net/torvald/terrarum/gameactors/Luminous.kt index 5694c5a3d..72f533c2e 100644 --- a/src/net/torvald/terrarum/gameactors/Luminous.kt +++ b/src/net/torvald/terrarum/gameactors/Luminous.kt @@ -2,37 +2,28 @@ package net.torvald.terrarum.gameactors import net.torvald.gdx.graphics.Cvec +data class Lightbox(val hitbox: Hitbox, val getLight: () -> Cvec) + /** + * For actors that either emits or blocks lights + * * Created by minjaesong on 2016-02-19. */ interface Luminous { - /** - * Range of 0.0 - 4.0 for each channel - * - * Recommended implementation: - * - override var color: Color - get() = Color( - (actorValue.getAsFloat(AVKey.LUMR) ?: 0f) / LightmapRenderer.MUL_FLOAT, - (actorValue.getAsFloat(AVKey.LUMG) ?: 0f) / LightmapRenderer.MUL_FLOAT, - (actorValue.getAsFloat(AVKey.LUMB) ?: 0f) / LightmapRenderer.MUL_FLOAT, - (actorValue.getAsFloat(AVKey.LUMA) ?: 0f) / LightmapRenderer.MUL_FLOAT, - ) - set(value) { - actorValue[AVKey.LUMR] = value.r * LightmapRenderer.MUL_FLOAT - actorValue[AVKey.LUMG] = value.g * LightmapRenderer.MUL_FLOAT - actorValue[AVKey.LUMB] = value.b * LightmapRenderer.MUL_FLOAT - actorValue[AVKey.LUMA] = value.a * LightmapRenderer.MUL_FLOAT - } - */ - var color: Cvec - /** * Arguments: * * Hitbox(x-offset, y-offset, width, height) * (Use ArrayList for normal circumstances) */ - val lightBoxList: List + val lightBoxList: List + + /** + * Arguments: + * + * Hitbox(x-offset, y-offset, width, height) + * (Use ArrayList for normal circumstances) + */ + val shadeBoxList: List } \ No newline at end of file diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/ActorHumanoid.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/ActorHumanoid.kt index c27ac77d2..ff8256212 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/ActorHumanoid.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/ActorHumanoid.kt @@ -64,7 +64,7 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L if (houseDesignation != null) houseDesignation!!.clear() } - override var color: Cvec + var actorValueColour: Cvec get() = Cvec( (actorValue.getAsFloat(AVKey.LUMR) ?: 0f), (actorValue.getAsFloat(AVKey.LUMG) ?: 0f), @@ -78,14 +78,32 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L actorValue[AVKey.LUMA] = value.a } + var actorValueShade: Cvec + get() = Cvec( + (actorValue.getAsFloat(AVKey.OPAR) ?: 0f), + (actorValue.getAsFloat(AVKey.OPAG) ?: 0f), + (actorValue.getAsFloat(AVKey.OPAB) ?: 0f), + (actorValue.getAsFloat(AVKey.OPAA) ?: 0f) + ) + set(value) { + actorValue[AVKey.OPAR] = value.r + actorValue[AVKey.OPAG] = value.g + actorValue[AVKey.OPAB] = value.b + actorValue[AVKey.OPAA] = value.a + } + /** * Arguments: * * Hitbox(x-offset, y-offset, width, height) * (Use ArrayList for normal circumstances) */ - override val lightBoxList: List - get() = arrayOf(Hitbox(2.0, 2.0, hitbox.width - 3, hitbox.height - 3)).toList() // things are asymmetric!! + override val lightBoxList: List + get() = arrayOf(Lightbox(Hitbox(2.0, 2.0, hitbox.width - 3, hitbox.height - 3)) { actorValueColour }).toList() // things are asymmetric!! + // use getter; dimension of the player may change by time. + + override val shadeBoxList: List + get() = arrayOf(Lightbox(Hitbox(2.0, 2.0, hitbox.width - 3, hitbox.height - 3)) { actorValueShade }).toList() // things are asymmetric!! // use getter; dimension of the player may change by time. @Transient val BASE_DENSITY = 980.0 diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureTikiTorch.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureTikiTorch.kt index 5c68ca83c..7bb78060e 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureTikiTorch.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureTikiTorch.kt @@ -10,6 +10,7 @@ import net.torvald.terrarum.Terrarum import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.gameactors.AVKey import net.torvald.terrarum.gameactors.Hitbox +import net.torvald.terrarum.gameactors.Lightbox import net.torvald.terrarum.gameactors.Luminous import net.torvald.terrarum.gameparticles.ParticleVanishingSprite import net.torvald.terrarum.langpack.Lang @@ -25,13 +26,14 @@ internal class FixtureTikiTorch : FixtureBase, Luminous { private val rndHash1 = rng.nextInt() private val rndHash2 = rng.nextInt() - override var color: Cvec + private var color: Cvec get() = BlockCodex[Block.TORCH].getLumCol(rndHash1, rndHash2) set(value) { throw UnsupportedOperationException() } - override val lightBoxList: ArrayList = ArrayList(1) + override val lightBoxList: ArrayList = ArrayList(1) + override val shadeBoxList: ArrayList = ArrayList(1) constructor() : super( BlockBox(BlockBox.NO_COLLISION, 1, 2), @@ -51,7 +53,7 @@ internal class FixtureTikiTorch : FixtureBase, Luminous { setHitboxDimension(16, 32, 0, 0) - lightBoxList.add(Hitbox(6.0, 5.0, 4.0, 3.0)) + lightBoxList.add(Lightbox(Hitbox(6.0, 5.0, 4.0, 3.0)) { color }) makeNewSprite(CommonResourcePool.getAsTextureRegionPack("sprites-fixtures-tiki_torch.tga")) sprite!!.setRowsAndFrames(1, 2) diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/ProjectileSimple.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/ProjectileSimple.kt index 3cbcc86e4..a3c83519b 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/ProjectileSimple.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/ProjectileSimple.kt @@ -7,13 +7,10 @@ import net.torvald.terrarum.Point2d import net.torvald.terrarum.Terrarum import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.blockproperties.BlockCodex -import net.torvald.terrarum.gameactors.ActorWithBody -import net.torvald.terrarum.gameactors.Hitbox -import net.torvald.terrarum.gameactors.Luminous -import net.torvald.terrarum.gameactors.PhysProperties import org.dyn4j.geometry.Vector2 import java.util.* import net.torvald.terrarum.* +import net.torvald.terrarum.gameactors.* /** * Simplest projectile. @@ -31,7 +28,7 @@ open class ProjectileSimple : ActorWithBody, Luminous, Projectile { var speed: Int = 0 - override var color: Cvec + private var color: Cvec get() = (bulletDatabase[type][OFFSET_LUMINOSITY] as Cvec).cpy() set(value) { } @@ -41,7 +38,8 @@ open class ProjectileSimple : ActorWithBody, Luminous, Projectile { * Hitbox(x-offset, y-offset, width, height) * (Use ArrayList for normal circumstances) */ - override val lightBoxList = ArrayList() + override val lightBoxList = ArrayList() + override val shadeBoxList = ArrayList() private val lifetimeMax = 2500 private var lifetimeCounter = 0f @@ -60,7 +58,7 @@ open class ProjectileSimple : ActorWithBody, Luminous, Projectile { setPosition(fromPoint.x, fromPoint.y) posPre = Point2d(fromPoint.x, fromPoint.y) // lightbox sized 8x8 centered to the bullet - lightBoxList.add(Hitbox(-4.0, -4.0, 8.0, 8.0)) + lightBoxList.add(Lightbox(Hitbox(-4.0, -4.0, 8.0, 8.0)) { color }) //this.externalV.set(velocity) damage = bulletDatabase[type][OFFSET_DAMAGE] as Int diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/WeaponSwung.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/WeaponSwung.kt index c272e4eb6..bde9efccf 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/WeaponSwung.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/WeaponSwung.kt @@ -1,10 +1,7 @@ package net.torvald.terrarum.modulebasegame.gameactors import net.torvald.gdx.graphics.Cvec -import net.torvald.terrarum.gameactors.ActorWithBody -import net.torvald.terrarum.gameactors.Hitbox -import net.torvald.terrarum.gameactors.Luminous -import net.torvald.terrarum.gameactors.PhysProperties +import net.torvald.terrarum.gameactors.* import net.torvald.terrarum.gameitems.ItemID /** @@ -32,7 +29,7 @@ class WeaponSwung : ActorWithBody, Luminous { actorValue[AVKey.LUMINOSITY] = value } */ - override var color: Cvec + private var color: Cvec get() = throw UnsupportedOperationException() set(value) { } @@ -42,7 +39,9 @@ class WeaponSwung : ActorWithBody, Luminous { * Hitbox(x-offset, y-offset, width, height) * (Use ArrayList for normal circumstances) */ - override val lightBoxList: List + override val lightBoxList: List + get() = throw UnsupportedOperationException() + override val shadeBoxList: List get() = throw UnsupportedOperationException() init { diff --git a/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt b/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt index 4471e8963..aded501b4 100644 --- a/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt +++ b/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt @@ -20,7 +20,6 @@ import net.torvald.terrarum.modulebasegame.ui.abs import net.torvald.terrarum.realestate.LandUtil import java.util.* import kotlin.math.roundToInt -import kotlin.system.exitProcess /** * Sub-portion of IngameRenderer. You are not supposed to directly deal with this. @@ -73,6 +72,7 @@ object LightmapRenderer { //private val noopMask = HashSet((LIGHTMAP_WIDTH + LIGHTMAP_HEIGHT) * 2) private val lanternMap = HashMap((Terrarum.ingame?.ACTORCONTAINER_INITIAL_SIZE ?: 2) * 4) + private val shadowMap = HashMap((Terrarum.ingame?.ACTORCONTAINER_INITIAL_SIZE ?: 2) * 4) private val giMap = HashMap((Terrarum.ingame?.ACTORCONTAINER_INITIAL_SIZE ?: 2) * 4) /** * Float value, 1.0 for 1023 @@ -340,12 +340,14 @@ object LightmapRenderer { private fun buildLanternmap(actorContainer: List) { lanternMap.clear() + shadowMap.clear() actorContainer.forEach { if (it is Luminous) { val lightBoxCopy = it.lightBoxList.subList(0, it.lightBoxList.size) // make copy to prevent ConcurrentModificationException + val shadeBoxCopy = it.shadeBoxList.subList(0, it.shadeBoxList.size) // make copy to prevent ConcurrentModificationException // put lanterns to the area the luminantBox is occupying - for (lightBox in lightBoxCopy) { + lightBoxCopy.forEach { (lightBox, colour) -> val lightBoxX = it.hitbox.startX + lightBox.startX val lightBoxY = it.hitbox.startY + lightBox.startY val lightBoxW = lightBox.width @@ -356,12 +358,31 @@ object LightmapRenderer { ..lightBoxX.plus(lightBoxW).div(TILE_SIZE).floorInt()) { val oldLight = lanternMap[LandUtil.getBlockAddr(world, x, y)] ?: Cvec(0) // if two or more luminous actors share the same block, mix the light - val actorLight = it.color + val actorLight = colour() lanternMap[LandUtil.getBlockAddr(world, x, y)] = oldLight.maxAndAssign(actorLight) } } } + + // put shades to the area the luminantBox is occupying + shadeBoxCopy.forEach { (shadeBox, colour) -> + val lightBoxX = it.hitbox.startX + shadeBox.startX + val lightBoxY = it.hitbox.startY + shadeBox.startY + val lightBoxW = shadeBox.width + val lightBoxH = shadeBox.height + for (y in lightBoxY.div(TILE_SIZE).floorInt() + ..lightBoxY.plus(lightBoxH).div(TILE_SIZE).floorInt()) { + for (x in lightBoxX.div(TILE_SIZE).floorInt() + ..lightBoxX.plus(lightBoxW).div(TILE_SIZE).floorInt()) { + + val oldLight = shadowMap[LandUtil.getBlockAddr(world, x, y)] ?: Cvec(0) // if two or more luminous actors share the same block, mix the light + val actorLight = colour() + + shadowMap[LandUtil.getBlockAddr(world, x, y)] = oldLight.maxAndAssign(actorLight) + } + } + } } } } @@ -464,15 +485,18 @@ object LightmapRenderer { _fluidAmountToCol.set(_thisFluid.amount, _thisFluid.amount, _thisFluid.amount, _thisFluid.amount) _thisTileLuminosity.set(_thisTerrainProp.getLumCol(worldX, worldY)) - _thisTileLuminosity.maxAndAssign(_thisFluidProp.getLumCol(worldX, worldY).mul(_fluidAmountToCol)) // already been div by four + _thisTileLuminosity.maxAndAssign(_thisFluidProp.getLumCol(worldX, worldY).mul(_fluidAmountToCol)) _mapThisTileOpacity.setVec(lx, ly, _thisTerrainProp.opacity) - _mapThisTileOpacity.max(lx, ly, _thisFluidProp.opacity.mul(_fluidAmountToCol))// already been div by four + _mapThisTileOpacity.max(lx, ly, _thisFluidProp.opacity.mul(_fluidAmountToCol)) } else { _thisTileLuminosity.set(_thisTerrainProp.getLumCol(worldX, worldY)) _mapThisTileOpacity.setVec(lx, ly, _thisTerrainProp.opacity) } + // blend shade + _mapThisTileOpacity.max(lx, ly, shadowMap[LandUtil.getBlockAddr(world, worldX, worldY)] ?: colourNull) + _mapThisTileOpacity2.setR(lx, ly, _mapThisTileOpacity.getR(lx, ly) * 1.41421356f) _mapThisTileOpacity2.setG(lx, ly, _mapThisTileOpacity.getG(lx, ly) * 1.41421356f) _mapThisTileOpacity2.setB(lx, ly, _mapThisTileOpacity.getB(lx, ly) * 1.41421356f)