door and its ghost now spawns at the right position in the world

This commit is contained in:
minjaesong
2022-07-19 21:46:59 +09:00
parent 06ef46d369
commit 78d249cb6e
6 changed files with 83 additions and 77 deletions

View File

@@ -36,7 +36,7 @@ class ItemHomeComputer(originalID: ItemID) : GameItem(originalID) {
override fun startPrimaryUse(actor: ActorWithBody, delta: Float) = mouseInInteractableRange(actor) { override fun startPrimaryUse(actor: ActorWithBody, delta: Float) = mouseInInteractableRange(actor) {
val item = FixtureHomeComputer() 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 // return true when placed, false when cannot be placed
} }
} }

View File

@@ -66,10 +66,9 @@ class BlockMarkerActor : ActorWithBody(Actor.RenderOrder.OVERLAY, physProp = Phy
override fun update(delta: Float) { override fun update(delta: Float) {
if (isVisible) { if (isVisible) {
hitbox.setPosition( val hbx = (Terrarum.mouseTileX - floor((hitbox.width - 0.5).div(2) / TILE_SIZED)) * TILE_SIZED
Terrarum.mouseTileX * TILE_SIZED, val hby = (Terrarum.mouseTileY - floor((hitbox.height - 0.5) / TILE_SIZED)) * TILE_SIZED
(Terrarum.mouseTileY - floor((hitbox.height - 0.5) / TILE_SIZED)) * TILE_SIZED hitbox.setPosition(hbx, hby)
)
} }
} }

View File

@@ -2,6 +2,9 @@ package net.torvald.terrarum.gameactors
import net.torvald.gdx.graphics.Cvec import net.torvald.gdx.graphics.Cvec
/**
* Lightbox is defined based on pixelwise position in the world!
*/
class Lightbox() { class Lightbox() {
var hitbox: Hitbox = Hitbox(0.0,0.0,0.0,0.0) var hitbox: Hitbox = Hitbox(0.0,0.0,0.0,0.0)
var light: Cvec = Cvec() var light: Cvec = Cvec()

View File

@@ -2,6 +2,7 @@ package net.torvald.terrarum.modulebasegame.gameactors
import net.torvald.terrarum.* import net.torvald.terrarum.*
import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.gameactors.ActorID import net.torvald.terrarum.gameactors.ActorID
@@ -59,6 +60,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
id: ActorID? = null id: ActorID? = null
) : super(renderOrder, PhysProperties.IMMOBILE, id) { ) : super(renderOrder, PhysProperties.IMMOBILE, id) {
blockBox = blockBox0 blockBox = blockBox0
setHitboxDimension(TILE_SIZE * blockBox.width, TILE_SIZE * blockBox.height, 0, 0)
this.blockBoxProps = blockBoxProps this.blockBoxProps = blockBoxProps
this.renderOrder = renderOrder this.renderOrder = renderOrder
this.nameFun = nameFun this.nameFun = nameFun
@@ -112,11 +114,11 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
/** /**
* Adds this instance of the fixture to the world * Adds this instance of the fixture to the world
* *
* @param posX tile-wise top-left position of the fixture * @param posX0 tile-wise bottem-centre position of the fixture (usually [Terrarum.mouseTileX])
* @param posY tile-wise top-left position of the fixture * @param posY0 tile-wise bottem-centre position of the fixture (usually [Terrarum.mouseTileY])
* @return true if successfully spawned, false if was not (e.g. occupied space) * @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 filler blocks
// place the filler blocks where: // place the filler blocks where:
// origin posX: centre-left if mouseX is on the right-half of the game window, // 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 // using the actor's hitbox
// wrap x-position val posX = (posX0 - blockBox.width.div(2)) fmod world!!.width
val posX = posX fmod world!!.width val posY = posY0 - blockBox.height + 1
// 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})")
// set the position of this actor // set the position of this actor
worldBlockPos = Point2i(posX, posY) 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 // fill the area with the filler blocks
placeActorBlocks() placeActorBlocks()

View File

@@ -22,9 +22,9 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
class FixtureSwingingDoorBase : FixtureBase, Luminous { class FixtureSwingingDoorBase : FixtureBase, Luminous {
/* OVERRIDE THESE TO CUSTOMISE */ /* OVERRIDE THESE TO CUSTOMISE */
open val tw = 2 open val tw = 2 // tilewise width of the door when opened
open val th = 3 open val th = 3 // tilewise height of the door
open val twClosed = 1 open val twClosed = 1 // tilewise width of the door when closed
open val opacity = BlockCodex[Block.STONE].opacity open val opacity = BlockCodex[Block.STONE].opacity
open val isOpacityActuallyLuminosity = false open val isOpacityActuallyLuminosity = false
open val moduleName = "basegame" open val moduleName = "basegame"
@@ -33,6 +33,12 @@ class FixtureSwingingDoorBase : FixtureBase, Luminous {
open val customNameFun = { "DOOR_BASE" } open val customNameFun = { "DOOR_BASE" }
/* END OF CUTOMISABLE PARAMETERS */ /* 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<Lightbox> = ArrayList() @Transient override val lightBoxList: ArrayList<Lightbox> = ArrayList()
@Transient override val shadeBoxList: ArrayList<Lightbox> = ArrayList() @Transient override val shadeBoxList: ArrayList<Lightbox> = ArrayList()
@@ -41,12 +47,9 @@ class FixtureSwingingDoorBase : FixtureBase, Luminous {
// @Transient private var placeActorBlockLatch = false // @Transient private var placeActorBlockLatch = false
constructor() : super( 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!" } nameFun = { "item not loaded properly, alas!" }
) { ) {
val hbw = TILE_SIZE * (tw * 2 - twClosed)
val hbh = TILE_SIZE * th
nameFun = customNameFun nameFun = customNameFun
density = 1200.0 density = 1200.0
@@ -54,59 +57,69 @@ class FixtureSwingingDoorBase : FixtureBase, Luminous {
// loading textures // loading textures
CommonResourcePool.addToLoadingList("$moduleName-$textureIdentifier") { CommonResourcePool.addToLoadingList("$moduleName-$textureIdentifier") {
TextureRegionPack(ModMgr.getGdxFile(moduleName, texturePath), hbw, hbh) TextureRegionPack(ModMgr.getGdxFile(moduleName, texturePath), pixelwiseHitboxWidth, pixelwiseHitboxHeight)
} }
CommonResourcePool.loadAll() CommonResourcePool.loadAll()
makeNewSprite(FixtureBase.getSpritesheet(moduleName, texturePath, hbw, hbh)).let { makeNewSprite(FixtureBase.getSpritesheet(moduleName, texturePath, pixelwiseHitboxWidth, pixelwiseHitboxHeight)).let {
it.setRowsAndFrames(3,1) it.setRowsAndFrames(3,1)
} }
// define light/shadebox // define light/shadebox
// TODO: redefine when opened to left/right
(if (isOpacityActuallyLuminosity) lightBoxList else shadeBoxList).add( (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() 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 // 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 * Identical to `spawn(Int, Int)` except it takes user-defined hitbox dimension instead of taking value from [blockBox].
val posX = posX fmod world!!.width * 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 // set the position of this actor
setHitboxDimension(hbw, hbh, 0, 0) worldBlockPos = Point2i(posX, posY)
/*this.hitbox.setFromWidthHeight(
// define physical position
this.hitbox.setFromWidthHeight(
posX * TILE_SIZED, posX * TILE_SIZED,
posY * TILE_SIZED, posY * TILE_SIZED,
blockBox.width * TILE_SIZED, blockBox.width * TILE_SIZED,
blockBox.height * TILE_SIZED blockBox.height * TILE_SIZED
)*/ )
blockBox = BlockBox(BlockBox.FULL_COLLISION, tw * 2 - twClosed, th)
// check for existing blocks (and fixtures) // check for existing blocks (and fixtures)
var hasCollision = false var hasCollision = false
checkForCollision@ forEachBlockbox { x, y, _, _ ->
for (y in posY until posY + blockBox.height) { if (!hasCollision) {
for (x in posX until posX + blockBox.width) {
val tile = world!!.getTileFromTerrain(x, y) val tile = world!!.getTileFromTerrain(x, y)
if (BlockCodex[tile].isSolid || BlockCodex[tile].isActorBlock) { if (BlockCodex[tile].isSolid || BlockCodex[tile].isActorBlock) {
hasCollision = true hasCollision = true
break@checkForCollision
} }
} }
} }
if (hasCollision) { 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 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 // fill the area with the filler blocks
placeActorBlocks() placeActorBlocks()
@@ -128,19 +141,11 @@ class FixtureSwingingDoorBase : FixtureBase, Luminous {
nameFun = customNameFun nameFun = customNameFun
val hbw = TILE_SIZE * (tw * 2 - twClosed) // define light/shadebox
val hbh = TILE_SIZE * th // 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() { open protected fun closeDoor() {
@@ -169,12 +174,14 @@ class FixtureSwingingDoorBase : FixtureBase, Luminous {
override fun placeActorBlocks() { override fun placeActorBlocks() {
forEachBlockbox { x, y, ox, oy -> forEachBlockbox { x, y, ox, oy ->
printdbg(this, "placeActorBlocks xy=$x,$y oxy=$ox,$oy")
val tile = when (doorState) { val tile = when (doorState) {
// CLOSED -- // CLOSED --
// fill the actorBlock so that: // fill the actorBlock so that:
// N..N F N..N (repeated `th` times; N: no collision, F: full collision) // N..N F N..N (repeated `th` times; N: no collision, F: full collision)
0/*CLOSED*/ -> { 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 Block.ACTORBLOCK_NO_COLLISION
} }
else/*OPENED*/ -> Block.ACTORBLOCK_NO_COLLISION else/*OPENED*/ -> Block.ACTORBLOCK_NO_COLLISION

View File

@@ -33,8 +33,8 @@ open class FixtureItemBase(originalID: ItemID, val fixtureClassName: String) : G
// println("FixtureItemBase init: $hash") // println("FixtureItemBase init: $hash")
} }
// private var _ghostItem: FixtureBase? = null
@Transient private var ghostItem = AtomicReference<FixtureBase>() @Transient private var ghostItem = AtomicReference<FixtureBase>()
@Transient private var ghostInit = AtomicBoolean(false)
override var dynamicID: ItemID = originalID override var dynamicID: ItemID = originalID
override val originalName = "FIXTUREBASE" override val originalName = "FIXTUREBASE"
@@ -55,7 +55,6 @@ open class FixtureItemBase(originalID: ItemID, val fixtureClassName: String) : G
override var baseToolSize: Double? = baseMass override var baseToolSize: Double? = baseMass
@Transient private var ghostInit = AtomicBoolean(false)
override fun effectWhileEquipped(actor: ActorWithBody, delta: Float) { override fun effectWhileEquipped(actor: ActorWithBody, delta: Float) {
// println("ghost: ${ghostItem}; ghostInit = $ghostInit; instance: $hash") // 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) { 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 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 // return true when placed, false when cannot be placed
} }