mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-11 11:04:05 +09:00
fix: actor tooltip was repeatedly showing and hiding itself
This commit is contained in:
@@ -23,6 +23,7 @@ import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
|||||||
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
import net.torvald.terrarum.modulebasegame.gameactors.IngamePlayer
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
import net.torvald.terrarum.modulebasegame.gameactors.Pocketed
|
||||||
|
import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellCommonRes.tooltipShowing
|
||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
|
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
|
||||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||||
@@ -97,6 +98,8 @@ open class ActorWithBody : Actor {
|
|||||||
val mouseUp: Boolean
|
val mouseUp: Boolean
|
||||||
get() = hitbox.containsPoint((world?.width ?: 0) * TILE_SIZED, Terrarum.mouseX, Terrarum.mouseY)
|
get() = hitbox.containsPoint((world?.width ?: 0) * TILE_SIZED, Terrarum.mouseX, Terrarum.mouseY)
|
||||||
|
|
||||||
|
@Transient private val tooltipHash = System.nanoTime()
|
||||||
|
|
||||||
var hitboxTranslateX: Int = 0// relative to spritePosX
|
var hitboxTranslateX: Int = 0// relative to spritePosX
|
||||||
protected set
|
protected set
|
||||||
var hitboxTranslateY: Int = 0// relative to spritePosY
|
var hitboxTranslateY: Int = 0// relative to spritePosY
|
||||||
@@ -669,11 +672,15 @@ open class ActorWithBody : Actor {
|
|||||||
feetPosTile.set(hIntTilewiseHitbox.centeredX.floorToInt(), hIntTilewiseHitbox.endY.floorToInt())
|
feetPosTile.set(hIntTilewiseHitbox.centeredX.floorToInt(), hIntTilewiseHitbox.endY.floorToInt())
|
||||||
|
|
||||||
|
|
||||||
if (mouseUp && this.tooltipText != null) INGAME.setTooltipMessage(this.tooltipText)
|
if (mouseUp && tooltipText != null && tooltipShowing[tooltipHash] != true) {
|
||||||
|
INGAME.setTooltipMessage(tooltipText)
|
||||||
|
tooltipShowing[tooltipHash] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure tooltip to disable even when the actor's update is paused at unfortunate time
|
if (tooltipText == null || !mouseUp) {
|
||||||
if (!mouseUp && INGAME.getTooltipMessage() == this.tooltipText) INGAME.setTooltipMessage(null)
|
tooltipShowing[tooltipHash] = false
|
||||||
|
}
|
||||||
|
|
||||||
// isStationary = (hitbox - oldHitbox).magnitudeSquared < PHYS_EPSILON_VELO
|
// isStationary = (hitbox - oldHitbox).magnitudeSquared < PHYS_EPSILON_VELO
|
||||||
isStationary = isCloseEnough(hitbox.startX, oldHitbox.startX) && // this is supposed to be more accurate, idk
|
isStationary = isCloseEnough(hitbox.startX, oldHitbox.startX) && // this is supposed to be more accurate, idk
|
||||||
|
|||||||
200
src/net/torvald/terrarum/modulebasegame/gameactors/Electric.kt
Normal file
200
src/net/torvald/terrarum/modulebasegame/gameactors/Electric.kt
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
package net.torvald.terrarum.modulebasegame.gameactors
|
||||||
|
|
||||||
|
import net.torvald.terrarum.*
|
||||||
|
import net.torvald.terrarum.gameactors.ActorID
|
||||||
|
import net.torvald.terrarum.gameactors.PhysProperties
|
||||||
|
import net.torvald.terrarum.ui.UICanvas
|
||||||
|
import org.dyn4j.geometry.Vector2
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
typealias WireEmissionType = String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2021-08-10.
|
||||||
|
*/
|
||||||
|
open class Electric : FixtureBase {
|
||||||
|
|
||||||
|
protected constructor() : super() {
|
||||||
|
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||||
|
newSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Making the sprite: do not address the CommonResourcePool directly; just do it like this snippet:
|
||||||
|
*
|
||||||
|
* ```makeNewSprite(FixtureBase.getSpritesheet("basegame", "sprites/fixtures/tiki_torch.tga", 16, 32))```
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
blockBox0: BlockBox,
|
||||||
|
blockBoxProps: BlockBoxProps = BlockBoxProps(0),
|
||||||
|
renderOrder: RenderOrder = RenderOrder.MIDDLE,
|
||||||
|
nameFun: () -> String,
|
||||||
|
mainUI: UICanvas? = null,
|
||||||
|
inventory: FixtureInventory? = null,
|
||||||
|
id: ActorID? = null
|
||||||
|
) : super(renderOrder, PhysProperties.IMMOBILE(), id) {
|
||||||
|
blockBox = blockBox0
|
||||||
|
setHitboxDimension(TerrarumAppConfiguration.TILE_SIZE * blockBox.width, TerrarumAppConfiguration.TILE_SIZE * blockBox.height, 0, 0)
|
||||||
|
this.blockBoxProps = blockBoxProps
|
||||||
|
this.renderOrder = renderOrder
|
||||||
|
this.nameFun = nameFun
|
||||||
|
this.mainUI = mainUI
|
||||||
|
this.inventory = inventory
|
||||||
|
|
||||||
|
if (mainUI != null)
|
||||||
|
App.disposables.add(mainUI)
|
||||||
|
|
||||||
|
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||||
|
newSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val ELECTRIC_THRESHOLD_HIGH = 0.9
|
||||||
|
const val ELECTRIC_THRESHOLD_LOW = 0.1
|
||||||
|
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(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(x: Int, y: Int) = this.wireSinkTypes[pointToBlockBoxIndex(x, y)]
|
||||||
|
|
||||||
|
fun setWireEmitterAt(x: Int, y: Int, type: WireEmissionType) { wireEmitterTypes[pointToBlockBoxIndex(x, y)] = type }
|
||||||
|
fun setWireSinkAt(x: Int, y: Int, type: WireEmissionType) { wireSinkTypes[pointToBlockBoxIndex(x, y)] = type }
|
||||||
|
fun setWireEmissionAt(x: Int, y: Int, emission: Vector2) { wireEmission[pointToBlockBoxIndex(x, y)] = emission }
|
||||||
|
fun setWireConsumptionAt(x: Int, y: Int, consumption: Vector2) { wireConsumption[pointToBlockBoxIndex(x, y)] = consumption }
|
||||||
|
|
||||||
|
fun clearStatus() {
|
||||||
|
wireSinkTypes.clear()
|
||||||
|
wireEmitterTypes.clear()
|
||||||
|
wireEmission.clear()
|
||||||
|
wireConsumption.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
// these are characteristic properties of the fixture (they have constant value) so must not be serialised
|
||||||
|
@Transient val wireEmitterTypes: HashMap<BlockBoxIndex, WireEmissionType> = HashMap()
|
||||||
|
@Transient val wireSinkTypes: HashMap<BlockBoxIndex, WireEmissionType> = HashMap()
|
||||||
|
|
||||||
|
val wireEmission: HashMap<BlockBoxIndex, Vector2> = HashMap()
|
||||||
|
val wireConsumption: HashMap<BlockBoxIndex, Vector2> = HashMap()
|
||||||
|
|
||||||
|
// these are NOT constant so they ARE serialised. Type: Map<SinkType (String) -> Charge (Double>
|
||||||
|
// Use case: signal buffer (sinkType=digital_bit), battery (sinkType=electricity), etc.
|
||||||
|
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 */
|
||||||
|
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 */
|
||||||
|
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 */
|
||||||
|
//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 */
|
||||||
|
//open fun onSignalLow(readFrom: BlockBoxIndex) {}
|
||||||
|
|
||||||
|
open fun updateSignal() {}
|
||||||
|
|
||||||
|
fun getWireStateAt(offsetX: Int, offsetY: Int, sinkType: WireEmissionType): Vector2 {
|
||||||
|
val index = pointToBlockBoxIndex(offsetX, offsetY)
|
||||||
|
val wx = offsetX + intTilewiseHitbox.startX.toInt()
|
||||||
|
val wy = offsetY + intTilewiseHitbox.startY.toInt()
|
||||||
|
|
||||||
|
return WireCodex.getAllWiresThatAccepts(sinkType).fold(Vector2()) { acc, (id, _) ->
|
||||||
|
INGAME.world.getWireEmitStateOf(wx, wy, id).let {
|
||||||
|
Vector2(acc.x + (it?.x ?: 0.0), acc.y + (it?.y ?: 0.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getWireEmissionAt(offsetX: Int, offsetY: Int): Vector2 {
|
||||||
|
return wireEmission[pointToBlockBoxIndex(offsetX, offsetY)] ?: Vector2()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns true if at least one of following condition is `true`
|
||||||
|
* - `getWireStateAt(x, y, "digital_bit").x` is equal to or greater than `ELECTIC_THRESHOLD_HIGH`
|
||||||
|
* - `getWireEmissionAt(x, y).x` is equal to or greater than `ELECTIC_THRESHOLD_HIGH`
|
||||||
|
*
|
||||||
|
* This function does NOT check if the given port receives/emits `digital_bit` signal; if not, the result is undefined.
|
||||||
|
*/
|
||||||
|
fun isSignalHigh(offsetX: Int, offsetY: Int) =
|
||||||
|
getWireStateAt(offsetX, offsetY, "digital_bit").x >= ELECTRIC_THRESHOLD_HIGH ||
|
||||||
|
getWireEmissionAt(offsetX, offsetY).x >= ELECTRIC_THRESHOLD_HIGH
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns true if at least one of following condition is `true`
|
||||||
|
* - `getWireStateAt(x, y, "digital_bit").x` is equal to or lesser than `ELECTRIC_THRESHOLD_LOW`
|
||||||
|
* - `getWireEmissionAt(x, y).x` is equal to or lesser than `ELECTRIC_THRESHOLD_LOW`
|
||||||
|
*
|
||||||
|
* This function does NOT check if the given port receives/emits `digital_bit` signal; if not, the result is undefined.
|
||||||
|
*/
|
||||||
|
fun isSignalLow(offsetX: Int, offsetY: Int) =
|
||||||
|
getWireStateAt(offsetX, offsetY, "digital_bit").x <= ELECTRIC_THRESHOLD_LOW ||
|
||||||
|
getWireEmissionAt(offsetX, offsetY).x <= ELECTRIC_THRESHOLD_LOW
|
||||||
|
|
||||||
|
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, _) ->
|
||||||
|
INGAME.world.getWireEmitStateOf(wx, wy, id).let {
|
||||||
|
Vector2(acc.x + (it?.x ?: 0.0), acc.y + (it?.y ?: 0.0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
oldSinkStatus[index].set(new2)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refrain from updating signal output from this function: there will be 1 extra tick delay if you do so
|
||||||
|
*/
|
||||||
|
override fun updateImpl(delta: Float) {
|
||||||
|
super.updateImpl(delta)
|
||||||
|
|
||||||
|
val risingEdgeIndices = ArrayList<BlockBoxIndex>()
|
||||||
|
val fallingEdgeIndices = ArrayList<BlockBoxIndex>()
|
||||||
|
|
||||||
|
for (y in 0 until blockBox.height) {
|
||||||
|
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 >= ELECTRIC_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)
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,200 +11,10 @@ import net.torvald.terrarum.gameworld.fmod
|
|||||||
import net.torvald.terrarum.modulebasegame.gameitems.PickaxeCore
|
import net.torvald.terrarum.modulebasegame.gameitems.PickaxeCore
|
||||||
import net.torvald.terrarum.ui.UICanvas
|
import net.torvald.terrarum.ui.UICanvas
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
import org.dyn4j.geometry.Vector2
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.HashMap
|
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
typealias BlockBoxIndex = Int
|
typealias BlockBoxIndex = Int
|
||||||
typealias WireEmissionType = String
|
|
||||||
|
|
||||||
open class Electric : FixtureBase {
|
|
||||||
|
|
||||||
protected constructor() : super() {
|
|
||||||
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
|
||||||
newSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Making the sprite: do not address the CommonResourcePool directly; just do it like this snippet:
|
|
||||||
*
|
|
||||||
* ```makeNewSprite(FixtureBase.getSpritesheet("basegame", "sprites/fixtures/tiki_torch.tga", 16, 32))```
|
|
||||||
*/
|
|
||||||
constructor(
|
|
||||||
blockBox0: BlockBox,
|
|
||||||
blockBoxProps: BlockBoxProps = BlockBoxProps(0),
|
|
||||||
renderOrder: RenderOrder = RenderOrder.MIDDLE,
|
|
||||||
nameFun: () -> String,
|
|
||||||
mainUI: UICanvas? = null,
|
|
||||||
inventory: FixtureInventory? = null,
|
|
||||||
id: ActorID? = null
|
|
||||||
) : super(renderOrder, PhysProperties.IMMOBILE(), id) {
|
|
||||||
blockBox = blockBox0
|
|
||||||
setHitboxDimension(TILE_SIZE * blockBox.width, TILE_SIZE * blockBox.height, 0, 0)
|
|
||||||
this.blockBoxProps = blockBoxProps
|
|
||||||
this.renderOrder = renderOrder
|
|
||||||
this.nameFun = nameFun
|
|
||||||
this.mainUI = mainUI
|
|
||||||
this.inventory = inventory
|
|
||||||
|
|
||||||
if (mainUI != null)
|
|
||||||
App.disposables.add(mainUI)
|
|
||||||
|
|
||||||
oldSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
|
||||||
newSinkStatus = Array(blockBox.width * blockBox.height) { Vector2() }
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val ELECTRIC_THRESHOLD_HIGH = 0.9
|
|
||||||
const val ELECTRIC_THRESHOLD_LOW = 0.1
|
|
||||||
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(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(x: Int, y: Int) = this.wireSinkTypes[pointToBlockBoxIndex(x, y)]
|
|
||||||
|
|
||||||
fun setWireEmitterAt(x: Int, y: Int, type: WireEmissionType) { wireEmitterTypes[pointToBlockBoxIndex(x, y)] = type }
|
|
||||||
fun setWireSinkAt(x: Int, y: Int, type: WireEmissionType) { wireSinkTypes[pointToBlockBoxIndex(x, y)] = type }
|
|
||||||
fun setWireEmissionAt(x: Int, y: Int, emission: Vector2) { wireEmission[pointToBlockBoxIndex(x, y)] = emission }
|
|
||||||
fun setWireConsumptionAt(x: Int, y: Int, consumption: Vector2) { wireConsumption[pointToBlockBoxIndex(x, y)] = consumption }
|
|
||||||
|
|
||||||
fun clearStatus() {
|
|
||||||
wireSinkTypes.clear()
|
|
||||||
wireEmitterTypes.clear()
|
|
||||||
wireEmission.clear()
|
|
||||||
wireConsumption.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
// these are characteristic properties of the fixture (they have constant value) so must not be serialised
|
|
||||||
@Transient val wireEmitterTypes: HashMap<BlockBoxIndex, WireEmissionType> = HashMap()
|
|
||||||
@Transient val wireSinkTypes: HashMap<BlockBoxIndex, WireEmissionType> = HashMap()
|
|
||||||
|
|
||||||
val wireEmission: HashMap<BlockBoxIndex, Vector2> = HashMap()
|
|
||||||
val wireConsumption: HashMap<BlockBoxIndex, Vector2> = HashMap()
|
|
||||||
|
|
||||||
// these are NOT constant so they ARE serialised. Type: Map<SinkType (String) -> Charge (Double>
|
|
||||||
// Use case: signal buffer (sinkType=digital_bit), battery (sinkType=electricity), etc.
|
|
||||||
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 */
|
|
||||||
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 */
|
|
||||||
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 */
|
|
||||||
//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 */
|
|
||||||
//open fun onSignalLow(readFrom: BlockBoxIndex) {}
|
|
||||||
|
|
||||||
open fun updateSignal() {}
|
|
||||||
|
|
||||||
fun getWireStateAt(offsetX: Int, offsetY: Int, sinkType: WireEmissionType): Vector2 {
|
|
||||||
val index = pointToBlockBoxIndex(offsetX, offsetY)
|
|
||||||
val wx = offsetX + intTilewiseHitbox.startX.toInt()
|
|
||||||
val wy = offsetY + intTilewiseHitbox.startY.toInt()
|
|
||||||
|
|
||||||
return WireCodex.getAllWiresThatAccepts(sinkType).fold(Vector2()) { acc, (id, _) ->
|
|
||||||
INGAME.world.getWireEmitStateOf(wx, wy, id).let {
|
|
||||||
Vector2(acc.x + (it?.x ?: 0.0), acc.y + (it?.y ?: 0.0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getWireEmissionAt(offsetX: Int, offsetY: Int): Vector2 {
|
|
||||||
return wireEmission[pointToBlockBoxIndex(offsetX, offsetY)] ?: Vector2()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* returns true if at least one of following condition is `true`
|
|
||||||
* - `getWireStateAt(x, y, "digital_bit").x` is equal to or greater than `ELECTIC_THRESHOLD_HIGH`
|
|
||||||
* - `getWireEmissionAt(x, y).x` is equal to or greater than `ELECTIC_THRESHOLD_HIGH`
|
|
||||||
*
|
|
||||||
* This function does NOT check if the given port receives/emits `digital_bit` signal; if not, the result is undefined.
|
|
||||||
*/
|
|
||||||
fun isSignalHigh(offsetX: Int, offsetY: Int) =
|
|
||||||
getWireStateAt(offsetX, offsetY, "digital_bit").x >= ELECTRIC_THRESHOLD_HIGH ||
|
|
||||||
getWireEmissionAt(offsetX, offsetY).x >= ELECTRIC_THRESHOLD_HIGH
|
|
||||||
|
|
||||||
/**
|
|
||||||
* returns true if at least one of following condition is `true`
|
|
||||||
* - `getWireStateAt(x, y, "digital_bit").x` is equal to or lesser than `ELECTRIC_THRESHOLD_LOW`
|
|
||||||
* - `getWireEmissionAt(x, y).x` is equal to or lesser than `ELECTRIC_THRESHOLD_LOW`
|
|
||||||
*
|
|
||||||
* This function does NOT check if the given port receives/emits `digital_bit` signal; if not, the result is undefined.
|
|
||||||
*/
|
|
||||||
fun isSignalLow(offsetX: Int, offsetY: Int) =
|
|
||||||
getWireStateAt(offsetX, offsetY, "digital_bit").x <= ELECTRIC_THRESHOLD_LOW ||
|
|
||||||
getWireEmissionAt(offsetX, offsetY).x <= ELECTRIC_THRESHOLD_LOW
|
|
||||||
|
|
||||||
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, _) ->
|
|
||||||
INGAME.world.getWireEmitStateOf(wx, wy, id).let {
|
|
||||||
Vector2(acc.x + (it?.x ?: 0.0), acc.y + (it?.y ?: 0.0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
oldSinkStatus[index].set(new2)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Refrain from updating signal output from this function: there will be 1 extra tick delay if you do so
|
|
||||||
*/
|
|
||||||
override fun updateImpl(delta: Float) {
|
|
||||||
super.updateImpl(delta)
|
|
||||||
|
|
||||||
val risingEdgeIndices = ArrayList<BlockBoxIndex>()
|
|
||||||
val fallingEdgeIndices = ArrayList<BlockBoxIndex>()
|
|
||||||
|
|
||||||
for (y in 0 until blockBox.height) {
|
|
||||||
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 >= ELECTRIC_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)
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protip: do not make child classes take any argument, especially no function (function "classes" have no zero-arg constructor)
|
* Protip: do not make child classes take any argument, especially no function (function "classes" have no zero-arg constructor)
|
||||||
@@ -536,6 +346,8 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
|
|||||||
|
|
||||||
makeNoiseAndDust(posX, posY)
|
makeNoiseAndDust(posX, posY)
|
||||||
|
|
||||||
|
onSpawn(posX0, posY0)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -645,6 +457,7 @@ interface CuedByWireChange {
|
|||||||
fun updateForWireChange(cue: IngameInstance.BlockChangeQueueItem)
|
fun updateForWireChange(cue: IngameInstance.BlockChangeQueueItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface DeferredSpawn
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard 32-bit binary flags.
|
* Standard 32-bit binary flags.
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import kotlin.properties.Delegates
|
|||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2017-01-07.
|
* Created by minjaesong on 2017-01-07.
|
||||||
*/
|
*/
|
||||||
internal class FixtureTapestry : FixtureBase {
|
internal class FixtureTapestry : FixtureBase, DeferredSpawn {
|
||||||
|
|
||||||
@Transient override val spawnNeedsWall = true
|
@Transient override val spawnNeedsWall = true
|
||||||
@Transient override val spawnNeedsFloor = false
|
@Transient override val spawnNeedsFloor = false
|
||||||
|
|||||||
Reference in New Issue
Block a user