physics sorta works well with player, but not balls

- bounce for downward works, bounce for left/right wall hit does not
- headbutt is still undefined behaviour for all phys objs
This commit is contained in:
minjaesong
2017-05-27 15:48:35 +09:00
parent 80777fcccb
commit b96daa7d3d

View File

@@ -77,16 +77,7 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
* for "Controllable" actors * for "Controllable" actors
*/ */
var controllerMoveDelta: Vector2? = if (this is Controllable) Vector2() else null var controllerMoveDelta: Vector2? = if (this is Controllable) Vector2() else null
var walkX: Double
get() = controllerMoveDelta!!.x
protected set(value) {
controllerMoveDelta?.x = value
}
var walkY: Double
get() = controllerMoveDelta!!.y
protected set(value) {
controllerMoveDelta?.y = value
}
// not sure we need this... // not sure we need this...
//var jumpable = true // this is kind of like "semaphore" //var jumpable = true // this is kind of like "semaphore"
@@ -219,8 +210,8 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
@Transient private val COLLIDING_UD = 4 @Transient private val COLLIDING_UD = 4
@Transient private val COLLIDING_LR = 5 @Transient private val COLLIDING_LR = 5
@Transient private val COLLIDING_ALLSIDE = 6 @Transient private val COLLIDING_ALLSIDE = 6
@Transient private val COLLIDING_LEFT_EXTRA = 7 //@Transient private val COLLIDING_LEFT_EXTRA = 7
@Transient private val COLLIDING_RIGHT_EXTRA = 7 //@Transient private val COLLIDING_RIGHT_EXTRA = 7
/** /**
* Temporary variables * Temporary variables
@@ -593,7 +584,7 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
} }
fun debug2(wut: Any?) { fun debug2(wut: Any?) {
// vvvvv set it true to make debug print work // vvvvv set it true to make debug print work
if (true) println(wut) if (false) println(wut)
} }
fun debug3(wut: Any?) { fun debug3(wut: Any?) {
// vvvvv set it true to make debug print work // vvvvv set it true to make debug print work
@@ -601,7 +592,7 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
} }
fun debug4(wut: Any?) { fun debug4(wut: Any?) {
// vvvvv set it true to make debug print work // vvvvv set it true to make debug print work
if (false) println(wut) if (true) println(wut)
} }
//val moveDelta = externalForce + controllerMoveDelta //val moveDelta = externalForce + controllerMoveDelta
@@ -720,19 +711,19 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
// apply Normal Force // apply Normal Force
// next step (resolve controllerMoveDelta) requires this to be pre-handled // next step (resolve controllerMoveDelta) requires this to be pre-handled
if (isTouchingSide(simulationHitbox, COLLIDING_BOTTOM)) { if (isTouchingSide(simulationHitbox, COLLIDING_BOTTOM)) {
walkY *= elasticity controllerMoveDelta?.y?.let { controllerMoveDelta!!.y *= -elasticity }
externalForce.y *= elasticity externalForce.y *= elasticity
debug1("!! grounded ${Random().nextInt(1000)}!!") debug1("!! grounded ${Random().nextInt(1000)}!!")
} }
else if (isTouchingSide(simulationHitbox, COLLIDING_TOP)) { else if (isTouchingSide(simulationHitbox, COLLIDING_TOP)) {
walkY *= elasticity controllerMoveDelta?.y?.let { controllerMoveDelta!!.y *= -elasticity }
externalForce.y *= elasticity externalForce.y *= -elasticity
debug1("!! headbutt ${Random().nextInt(1000)}!!") debug1("!! headbutt ${Random().nextInt(1000)}!!")
} }
if (isTouchingSide(simulationHitbox, COLLIDING_LR)) { if (isTouchingSide(simulationHitbox, COLLIDING_LR)) {
//walkX *= elasticity //walkX *= elasticity
externalForce.x *= elasticity externalForce.x *= -elasticity
debug1("!! tackle ${Random().nextInt(1000)}!!") debug1("!! tackle ${Random().nextInt(1000)}!!")
} }
} }
@@ -842,15 +833,18 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
val vectorSum = externalForce + controllerMoveDelta val vectorSum = externalForce + controllerMoveDelta
// --> Y-Axis // --> Y-Axis (bottom)
if (simulationHitbox.endY.modTileDelta() > 0 && isTouchingSide(simulationHitbox, COLLIDING_BOTTOM)) { if (simulationHitbox.endY.modTileDelta() > 0 && isTouchingSide(simulationHitbox, COLLIDING_BOTTOM)) {
//val displacementMainAxis = -1.00001 //val displacementMainAxis = -1.00001
//val displacementSecondAxis = displacementMainAxis * vectorSum.x / vectorSum.y // use controllerMoveDelta.x / controllerMoveDelta.y ? //val displacementSecondAxis = displacementMainAxis * vectorSum.x / vectorSum.y // use controllerMoveDelta.x / controllerMoveDelta.y ?
//simulationHitbox.translate(displacementSecondAxis, displacementMainAxis) //simulationHitbox.translate(displacementSecondAxis, displacementMainAxis)
//debug2("1 dx: $displacementSecondAxis, dy: $displacementMainAxis") //debug2("1 dx: $displacementSecondAxis, dy: $displacementMainAxis")
debug2("1 modeTileDelta = ${simulationHitbox.endY.modTileDelta()}") debug4("1 modeTileDelta = ${simulationHitbox.endY.modTileDelta()}")
simulationHitbox.translate(0.0, -simulationHitbox.endY.modTileDelta()) simulationHitbox.translate(0.0, -simulationHitbox.endY.modTileDelta())
} // NO COMMENT OUT: another quirk
hitAndReflectY()
}
// --> Y-Axis (top)
/*else if (vectorSum.y < 0.0 && isTouchingSide(simulationHitbox, COLLIDING_TOP)) { /*else if (vectorSum.y < 0.0 && isTouchingSide(simulationHitbox, COLLIDING_TOP)) {
//val displacementMainAxis = 1.0 //val displacementMainAxis = 1.0
//val displacementSecondAxis = displacementMainAxis * vectorSum.x / vectorSum.y //val displacementSecondAxis = displacementMainAxis * vectorSum.x / vectorSum.y
@@ -859,18 +853,23 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
simulationHitbox.translate(0.0, 1.0) simulationHitbox.translate(0.0, 1.0)
}*/ }*/
// --> X-Axis // --> X-Axis (right side)
if (vectorSum.x > 0 && simulationHitbox.endX.modTileDelta() >= 15.99999) { if (vectorSum.x > 0 && simulationHitbox.endX.modTileDelta() >= 15.99999) {
val target = simulationHitbox.endX.div(TILE_SIZE).floorInt().plus(1).times(TILE_SIZE).toDouble() val target = simulationHitbox.endX.div(TILE_SIZE).floorInt().plus(1).times(TILE_SIZE).toDouble()
val delta = target - simulationHitbox.endX val delta = target - simulationHitbox.endX
debug2("xR target: $target, delta: $delta") debug4("xR: endX: ${simulationHitbox.endX}, target: $target, delta: $delta")
simulationHitbox.translatePosX(delta) simulationHitbox.translatePosX(delta)
hitAndReflectX()
} }
// --> X-Axis (left side)
else if (vectorSum.x < 0 && simulationHitbox.startX.modTileDelta() >= 0.99999 && simulationHitbox.startX.modTileDelta() < 1.0) { else if (vectorSum.x < 0 && simulationHitbox.startX.modTileDelta() >= 0.99999 && simulationHitbox.startX.modTileDelta() < 1.0) {
val target = simulationHitbox.startX.div(TILE_SIZE).floorInt().times(TILE_SIZE).toDouble() val target = simulationHitbox.startX.div(TILE_SIZE).floorInt().times(TILE_SIZE).toDouble()
val delta = target - simulationHitbox.startX val delta = target - simulationHitbox.startX
debug2("xL target: $target, delta: $delta") debug4("xL: startX: ${simulationHitbox.startX}, target: $target, delta: $delta")
simulationHitbox.translatePosX(delta) simulationHitbox.translatePosX(delta)
hitAndReflectX()
} }
@@ -878,14 +877,14 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
if (isTouchingSide(simulationHitbox, COLLIDING_LR)) { if (isTouchingSide(simulationHitbox, COLLIDING_LR)) {
//controllerMoveDelta!!.x *= elasticity // FIXME commented: "brake" applied when climbing down several steps //controllerMoveDelta?.x?.let { controllerMoveDelta!!.x *= -elasticity } // FIXME commented: "brake" applied when climbing down several steps
} }
if (isTouchingSide(simulationHitbox, COLLIDING_TOP)) { if (isTouchingSide(simulationHitbox, COLLIDING_TOP)) {
controllerMoveDelta!!.y *= elasticity controllerMoveDelta?.y?.let { controllerMoveDelta!!.y *= -elasticity }
} }
debug4("final controller: $controllerMoveDelta, displacement: ${simulationHitbox - hitbox}") debug1("final controller: $controllerMoveDelta, displacement: ${simulationHitbox - hitbox}")
hitbox.reassign(simulationHitbox) hitbox.reassign(simulationHitbox)
@@ -902,34 +901,13 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
private fun hitAndReflectX() { private fun hitAndReflectX() {
// when it sticks, externalForce.x goes back and forth
/*
1123921356 trying to reflectX
1123921356 -1.3677473305837262
1123921356 trying to reflectX
1123921356 0.8150659571934893
1123921356 trying to reflectX
1123921356 -0.48545419966417575
1123921356 trying to reflectX
1123921356 0.28939570979162116
1123921356 trying to reflectX
1123921356 -0.17225986626214265
1123921356 trying to reflectX
1123921356 0.1027945259506898
1123921356 trying to reflectX
1123921356 -0.06108288092971576
*/
externalForce.x *= -elasticity externalForce.x *= -elasticity
if (this is Controllable) walkX *= -elasticity // commented; should be managed by displaceHitbox() //controllerMoveDelta?.x?.let { controllerMoveDelta!!.x *= -elasticity }
//println("$this\t${externalForce.x}")
} }
private fun hitAndReflectY() { private fun hitAndReflectY() {
println("** reflY **")
externalForce.y *= -elasticity externalForce.y *= -elasticity
if (this is Controllable) walkY *= -elasticity // commented; should be managed by displaceHitbox() //controllerMoveDelta?.y?.let { controllerMoveDelta!!.x *= -elasticity }
} }
@Transient private val CEILING_HIT_ELASTICITY = 0.3 @Transient private val CEILING_HIT_ELASTICITY = 0.3
@@ -975,9 +953,9 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
if (isNoCollideWorld) return false if (isNoCollideWorld) return false
// detectors are inside of the bounding box // detectors are inside of the bounding box
val x1 = hitbox.startX val x1 = hitbox.startX - A_PIXEL // to compensate for asym, x1 is moved a pixel left
val x2 = hitbox.endX - A_PIXEL val x2 = hitbox.endX - A_PIXEL
val y1 = hitbox.startY val y1 = hitbox.startY - A_PIXEL // CONJECTURE: to compensate for asym, y1 is moved a pixel up
val y2 = hitbox.endY - A_PIXEL val y2 = hitbox.endY - A_PIXEL
@@ -1006,10 +984,12 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
=| |= =| |=
=+-----+= =+-----+=
####### // BOTTOM ####### // BOTTOM
IMPORTANT AF NOTE: things are ASYMMETRIC!
*/ */
// detectors are inside of the bounding box // detectors are inside of the bounding box
if (option == COLLIDING_TOP) { if (option == COLLIDING_TOP) { // CONJECTURE: to compensate for asym, y1 is moved a pixel up
x1 = hitbox.startX x1 = hitbox.startX
x2 = hitbox.endX - A_PIXEL x2 = hitbox.endX - A_PIXEL
y1 = hitbox.startY - A_PIXEL - A_PIXEL y1 = hitbox.startY - A_PIXEL - A_PIXEL
@@ -1021,8 +1001,8 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
y1 = hitbox.endY y1 = hitbox.endY
y2 = y1 y2 = y1
} }
else if (option == COLLIDING_LEFT) { else if (option == COLLIDING_LEFT) { // to compensate for asym, x1 is moved a pixel left
x1 = hitbox.startX - A_PIXEL x1 = hitbox.startX - 2 * A_PIXEL
x2 = x1 x2 = x1
y1 = hitbox.startY y1 = hitbox.startY
y2 = hitbox.endY - A_PIXEL y2 = hitbox.endY - A_PIXEL
@@ -1033,18 +1013,6 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
y1 = hitbox.startY y1 = hitbox.startY
y2 = hitbox.endY - A_PIXEL y2 = hitbox.endY - A_PIXEL
} }
else if (option == COLLIDING_LEFT_EXTRA) {
x1 = hitbox.startX - A_PIXEL - A_PIXEL
x2 = x1 + A_PIXEL
y1 = hitbox.startY
y2 = hitbox.endY - A_PIXEL
}
else if (option == COLLIDING_RIGHT_EXTRA) {
x1 = hitbox.endX
x2 = x1 + A_PIXEL
y1 = hitbox.startY
y2 = hitbox.endY - A_PIXEL
}
else if (option == COLLIDING_ALLSIDE) { else if (option == COLLIDING_ALLSIDE) {
return isTouchingSide(hitbox, COLLIDING_LEFT) || isTouchingSide(hitbox, COLLIDING_RIGHT) || return isTouchingSide(hitbox, COLLIDING_LEFT) || isTouchingSide(hitbox, COLLIDING_RIGHT) ||
isTouchingSide(hitbox, COLLIDING_BOTTOM) || isTouchingSide(hitbox, COLLIDING_TOP) isTouchingSide(hitbox, COLLIDING_BOTTOM) || isTouchingSide(hitbox, COLLIDING_TOP)
@@ -1144,13 +1112,13 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
} }
if (this is Controllable) { if (this is Controllable) {
if (walkX < 0) { if (controllerMoveDelta!!.x < 0) {
walkX += friction controllerMoveDelta!!.x += friction
if (walkX > 0) walkX = 0.0 if (controllerMoveDelta!!.x > 0) controllerMoveDelta!!.x = 0.0
} }
else if (walkX > 0) { else if (controllerMoveDelta!!.x > 0) {
walkX -= friction controllerMoveDelta!!.x -= friction
if (walkX < 0) walkX = 0.0 if (controllerMoveDelta!!.x < 0) controllerMoveDelta!!.x = 0.0
} }
} }
} }
@@ -1171,13 +1139,13 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
} }
if (this is Controllable) { if (this is Controllable) {
if (walkY < 0) { if (controllerMoveDelta!!.y < 0) {
walkY += friction controllerMoveDelta!!.y += friction
if (walkY > 0) walkY = 0.0 if (controllerMoveDelta!!.y > 0) controllerMoveDelta!!.y = 0.0
} }
else if (walkY > 0) { else if (controllerMoveDelta!!.y > 0) {
walkY -= friction controllerMoveDelta!!.y -= friction
if (walkY < 0) walkY = 0.0 if (controllerMoveDelta!!.y < 0) controllerMoveDelta!!.y = 0.0
} }
} }
} }
@@ -1343,11 +1311,11 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
blendLightenOnly() blendLightenOnly()
val offsetX = if (!spriteGlow!!.flippedHorizontal()) val offsetX = if (!spriteGlow!!.flippedHorizontal())
hitboxTranslateX * scale hitboxTranslateX * scale - 1
else else
spriteGlow!!.cellWidth * scale - (hitbox.width + hitboxTranslateX * scale) spriteGlow!!.cellWidth * scale - (hitbox.width + hitboxTranslateX * scale) - 1
val offsetY = spriteGlow!!.cellHeight * scale - hitbox.height - hitboxTranslateY * scale - 2 val offsetY = spriteGlow!!.cellHeight * scale - hitbox.height - hitboxTranslateY * scale - 1
if (WorldCamera.xCentre > leftsidePadding && centrePosPoint.x <= rightsidePadding) { if (WorldCamera.xCentre > leftsidePadding && centrePosPoint.x <= rightsidePadding) {
// camera center neg, actor center pos // camera center neg, actor center pos
@@ -1384,11 +1352,11 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
BlendMode.resolve(drawMode) BlendMode.resolve(drawMode)
val offsetX = if (!sprite!!.flippedHorizontal()) val offsetX = if (!sprite!!.flippedHorizontal())
hitboxTranslateX * scale hitboxTranslateX * scale - 1
else else
sprite!!.cellWidth * scale - (hitbox.width + hitboxTranslateX * scale) sprite!!.cellWidth * scale - (hitbox.width + hitboxTranslateX * scale) - 1
val offsetY = sprite!!.cellHeight * scale - hitbox.height - hitboxTranslateY * scale - 2 val offsetY = sprite!!.cellHeight * scale - hitbox.height - hitboxTranslateY * scale - 1
if (WorldCamera.xCentre > leftsidePadding && centrePosPoint.x <= rightsidePadding) { if (WorldCamera.xCentre > leftsidePadding && centrePosPoint.x <= rightsidePadding) {
// camera center neg, actor center pos // camera center neg, actor center pos