first working instance of wire signal source block

This commit is contained in:
minjaesong
2021-08-09 17:00:02 +09:00
parent 4c4817f2fb
commit a9f46613a2
4 changed files with 84 additions and 77 deletions

View File

@@ -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<Q> {
val ret = ArrayList<Q>()
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<FixtureBase>()
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<FixtureBase> =
Terrarum.ingame!!.actorContainerActive.filter {
it is FixtureBase && it.inUpdateRange(world) && it.wireEmitterType.isNotBlank()
} as List<FixtureBase>
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 }

View File

@@ -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<Int> = ArrayList<Int>()
@@ -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.

View File

@@ -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)
}
}

View File

@@ -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)
}
}
}
}