From 9732c6d66f28ded6dda000b2477e6606c870fedf Mon Sep 17 00:00:00 2001 From: minjaesong Date: Tue, 9 May 2017 00:46:38 +0900 Subject: [PATCH] y-down blocking work (can jump down to hit the ground but not the ceiling) --- .../terrarum/gameactors/ActorHumanoid.kt | 9 +- .../terrarum/gameactors/ActorWithPhysics.kt | 136 ++++++++++-------- .../terrarum/ui/BasicDebugInfoWindow.kt | 21 +-- 3 files changed, 93 insertions(+), 73 deletions(-) diff --git a/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt b/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt index 84c3a2de9..d401f56d6 100644 --- a/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt +++ b/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt @@ -459,7 +459,10 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null) jumpAcc = pwr * timedJumpCharge * JUMP_ACCELERATION_MOD * Math.sqrt(scale) // positive value - walkY -= jumpAcc + walkY -= jumpAcc // feed negative value to the vector + // do not think of resetting this to zero when counter hit the ceiling; that's HOW NOT + // newtonian physics work, stupid myself :( + } // not sure we need this... /*else if (!jumpable) { @@ -502,7 +505,7 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null) noClip = b if (b) { - moveDelta.zero() + externalForce.zero() controllerMoveDelta?.zero() } } @@ -517,7 +520,7 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null) if (grounded) { // set anim row - if (moveDelta.x != 0.0) { + if (controllerMoveDelta?.x != 0.0) { if (sprite != null) sprite!!.switchRow(SPRITE_ROW_WALK) if (spriteGlow != null) spriteGlow!!.switchRow(SPRITE_ROW_WALK) } diff --git a/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt b/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt index bd8ca6b57..55d207ad0 100644 --- a/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt +++ b/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt @@ -521,14 +521,14 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean if (moveDelta.y > 0.0) { if (isTouchingSide(hitbox, COLLIDING_TOP)) { // hit the ceiling hitAndReflectY() //hitAndForciblyReflectY() - grounded = false + //grounded = false } else if (isTouchingSide(hitbox, COLLIDING_BOTTOM)) { // actor hit something on its bottom hitAndReflectY() grounded = true } else { // the actor is not grounded at all - grounded = false + //grounded = false } } // or was moving upward? @@ -653,77 +653,89 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean // collision not found + var collisionNotFound = false if (ccdTick == ccdSteps) { hitbox.translate(externalForce) println("no collision; endX = ${hitbox.endPointX}") - return + collisionNotFound = true } + if (!collisionNotFound) { + println("embedding befure: ${simulationHitbox.endPointX}") - println("embedding befure: ${simulationHitbox.endPointX}") + // find no-collision point using binary search + // trust me, X- and Y-axis must move simultaneously. + //// binary search //// + if (ccdTick >= 1) { + var low = (ccdTick - 1).toDouble() / ccdSteps + var high = (ccdTick).toDouble() / ccdSteps + var bmid: Double - // find no-collision point using binary search - // trust me, X- and Y-axis must move simultaneously. - //// binary search //// - if (ccdTick >= 1) { - var low = (ccdTick - 1).toDouble() / ccdSteps - var high = (ccdTick).toDouble() / ccdSteps - var bmid: Double + (1..binaryBranchingMax).forEach { _ -> - (1..binaryBranchingMax).forEach { _ -> + bmid = (low + high) / 2.0 - bmid = (low + high) / 2.0 + simulationHitbox.reassign(hitbox) + simulationHitbox.translate(getBacktrackDelta(bmid)) - simulationHitbox.reassign(hitbox) - simulationHitbox.translate(getBacktrackDelta(bmid)) + print("bmid = $bmid, new endY: ${simulationHitbox.endPointY}") - print("bmid = $bmid, new endY: ${simulationHitbox.endPointY}") - - // set new mid - if (isColliding(simulationHitbox)) { //COLLIDING_EXTRA_SIZE: doing trick so that final pos would be x.99800000 instead of y.0000000 - print(", going back\n") - high = bmid - } - else { - print(", going forth\n") - low = bmid + // set new mid + if (isColliding(simulationHitbox)) { //COLLIDING_EXTRA_SIZE: doing trick so that final pos would be x.99800000 instead of y.0000000 + print(", going back\n") + high = bmid + } + else { + print(", going forth\n") + low = bmid + } } + + println("binarySearch embedding: ${simulationHitbox.endPointY}") + + + // force set grounded-ness + grounded = true + // reset walkY + walkY = 0.0 + println("!! grounded !!") } - println("binarySearch embedding: ${simulationHitbox.endPointY}") + + // snap to closest tile + // naturally, binarySearch gives you a point like 7584.99999999 (barely not colliding) or + // 7585.000000000 (colliding as fuck), BUT what we want is 7584.00000000 . + // [Procedure] + // 1. get touching area of four sides incl. edge points + // 2. a side with most touching area is the "colliding side" + // 3. round the hitbox so that coord of "colliding" side be integer + // 3.1. there's two main cases: "main axis" being X; "main axis" being Y + // 3.2. edge cases: (TBA) + + // test: assume hitting bottom + //val roundedInteger = simulationHitbox.endPointY.div(TILE_SIZE).roundInt() * TILE_SIZE + val displacementMainAxis = -1.0// - simulationHitbox.endPointY + val displacementSecondAxis = displacementMainAxis * externalForce.x / externalForce.y + + simulationHitbox.translate(displacementSecondAxis, displacementMainAxis) + println("dx: $displacementSecondAxis, dy: $displacementMainAxis") + + + println("externalForce: $externalForce, displacement: ${simulationHitbox - hitbox}") + //hitbox.translate(getBacktrackDelta(bmid)) + hitbox.reassign(simulationHitbox) } - - - // snap to closest tile - // naturally, binarySearch gives you a point like 7584.99999999 (barely not colliding) or - // 7585.000000000 (colliding as fuck), BUT what we want is 7584.00000000 . - // [Procedure] - // 1. get touching area of four sides incl. edge points - // 2. a side with most touching area is the "colliding side" - // 3. round the hitbox so that coord of "colliding" side be integer - // 3.1. there's two main cases: "main axis" being X; "main axis" being Y - // 3.2. edge cases: (TBA) - - // test: assume hitting bottom - val roundedInteger = simulationHitbox.endPointY.div(TILE_SIZE).roundInt() * TILE_SIZE - val displacementMainAxis = roundedInteger - simulationHitbox.endPointY - val displacementSecondAxis = displacementMainAxis * externalForce.x / externalForce.y - - simulationHitbox.translate(displacementSecondAxis, displacementMainAxis) - println("dx: $displacementSecondAxis, dy: $displacementMainAxis") - - - println("externalForce: $externalForce, displacement: ${simulationHitbox - hitbox}") - //hitbox.translate(getBacktrackDelta(bmid)) - hitbox.reassign(simulationHitbox) } // resolve controllerMoveDelta + if (controllerMoveDelta != null) { + hitbox.translate(controllerMoveDelta) + } - println("# final hitbox.endY = ${hitbox.endPointY}") + println("# final hitbox: $hitbox, wx: $walkX, wy: $walkY") @@ -752,7 +764,7 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean */ externalForce.x *= -elasticity - if (this is Controllable) walkX *= -elasticity + //if (this is Controllable) walkX *= -elasticity //println("$this\t${externalForce.x}") } @@ -760,7 +772,7 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean private fun hitAndReflectY() { println("** reflY **") externalForce.y *= -elasticity - if (this is Controllable) walkY *= -elasticity + //if (this is Controllable) walkY *= -elasticity } @Transient private val CEILING_HIT_ELASTICITY = 0.3 @@ -843,28 +855,28 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean */ if (option == COLLIDING_TOP) { - x1 = hitbox.posX - A_PIXEL - x2 = hitbox.endPointX + x1 = hitbox.posX + x2 = hitbox.endPointX - A_PIXEL y1 = hitbox.posY - A_PIXEL - A_PIXEL y2 = y1 } else if (option == COLLIDING_BOTTOM) { - x1 = hitbox.posX - A_PIXEL - x2 = hitbox.endPointX - y1 = hitbox.endPointY + A_PIXEL + x1 = hitbox.posX + x2 = hitbox.endPointX - A_PIXEL + y1 = hitbox.endPointY y2 = y1 } else if (option == COLLIDING_LEFT) { x1 = hitbox.posX - A_PIXEL x2 = x1 - y1 = hitbox.posY - A_PIXEL - y2 = hitbox.endPointY + y1 = hitbox.posY + y2 = hitbox.endPointY - A_PIXEL } else if (option == COLLIDING_RIGHT) { x1 = hitbox.endPointX x2 = x1 - y1 = hitbox.posY - A_PIXEL - y2 = hitbox.endPointY + y1 = hitbox.posY + y2 = hitbox.endPointY - A_PIXEL } else throw IllegalArgumentException() diff --git a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt index 853092167..c3cc78e87 100644 --- a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt +++ b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt @@ -8,6 +8,7 @@ import net.torvald.terrarum.worlddrawer.FeaturesDrawer import net.torvald.terrarum.Terrarum import net.torvald.terrarum.blendNormal import net.torvald.terrarum.blendScreen +import net.torvald.terrarum.gameactors.ActorWithPhysics import net.torvald.terrarum.worlddrawer.WorldCamera import org.newdawn.slick.Color import org.newdawn.slick.GameContainer @@ -43,14 +44,14 @@ class BasicDebugInfoWindow : UICanvas { } override fun update(gc: GameContainer, delta: Int) { - val player = Terrarum.ingame!!.player - val hitbox = player?.hitbox + val player = Terrarum.ingame!!.player!! + val hitbox = player.hitbox - xdelta = hitbox?.pointedX ?: 0 - prevPlayerX - ydelta = hitbox?.pointedY ?: 0 - prevPlayerY + xdelta = hitbox.pointedX - prevPlayerX + ydelta = hitbox.pointedY - prevPlayerY - prevPlayerX = hitbox?.pointedX ?: 0.0 - prevPlayerY = hitbox?.pointedY ?: 0.0 + prevPlayerX = hitbox.pointedX + prevPlayerY = hitbox.pointedY } override fun render(gc: GameContainer, g: Graphics) { @@ -85,8 +86,8 @@ class BasicDebugInfoWindow : UICanvas { + (hitbox?.endPointY?.div(FeaturesDrawer.TILE_SIZE))?.toInt().toString() + ")") - printLine(g, 3, "veloX reported $ccG${player?.moveDelta?.x}") - printLine(g, 4, "veloY reported $ccG${player?.moveDelta?.y}") + printLine(g, 3, "veloX reported $ccG${player?.externalForce?.x} ${player?.controllerMoveDelta?.x}") + printLine(g, 4, "veloY reported $ccG${player?.externalForce?.y} ${player?.controllerMoveDelta?.y}") printLineColumn(g, 2, 3, "veloX measured $ccG${xdelta}") printLineColumn(g, 2, 4, "veloY measured $ccG${ydelta}") @@ -98,10 +99,14 @@ class BasicDebugInfoWindow : UICanvas { if (player != null) { printLine(g, 7, "walled ${if (player.walledLeft) "$ccR" else "$ccG"}L" + + "${if (player.walledTop) "$ccR" else "$ccG"}${0x1E.toChar()}" + + "${if (player.walledBottom) "$ccR" else "$ccG"}${0x1F.toChar()}" + "${if (player.walledRight) "$ccR" else "$ccG"}R" ) } + + //printLine(g, 7, "jump $ccG${player.jumpAcc}") val lightVal: String