propagation delay is now consistent; cosmetic wip

This commit is contained in:
minjaesong
2024-03-04 19:07:25 +09:00
parent 1c39036cc8
commit 4602cb5bc1
4 changed files with 83 additions and 64 deletions

View File

@@ -23,6 +23,7 @@ open class Electric : FixtureBase {
protected constructor() : super() { protected constructor() : super() {
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() } oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
newSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
} }
/** /**
@@ -51,6 +52,7 @@ open class Electric : FixtureBase {
App.disposables.add(mainUI) App.disposables.add(mainUI)
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() } oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
newSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
} }
companion object { companion object {
@@ -59,8 +61,10 @@ open class Electric : FixtureBase {
const val ELECTRIC_THRESHOLD_EDGE_DELTA = 0.7 const val ELECTRIC_THRESHOLD_EDGE_DELTA = 0.7
} }
fun getWireEmitterAt(blockBoxIndex: BlockBoxIndex) = this.wireEmitterTypes[blockBoxIndex]
fun getWireEmitterAt(point: Point2i) = this.wireEmitterTypes[pointToBlockBoxIndex(point)] fun getWireEmitterAt(point: Point2i) = this.wireEmitterTypes[pointToBlockBoxIndex(point)]
fun getWireEmitterAt(x: Int, y: Int) = this.wireEmitterTypes[pointToBlockBoxIndex(x, y)] fun getWireEmitterAt(x: Int, y: Int) = this.wireEmitterTypes[pointToBlockBoxIndex(x, y)]
fun getWireSinkAt(blockBoxIndex: BlockBoxIndex) = this.wireSinkTypes[blockBoxIndex]
fun getWireSinkAt(point: Point2i) = this.wireSinkTypes[pointToBlockBoxIndex(point)] fun getWireSinkAt(point: Point2i) = this.wireSinkTypes[pointToBlockBoxIndex(point)]
fun getWireSinkAt(x: Int, y: Int) = this.wireSinkTypes[pointToBlockBoxIndex(x, y)] fun getWireSinkAt(x: Int, y: Int) = this.wireSinkTypes[pointToBlockBoxIndex(x, y)]
@@ -79,33 +83,42 @@ open class Electric : FixtureBase {
// Use case: signal buffer (sinkType=digital_bit), battery (sinkType=electricity), etc. // Use case: signal buffer (sinkType=digital_bit), battery (sinkType=electricity), etc.
val chargeStored: HashMap<String, Double> = HashMap() val chargeStored: HashMap<String, Double> = HashMap()
private val newStates = HashMap<BlockBoxIndex, Vector2>()
/** Triggered when 'digital_bit' rises from low to high. Edge detection only considers the real component (labeled as 'x') of the vector */ /** Triggered when 'digital_bit' rises from low to high. Edge detection only considers the real component (labeled as 'x') of the vector */
open fun onRisingEdge(readFrom: BlockBoxIndex) {} open fun onRisingEdge(readFrom: BlockBoxIndex) {}
/** Triggered when 'digital_bit' rises from high to low. Edge detection only considers the real component (labeled as 'x') of the vector */ /** Triggered when 'digital_bit' rises from high to low. Edge detection only considers the real component (labeled as 'x') of the vector */
open fun onFallingEdge(readFrom: BlockBoxIndex) {} open fun onFallingEdge(readFrom: BlockBoxIndex) {}
/** Triggered when 'digital_bit' is held high. This function WILL NOT be triggered simultaneously with the rising edge. Level detection only considers the real component (labeled as 'x') of the vector */ /** Triggered when 'digital_bit' is held high. This function WILL NOT be triggered simultaneously with the rising edge. Level detection only considers the real component (labeled as 'x') of the vector */
open fun onSignalHigh(readFrom: BlockBoxIndex) {} //open fun onSignalHigh(readFrom: BlockBoxIndex) {}
/** Triggered when 'digital_bit' is held low. This function WILL NOT be triggered simultaneously with the falling edge. Level detection only considers the real component (labeled as 'x') of the vector */ /** Triggered when 'digital_bit' is held low. This function WILL NOT be triggered simultaneously with the falling edge. Level detection only considers the real component (labeled as 'x') of the vector */
open fun onSignalLow(readFrom: BlockBoxIndex) {} //open fun onSignalLow(readFrom: BlockBoxIndex) {}
fun getWireStateAt(offsetX: Int, offsetY: Int): Vector2 { open fun updateSignal() {}
fun getWireStateAt(offsetX: Int, offsetY: Int, sinkType: WireEmissionType): Vector2 {
val index = pointToBlockBoxIndex(offsetX, offsetY) val index = pointToBlockBoxIndex(offsetX, offsetY)
return oldSinkStatus[index]
}
private val oldSinkStatus: Array<Vector2>
open fun updateOnWireGraphTraversal(offsetX: Int, offsetY: Int, sinkType: WireEmissionType) {
val index = pointToBlockBoxIndex(offsetX, offsetY)
val old = oldSinkStatus[index]
val wx = offsetX + intTilewiseHitbox.startX.toInt() val wx = offsetX + intTilewiseHitbox.startX.toInt()
val wy = offsetY + intTilewiseHitbox.startY.toInt() val wy = offsetY + intTilewiseHitbox.startY.toInt()
val new = WireCodex.getAllWiresThatAccepts("digital_bit").fold(Vector2()) { acc, (id, _) ->
return WireCodex.getAllWiresThatAccepts(sinkType).fold(Vector2()) { acc, (id, _) ->
INGAME.world.getWireEmitStateOf(wx, wy, id).let { INGAME.world.getWireEmitStateOf(wx, wy, id).let {
Vector2(acc.x + (it?.x ?: 0.0), acc.y + (it?.y ?: 0.0)) Vector2(acc.x + (it?.x ?: 0.0), acc.y + (it?.y ?: 0.0))
} }
} }
}
fun getWireEmissionAt(offsetX: Int, offsetY: Int): Vector2 {
return wireEmission[pointToBlockBoxIndex(offsetY, offsetY)] ?: Vector2()
}
private val oldSinkStatus: Array<Vector2>
private val newSinkStatus: Array<Vector2>
open fun updateOnWireGraphTraversal(offsetX: Int, offsetY: Int, sinkType: WireEmissionType) {
val index = pointToBlockBoxIndex(offsetX, offsetY)
val wx = offsetX + intTilewiseHitbox.startX.toInt()
val wy = offsetY + intTilewiseHitbox.startY.toInt()
val new2 = WireCodex.getAllWiresThatAccepts(wireSinkTypes[index] ?: "").fold(Vector2()) { acc, (id, _) -> val new2 = WireCodex.getAllWiresThatAccepts(wireSinkTypes[index] ?: "").fold(Vector2()) { acc, (id, _) ->
INGAME.world.getWireEmitStateOf(wx, wy, id).let { INGAME.world.getWireEmitStateOf(wx, wy, id).let {
@@ -113,16 +126,6 @@ open class Electric : FixtureBase {
} }
} }
if (sinkType == "digital_bit") {
if (new.x - old.x >= ELECTRIC_THRESHOLD_EDGE_DELTA && new.x >= ELECTIC_THRESHOLD_HIGH)
onRisingEdge(index)
else if (old.x - new.x >= ELECTRIC_THRESHOLD_EDGE_DELTA && new.x <= ELECTRIC_THRESHOLD_LOW)
onFallingEdge(index)
else if (new.x >= ELECTIC_THRESHOLD_HIGH)
onSignalHigh(index)
else if (new.y <= ELECTRIC_THRESHOLD_LOW)
onSignalLow(index)
}
oldSinkStatus[index].set(new2) oldSinkStatus[index].set(new2)
} }
@@ -132,14 +135,42 @@ open class Electric : FixtureBase {
*/ */
override fun updateImpl(delta: Float) { override fun updateImpl(delta: Float) {
super.updateImpl(delta) super.updateImpl(delta)
/*oldSinkStatus.indices.forEach { index ->
val wx = (index % blockBox.width) + intTilewiseHitbox.startX.toInt() val risingEdgeIndices = ArrayList<BlockBoxIndex>()
val wy = (index / blockBox.width) + intTilewiseHitbox.startY.toInt() val fallingEdgeIndices = ArrayList<BlockBoxIndex>()
val new = WireCodex.getAllWiresThatAccepts(getWireSinkAt(index % blockBox.width, index / blockBox.width) ?: "").fold(Vector2()) { acc, (id, _) ->
INGAME.world.getWireEmitStateOf(wx, wy, id).let { for (y in 0 until blockBox.height) {
Vector2(acc.x + (it?.x ?: 0.0), acc.y + (it?.y ?: 0.0)) for (x in 0 until blockBox.width) {
// get indices of "rising edges"
// get indices of "falling edges"
val wx = x + intTilewiseHitbox.startX.toInt()
val wy = y + intTilewiseHitbox.startY.toInt()
val new = WireCodex.getAllWiresThatAccepts(getWireSinkAt(x, y) ?: "").fold(Vector2()) { acc, (id, _) ->
INGAME.world.getWireEmitStateOf(wx, wy, id).let {
Vector2(acc.x + (it?.x ?: 0.0), acc.y + (it?.y ?: 0.0))
}
} }
val index = pointToBlockBoxIndex(x, y)
if (new.x - oldSinkStatus[index].x >= ELECTRIC_THRESHOLD_EDGE_DELTA && new.x >= ELECTIC_THRESHOLD_HIGH)
risingEdgeIndices.add(index)
else if (oldSinkStatus[index].x - new.x >= ELECTRIC_THRESHOLD_EDGE_DELTA && new.x <= ELECTRIC_THRESHOLD_LOW)
fallingEdgeIndices.add(index)
oldSinkStatus[index].set(new)
} }
}
risingEdgeIndices.forEach { onRisingEdge(it) }
fallingEdgeIndices.forEach { onFallingEdge(it) }
updateSignal()
/*oldSinkStatus.indices.forEach { index ->
oldSinkStatus[index].set(new) oldSinkStatus[index].set(new)
}*/ }*/
} }

View File

@@ -85,11 +85,11 @@ class FixtureSignalBlocker : Electric, Reorientable {
makeNewSprite(TextureRegionPack(itemImage.texture, 2*TILE_SIZE, 2*TILE_SIZE)).let { makeNewSprite(TextureRegionPack(itemImage.texture, 2*TILE_SIZE, 2*TILE_SIZE)).let {
it.setRowsAndFrames(16,4) it.setRowsAndFrames(16,4)
it.delays = FloatArray(8) { Float.POSITIVE_INFINITY } it.delays = FloatArray(16) { Float.POSITIVE_INFINITY }
} }
makeNewSpriteEmissive(TextureRegionPack(itemImage2.texture, 2*TILE_SIZE, 2*TILE_SIZE)).let { makeNewSpriteEmissive(TextureRegionPack(itemImage2.texture, 2*TILE_SIZE, 2*TILE_SIZE)).let {
it.setRowsAndFrames(16,4) it.setRowsAndFrames(16,4)
it.delays = FloatArray(8) { Float.POSITIVE_INFINITY } it.delays = FloatArray(16) { Float.POSITIVE_INFINITY }
} }
setEmitterAndSink() setEmitterAndSink()
@@ -103,19 +103,19 @@ class FixtureSignalBlocker : Electric, Reorientable {
private val I: Boolean private val I: Boolean
get() = when (orientation) { get() = when (orientation) {
0 -> getWireStateAt(0, 0).x >= ELECTIC_THRESHOLD_HIGH 0 -> getWireStateAt(0, 0, "digital_bit").x >= ELECTIC_THRESHOLD_HIGH
1 -> getWireStateAt(1, 0).x >= ELECTIC_THRESHOLD_HIGH 1 -> getWireStateAt(1, 0, "digital_bit").x >= ELECTIC_THRESHOLD_HIGH
2 -> getWireStateAt(1, 1).x >= ELECTIC_THRESHOLD_HIGH 2 -> getWireStateAt(1, 1, "digital_bit").x >= ELECTIC_THRESHOLD_HIGH
3 -> getWireStateAt(0, 1).x >= ELECTIC_THRESHOLD_HIGH 3 -> getWireStateAt(0, 1, "digital_bit").x >= ELECTIC_THRESHOLD_HIGH
else -> throw IllegalStateException("Orientation not in range ($orientation)") else -> throw IllegalStateException("Orientation not in range ($orientation)")
} }
private val J: Boolean private val J: Boolean
get() = when (orientation) { get() = when (orientation) {
0 -> getWireStateAt(0, 1).x >= ELECTIC_THRESHOLD_HIGH 0 -> getWireStateAt(0, 1, "digital_bit").x >= ELECTIC_THRESHOLD_HIGH
1 -> getWireStateAt(0, 0).x >= ELECTIC_THRESHOLD_HIGH 1 -> getWireStateAt(0, 0, "digital_bit").x >= ELECTIC_THRESHOLD_HIGH
2 -> getWireStateAt(1, 0).x >= ELECTIC_THRESHOLD_HIGH 2 -> getWireStateAt(1, 0, "digital_bit").x >= ELECTIC_THRESHOLD_HIGH
3 -> getWireStateAt(1, 1).x >= ELECTIC_THRESHOLD_HIGH 3 -> getWireStateAt(1, 1, "digital_bit").x >= ELECTIC_THRESHOLD_HIGH
else -> throw IllegalStateException("Orientation not in range ($orientation)") else -> throw IllegalStateException("Orientation not in range ($orientation)")
} }
@@ -130,10 +130,10 @@ class FixtureSignalBlocker : Electric, Reorientable {
setWireEmissionAt(x, y, Vector2(I nimply J, 0.0)) setWireEmissionAt(x, y, Vector2(I nimply J, 0.0))
// update sprite // update sprite
val one = getWireStateAt(0, 0).x >= ELECTIC_THRESHOLD_HIGH val one = getWireStateAt(0, 0, "digital_bit").x >= ELECTIC_THRESHOLD_HIGH || getWireEmissionAt(0, 0).x >= ELECTIC_THRESHOLD_HIGH
val two = getWireStateAt(1, 0).x >= ELECTIC_THRESHOLD_HIGH val two = getWireStateAt(1, 0, "digital_bit").x >= ELECTIC_THRESHOLD_HIGH || getWireEmissionAt(1, 0).x >= ELECTIC_THRESHOLD_HIGH
val four = getWireStateAt(0, 1).x >= ELECTIC_THRESHOLD_HIGH val four = getWireStateAt(0, 1, "digital_bit").x >= ELECTIC_THRESHOLD_HIGH || getWireEmissionAt(0, 1).x >= ELECTIC_THRESHOLD_HIGH
val eight = getWireStateAt(1, 1).x >= ELECTIC_THRESHOLD_HIGH val eight = getWireStateAt(1, 1, "digital_bit").x >= ELECTIC_THRESHOLD_HIGH || getWireEmissionAt(1, 1).x >= ELECTIC_THRESHOLD_HIGH
val state = one.toInt(0) or two.toInt(1) or four.toInt(2) or eight.toInt(3) val state = one.toInt(0) or two.toInt(1) or four.toInt(2) or eight.toInt(3)
@@ -141,22 +141,10 @@ class FixtureSignalBlocker : Electric, Reorientable {
(spriteEmissive as SheetSpriteAnimation).currentRow = state (spriteEmissive as SheetSpriteAnimation).currentRow = state
} }
override fun onRisingEdge(readFrom: BlockBoxIndex) {
updateK()
}
override fun onFallingEdge(readFrom: BlockBoxIndex) {
updateK()
}
override fun onSignalHigh(readFrom: BlockBoxIndex) {
updateK()
}
override fun onSignalLow(readFrom: BlockBoxIndex) {
updateK()
}
private infix fun Boolean.nimply(other: Boolean) = (this && !other).toInt().toDouble() private infix fun Boolean.nimply(other: Boolean) = (this && !other).toInt().toDouble()
override fun updateSignal() {
updateK()
}
} }

View File

@@ -49,11 +49,8 @@ class FixtureSignalBulb : Electric {
(spriteEmissive as SheetSpriteAnimation).currentRow = state.toInt() (spriteEmissive as SheetSpriteAnimation).currentRow = state.toInt()
} }
override fun onSignalHigh(readFrom: BlockBoxIndex) { override fun updateImpl(delta: Float) {
light(true) super.updateImpl(delta)
} light(getWireStateAt(0, 0, "digital_bit").x >= ELECTIC_THRESHOLD_HIGH)
override fun onSignalLow(readFrom: BlockBoxIndex) {
light(false)
} }
} }

View File

@@ -62,6 +62,9 @@ class FixtureWorldPortal : Electric {
} }
override fun onRisingEdge(readFrom: BlockBoxIndex) { override fun onRisingEdge(readFrom: BlockBoxIndex) {
if (getWireSinkAt(readFrom) != "digital_bit") return
printdbg(this, "teleport! $teleportRequest") printdbg(this, "teleport! $teleportRequest")
teleportRequest?.let { teleportRequest?.let {
if (it.worldDiskToLoad != null && it.worldLoadParam != null) { if (it.worldDiskToLoad != null && it.worldLoadParam != null) {