diff --git a/ModuleComputers/src/net/torvald/terrarum/modulecomputers/gameitems/ItemHomeComputer.kt b/ModuleComputers/src/net/torvald/terrarum/modulecomputers/gameitems/ItemHomeComputer.kt index 7f4f3bc57..f3c870135 100644 --- a/ModuleComputers/src/net/torvald/terrarum/modulecomputers/gameitems/ItemHomeComputer.kt +++ b/ModuleComputers/src/net/torvald/terrarum/modulecomputers/gameitems/ItemHomeComputer.kt @@ -36,7 +36,7 @@ class ItemHomeComputer(originalID: ItemID) : GameItem(originalID) { override fun startPrimaryUse(actor: ActorWithBody, delta: Float) = mouseInInteractableRange(actor) { val item = FixtureHomeComputer() - if (item.spawn(Terrarum.mouseTileX, Terrarum.mouseTileY - item.blockBox.height + 1)) 1L else -1L + if (item.spawn(Terrarum.mouseTileX, Terrarum.mouseTileY)) 1L else -1L // return true when placed, false when cannot be placed } } \ No newline at end of file diff --git a/src/net/torvald/terrarum/gameactors/BlockMarkerActor.kt b/src/net/torvald/terrarum/gameactors/BlockMarkerActor.kt index 0d8304716..1bf649421 100644 --- a/src/net/torvald/terrarum/gameactors/BlockMarkerActor.kt +++ b/src/net/torvald/terrarum/gameactors/BlockMarkerActor.kt @@ -66,10 +66,9 @@ class BlockMarkerActor : ActorWithBody(Actor.RenderOrder.OVERLAY, physProp = Phy override fun update(delta: Float) { if (isVisible) { - hitbox.setPosition( - Terrarum.mouseTileX * TILE_SIZED, - (Terrarum.mouseTileY - floor((hitbox.height - 0.5) / TILE_SIZED)) * TILE_SIZED - ) + val hbx = (Terrarum.mouseTileX - floor((hitbox.width - 0.5).div(2) / TILE_SIZED)) * TILE_SIZED + val hby = (Terrarum.mouseTileY - floor((hitbox.height - 0.5) / TILE_SIZED)) * TILE_SIZED + hitbox.setPosition(hbx, hby) } } diff --git a/src/net/torvald/terrarum/gameactors/Luminous.kt b/src/net/torvald/terrarum/gameactors/Luminous.kt index d04b338c2..f6e6763ab 100644 --- a/src/net/torvald/terrarum/gameactors/Luminous.kt +++ b/src/net/torvald/terrarum/gameactors/Luminous.kt @@ -2,6 +2,9 @@ package net.torvald.terrarum.gameactors import net.torvald.gdx.graphics.Cvec +/** + * Lightbox is defined based on pixelwise position in the world! + */ class Lightbox() { var hitbox: Hitbox = Hitbox(0.0,0.0,0.0,0.0) var light: Cvec = Cvec() diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt index d0a4de594..01ec5cfb9 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt @@ -2,6 +2,7 @@ package net.torvald.terrarum.modulebasegame.gameactors import net.torvald.terrarum.* import net.torvald.terrarum.App.printdbg +import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.gameactors.ActorID @@ -59,6 +60,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange { 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 @@ -112,11 +114,11 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange { /** * Adds this instance of the fixture to the world * - * @param posX tile-wise top-left position of the fixture - * @param posY tile-wise top-left position of the fixture - * @return true if successfully spawned, false if was not (e.g. occupied space) + * @param posX0 tile-wise bottem-centre position of the fixture (usually [Terrarum.mouseTileX]) + * @param posY0 tile-wise bottem-centre position of the fixture (usually [Terrarum.mouseTileY]) + * @return true if successfully spawned, false if was not (e.g. space to spawn is occupied by something else) */ - open fun spawn(posX: Int, posY: Int): Boolean { + open fun spawn(posX0: Int, posY0: Int): Boolean { // place filler blocks // place the filler blocks where: // origin posX: centre-left if mouseX is on the right-half of the game window, @@ -128,33 +130,29 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange { // using the actor's hitbox - // wrap x-position - val posX = posX fmod world!!.width - - - // check for existing blocks (and fixtures) - var hasCollision = false - checkForCollision@ - for (y in posY until posY + blockBox.height) { - for (x in posX until posX + blockBox.width) { - val tile = world!!.getTileFromTerrain(x, y) - if (BlockCodex[tile].isSolid || BlockCodex[tile].isActorBlock) { - hasCollision = true - break@checkForCollision - } - } - } - - if (hasCollision) { - printdbg(this, "cannot spawn fixture ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, has tile collision; tilewise dim: (${blockBox.width}, ${blockBox.height}) ") - return false - } - - printdbg(this, "spawn fixture ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, tilewise dim: (${blockBox.width}, ${blockBox.height})") + val posX = (posX0 - blockBox.width.div(2)) fmod world!!.width + val posY = posY0 - blockBox.height + 1 // set the position of this actor worldBlockPos = Point2i(posX, posY) + // check for existing blocks (and fixtures) + var hasCollision = false + forEachBlockbox { x, y, _, _ -> + if (!hasCollision) { + val tile = world!!.getTileFromTerrain(x, y) + if (BlockCodex[tile].isSolid || BlockCodex[tile].isActorBlock) { + hasCollision = true + } + } + } + if (hasCollision) { + printdbg(this, "cannot spawn fixture ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, has tile collision; xy=($posX,$posY) tDim=(${blockBox.width},${blockBox.height})") + return false + } + printdbg(this, "spawn fixture ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, xy=($posX,$posY) tDim=(${blockBox.width},${blockBox.height})") + + // fill the area with the filler blocks placeActorBlocks() diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureSwingingDoorBase.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureSwingingDoorBase.kt index 87063ce71..be0e024bf 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureSwingingDoorBase.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureSwingingDoorBase.kt @@ -22,9 +22,9 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack class FixtureSwingingDoorBase : FixtureBase, Luminous { /* OVERRIDE THESE TO CUSTOMISE */ - open val tw = 2 - open val th = 3 - open val twClosed = 1 + open val tw = 2 // tilewise width of the door when opened + open val th = 3 // tilewise height of the door + open val twClosed = 1 // tilewise width of the door when closed open val opacity = BlockCodex[Block.STONE].opacity open val isOpacityActuallyLuminosity = false open val moduleName = "basegame" @@ -33,6 +33,12 @@ class FixtureSwingingDoorBase : FixtureBase, Luminous { open val customNameFun = { "DOOR_BASE" } /* END OF CUTOMISABLE PARAMETERS */ + private val tilewiseHitboxWidth = tw * 2 - twClosed + private val tilewiseHitboxHeight = th + private val pixelwiseHitboxWidth = TILE_SIZE * tilewiseHitboxWidth + private val pixelwiseHitboxHeight = TILE_SIZE * tilewiseHitboxHeight + private val tilewiseDistToAxis = tw - twClosed + @Transient override val lightBoxList: ArrayList = ArrayList() @Transient override val shadeBoxList: ArrayList = ArrayList() @@ -41,12 +47,9 @@ class FixtureSwingingDoorBase : FixtureBase, Luminous { // @Transient private var placeActorBlockLatch = false constructor() : super( - BlockBox(BlockBox.FULL_COLLISION, 1, 3), // temporary value, will be overwritten by reload() + BlockBox(BlockBox.FULL_COLLISION, 1, 1), // temporary value, will be overwritten by spawn() nameFun = { "item not loaded properly, alas!" } ) { - val hbw = TILE_SIZE * (tw * 2 - twClosed) - val hbh = TILE_SIZE * th - nameFun = customNameFun density = 1200.0 @@ -54,59 +57,69 @@ class FixtureSwingingDoorBase : FixtureBase, Luminous { // loading textures CommonResourcePool.addToLoadingList("$moduleName-$textureIdentifier") { - TextureRegionPack(ModMgr.getGdxFile(moduleName, texturePath), hbw, hbh) + TextureRegionPack(ModMgr.getGdxFile(moduleName, texturePath), pixelwiseHitboxWidth, pixelwiseHitboxHeight) } CommonResourcePool.loadAll() - makeNewSprite(FixtureBase.getSpritesheet(moduleName, texturePath, hbw, hbh)).let { + makeNewSprite(FixtureBase.getSpritesheet(moduleName, texturePath, pixelwiseHitboxWidth, pixelwiseHitboxHeight)).let { it.setRowsAndFrames(3,1) } // define light/shadebox + // TODO: redefine when opened to left/right (if (isOpacityActuallyLuminosity) lightBoxList else shadeBoxList).add( - Lightbox(Hitbox(0.0, 0.0, TILE_SIZED, th * TILE_SIZED), opacity)) + Lightbox(Hitbox(TILE_SIZED * tilewiseDistToAxis, 0.0, TILE_SIZED * twClosed, TILE_SIZED * th), opacity)) + + // define physical size + setHitboxDimension(TILE_SIZE * tilewiseHitboxWidth, TILE_SIZE * tilewiseHitboxHeight, 0, 0) + blockBox = BlockBox(BlockBox.FULL_COLLISION, tilewiseHitboxWidth, tilewiseHitboxHeight) reload() } - override fun spawn(posX: Int, posY: Int) = spawn(posX, posY, TILE_SIZE * (tw * 2 - twClosed), TILE_SIZE * th) + override fun spawn(posX: Int, posY: Int) = spawn(posX, posY, tilewiseHitboxWidth, tilewiseHitboxHeight) // TODO move this function over FixtureBase once it's done and perfected - protected fun spawn(posX: Int, posY: Int, hbw: Int, hbh: Int): Boolean { - // wrap x-position - val posX = posX fmod world!!.width + /** + * Identical to `spawn(Int, Int)` except it takes user-defined hitbox dimension instead of taking value from [blockBox]. + * Useful if [blockBox] cannot be determined on the time of the constructor call. + * + * @param posX tile-wise bottem-centre position of the fixture + * @param posY tile-wise bottem-centre position of the fixture + * @param thbw tile-wise Hitbox width + * @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) + */ + protected fun spawn(posX0: Int, posY0: Int, thbw: Int, thbh: Int): Boolean { + val posX = (posX0 - thbw.div(2)) fmod world!!.width + val posY = posY0 - thbh + 1 - // define physical size - setHitboxDimension(hbw, hbh, 0, 0) - /*this.hitbox.setFromWidthHeight( + // set the position of this actor + worldBlockPos = Point2i(posX, posY) + + // define physical position + this.hitbox.setFromWidthHeight( posX * TILE_SIZED, posY * TILE_SIZED, blockBox.width * TILE_SIZED, blockBox.height * TILE_SIZED - )*/ - blockBox = BlockBox(BlockBox.FULL_COLLISION, tw * 2 - twClosed, th) + ) // check for existing blocks (and fixtures) var hasCollision = false - checkForCollision@ - for (y in posY until posY + blockBox.height) { - for (x in posX until posX + blockBox.width) { + forEachBlockbox { x, y, _, _ -> + if (!hasCollision) { val tile = world!!.getTileFromTerrain(x, y) if (BlockCodex[tile].isSolid || BlockCodex[tile].isActorBlock) { hasCollision = true - break@checkForCollision } } } - if (hasCollision) { - printdbg(this, "cannot spawn fixture ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, has tile collision; tilewise dim: (${blockBox.width}, ${blockBox.height}) ") + printdbg(this, "cannot spawn fixture ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, has tile collision; xy=($posX,$posY) tDim=(${blockBox.width},${blockBox.height})") return false } + printdbg(this, "spawn fixture ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, xy=($posX,$posY) tDim=(${blockBox.width},${blockBox.height})") - printdbg(this, "spawn fixture ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, tilewise dim: (${blockBox.width}, ${blockBox.height})") - - // set the position of this actor - worldBlockPos = Point2i(posX - (hbw - 1) / 2, posY) // fill the area with the filler blocks placeActorBlocks() @@ -128,19 +141,11 @@ class FixtureSwingingDoorBase : FixtureBase, Luminous { nameFun = customNameFun - val hbw = TILE_SIZE * (tw * 2 - twClosed) - val hbh = TILE_SIZE * th + // define light/shadebox + // TODO: redefine when opened to left/right + (if (isOpacityActuallyLuminosity) lightBoxList else shadeBoxList).add( + Lightbox(Hitbox(TILE_SIZED * tilewiseDistToAxis, 0.0, TILE_SIZED * twClosed, TILE_SIZED * th), opacity)) - // redefined things that are affected by sprite size -// blockBox = BlockBox(BlockBox.FULL_COLLISION, tw * 2 - twClosed, th) - - // loading textures - -// setHitboxDimension(hbw, hbh, TILE_SIZE * (tw * 2 - twClosed), 0) -// setHitboxDimension(hbw, hbh, TILE_SIZE * ((tw * 2 - twClosed - 1) / 2), 0) - - -// placeActorBlockLatch = false } open protected fun closeDoor() { @@ -169,12 +174,14 @@ class FixtureSwingingDoorBase : FixtureBase, Luminous { override fun placeActorBlocks() { forEachBlockbox { x, y, ox, oy -> + printdbg(this, "placeActorBlocks xy=$x,$y oxy=$ox,$oy") + val tile = when (doorState) { // CLOSED -- // fill the actorBlock so that: // N..N F N..N (repeated `th` times; N: no collision, F: full collision) 0/*CLOSED*/ -> { - if (ox in tw-1 until tw-1+twClosed) Block.ACTORBLOCK_FULL_COLLISION + if (ox in tilewiseDistToAxis until tilewiseDistToAxis + twClosed) Block.ACTORBLOCK_FULL_COLLISION else Block.ACTORBLOCK_NO_COLLISION } else/*OPENED*/ -> Block.ACTORBLOCK_NO_COLLISION diff --git a/src/net/torvald/terrarum/modulebasegame/gameitems/FixtureItemBase.kt b/src/net/torvald/terrarum/modulebasegame/gameitems/FixtureItemBase.kt index 3ace402e3..3dcdab82a 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameitems/FixtureItemBase.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameitems/FixtureItemBase.kt @@ -33,8 +33,8 @@ open class FixtureItemBase(originalID: ItemID, val fixtureClassName: String) : G // println("FixtureItemBase init: $hash") } -// private var _ghostItem: FixtureBase? = null @Transient private var ghostItem = AtomicReference() + @Transient private var ghostInit = AtomicBoolean(false) override var dynamicID: ItemID = originalID override val originalName = "FIXTUREBASE" @@ -55,7 +55,6 @@ open class FixtureItemBase(originalID: ItemID, val fixtureClassName: String) : G override var baseToolSize: Double? = baseMass - @Transient private var ghostInit = AtomicBoolean(false) override fun effectWhileEquipped(actor: ActorWithBody, delta: Float) { // println("ghost: ${ghostItem}; ghostInit = $ghostInit; instance: $hash") @@ -87,7 +86,7 @@ open class FixtureItemBase(originalID: ItemID, val fixtureClassName: String) : G override fun startPrimaryUse(actor: ActorWithBody, delta: Float) = mouseInInteractableRange(actor) { val item = ghostItem.getAndSet(makeFixture()) // renew the "ghost" otherwise you'll be spawning exactly the same fixture again; old ghost will be returned - if (item.spawn(Terrarum.mouseTileX, Terrarum.mouseTileY - item.blockBox.height + 1)) 1 else -1 + if (item.spawn(Terrarum.mouseTileX, Terrarum.mouseTileY)) 1 else -1 // return true when placed, false when cannot be placed }