From a9f46613a226d996ae90dd116b59a6b71e4a2fd1 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Mon, 9 Aug 2021 17:00:02 +0900 Subject: [PATCH] first working instance of wire signal source block --- .../terrarum/gameworld/WorldSimulator.kt | 31 +++---- .../terrarum/modulebasegame/TerrarumIngame.kt | 92 ++++++++++--------- .../modulebasegame/gameactors/FixtureBase.kt | 28 +++--- .../gameactors/FixtureLogicSignalEmitter.kt | 10 ++ 4 files changed, 84 insertions(+), 77 deletions(-) diff --git a/src/net/torvald/terrarum/gameworld/WorldSimulator.kt b/src/net/torvald/terrarum/gameworld/WorldSimulator.kt index bb82d2958..e8fdfea38 100644 --- a/src/net/torvald/terrarum/gameworld/WorldSimulator.kt +++ b/src/net/torvald/terrarum/gameworld/WorldSimulator.kt @@ -9,6 +9,7 @@ import net.torvald.terrarum.blockproperties.Fluid import net.torvald.terrarum.gameactors.ActorWithBody import net.torvald.terrarum.gamecontroller.KeyToggler import net.torvald.terrarum.gameitem.ItemID +import net.torvald.terrarum.modulebasegame.TerrarumIngame.Companion.inUpdateRange import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase import net.torvald.terrarum.worlddrawer.BlocksDrawer @@ -452,28 +453,18 @@ object WorldSimulator { private val wiresimOverscan = 60 - /*private fun wiresimGetSourceBlocks(): List { - val ret = ArrayList() - - 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 - - val fixtures = Terrarum.ingame!!.actorContainer.filterIsInstance() - - for (y in for_y_start - wiresimOverscan..for_y_end + wiresimOverscan) { - for (x in for_x_start - wiresimOverscan..for_x_end + wiresimOverscan) { - - } - } - - return ret - }*/ + private fun wiresimGetSourceBlocks(): List = + Terrarum.ingame!!.actorContainerActive.filter { + it is FixtureBase && it.inUpdateRange(world) && it.wireEmitterType.isNotBlank() + } as List private fun simulateWires(delta: Float) { - //val sourceBlocks = wiresimGetSourceBlocks() + wiresimGetSourceBlocks().let { sources -> + // signal-emitting fixtures must set emitState of its own tiles via update() + sources.forEach { + // TODO + } + } } private enum class WireConStatus { THRU, END, BRANCH } diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt index a090601b9..1807c2fc7 100644 --- a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt +++ b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt @@ -25,6 +25,7 @@ import net.torvald.terrarum.itemproperties.ItemCodex import net.torvald.terrarum.console.AVTracker import net.torvald.terrarum.console.ActorsList import net.torvald.terrarum.gameactors.WireActor +import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.modulebasegame.gameactors.* import net.torvald.terrarum.modulebasegame.gameactors.physicssolver.CollisionSolver import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension @@ -53,8 +54,6 @@ import kotlin.math.roundToInt open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { - private val ACTOR_UPDATE_RANGE = 4096 - var historicalFigureIDBucket: ArrayList = ArrayList() @@ -100,6 +99,45 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { " $EMDASH M: J${Terrarum.memJavaHeap}M / N${Terrarum.memNativeHeap}M / U${Terrarum.memUnsafe}M / X${Terrarum.memXmx}M" else "" + + val ACTOR_UPDATE_RANGE = 4096 + + fun distToActorSqr(world: GameWorld, a: ActorWithBody, p: ActorWithBody) = + minOf(// take min of normal position and wrapped (x < 0) position + (a.hitbox.centeredX - p.hitbox.centeredX).sqr() + + (a.hitbox.centeredY - p.hitbox.centeredY).sqr(), + ((a.hitbox.centeredX + world.width * TILE_SIZE) - p.hitbox.centeredX).sqr() + + (a.hitbox.centeredY - p.hitbox.centeredY).sqr(), + ((a.hitbox.centeredX - world.width * TILE_SIZE) - p.hitbox.centeredX).sqr() + + (a.hitbox.centeredY - p.hitbox.centeredY).sqr() + ) + fun distToCameraSqr(world: GameWorld, a: ActorWithBody) = + minOf( + (a.hitbox.centeredX - WorldCamera.xCentre).sqr() + + (a.hitbox.centeredY - WorldCamera.yCentre).sqr(), + ((a.hitbox.centeredX + world.width * TILE_SIZE) - WorldCamera.xCentre).sqr() + + (a.hitbox.centeredY - WorldCamera.yCentre).sqr(), + ((a.hitbox.centeredX - world.width * TILE_SIZE) - WorldCamera.xCentre).sqr() + + (a.hitbox.centeredY - WorldCamera.yCentre).sqr() + ) + + /** whether the actor is within update range */ + fun ActorWithBody.inUpdateRange(world: GameWorld) = distToCameraSqr(world, this) <= ACTOR_UPDATE_RANGE.sqr() + + /** whether the actor is within screen */ + fun ActorWithBody.inScreen(world: GameWorld) = + + // y + this.hitbox.endY >= WorldCamera.y && this.hitbox.startY <= WorldCamera.yEnd + + && + + // x: camera is on the right side of the seam + ((this.hitbox.endX - world.width >= WorldCamera.x && this.hitbox.startX - world.width <= WorldCamera.xEnd) || + // x: camera in on the left side of the seam + (this.hitbox.endX + world.width >= WorldCamera.x && this.hitbox.startX + world.width <= WorldCamera.xEnd) || + // x: neither + (this.hitbox.endX >= WorldCamera.x && this.hitbox.startX <= WorldCamera.xEnd)) } @@ -708,11 +746,11 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { } private fun filterVisibleActors() { - visibleActorsRenderBehind = actorsRenderBehind.filter { it.inScreen() } - visibleActorsRenderMiddle = actorsRenderMiddle.filter { it.inScreen() } - visibleActorsRenderMidTop = actorsRenderMidTop.filter { it.inScreen() } - visibleActorsRenderFront = actorsRenderFront.filter { it.inScreen() } - visibleActorsRenderOverlay=actorsRenderOverlay.filter { it.inScreen() } + visibleActorsRenderBehind = actorsRenderBehind.filter { it.inScreen(world) } + visibleActorsRenderMiddle = actorsRenderMiddle.filter { it.inScreen(world) } + visibleActorsRenderMidTop = actorsRenderMidTop.filter { it.inScreen(world) } + visibleActorsRenderFront = actorsRenderFront.filter { it.inScreen(world) } + visibleActorsRenderOverlay=actorsRenderOverlay.filter { it.inScreen(world) } } private fun repossessActor() { @@ -761,7 +799,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { var i = 0 while (i < actorContainerSize) { // loop through actorContainerInactive val actor = actorContainerInactive[i] - if (actor is ActorWithBody && actor.inUpdateRange() && !actor.forceDormant) { + if (actor is ActorWithBody && actor.inUpdateRange(world) && !actor.forceDormant) { activateDormantActor(actor) // duplicates are checked here actorContainerSize -= 1 i-- // array removed 1 elem, so we also decrement counter by 1 @@ -788,7 +826,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { i-- // array removed 1 elem, so we also decrement counter by 1 } // inactivate distant actors - else if (actor is ActorWithBody && (!actor.inUpdateRange() || actor.forceDormant)) { + else if (actor is ActorWithBody && (!actor.inUpdateRange(world) || actor.forceDormant)) { if (actor !is Projectile) { // if it's a projectile, don't inactivate it; just kill it. actorContainerInactive.add(actor) // naïve add; duplicates are checked when the actor is re-activated } @@ -857,39 +895,6 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { d.forEach { if (it < ret) ret = it } return ret } - private fun distToActorSqr(a: ActorWithBody, p: ActorWithBody) = - min(// take min of normal position and wrapped (x < 0) position - (a.hitbox.centeredX - p.hitbox.centeredX).sqr() + - (a.hitbox.centeredY - p.hitbox.centeredY).sqr(), - ((a.hitbox.centeredX + world.width * TILE_SIZE) - p.hitbox.centeredX).sqr() + - (a.hitbox.centeredY - p.hitbox.centeredY).sqr(), - ((a.hitbox.centeredX - world.width * TILE_SIZE) - p.hitbox.centeredX).sqr() + - (a.hitbox.centeredY - p.hitbox.centeredY).sqr() - ) - private fun distToCameraSqr(a: ActorWithBody) = - min( - (a.hitbox.centeredX - WorldCamera.xCentre).sqr() + - (a.hitbox.centeredY - WorldCamera.yCentre).sqr(), - ((a.hitbox.centeredX + world.width * TILE_SIZE) - WorldCamera.xCentre).sqr() + - (a.hitbox.centeredY - WorldCamera.yCentre).sqr(), - ((a.hitbox.centeredX - world.width * TILE_SIZE) - WorldCamera.xCentre).sqr() + - (a.hitbox.centeredY - WorldCamera.yCentre).sqr() - ) - - /** whether the actor is within screen */ - private fun ActorWithBody.inScreen() = - - // y - this.hitbox.endY >= WorldCamera.y && this.hitbox.startY <= WorldCamera.yEnd - - && - - // x: camera is on the right side of the seam - ((this.hitbox.endX - worldWidth >= WorldCamera.x && this.hitbox.startX - worldWidth <= WorldCamera.xEnd) || - // x: camera in on the left side of the seam - (this.hitbox.endX + worldWidth >= WorldCamera.x && this.hitbox.startX + worldWidth <= WorldCamera.xEnd) || - // x: neither - (this.hitbox.endX >= WorldCamera.x && this.hitbox.startX <= WorldCamera.xEnd)) private val cameraWindowX = WorldCamera.x.toDouble()..WorldCamera.xEnd.toDouble() @@ -905,9 +910,6 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) { } } - /** whether the actor is within update range */ - private fun ActorWithBody.inUpdateRange() = distToCameraSqr(this) <= ACTOR_UPDATE_RANGE.sqr() - override fun removeActor(ID: Int) = removeActor(getActorByID(ID)) /** * get index of the actor and delete by the index. diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt index 69743d656..24598576f 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt @@ -37,13 +37,23 @@ open class FixtureBase( /** * Block-wise position of this fixture when it's placed on the world. Null if it's not on the world */ - private var worldBlockPos: Point2i? = null + protected var worldBlockPos: Point2i? = null init { if (mainUI != null) AppLoader.disposableSingletonsPool.add(mainUI) } + fun forEachBlockbox(action: (Int, Int) -> Unit) { + worldBlockPos?.let { (posX, posY) -> + for (y in posY until posY + blockBox.height) { + for (x in posX until posX + blockBox.width) { + action(x, y) + } + } + } + } + /** * Adds this instance of the fixture to the world * @@ -80,8 +90,7 @@ open class FixtureBase( // fill the area with the filler blocks - for (y in posY until posY + blockBox.height) { - for (x in posX until posX + blockBox.width) { + forEachBlockbox { 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!) @@ -90,7 +99,6 @@ open class FixtureBase( } else world!!.setTileTerrain(x, y, blockBox.collisionType, false) - } } // set the position of this actor @@ -115,10 +123,8 @@ open class FixtureBase( val posY = worldBlockPos!!.y // remove filler block - for (x in posX until posX + blockBox.width) { - for (y in posY until posY + blockBox.height) { + forEachBlockbox { x, y -> world!!.setTileTerrain(x, y, Block.AIR, false) - } } worldBlockPos = null @@ -156,11 +162,9 @@ open class FixtureBase( if (dropThis) { // fill blockbox with air - for (x in posX until posX + blockBox.width) { - for (y in posY until posY + blockBox.height) { - if (world!!.getTileFromTerrain(x, y) == blockBox.collisionType) { - world!!.setTileTerrain(x, y, Block.AIR, false) - } + forEachBlockbox { x, y -> + if (world!!.getTileFromTerrain(x, y) == blockBox.collisionType) { + world!!.setTileTerrain(x, y, Block.AIR, false) } } diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureLogicSignalEmitter.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureLogicSignalEmitter.kt index fc6601f8f..b5e735683 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureLogicSignalEmitter.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureLogicSignalEmitter.kt @@ -3,6 +3,7 @@ package net.torvald.terrarum.modulebasegame.gameactors import net.torvald.terrarum.CommonResourcePool import net.torvald.terrarum.ModMgr import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE +import net.torvald.terrarum.blockproperties.WireCodex import net.torvald.terrarum.gameactors.AVKey import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack import org.dyn4j.geometry.Vector2 @@ -27,5 +28,14 @@ class FixtureLogicSignalEmitter(nameFun: () -> String) : FixtureBase(BlockBox(Bl companion object { const val MASS = 1.0 } + + override fun update(delta: Float) { + // set emit + worldBlockPos?.let { (x, y) -> + WireCodex.getAll().filter { it.renderClass == "signal" }.forEach { prop -> + world?.setWireEmitStateOf(x, y, prop.id, wireEmission) + } + } + } }