diff --git a/src/net/torvald/terrarum/IngameInstance.kt b/src/net/torvald/terrarum/IngameInstance.kt index d62e5503b..789751926 100644 --- a/src/net/torvald/terrarum/IngameInstance.kt +++ b/src/net/torvald/terrarum/IngameInstance.kt @@ -71,9 +71,9 @@ open class IngameInstance(val batch: SpriteBatch) : Screen { val actorContainerInactive = SortedArrayList(ACTORCONTAINER_INITIAL_SIZE) // FIXME queues will not work; input processing (blocks will queue) and queue consuming cannot be synchronised - protected val terrainChangeQueue = ArrayList() - protected val wallChangeQueue = ArrayList() - protected val wireChangeQueue = ArrayList() // if 'old' is set and 'new' is blank, it's a wire cutter + val terrainChangeQueue = ArrayList() + val wallChangeQueue = ArrayList() + val wireChangeQueue = ArrayList() // if 'old' is set and 'new' is blank, it's a wire cutter override fun hide() { } diff --git a/src/net/torvald/terrarum/gameactors/ActorWithBody.kt b/src/net/torvald/terrarum/gameactors/ActorWithBody.kt index 9a06dd348..e15c1bef7 100644 --- a/src/net/torvald/terrarum/gameactors/ActorWithBody.kt +++ b/src/net/torvald/terrarum/gameactors/ActorWithBody.kt @@ -628,6 +628,8 @@ open class ActorWithBody(renderOrder: RenderOrder, val physProp: PhysProperties, fun Double.modTileDelta() = this - this.modTile() + // the job of the ccd is that the "next hitbox" would not dig into the terrain greater than the tile size, + // in which the modTileDelta returns a wrong value val vectorSum = (externalV + controllerV) val ccdSteps = (vectorSum.magnitude / TILE_SIZE).floorInt().coerceIn(2, 16) // adaptive diff --git a/src/net/torvald/terrarum/gameworld/WorldSimulator.kt b/src/net/torvald/terrarum/gameworld/WorldSimulator.kt index df3747503..3d0433e40 100644 --- a/src/net/torvald/terrarum/gameworld/WorldSimulator.kt +++ b/src/net/torvald/terrarum/gameworld/WorldSimulator.kt @@ -17,6 +17,8 @@ import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid import net.torvald.terrarum.modulebasegame.gameactors.BlockBoxIndex import net.torvald.terrarum.modulebasegame.gameactors.Electric import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase +import net.torvald.terrarum.worlddrawer.BlocksDrawer +import net.torvald.terrarum.worlddrawer.WorldCamera import net.torvald.util.IntArrayStack import org.dyn4j.geometry.Vector2 import org.khelekore.prtree.* @@ -95,6 +97,8 @@ object WorldSimulator { updateYTo = updateYFrom + DOUBLE_RADIUS } + degrass() + AppLoader.measureDebugTime("WorldSimulator.fluids") { //moveFluids(delta) } @@ -145,6 +149,52 @@ object WorldSimulator { null } + fun degrass() { + if (ingame.terrainChangeQueue.isNotEmpty()) { AppLoader.measureDebugTime("WorldSimulator.degrass") { + + //val grassPlacedByPlayer = ArrayList() + + ingame.terrainChangeQueue.forEach { + if (BlockCodex[it.new].isSolid) { + if (world.getTileFromTerrain(it.posX, it.posY + 1) == Block.GRASS) { + //grassPlacedByPlayer.add(it) + world.setTileTerrain(it.posX, it.posY + 1, Block.DIRT, true) + } + } + } + + // kill grasses surrounded by dirts in cruciform formation + // NOPE this part would not work; environment-depending degrassing must be done by the "grass spread simulator" + /*val for_y_start = (WorldCamera.y.toFloat() / TILE_SIZE).floorInt() + val for_y_end = for_y_start + BlocksDrawer.tilesInVertical - 1 + + val for_x_start = (WorldCamera.x.toFloat() / TILE_SIZE).floorInt() + val for_x_end = for_x_start + BlocksDrawer.tilesInHorizontal - 1 + for (y in for_y_start..for_y_end) { + for (x in for_x_start..for_x_end) { + // do not de-grass ones placed by player + var nogo = false + grassPlacedByPlayer.forEach { + if (x == it.posX && y == it.posY) nogo = true + } + + if (!nogo) { + val tile = world.getTileFromTerrain(x, y) + if (tile == Block.GRASS) { + if (world.getTileFromTerrain(x - 1, y) != Block.GRASS && + world.getTileFromTerrain(x + 1, y) != Block.GRASS && + world.getTileFromTerrain(x, y - 1) != Block.GRASS && + world.getTileFromTerrain(x, y + 1) != Block.GRASS) { + world.setTileTerrain(x, y, Block.DIRT, true) + } + } + } + } + }*/ + + } } + } + /** * displace fluids. Note that the code assumes the gravity pulls things downward ONLY, * which means you'll need to modify the code A LOT if you're going to implement zero- or diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt index c307be92c..a78044c50 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt @@ -69,6 +69,20 @@ open class FixtureBase( // TODO check for despawn code here } + private fun fillFillerBlock(bypassEvent: Boolean = false) { + forEachBlockbox { x, y -> + //printdbg(this, "fillerblock ${blockBox.collisionType} at ($x, $y)") + if (blockBox.collisionType == BlockBox.ALLOW_MOVE_DOWN) { + // if the collision type is allow_move_down, only the top surface tile should be "the platform" + // lower part must not have such property (think of the table!) + // TODO does this ACTUALLY work ?! + world!!.setTileTerrain(x, y, if (y == worldBlockPos!!.y) BlockBox.ALLOW_MOVE_DOWN else BlockBox.NO_COLLISION, bypassEvent) + } + else + world!!.setTileTerrain(x, y, blockBox.collisionType, bypassEvent) + } + } + /** * Adds this instance of the fixture to the world * @@ -109,17 +123,7 @@ open class FixtureBase( worldBlockPos = Point2i(posX, posY) // fill the area with the filler blocks - forEachBlockbox { x, y -> - printdbg(this, "fillerblock ${blockBox.collisionType} at ($x, $y)") - if (blockBox.collisionType == BlockBox.ALLOW_MOVE_DOWN) { - // if the collision type is allow_move_down, only the top surface tile should be "the platform" - // lower part must not have such property (think of the table!) - // TODO does this ACTUALLY work ?! - world!!.setTileTerrain(x, y, if (y == posY) BlockBox.ALLOW_MOVE_DOWN else BlockBox.NO_COLLISION, false) - } - else - world!!.setTileTerrain(x, y, blockBox.collisionType, false) - } + fillFillerBlock() this.isVisible = true @@ -142,43 +146,27 @@ open class FixtureBase( // remove filler block forEachBlockbox { x, y -> + if (world!!.getTileFromTerrain(x, y) == blockBox.collisionType) { world!!.setTileTerrain(x, y, Block.AIR, false) + } } worldBlockPos = null mainUI?.dispose() this.isVisible = false + + // TODO drop self as an item (instance of DroppedItem) } override fun update(delta: Float) { super.update(delta) - - val posX = worldBlockPos!!.x - val posY = worldBlockPos!!.y - var dropThis = false - - // remove filler block - outerLoop@ - for (x in posX until posX + blockBox.width) { - for (y in posY until posY + blockBox.height) { - if (world!!.getTileFromTerrain(x, y) != blockBox.collisionType) { - dropThis = true - break@outerLoop - } - } + // if not flagged to despawn and not actually despawned (which sets worldBlockPos as null), always fill up fillerBlock + if (!flagDespawn && worldBlockPos != null) { + fillFillerBlock(true) } - - if (dropThis) { - // fill blockbox with air - forEachBlockbox { x, y -> - if (world!!.getTileFromTerrain(x, y) == blockBox.collisionType) { - world!!.setTileTerrain(x, y, Block.AIR, false) - } - } - - // TODO drop self as an item (instance of DroppedItem) - + else if (flagDespawn) { + despawn() } } diff --git a/src/net/torvald/terrarum/modulebasegame/gameitems/BlockBase.kt b/src/net/torvald/terrarum/modulebasegame/gameitems/BlockBase.kt index 75bba85ac..35a9a2a80 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameitems/BlockBase.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameitems/BlockBase.kt @@ -3,6 +3,7 @@ package net.torvald.terrarum.modulebasegame.gameitems import net.torvald.terrarum.Point2d import net.torvald.terrarum.Point2i import net.torvald.terrarum.Terrarum +import net.torvald.terrarum.blockproperties.BlockCodex import net.torvald.terrarum.blockproperties.WireCodex import net.torvald.terrarum.gameactors.ActorWithBody import net.torvald.terrarum.gameitem.GameItem @@ -39,11 +40,14 @@ object BlockBase { if (!ret1) return ret1 } - // return false if the tile is already there + // return false if the tile underneath is: + // 0. same tile + // 1. actorblock if (gameItem.inventoryCategory == GameItem.Category.BLOCK && gameItem.dynamicID == ingame.world.getTileFromTerrain(mouseTile.x, mouseTile.y) || gameItem.inventoryCategory == GameItem.Category.WALL && - gameItem.dynamicID == "wall@"+ingame.world.getTileFromWall(mouseTile.x, mouseTile.y) + gameItem.dynamicID == "wall@" + ingame.world.getTileFromWall(mouseTile.x, mouseTile.y) || + BlockCodex[ingame.world.getTileFromTerrain(mouseTile.x, mouseTile.y)].nameKey.contains("ACTORBLOCK_") ) return false