diff --git a/src/net/torvald/spriteanimation/AssembledSpriteAnimation.kt b/src/net/torvald/spriteanimation/AssembledSpriteAnimation.kt index 248736f72..1187fc360 100644 --- a/src/net/torvald/spriteanimation/AssembledSpriteAnimation.kt +++ b/src/net/torvald/spriteanimation/AssembledSpriteAnimation.kt @@ -1,6 +1,5 @@ package net.torvald.spriteanimation -import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Pixmap import com.badlogic.gdx.graphics.Texture import com.badlogic.gdx.graphics.g2d.SpriteBatch @@ -162,6 +161,7 @@ class AssembledSpriteAnimation( override fun render(batch: SpriteBatch, posX: Float, posY: Float, scale: Float) { if (parentActor.isVisible) { + batch.color = colourFilter renderThisAnimation(batch, posX, posY, scale, "${currentAnimation}_${1+currentFrame}") } } diff --git a/src/net/torvald/spriteanimation/SpriteAnimation.kt b/src/net/torvald/spriteanimation/SpriteAnimation.kt index 20be67aff..0eecd2db9 100644 --- a/src/net/torvald/spriteanimation/SpriteAnimation.kt +++ b/src/net/torvald/spriteanimation/SpriteAnimation.kt @@ -1,5 +1,6 @@ package net.torvald.spriteanimation +import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.utils.Disposable import com.jme3.math.FastMath @@ -19,6 +20,7 @@ abstract class SpriteAnimation(@Transient val parentActor: ActorWithBody) : Disp var flipHorizontal = false var flipVertical = false + var colourFilter = Color(-1) open fun flip(horizontal: Boolean, vertical: Boolean) { flipHorizontal = horizontal @@ -144,8 +146,7 @@ class SheetSpriteAnimation(parentActor: ActorWithBody) : SpriteAnimation(parentA if (visible) { val region = textureRegion.get(currentFrame, currentRow) -// batch.color = colorFilter - + batch.color = colourFilter val tx = (parentActor.hitboxTranslateX) * scale val txF = (parentActor.hitboxTranslateX + parentActor.baseHitboxW) * scale diff --git a/src/net/torvald/terrarum/gameactors/ActorWithBody.kt b/src/net/torvald/terrarum/gameactors/ActorWithBody.kt index bfd030523..ae3cfa4d0 100644 --- a/src/net/torvald/terrarum/gameactors/ActorWithBody.kt +++ b/src/net/torvald/terrarum/gameactors/ActorWithBody.kt @@ -67,7 +67,7 @@ open class ActorWithBody : Actor { protected set open var tooltipText: String? = null // null: display nothing val mouseUp: Boolean - get() = hitbox.containsPoint(Terrarum.mouseX, Terrarum.mouseY) + get() = hitbox.containsPoint((world?.width ?: 0) * TILE_SIZED, Terrarum.mouseX, Terrarum.mouseY) var hitboxTranslateX: Int = 0// relative to spritePosX protected set diff --git a/src/net/torvald/terrarum/gameactors/Hitbox.kt b/src/net/torvald/terrarum/gameactors/Hitbox.kt index fcae0de6a..43acfd82a 100644 --- a/src/net/torvald/terrarum/gameactors/Hitbox.kt +++ b/src/net/torvald/terrarum/gameactors/Hitbox.kt @@ -158,21 +158,24 @@ class Hitbox { return this } - // TODO consider ROUNDWORLD - fun containsPoint(x: Double, y: Double) = (x - hitboxStart.x) in 0.0..width && (y - hitboxStart.y) in 0.0..height - fun containsPoint(p: Point2d) = containsPoint(p.x, p.y) - - - infix fun intersects(position: Point2d) = - (position.x >= startX && position.x <= startX + width) && - (position.y >= startY && position.y <= startY + height) - infix fun intersects(other: Hitbox) = - (this.startX <= other.startX && other.startX <= this.endX) || - (this.startX <= other.endX && other.endX <= this.endX) && - - (this.startY <= other.startY && other.startY <= this.endY) || - (this.startY <= other.endY && other.endY <= this.endY) + /** *ROUNDWORLD*-aware version of intersects(Double, Double). */ + fun containsPoint(worldWidth: Double, x: Double, y: Double) = intersects(x, y) || intersects(x + worldWidth, y) || intersects(x - worldWidth, y) + /** *ROUNDWORLD*-aware version of intersects(Poind2d). */ + fun containsPoint(worldWidth: Double, p: Point2d) = containsPoint(worldWidth, p.x, p.y) + /** *ROUNDWORLD*-aware version of intersects(Hitbox). */ + fun containsHitbox(worldWidth: Double, other: Hitbox): Boolean { + val osx = other.startX; val osy = other.startY; val oex = other.endX; val oey = other.endY // to avoid redundant maths operations + return intersects(osx, osy, oex, oey) || intersects(osx + worldWidth, osy, oex + worldWidth, oey) || intersects(osx - worldWidth, osy, oex - worldWidth, oey) + } + fun intersects(px: Double, py: Double) = + (px in startX..endX) && + (py in startY..endY) + infix fun intersects(position: Point2d) = intersects(position.x, position.y) + infix fun intersects(other: Hitbox) = intersects(other.startX, other.startY, other.endX, other.endY) + fun intersects(otherStartX: Double, otherStartY: Double, otherEndX: Double, otherEndY: Double) = + (this.endX >= otherStartX && otherEndX >= this.startX) && + (this.endY >= otherStartY && otherEndY >= this.startY) fun toVector(): Vector2 = Vector2(startX, startY) diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt index 1f1497e40..68533c821 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt @@ -84,6 +84,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange { * @param action a function with following arguments: posX, posY, offX, offY */ open fun forEachBlockbox(action: (Int, Int, Int, Int) -> Unit) { + // TODO scale-aware worldBlockPos?.let { (posX, posY) -> for (y in posY until posY + blockBox.height) { for (x in posX until posX + blockBox.width) { diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureSwingingDoorBase.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureSwingingDoorBase.kt index 818baa4e0..b9d20cb35 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureSwingingDoorBase.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureSwingingDoorBase.kt @@ -105,6 +105,7 @@ open class FixtureSwingingDoorBase : FixtureBase, Luminous { doorState = 0 placeActorBlocks() } + doorCloseQueued = false } open protected fun openToRight() { @@ -113,6 +114,7 @@ open class FixtureSwingingDoorBase : FixtureBase, Luminous { doorState = 1 placeActorBlocks() } + doorCloseQueued = false } open protected fun openToLeft() { @@ -121,6 +123,7 @@ open class FixtureSwingingDoorBase : FixtureBase, Luminous { doorState = -1 placeActorBlocks() } + doorCloseQueued = false } /*override fun forEachBlockbox(action: (Int, Int, Int, Int) -> Unit) { @@ -174,10 +177,10 @@ open class FixtureSwingingDoorBase : FixtureBase, Luminous { } private fun ActorWithBody.ontheLeftSideOfDoor(): Boolean { - return this.hitbox.centeredX < this@FixtureSwingingDoorBase.hitbox.centeredX + return this.hitbox.startX < this@FixtureSwingingDoorBase.hitbox.centeredX } private fun ActorWithBody.ontheRightSideOfDoor(): Boolean { - return this.hitbox.centeredX > this@FixtureSwingingDoorBase.hitbox.centeredX + return this.hitbox.endX > this@FixtureSwingingDoorBase.hitbox.centeredX } private fun ActorWithBody.movingTowardsRight(): Boolean { @@ -190,66 +193,102 @@ open class FixtureSwingingDoorBase : FixtureBase, Luminous { return ((this.controllerV ?: Vector2()) + this.externalV).x.absoluteValue < PHYS_EPSILON_VELO } + private var doorCloseQueueTimer = 0f + private var doorCloseQueued = false + + private fun queueDoorClosing() { + doorCloseQueueTimer = 0f + doorCloseQueued = true + } + override fun update(delta: Float) { super.update(delta) + + // debug colouring +// this.sprite?.colourFilter = +// if (doorCloseQueued) Color.YELLOW +// else if (doorStateTimer > doorHoldLength[doorState]!!) Color.LIME +// else Color.CORAL + + if (!flagDespawn && worldBlockPos != null) { - val actors = INGAME.actorContainerActive.filterIsInstance() - - // auto opening and closing - // TODO make this work with "player_alies" faction, not just a player - val installer: IngamePlayer? = if (actorThatInstalledThisFixture == null) null else INGAME.actorContainerActive.filterIsInstance().filter { it.uuid == actorThatInstalledThisFixture }.ifEmpty { - INGAME.actorContainerInactive.filterIsInstance().filter { it.uuid == actorThatInstalledThisFixture } - }.getOrNull(0) - - // if the door is "owned" by someone, restrict access to its "amicable" (defined using Faction subsystem) actors - // if the door is owned by null, restrict access to ActorHumanoid and actors with "intelligent" actor value set up - if (actorThatInstalledThisFixture == null || installer != null) { - val amicableActors: List = ArrayList( - if (actorThatInstalledThisFixture == null) - actors.filterIsInstance() union actors.filter { it.actorValue.getAsBoolean("intelligent") == true } - else { - val goodFactions = installer?.faction?.flatMap { it.factionAmicable }?.toHashSet() - if (goodFactions != null) - actors.filterIsInstance().filter { - (it.faction.map { it.factionName } intersect goodFactions).isNotEmpty() - } as List - else - listOf() - } - ).also { - // add the installer of the door to the amicableActors if for some reason it was not added - if (installer != null && !it.contains(installer)) it.add(0, installer) - }.filter { - // filter amicableActors so that ones standing near the door remain - it.hitbox.intersects(this.hitbox) - } - - // automatic opening/closing - if (doorStateTimer > doorHoldLength[doorState]!!) { - var nobodyIsThere = true - for (actor in amicableActors) { - if (actor.ontheLeftSideOfDoor() && actor.movingTowardsRight()) { - openToRight() - nobodyIsThere = false - break - } - else if (actor.ontheRightSideOfDoor() && actor.movingTowardsLeft()) { - openToLeft() - nobodyIsThere = false - break - } - } - if (nobodyIsThere) { - closeDoor() - } - - doorStateTimer = 0f - } + // delayed auto closing + if (doorCloseQueued && doorCloseQueueTimer >= doorOpenedHoldLength) { + closeDoor() + } + else if (doorCloseQueued) { + doorCloseQueueTimer += delta } + // automatic opening/closing + if (doorStateTimer > doorHoldLength[doorState]!!) { + val actors = INGAME.actorContainerActive.filterIsInstance() + + // auto opening and closing + // TODO make this work with "player_alies" faction, not just a player + val installer: IngamePlayer? = if (actorThatInstalledThisFixture == null) null + else INGAME.actorContainerActive.filterIsInstance().filter { it.uuid == actorThatInstalledThisFixture }.ifEmpty { + INGAME.actorContainerInactive.filterIsInstance().filter { it.uuid == actorThatInstalledThisFixture } + }.getOrNull(0) + + // if the door is "owned" by someone, restrict access to its "amicable" (defined using Faction subsystem) actors + // if the door is owned by null, restrict access to ActorHumanoid and actors with "intelligent" actor value set up + if (actorThatInstalledThisFixture == null || installer != null) { + val amicableActors: List = ArrayList( + if (actorThatInstalledThisFixture == null) + actors.filterIsInstance() union actors.filter { it.actorValue.getAsBoolean("intelligent") == true } + else { + val goodFactions = installer?.faction?.flatMap { it.factionAmicable }?.toHashSet() + if (goodFactions != null) + actors.filterIsInstance().filter { + (it.faction.map { it.factionName } intersect goodFactions).isNotEmpty() + } as List + else + listOf() + } + ).also { + // add the installer of the door to the amicableActors if for some reason it was not added + if (installer != null && !it.contains(installer)) it.add(0, installer) + }.filter { + // filter amicableActors so that ones standing near the door remain + this.hitbox.containsHitbox(INGAME.world.width * TILE_SIZED, it.hitbox) + } + + var nobodyIsThere = true + val oldState = doorState + + for (actor in amicableActors) { + if (doorState != 0) { + if (this.hitbox.containsHitbox(INGAME.world.width * TILE_SIZED, actor.hitbox)) { + nobodyIsThere = false + break + } + } + else { + if (actor.ontheLeftSideOfDoor() && actor.movingTowardsRight()) { + openToRight() + nobodyIsThere = false + break + } + else if (actor.ontheRightSideOfDoor() && actor.movingTowardsLeft()) { + openToLeft() + nobodyIsThere = false + break + } + } + } + if (nobodyIsThere && !doorCloseQueued && doorState != 0) { + queueDoorClosing() + } + + if (oldState != doorState) doorStateTimer = 0f + } + } + else { + doorStateTimer += delta + } - doorStateTimer += delta } }