From 02db6b8fedc91cf6747fbeb86238b3128e4292f7 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Sun, 6 Oct 2024 14:06:04 +0900 Subject: [PATCH] reorientable gearbox because input and output cannot be on the same location --- .../basegame/sprites/fixtures/gearbox.tga | 3 + src/net/torvald/terrarum/Point2d.kt | 4 + .../terrarum/modulebasegame/WorldSimulator.kt | 2 +- .../modulebasegame/gameactors/Electric.kt | 12 +- .../modulebasegame/gameactors/FixtureBase.kt | 19 ++- .../gameactors/FixtureInductionMotor.kt | 143 ++++++++++-------- .../gameactors/FixtureLogicSignalAdder.kt | 2 +- .../gameactors/FixtureSwingingDoorBase.kt | 2 +- .../gameactors/FixtureTapestry.kt | 4 +- .../gameactors/FixtureTextSignCopper.kt | 5 +- .../graphics/sprites/fixtures/gearbox.kra | 4 +- 11 files changed, 118 insertions(+), 82 deletions(-) create mode 100644 assets/mods/basegame/sprites/fixtures/gearbox.tga diff --git a/assets/mods/basegame/sprites/fixtures/gearbox.tga b/assets/mods/basegame/sprites/fixtures/gearbox.tga new file mode 100644 index 000000000..7cd258369 --- /dev/null +++ b/assets/mods/basegame/sprites/fixtures/gearbox.tga @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:80fb0cacb36c15a8a7021900b9ad00bcf542f8b63d35ae58d4524de7ec67ef5f +size 2194 diff --git a/src/net/torvald/terrarum/Point2d.kt b/src/net/torvald/terrarum/Point2d.kt index bd6e52695..68032db8d 100644 --- a/src/net/torvald/terrarum/Point2d.kt +++ b/src/net/torvald/terrarum/Point2d.kt @@ -119,6 +119,10 @@ class Point2i() { } override fun hashCode(): Int = XXHash32.hashGeoCoord(x, y) + override fun equals(other: Any?) = if (other is Point2i) + this.x == other.x && this.y == other.y + else + false override fun toString() = "Point2i($x, $y)" diff --git a/src/net/torvald/terrarum/modulebasegame/WorldSimulator.kt b/src/net/torvald/terrarum/modulebasegame/WorldSimulator.kt index c88bf48ad..57e27c89a 100644 --- a/src/net/torvald/terrarum/modulebasegame/WorldSimulator.kt +++ b/src/net/torvald/terrarum/modulebasegame/WorldSimulator.kt @@ -630,7 +630,7 @@ object WorldSimulator { INGAME.getActorsAt(point.x * TILE_SIZED, point.y * TILE_SIZED).filterIsInstance().firstOrNull().let { found -> if (found != null) { // get offset from the fixture's origin - tileOffsetFromFixture = found.intTilewiseHitbox.let { Point2i(it.startX.toInt(), it.startY.toInt()) } - tilePoint + tileOffsetFromFixture = found.worldBlockPos!! - tilePoint // println("$tilePoint; ${found.javaClass.canonicalName}, $tileOffsetFromFixture, ${found.getWireSinkAt(tileOffsetFromFixture!!)}") diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/Electric.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/Electric.kt index 2f96a348b..b26733b8a 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/Electric.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/Electric.kt @@ -100,8 +100,8 @@ open class Electric : FixtureBase { open fun updateSignal() {} fun getWireStateAt(offsetX: Int, offsetY: Int, sinkType: WireEmissionType): Vector2 { - val wx = offsetX + intTilewiseHitbox.startX.toInt() - val wy = offsetY + intTilewiseHitbox.startY.toInt() + val wx = offsetX + worldBlockPos!!.x + val wy = offsetY + worldBlockPos!!.y return WireCodex.getAllWiresThatAccepts(sinkType).fold(Vector2()) { acc, (id, _) -> INGAME.world.getWireEmitStateOf(wx, wy, id).let { @@ -141,8 +141,8 @@ open class Electric : FixtureBase { 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 wx = offsetX + worldBlockPos!!.x + val wy = offsetY + worldBlockPos!!.y val new2 = WireCodex.getAllWiresThatAccepts(wireSinkTypes[index] ?: "").fold(Vector2()) { acc, (id, _) -> INGAME.world.getWireEmitStateOf(wx, wy, id).let { @@ -168,8 +168,8 @@ open class Electric : FixtureBase { // get indices of "rising edges" // get indices of "falling edges" - val wx = x + intTilewiseHitbox.startX.toInt() - val wy = y + intTilewiseHitbox.startY.toInt() + val wx = x + worldBlockPos!!.x + val wy = y + worldBlockPos!!.y 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)) diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt index 50716b861..a9ed6209e 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt @@ -183,6 +183,8 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange { return (posX until posX + blockBox.width).toList().cartesianProduct((posY until posY + blockBox.height).toList()) } + open fun spawnCustomGetSpawningOffset() = 0 to 0 + /** * Returns BlockBox definition as a list of individual blocks, absolute position in the world. * @@ -306,8 +308,12 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange { // posY: bottom of the blockBox // using the actor's hitbox - val posX = (posX0 - blockBox.width.minus(1).div(2)) fmod world!!.width // width.minus(1) so that spawning position would be same as the ghost's position - val posY = posY0 - blockBox.height + 1 + val (ox, oy) = spawnCustomGetSpawningOffset() + val posX0 = posX0 + ox + val posY0 = posY0 + oy + + val posX = ox + (posX0 - blockBox.width.minus(1).div(2)) fmod world!!.width // width.minus(1) so that spawning position would be same as the ghost's position + val posY = oy + posY0 - blockBox.height + 1 if (!canSpawnHere(posX0, posY0)) { printdbg(this, "cannot spawn fixture1 ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, has tile collision; xy=($posX,$posY) tDim=(${blockBox.width},${blockBox.height})") @@ -317,10 +323,12 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange { printdbg(this, "spawn fixture ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, xy=($posX,$posY) tDim=(${blockBox.width},${blockBox.height})") + // at this point, worldBlockPos was set by the canSpawnHere() function + + // fill the area with the filler blocks placeActorBlocks() - this.isVisible = true this.hitbox.setFromWidthHeight( posX * TILE_SIZED, @@ -358,7 +366,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange { * @param thbh tile-wise Hitbox height * @return true if successfully spawned, false if was not (e.g. space to spawn is occupied by something else) */ - open fun spawn(posX0: Int, posY0: Int, installersUUID: UUID?, thbw: Int, thbh: Int): Boolean { + open fun spawnUsingCustomBoxSize(posX0: Int, posY0: Int, installersUUID: UUID?, thbw: Int, thbh: Int): Boolean { val posX = (posX0 - thbw.minus(1).div(2)) fmod world!!.width // width.minus(1) so that spawning position would be same as the ghost's position val posY = posY0 - thbh + 1 @@ -453,6 +461,9 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange { * This function MUST BE super-called for make despawn call to work at all. */ override fun updateImpl(delta: Float) { + actorValue.set(AVKey.SCALE, 1.0) + actorValue.set(AVKey.SCALEBUFF, 1.0) + //////////////////////////////////////////////////////////// super.updateImpl(delta) chunkAnchoring = inOperation diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureInductionMotor.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureInductionMotor.kt index ff272d9ca..474b22d5f 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureInductionMotor.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureInductionMotor.kt @@ -1,11 +1,14 @@ package net.torvald.terrarum.modulebasegame.gameactors +import com.badlogic.gdx.graphics.g2d.SpriteBatch import net.torvald.spriteanimation.SheetSpriteAnimation import net.torvald.terrarum.App import net.torvald.terrarum.INGAME import net.torvald.terrarum.Point2i import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE +import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED import net.torvald.terrarum.gameactors.AVKey +import net.torvald.terrarum.gameworld.fmod import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.modulebasegame.gameactors.FixtureInductionMotor.Companion.MASS import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase @@ -68,7 +71,7 @@ class FixtureInductionMotor : Electric { /** * Created by minjaesong on 2024-10-05. */ -class FixtureGearbox : Electric { +class FixtureGearbox : Electric, Reorientable { @Transient override val spawnNeedsFloor = true @Transient override val spawnNeedsWall = false @@ -82,95 +85,104 @@ class FixtureGearbox : Electric { return listOf(posX+1 to posY+1) } + override fun spawnCustomGetSpawningOffset() = 0 to 1 + + override fun orientClockwise() { + orientation = 1 - orientation + reorient(); setEmitterAndSink(); updateSignal() + } + + override fun orientAnticlockwise() { + orientation = 1 - orientation + reorient(); setEmitterAndSink(); updateSignal() + } + + override var orientation = 0 // 0 or 1 + + private fun reorient() { + (sprite as SheetSpriteAnimation).currentRow = orientation + } + + private fun setEmitterAndSink() { + clearStatus() + when (orientation) { + 0 -> { + posVecsIn.forEach { (x, y) -> + setWireSinkAt(x, y, "axle") + } + posVecsOut.forEach { (x, y) -> + setWireEmitterAt(x, y, "axle") + } + } + 1 -> { + posVecsIn.forEach { (x, y) -> + setWireEmitterAt(x, y, "axle") + } + posVecsOut.forEach { (x, y) -> + setWireSinkAt(x, y, "axle") + } + } + } + } + init { val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/gearbox.tga") density = 7874.0 - setHitboxDimension(TILE_SIZE, TILE_SIZE, 0, TILE_SIZE) + setHitboxDimension(TILE_SIZE, TILE_SIZE, 0, 0) makeNewSprite(TextureRegionPack(itemImage.texture, TILE_SIZE, TILE_SIZE+1)).let { - it.setRowsAndFrames(1,1) + it.setRowsAndFrames(2,1) } actorValue[AVKey.BASEMASS] = MASS - posVecs.forEach { (x, y) -> - setWireEmitterAt(x, y, "axle") - setWireSinkAt(x, y, "axle") - } + setEmitterAndSink() } + override fun updateImpl(delta: Float) { - super.updateImpl(delta) - - // animate the sprite - val worldX = intTilewiseHitbox.startX.toInt() - val worldY = intTilewiseHitbox.startY.toInt() - - val targetTick = (App.TICK_SPEED / speedMax).let { - it.coerceIn(0.0, Long.MAX_VALUE.toDouble()) - }.roundToLong() - - val sprite = (sprite as SheetSpriteAnimation) - - val phaseShift = if (worldY % 2 == 0) - (worldX % 2 == 1) - else - (worldX % 2 == 0) - - - if (targetTick > 0) { - (INGAME.WORLD_UPDATE_TIMER % (targetTick * 2)).let { - sprite.currentFrame = - if (phaseShift) - (it < targetTick).toInt() - else - (it >= targetTick).toInt() - } + // re-position the hitbox because wtf + worldBlockPos?.let { (x, y) -> + val x = (x+1) * TILE_SIZED; val y = (y+1) * TILE_SIZED + hitbox.setFromTwoPoints(x, y, x + TILE_SIZED, y + TILE_SIZED) } + + super.updateImpl(delta) } @Transient private var speedMax = 0.0 - private var maxSpeedLoc = ArrayList() - private var minTorqueLoc = ArrayList() - - @Transient private val newMaxSpeedLoc = ArrayList() - @Transient private val newMinTorqueLoc = ArrayList() - override fun updateSignal() { + val a = when (orientation) { + 0 -> posVecsIn + 1 -> posVecsOut + else -> throw InternalError() + } + val b = when (orientation) { + 0 -> posVecsOut + 1 -> posVecsIn + else -> throw InternalError() + } + + var torqueMin = Double.POSITIVE_INFINITY - newMaxSpeedLoc.clear() - newMinTorqueLoc.clear() speedMax = 0.0 - posVecs.forEach { + a.forEach { val vec = getWireStateAt(it.x, it.y, "axle") - if (!maxSpeedLoc.contains(it) && vec.x >= speedMax) { - newMaxSpeedLoc.add(Point2i(it.x, it.y)) + if (vec.x.absoluteValue >= ELECTRIC_EPSILON_GENERIC && vec.x >= speedMax) { speedMax = vec.x } - if (!minTorqueLoc.contains(it) && vec.y.absoluteValue >= ELECTRIC_EPSILON_GENERIC && vec.y <= torqueMin) { - newMinTorqueLoc.add(Point2i(it.x, it.y)) + if (vec.y.absoluteValue >= ELECTRIC_EPSILON_GENERIC && vec.y <= torqueMin) { torqueMin = if (vec.y == Double.POSITIVE_INFINITY) 0.0 else vec.y } - - // FIXME: intTilewiseHitbox discrepancy with spawn position. - val wx = it.x + intTilewiseHitbox.startX.toInt() - val wy = it.y + intTilewiseHitbox.startY.toInt() - print("$wx,$wy\t") - - if (maxSpeedLoc.contains(it)) - println("$it*\t$vec") - else - println("$it\t$vec") } - println("--------") - maxSpeedLoc.clear(); maxSpeedLoc.addAll(newMaxSpeedLoc) - minTorqueLoc.clear(); minTorqueLoc.addAll(newMinTorqueLoc) + if (torqueMin == Double.POSITIVE_INFINITY) torqueMin = 0.0 - posVecs.forEach { (x, y) -> + + b.forEach { (x, y) -> setWireEmissionAt(x, y, Vector2(speedMax, torqueMin)) } } @@ -180,10 +192,17 @@ class FixtureGearbox : Electric { } companion object { - @Transient val posVecs = listOf( - Point2i(1, 0), + @Transient val posVecsIn = listOf( +// Point2i(1, 0), Point2i(0, 1), Point2i(2, 1), +// Point2i(1, 2), + ) + + @Transient val posVecsOut = listOf( + Point2i(1, 0), +// Point2i(0, 1), +// Point2i(2, 1), Point2i(1, 2), ) } diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureLogicSignalAdder.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureLogicSignalAdder.kt index 59762baf6..17fe08950 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureLogicSignalAdder.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureLogicSignalAdder.kt @@ -97,7 +97,7 @@ class FixtureLogicSignalAdder : Electric, Reorientable { private val I: Boolean get() = when (orientation) { -// 0 -> getWireStateAt(0, 0, "digital_bit").x >= ELECTRIC_THRESHOLD_HIGH + 0 -> getWireStateAt(0, 0, "digital_bit").x >= ELECTRIC_THRESHOLD_HIGH 1 -> getWireStateAt(1, 0, "digital_bit").x >= ELECTRIC_THRESHOLD_HIGH 2 -> getWireStateAt(1, 1, "digital_bit").x >= ELECTRIC_THRESHOLD_HIGH 3 -> getWireStateAt(0, 1, "digital_bit").x >= ELECTRIC_THRESHOLD_HIGH diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureSwingingDoorBase.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureSwingingDoorBase.kt index aaede77ec..024a5b164 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureSwingingDoorBase.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureSwingingDoorBase.kt @@ -143,7 +143,7 @@ open class FixtureSwingingDoorBase : FixtureBase { reload() } - override fun spawn(posX: Int, posY: Int, installersUUID: UUID?): Boolean = spawn(posX, posY, installersUUID, tilewiseHitboxWidth, tilewiseHitboxHeight) + override fun spawn(posX: Int, posY: Int, installersUUID: UUID?): Boolean = spawnUsingCustomBoxSize(posX, posY, installersUUID, tilewiseHitboxWidth, tilewiseHitboxHeight) override fun makeNoiseAndDust(posX: Int, posY: Int) { val posYb = posY + blockBox.height - 1 diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureTapestry.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureTapestry.kt index bcfbb2e60..40e6d778e 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureTapestry.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureTapestry.kt @@ -50,7 +50,7 @@ internal class FixtureTapestry : FixtureBase { reload() } - override fun spawn(posX: Int, posY: Int, installersUUID: UUID?): Boolean = spawn(posX, posY, installersUUID, tilewiseHitboxWidth, tilewiseHitboxHeight) + override fun spawn(posX: Int, posY: Int, installersUUID: UUID?): Boolean = spawnUsingCustomBoxSize(posX, posY, installersUUID, tilewiseHitboxWidth, tilewiseHitboxHeight) override fun reload() { super.reload() @@ -111,7 +111,7 @@ internal class FixtureTapestry : FixtureBase { // must be re-spawned on reload to make it visible after load - spawn( + spawnUsingCustomBoxSize( intTilewiseHitbox.canonicalX.toInt(), intTilewiseHitbox.canonicalY.toInt(), actorThatInstalledThisFixture, diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureTextSignCopper.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureTextSignCopper.kt index ba5f3ea5c..7dc749103 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureTextSignCopper.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureTextSignCopper.kt @@ -18,7 +18,6 @@ import net.torvald.terrarum.itemproperties.Item import net.torvald.terrarum.langpack.Lang import net.torvald.terrarum.modulebasegame.gameitems.ItemTextSignCopper import net.torvald.terrarum.modulebasegame.ui.UIItemInventoryCellCommonRes.tooltipShowing -import net.torvald.terrarum.ui.Toolkit import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack import net.torvald.unicode.TIMES import org.dyn4j.geometry.Vector2 @@ -71,7 +70,7 @@ class FixtureTextSignCopper : Electric { return item.dynamicID } - override fun spawn(posX: Int, posY: Int, installersUUID: UUID?): Boolean = spawn(posX, posY, installersUUID, panelCount.coerceAtLeast(2), 2) + override fun spawn(posX: Int, posY: Int, installersUUID: UUID?): Boolean = spawnUsingCustomBoxSize(posX, posY, installersUUID, panelCount.coerceAtLeast(2), 2) override fun reload() { super.reload() @@ -86,7 +85,7 @@ class FixtureTextSignCopper : Electric { } // must be re-spawned on reload to make it visible after load - spawn( + spawnUsingCustomBoxSize( intTilewiseHitbox.canonicalX.toInt(), intTilewiseHitbox.canonicalY.toInt(), actorThatInstalledThisFixture, diff --git a/work_files/graphics/sprites/fixtures/gearbox.kra b/work_files/graphics/sprites/fixtures/gearbox.kra index 30d6ad3e3..da6f76f02 100644 --- a/work_files/graphics/sprites/fixtures/gearbox.kra +++ b/work_files/graphics/sprites/fixtures/gearbox.kra @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fcd7f43303a3fe8f116714ab7e2643398e790e67bd459fe0c4b1f3d4c37f90f4 -size 121639 +oid sha256:4ee72be8783852b395658a53c623ec8aa454733df06fcad2e98dd2e2b34b53da +size 176896