fixing bug where the hitbox won't change when actor is rescaled, wip issue #34

This commit is contained in:
minjaesong
2020-03-10 06:52:40 +09:00
parent 8589f1f8fa
commit ed5c823154
6 changed files with 59 additions and 40 deletions

View File

@@ -130,17 +130,19 @@ class SpriteAnimation(@Transient val parentActor: ActorWBMovable) {
val region = textureRegion.get(currentFrame, currentRow)
batch.color = colorFilter
val scale = parentActor.scale.toFloat()
if (flipHorizontal && flipVertical) {
batch.draw(region,
FastMath.floor(posX).toFloat() + (2f * parentActor.hitboxTranslateX * parentActor.scale.toFloat() + parentActor.hitbox.width.toFloat()),
FastMath.floor(posY).toFloat() + (2f * parentActor.hitboxTranslateY * parentActor.scale.toFloat() + parentActor.hitbox.height.toFloat()),
FastMath.floor(posX).toFloat() + (2f * parentActor.hitboxTranslateX * scale + parentActor.hitbox.width.toFloat()),
FastMath.floor(posY).toFloat() + (2f * parentActor.hitboxTranslateY * scale + parentActor.hitbox.height.toFloat()),
-FastMath.floor(cellWidth * scale).toFloat(),
-FastMath.floor(cellHeight * scale).toFloat()
)
}
else if (flipHorizontal) {
batch.draw(region,
FastMath.floor(posX).toFloat() + (2f * parentActor.hitboxTranslateX * parentActor.scale.toFloat() + parentActor.hitbox.width.toFloat()),
FastMath.floor(posX).toFloat() + (2f * parentActor.hitboxTranslateX * scale + scale * parentActor.hitbox.width.toFloat()),
FastMath.floor(posY).toFloat(),
-FastMath.floor(cellWidth * scale).toFloat(),
FastMath.floor(cellHeight * scale).toFloat()
@@ -149,7 +151,7 @@ class SpriteAnimation(@Transient val parentActor: ActorWBMovable) {
else if (flipVertical) {
batch.draw(region,
FastMath.floor(posX).toFloat(),
FastMath.floor(posY).toFloat() + (2f * parentActor.hitboxTranslateY * parentActor.scale.toFloat() + parentActor.hitbox.height.toFloat()),
FastMath.floor(posY).toFloat() + (2f * parentActor.hitboxTranslateY * scale + parentActor.hitbox.height.toFloat()),
FastMath.floor(cellWidth * scale).toFloat(),
-FastMath.floor(cellHeight * scale).toFloat()
)

View File

@@ -132,15 +132,15 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
* Physical properties.
*/
/** Apparent scale. Use "avBaseScale" for base scale */
var scale: Double
val scale: Double
inline get() = (actorValue.getAsDouble(AVKey.SCALE) ?: 1.0) *
(actorValue.getAsDouble(AVKey.SCALEBUFF) ?: 1.0)
set(value) {
/*set(value) {
val scaleDelta = value - scale
actorValue[AVKey.SCALE] = value / (actorValue.getAsDouble(AVKey.SCALEBUFF) ?: 1.0)
// reposition
translatePosition(-baseHitboxW * scaleDelta / 2, -baseHitboxH * scaleDelta)
}
}*/
@Transient val MASS_LOWEST = 0.1 // Kilograms
/** Apparent mass. Use "avBaseMass" for base mass */
val mass: Double
@@ -298,6 +298,8 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
}
/**
* ONLY FOR INITIAL SETUP
*
* @param w
* @param h
* @param tx positive: translate sprite to LEFT.
@@ -318,6 +320,8 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
/**
* ONLY FOR INITIAL SETUP
*
* Set hitbox position from bottom-center point
* @param x
* @param y
@@ -330,10 +334,6 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
baseHitboxH * scale)
}
private fun translatePosition(dx: Double, dy: Double) {
hitbox.translate(dx, dy)
}
// get() methods are moved to update(), too much stray object being created is definitely not good
val centrePosVector: Vector2 = Vector2(0.0,0.0)
//get() = Vector2(hitbox.centeredX, hitbox.centeredY)
@@ -363,6 +363,11 @@ open class ActorWBMovable(renderOrder: RenderOrder, val immobileBody: Boolean =
override fun update(delta: Float) {
// re-scale hitbox
// it's just much better to poll them than use perfectly-timed setter because latter simply cannot exist
hitbox.canonicalResize(baseHitboxW * scale, baseHitboxH * scale)
val oldHitbox = hitbox.clone()
if (isUpdate && !flagDespawn) {

View File

@@ -33,9 +33,21 @@ class Hitbox (x1: Double, y1: Double, width: Double, height: Double, var suppres
}
}
override fun toString(): String {
return "[$hitboxStart - $hitboxEnd]"
}
val startX: Double
get() = hitboxStart.x
val startY: Double
get() = hitboxStart.y
val endX: Double
get() = hitboxStart.x + width
val endY: Double
get() = hitboxStart.y + height
val centeredX: Double
get() = hitboxStart.x + width * 0.5
val centeredY: Double
get() = hitboxStart.y + height * 0.5
/**
* @return bottom-centered point of hitbox.
@@ -49,11 +61,6 @@ class Hitbox (x1: Double, y1: Double, width: Double, height: Double, var suppres
inline val canonicalY: Double
get() = endY
val endX: Double
get() = hitboxStart.x + width
val endY: Double
get() = hitboxStart.y + height
/**
* Set to the point top left
* @param x1
@@ -111,34 +118,31 @@ class Hitbox (x1: Double, y1: Double, width: Double, height: Double, var suppres
return this
}
/**
* For initial setup only. Use CanonicalResize for graceful resizing
*/
fun setDimension(w: Double, h: Double): Hitbox {
width = w
height = h
return this
}
fun canonicalResize(w: Double, h: Double): Hitbox {
// sx_1 + 0.5w_1 = sx_2 + 0.5w_2 // equals because the final point must not move. sx_1: old start-x, sx_2: new start-x which is what we want
// sx_2 = sx_1 + 0.5w_1 - 0.5w_2 // move variables to right-hand side to derive final value sx_2
hitboxStart.set(
startX + 0.5 * width - 0.5 * w,
startY + height - h
)
width = w
height = h
return this
}
fun containsPoint(x: Double, y: Double) = (hitboxStart.x - x) in 0.0..width && (hitboxStart.y - y) in 0.0..height
fun containsPoint(p: Point2d) = containsPoint(p.x, p.y)
/**
* Returns x value of start point
* @return top-left point startX
*/
val startX: Double
get() = hitboxStart.x
/**
* Returns y value of start point
* @return top-left point startY
*/
val startY: Double
get() = hitboxStart.y
val centeredX: Double
get() = hitboxStart.x + width * 0.5
val centeredY: Double
get() = hitboxStart.y + height * 0.5
infix fun intersects(position: Point2d) =
(position.x >= startX && position.x <= startX + width) &&
@@ -162,4 +166,8 @@ class Hitbox (x1: Double, y1: Double, width: Double, height: Double, var suppres
this.width == other.width &&
this.height == other.height
}
override fun toString(): String {
return "[$hitboxStart - $hitboxEnd]"
}
}

View File

@@ -4,6 +4,7 @@ import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.console.ConsoleCommand
import net.torvald.terrarum.console.Echo
import net.torvald.terrarum.console.EchoError
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.gameactors.ActorWBMovable
@@ -27,7 +28,8 @@ internal object SetScale : ConsoleCommand {
EchoError("Target is not ActorWBMovable")
}
else {
target.scale = scale
target.actorValue[AVKey.SCALE] = scale
//target.scale = scale
}
}
catch (e: NumberFormatException) {

View File

@@ -2,6 +2,7 @@ package net.torvald.terrarum.modulebasegame.gameactors
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameactors.ActorWBMovable
import net.torvald.terrarum.gameitem.GameItem
import net.torvald.terrarum.itemproperties.ItemCodex
@@ -22,7 +23,7 @@ open class DroppedItem(private val item: GameItem) : ActorWBMovable(RenderOrder.
else
ItemCodex[item.dynamicID]!!.mass
scale = ItemCodex[item.dynamicID]!!.scale
actorValue[AVKey.SCALE] = ItemCodex[item.dynamicID]!!.scale
}
override fun update(delta: Float) {

View File

@@ -44,6 +44,7 @@ object PlayerBuilderTestSubject1 {
//p.actorValue[AVKey.LUMA] = 1.93
p.actorValue[AVKey.AIRJUMPPOINT] = 0
p.actorValue[AVKey.SCALE] = 2.0
return p
}