diff --git a/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt b/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt index a12252988..27062fa32 100644 --- a/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt +++ b/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt @@ -11,6 +11,7 @@ import net.torvald.terrarum.worlddrawer.WorldCamera import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.blockproperties.BlockProp import net.torvald.terrarum.gameactors.ai.toInt +import org.dyn4j.Epsilon import org.dyn4j.geometry.Vector2 import org.newdawn.slick.GameContainer import org.newdawn.slick.Graphics @@ -53,7 +54,6 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean * !! external class should not hitbox.set(); use setHitboxDimension() and setPosition() */ override val hitbox = Hitbox(0.0, 0.0, 0.0, 0.0) // Hitbox is implemented using Double; - //@Transient val nextHitbox = Hitbox(0.0, 0.0, 0.0, 0.0) // 52 mantissas ought to be enough for anybody... val tilewiseHitbox: Hitbox get() = Hitbox.fromTwoPoints( @@ -235,11 +235,6 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean protected val updateDelta: Int get() = Terrarum.delta - /** - * true: This actor had just made collision - */ - var ccdCollided = false - private set var isWalkingH = false var isWalkingV = false @@ -298,17 +293,10 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean y - (baseHitboxH - hitboxTranslateY) * scale, baseHitboxW * scale, baseHitboxH * scale) - - /*nextHitbox.setFromWidthHeight( - x - (baseHitboxW / 2 - hitboxTranslateX) * scale, - y - (baseHitboxH - hitboxTranslateY) * scale, - baseHitboxW * scale, - baseHitboxH * scale)*/ } private fun translatePosition(dx: Double, dy: Double) { hitbox.translate(dx, dy) - nextHitbox.translate(dx, dy) } val centrePosVector: Vector2 @@ -374,9 +362,9 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean moveDelta.y = moveDelta.y.bipolarClamp(VELO_HARD_LIMIT) if (!isChronostasis) { - /////////////////////////////////////////////////////// - // Codes that (SHOULD) displaces nextHitbox directly // - /////////////////////////////////////////////////////// + /////////////////////////////////////////////////// + // Codes that (SHOULD) displaces hitbox directly // + /////////////////////////////////////////////////// /** * solveCollision()? @@ -412,30 +400,31 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean displaceHitbox() applyNormalForce() } + else { + hitbox.translate(moveDelta) + } ////////////////////////////////////////////////////////////// // Codes that modifies velocity (after hitbox displacement) // ////////////////////////////////////////////////////////////// + // modified vectors below SHOULD NOT IMMEDIATELY APPLIED!! // + // these are FOR THE NEXT ROUND of update // + // ((DO NOT DELETE THIS; made same mistake twice already)) // + setHorizontalFriction() // friction SHOULD use and alter externalForce if (isPlayerNoClip) { // TODO also hanging on the rope, etc. setVerticalFriction() } - // some spacing // - - - // apply our compensation to actual hitbox - updateHitbox() - // make sure if the actor tries to go out of the map, loop back instead clampHitbox() } // cheap solution for sticking into the wall while Left or Right is held - walledLeft = isTouchingSide(nextHitbox, COLLIDING_LEFT) - walledRight = isTouchingSide(nextHitbox, COLLIDING_RIGHT) + walledLeft = isTouchingSide(hitbox, COLLIDING_LEFT) + walledRight = isTouchingSide(hitbox, COLLIDING_RIGHT) if (isPlayerNoClip) { walledLeft = false walledRight = false @@ -491,7 +480,7 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean * Apply only if not grounded; normal force is precessed separately. */ private fun applyGravitation() { - if (!isNoSubjectToGrav) { + if (!isNoSubjectToGrav && !isTouchingSide(hitbox, COLLIDING_BOTTOM)) { //if (!isTouchingSide(hitbox, COLLIDING_BOTTOM)) { /** * weight; gravitational force in action @@ -521,43 +510,27 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean // was moving downward? if (moveDelta.y > 0.0) { - if (moveDelta.y > 0.587777) { // dampening - if (isColliding(nextHitbox, COLLIDING_TOP)) { // hit the ceiling - hitAndReflectY() //hitAndForciblyReflectY() - grounded = false - } - else if (isColliding(nextHitbox)) { - hitAndReflectY() - grounded = true - } - else if (isTouchingSide(nextHitbox, COLLIDING_BOTTOM) && !isColliding(nextHitbox)) { // actor hit something on its bottom - hitAndReflectY() - grounded = true - } - else { // the actor is not grounded at all - grounded = false - } + if (isTouchingSide(hitbox, COLLIDING_TOP)) { // hit the ceiling + hitAndReflectY() //hitAndForciblyReflectY() + grounded = false } - else { // dampening + 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 + } } // or was moving upward? else if (moveDelta.y < 0.0) { - if (moveDelta.y < -0.587777) { // dampening - grounded = false - if (isTouchingSide(nextHitbox, COLLIDING_TOP)) { // actor hit something on its top - hitAndForciblyReflectY() // prevents sticking to the ceiling - } - else { // the actor is not grounded at all - } - } - else { // dampening - grounded = true // force grounded + grounded = false + if (isTouchingSide(hitbox, COLLIDING_TOP)) { // actor hit something on its top + hitAndForciblyReflectY() // prevents sticking to the ceiling } } // axis X - if (isTouchingSide(nextHitbox, COLLIDING_LEFT) || isTouchingSide(nextHitbox, COLLIDING_RIGHT)) { // check right and left + if (isTouchingSide(hitbox, COLLIDING_LEFT) || isTouchingSide(hitbox, COLLIDING_RIGHT)) { // check right and left // the actor is hitting the wall // FIXME balls are stuck in this @@ -572,14 +545,12 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean * nextHitbox must NOT be altered before this method is called! */ @Deprecated("It's stupid anyway.") private fun displaceByCCD() { - ccdCollided = false - if (!isNoCollideWorld) { - if (!isColliding(nextHitbox, COLLIDING_ALLSIDE)) + if (!isColliding(hitbox, COLLIDING_ALLSIDE)) return // do some CCD between hitbox and nextHitbox - val ccdDelta = (nextHitbox.toVector() - hitbox.toVector()) + val ccdDelta = (hitbox.toVector() - hitbox.toVector()) if (ccdDelta.x != 0.0 || ccdDelta.y != 0.0) { //ccdDelta.set(ccdDelta.setMagnitude(CCD_TICK)) // fixed tick val displacement = Math.min(1.0.div(moveDelta.magnitude * 2), 0.5) // adaptive tick @@ -589,9 +560,8 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean //println("deltaMax: $deltaMax") //println("ccdDelta: $ccdDelta") - while (!ccdDelta.isZero && isColliding(nextHitbox, COLLIDING_ALLSIDE)) { - nextHitbox.translate(-ccdDelta) - ccdCollided = true + while (!ccdDelta.isZero && isColliding(hitbox, COLLIDING_ALLSIDE)) { + hitbox.translate(-ccdDelta) } //println("ccdCollided: $ccdCollided") @@ -601,7 +571,8 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean /** * nextHitbox must NOT be altered before this method is called! */ - private val backtrackSteps = 16 // max allowed velocity = backtrackSteps * TILE_SIZE + private val ccdSteps = 16 // max allowed velocity = backtrackSteps * TILE_SIZE + private val binaryBranchingMax = 54 // higher = more precise; theoretical max = 54 (# of mantissa + 2) private fun displaceHitbox() { // I kinda need these notes when I'm not caffeinated @@ -614,240 +585,100 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean // - Displace `hitbox` directly // - Make sure "isTouching" is perfectly useable, it depends on it // [Procedure] - // backtrack (16) steps to determine it is embedded to the wall, or passed through it - // if (above procedure returns true): - // displace "hitbox" using linear interpolation - // else: - // hitbox = hitbox moved by the vector + // find "edge" point using binary search // [END OF SUBROUTINE] + if (moveDelta.isZero) return - fun getBacktrackDelta(counter: Double): Vector2 = - moveDelta * (counter) / backtrackSteps.toDouble() - var embeddedToTerrainCounter = 0.0 //0..16: embedding detected (detected at this-th try) + fun getBacktrackDelta(percentage: Double): Vector2 { + if (percentage < 0.0 || percentage > 1.0) + throw IllegalArgumentException("$percentage") + + return moveDelta * percentage + } + + + + val simulationHitbox = hitbox.clone() + var ccdTick: Int = ccdSteps // 0..15: collision detected, 16: not + + // do CCD first + for (i in 0..ccdSteps - 1) { // 0..15 because (i+1) is always implied by Binary Search + simulationHitbox.reassign(hitbox) + simulationHitbox.translate(getBacktrackDelta(i.toDouble() / ccdSteps)) - // it's rather a _simulator_ rather than _backtracker_, though - var simulationHitbox = hitbox.clone() - for (i in 0..backtrackSteps - 1) { - // check collision if (isColliding(simulationHitbox)) { + ccdTick = i break } - - val backtrackSize = getBacktrackDelta(i.toDouble()) //to avoid fp precision error derived from the Integration - simulationHitbox = hitbox.translate(backtrackSize) // make new hitbox every turn to avoid fp precision error - embeddedToTerrainCounter += 1.0 } - // collision detected - if (embeddedToTerrainCounter < backtrackSteps) { - // linear interpolation kicks in - // or block-wise binary search for the collision point - // do this along X- and Y-axis and take the lowest - - val HB_START = 1; val HB_END = -1 - val xDestInTileCoord: Int // may contain placeholder value - val yDestInTileCoord: Int // may contain placeholder value - val xDestMode: Int? // null means NO OPERATION - val yDestMode: Int? // null means NO OPERATION - - // doing whatever for X-axis - // determine if we should use LEFT or RIGHT side - if (moveDelta.x > 0) { // going RIGHT, use RIGHT side - var embedLow = embeddedToTerrainCounter - var embedHigh = embeddedToTerrainCounter + 1.0 - var low = (hitbox.endPointX + getBacktrackDelta(embedLow).x).div(TILE_SIZE).floorInt() - var lowY = hitbox.posY + getBacktrackDelta(embedLow).y - var high = (hitbox.endPointX + getBacktrackDelta(embedHigh).x).div(TILE_SIZE).floorInt() - var highY = hitbox.posY + getBacktrackDelta(embedHigh).y - - while (low <= high) { - val mid = (low + high).ushr(1) - val midY = (lowY / 2) + (highY / 2) // to eliminate precision loss (which is negligible anyway...) - // y pos : middle of (low, high) hbxs - val yStart = midY.div(TILE_SIZE).floorInt() - val yEnd = (midY + hitbox.height).div(TILE_SIZE).floorInt() - - val isColliding = (yStart..yEnd).map { - BlockCodex[world.getTileFromTerrain(mid, it) ?: Block.STONE].isSolid.toInt() - }.sum() != 0 - - if (isColliding) { - high = mid - 1 - embedHigh = (embedLow / 2) + (embedHigh / 2) - highY = hitbox.posY + getBacktrackDelta(embedHigh).y - } - else { - low = mid + 1 - embedLow = (embedLow / 2) + (embedHigh / 2) - lowY = hitbox.posY + getBacktrackDelta(embedLow).y - } - } - - xDestInTileCoord = minOf(low, high) - xDestMode = HB_END - } - else if (moveDelta.x < 0) { // going LEFT, use LEFT side - var embedLow = embeddedToTerrainCounter + 1.0 - var embedHigh = embeddedToTerrainCounter - var low = (hitbox.posX + getBacktrackDelta(embedLow).x).div(TILE_SIZE).floorInt() - var lowY = hitbox.posY + getBacktrackDelta(embedLow).y - var high = (hitbox.posX + getBacktrackDelta(embedHigh).x).div(TILE_SIZE).floorInt() - var highY = hitbox.posY + getBacktrackDelta(embedHigh).y - - while (low <= high) { - val mid = (low + high).ushr(1) - val midY = (lowY / 2) + (highY / 2) // to eliminate precision loss (which is negligible anyway...) - // y pos : middle of (low, high) hbxs - val yStart = midY.div(TILE_SIZE).floorInt() - val yEnd = (midY + hitbox.height).div(TILE_SIZE).floorInt() - - val isColliding = (yStart..yEnd).map { - BlockCodex[world.getTileFromTerrain(mid, it) ?: Block.STONE].isSolid.toInt() - }.sum() != 0 - - if (!isColliding) { - high = mid - 1 - embedHigh = (embedLow / 2) + (embedHigh / 2) - highY = hitbox.posY + getBacktrackDelta(embedHigh).y - } - else { - low = mid + 1 - embedLow = (embedLow / 2) + (embedHigh / 2) - lowY = hitbox.posY + getBacktrackDelta(embedLow).y - } - } - - xDestInTileCoord = maxOf(low, high) - xDestMode = HB_START - } - else { - xDestInTileCoord = 0 // placeholder - xDestMode = null - } - - // doing whatever for Y-axis - // determine if we should use UP or DOWN side - if (moveDelta.y > 0) { // going DOWN, use DOWN side - var embedLow = embeddedToTerrainCounter - var embedHigh = embeddedToTerrainCounter + 1.0 - var low = (hitbox.endPointY + getBacktrackDelta(embedLow).y).div(TILE_SIZE).floorInt() - var lowX = hitbox.posX + getBacktrackDelta(embedLow).x - var high = (hitbox.endPointY + getBacktrackDelta(embedHigh).y).div(TILE_SIZE).floorInt() - var highX = hitbox.posX + getBacktrackDelta(embedHigh).x - - while (low <= high) { - val mid = (low + high).ushr(1) - val midX = (lowX / 2) + (highX / 2) // to eliminate precision loss (which is negligible anyway...) - // x pos : middle of (low, high) hbxs - val xStart = midX.div(TILE_SIZE).floorInt() - val xEnd = (midX + hitbox.width).div(TILE_SIZE).floorInt() - - val isColliding = (xStart..xEnd).map { - BlockCodex[world.getTileFromTerrain(it, mid) ?: Block.STONE].isSolid.toInt() - }.sum() != 0 - - if (isColliding) { - high = mid - 1 - embedHigh = (embedLow / 2) + (embedHigh / 2) - highX = hitbox.posX + getBacktrackDelta(embedHigh).x - } - else { - low = mid + 1 - embedLow = (embedLow / 2) + (embedHigh / 2) - lowX = hitbox.posX + getBacktrackDelta(embedLow).x - } - } - - yDestInTileCoord = minOf(low, high) - yDestMode = HB_END - } - else if (moveDelta.y < 0) { // going UP, use UP side - var embedLow = embeddedToTerrainCounter + 1.0 - var embedHigh = embeddedToTerrainCounter - var low = (hitbox.posY + getBacktrackDelta(embedLow).y).div(TILE_SIZE).floorInt() - var lowX = hitbox.posX + getBacktrackDelta(embedLow).x - var high = (hitbox.posY + getBacktrackDelta(embedHigh).y).div(TILE_SIZE).floorInt() - var highX = hitbox.posX + getBacktrackDelta(embedHigh).x - - while (low <= high) { - val mid = (low + high).ushr(1) - val midX = (lowX / 2) + (highX / 2) // to eliminate precision loss (which is negligible anyway...) - // x pos : middle of (low, high) hbxs - val xStart = midX.div(TILE_SIZE).floorInt() - val xEnd = (midX + hitbox.width).div(TILE_SIZE).floorInt() - - val isColliding = (xStart..xEnd).map { - BlockCodex[world.getTileFromTerrain(it, mid) ?: Block.STONE].isSolid.toInt() - }.sum() != 0 - - if (!isColliding) { - high = mid - 1 - embedHigh = (embedLow / 2) + (embedHigh / 2) - highX = hitbox.posX + getBacktrackDelta(embedHigh).x - } - else { - low = mid + 1 - embedLow = (embedLow / 2) + (embedHigh / 2) - lowX = hitbox.posX + getBacktrackDelta(embedLow).x - } - } - - yDestInTileCoord = maxOf(low, high) - yDestMode = HB_START - } - else { - yDestInTileCoord = 0 // placeholder - yDestMode = null - } - - - // displace for axes - if (xDestMode != null) { - if (xDestMode == HB_START) { - hitbox.setFromTwoPoints( - xDestInTileCoord.times(TILE_SIZE).toDouble(), - hitbox.posY, - xDestInTileCoord.times(TILE_SIZE) + hitbox.width, - hitbox.endPointY - ) - } - else if (xDestMode == HB_END) { - hitbox.setFromTwoPoints( - xDestInTileCoord.times(TILE_SIZE) - hitbox.width, - hitbox.posY, - xDestInTileCoord.times(TILE_SIZE).toDouble(), - hitbox.endPointY - ) - } - } - if (yDestMode != null) { - if (yDestMode == HB_START) { - hitbox.setFromTwoPoints( - hitbox.posX, - yDestInTileCoord.times(TILE_SIZE).toDouble(), - hitbox.endPointX, - yDestInTileCoord.times(TILE_SIZE) + hitbox.height - ) - } - else if (yDestMode == HB_END) { - hitbox.setFromTwoPoints( - hitbox.posX, - yDestInTileCoord.times(TILE_SIZE) - hitbox.height, - hitbox.endPointX, - yDestInTileCoord.times(TILE_SIZE).toDouble() - ) - } - } - - } // END IF collision detected - else { + // collision not found + if (ccdTick == ccdSteps) { hitbox.translate(moveDelta) + return } + + // find no-collision point using binary search + // trust me, X- and Y-axis must move simultaneously. + //// binary search //// + var low = ccdTick.toDouble() / ccdSteps + var high = (ccdTick + 1).toDouble() / ccdSteps + //var mid = 0.5 + //var midDelta = 0.5 + var bmid = (low / 2.0) + (high / 2.0) + + (2..binaryBranchingMax + 1).forEach { + + bmid = (low / 2.0) + (high / 2.0) + + simulationHitbox.reassign(hitbox) + //simulationHitbox.translate(getBacktrackDelta(mid)) + simulationHitbox.translate(getBacktrackDelta(bmid)) + + // set new mid + if (isColliding(simulationHitbox)) { + //midDelta /= 2 + //mid -= midDelta + high = bmid + } + else { + //midDelta /= 2 + //mid += midDelta + low = bmid + } + } + + // unmove again (gah!) + TBA + + //println("moveDelta: $moveDelta, displacement: ${getBacktrackDelta(mid)}, mid: $mid") + //hitbox.translate(getBacktrackDelta(mid- 0.0000000000004)) + println("moveDelta: $moveDelta, displacement: ${getBacktrackDelta(bmid)}, mid: $bmid") + hitbox.translate(getBacktrackDelta(bmid)) + + + + /*var ccdStep = 0.0 + while (!isColliding(simulationHitbox) && ccdStep < 1.0) { + simulationHitbox.reassign(hitbox) + simulationHitbox.translate(getBacktrackDelta(ccdStep)) + ccdStep += 1.0/256.0 + } + + hitbox.translate(getBacktrackDelta(ccdStep)) + + println("endY: ${hitbox.endPointY}\tccdStep: $ccdStep")*/ + + + //println("pointedY: ${hitbox.pointedY}") + + // if collision not detected, just don't care; it's not your job to apply moveDelta } + private fun hitAndReflectX() { // when it sticks, externalForce.x goes back and forth /* @@ -904,7 +735,7 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean externalForce.y = moveDelta.y * CEILING_HIT_ELASTICITY //externalForce.y = 0.0 - nextHitbox.translatePosY(0.5) + hitbox.translatePosY(0.5) } else { throw Error("Check this out bitch (moveDelta.y = ${moveDelta.y})") @@ -963,10 +794,10 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean } } - val txStart = x1.div(TILE_SIZE).floorInt() - val txEnd = x2.div(TILE_SIZE).floorInt() - val tyStart = y1.div(TILE_SIZE).floorInt() - val tyEnd = y2.div(TILE_SIZE).floorInt() + val txStart = x1.plus(Epsilon.E) .div(TILE_SIZE).floorInt() + val txEnd = x2.minus(Epsilon.E).div(TILE_SIZE).floorInt() + val tyStart = y1.plus(Epsilon.E) .div(TILE_SIZE).floorInt() + val tyEnd = y2.minus(Epsilon.E).div(TILE_SIZE).floorInt() return isCollidingInternal(txStart, tyStart, txEnd, tyEnd) } @@ -1002,10 +833,10 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean } else throw IllegalArgumentException() - val txStart = x1.div(TILE_SIZE).floorInt() - val txEnd = x2.div(TILE_SIZE).floorInt() - val tyStart = y1.div(TILE_SIZE).floorInt() - val tyEnd = y2.div(TILE_SIZE).floorInt() + val txStart = x1.plus(Epsilon.E) .div(TILE_SIZE).floorInt() + val txEnd = x2.minus(Epsilon.E).div(TILE_SIZE).floorInt() + val tyStart = y1.plus(Epsilon.E) .div(TILE_SIZE).floorInt() + val tyEnd = y2.minus(Epsilon.E).div(TILE_SIZE).floorInt() return isCollidingInternal(txStart, tyStart, txEnd, tyEnd) } @@ -1042,10 +873,10 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean } else throw IllegalArgumentException() - val txStart = x1.div(TILE_SIZE).floorInt() - val txEnd = x2.div(TILE_SIZE).floorInt() - val tyStart = y1.div(TILE_SIZE).floorInt() - val tyEnd = y2.div(TILE_SIZE).floorInt() + val txStart = x1.plus(Epsilon.E) .div(TILE_SIZE).floorInt() + val txEnd = x2.minus(Epsilon.E).div(TILE_SIZE).floorInt() + val tyStart = y1.plus(Epsilon.E) .div(TILE_SIZE).floorInt() + val tyEnd = y2.minus(Epsilon.E).div(TILE_SIZE).floorInt() return isCollidingInternal(txStart, tyStart, txEnd, tyEnd) } @@ -1064,28 +895,28 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean private fun getContactingAreaFluid(side: Int, translateX: Int = 0, translateY: Int = 0): Int { var contactAreaCounter = 0 - for (i in 0..(if (side % 2 == 0) nextHitbox.width else nextHitbox.height).roundInt() - 1) { + for (i in 0..(if (side % 2 == 0) hitbox.width else hitbox.height).roundInt() - 1) { // set tile positions val tileX: Int val tileY: Int if (side == COLLIDING_LEFT) { - tileX = div16TruncateToMapWidth(nextHitbox.hitboxStart.x.roundInt() + tileX = div16TruncateToMapWidth(hitbox.hitboxStart.x.roundInt() + i + translateX) - tileY = div16TruncateToMapHeight(nextHitbox.hitboxEnd.y.roundInt() + translateY) + tileY = div16TruncateToMapHeight(hitbox.hitboxEnd.y.roundInt() + translateY) } else if (side == COLLIDING_TOP) { - tileX = div16TruncateToMapWidth(nextHitbox.hitboxStart.x.roundInt() + tileX = div16TruncateToMapWidth(hitbox.hitboxStart.x.roundInt() + i + translateX) - tileY = div16TruncateToMapHeight(nextHitbox.hitboxStart.y.roundInt() + translateY) + tileY = div16TruncateToMapHeight(hitbox.hitboxStart.y.roundInt() + translateY) } else if (side == COLLIDING_RIGHT) { - tileX = div16TruncateToMapWidth(nextHitbox.hitboxEnd.x.roundInt() + translateX) - tileY = div16TruncateToMapHeight(nextHitbox.hitboxStart.y.roundInt() + tileX = div16TruncateToMapWidth(hitbox.hitboxEnd.x.roundInt() + translateX) + tileY = div16TruncateToMapHeight(hitbox.hitboxStart.y.roundInt() + i + translateY) } else if (side == COLLIDING_LEFT) { - tileX = div16TruncateToMapWidth(nextHitbox.hitboxStart.x.roundInt() + translateX) - tileY = div16TruncateToMapHeight(nextHitbox.hitboxStart.y.roundInt() + tileX = div16TruncateToMapWidth(hitbox.hitboxStart.x.roundInt() + translateX) + tileY = div16TruncateToMapHeight(hitbox.hitboxStart.y.roundInt() + i + translateY) } else { @@ -1322,17 +1153,6 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean ) } - private fun setNewNextHitbox() { - nextHitbox.setFromWidthHeight( - hitbox.posX + moveDelta.x, - hitbox.posY + moveDelta.y, - baseHitboxW * scale, - baseHitboxH * scale - ) - } - - private fun updateHitbox() = hitbox.reassign(nextHitbox) - override fun drawGlow(g: Graphics) { if (isVisible && spriteGlow != null) { blendLightenOnly() @@ -1420,22 +1240,22 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean private fun clampW(x: Double): Double = - if (x < TILE_SIZE + nextHitbox.width / 2) { - TILE_SIZE + nextHitbox.width / 2 + if (x < TILE_SIZE + hitbox.width / 2) { + TILE_SIZE + hitbox.width / 2 } - else if (x >= (world.width * TILE_SIZE).toDouble() - TILE_SIZE.toDouble() - nextHitbox.width / 2) { - (world.width * TILE_SIZE).toDouble() - 1.0 - TILE_SIZE.toDouble() - nextHitbox.width / 2 + else if (x >= (world.width * TILE_SIZE).toDouble() - TILE_SIZE.toDouble() - hitbox.width / 2) { + (world.width * TILE_SIZE).toDouble() - 1.0 - TILE_SIZE.toDouble() - hitbox.width / 2 } else { x } private fun clampH(y: Double): Double = - if (y < TILE_SIZE + nextHitbox.height) { - TILE_SIZE + nextHitbox.height + if (y < TILE_SIZE + hitbox.height) { + TILE_SIZE + hitbox.height } - else if (y >= (world.height * TILE_SIZE).toDouble() - TILE_SIZE.toDouble() - nextHitbox.height) { - (world.height * TILE_SIZE).toDouble() - 1.0 - TILE_SIZE.toDouble() - nextHitbox.height + else if (y >= (world.height * TILE_SIZE).toDouble() - TILE_SIZE.toDouble() - hitbox.height) { + (world.height * TILE_SIZE).toDouble() - 1.0 - TILE_SIZE.toDouble() - hitbox.height } else { y @@ -1498,7 +1318,7 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean val tiles = ArrayList() // offset 1 pixel to the down so that friction would work - val y = nextHitbox.endPointY.plus(1.0).div(TILE_SIZE).floorInt() + val y = hitbox.endPointY.plus(1.0).div(TILE_SIZE).floorInt() for (x in tilewiseHitbox.posX.toInt()..tilewiseHitbox.endPointX.toInt()) { tiles.add(world.getTileFromTerrain(x, y)) @@ -1511,7 +1331,7 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean val tileProps = ArrayList() // offset 1 pixel to the down so that friction would work - val y = nextHitbox.endPointY.plus(1.0).div(TILE_SIZE).floorInt() + val y = hitbox.endPointY.plus(1.0).div(TILE_SIZE).floorInt() for (x in tilewiseHitbox.posX.toInt()..tilewiseHitbox.endPointX.toInt()) { tileProps.add(BlockCodex[world.getTileFromTerrain(x, y)]) diff --git a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt index 9caa61b1f..853092167 100644 --- a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt +++ b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt @@ -67,23 +67,22 @@ class BasicDebugInfoWindow : UICanvas { g.color = GameFontBase.codeToCol["y"] val hitbox = player?.hitbox - val nextHitbox = player?.nextHitbox /** * First column */ - printLine(g, 1, "posX " + printLine(g, 1, "pointedX " + ccG + "${hitbox?.pointedX}" + " (" + "${(hitbox?.pointedX?.div(FeaturesDrawer.TILE_SIZE))?.toInt()}" + ")") - printLine(g, 2, "posY " + printLine(g, 2, "endY " + ccG - + hitbox?.pointedY.toString() + + hitbox?.endPointY.toString() + " (" - + (hitbox?.pointedY?.div(FeaturesDrawer.TILE_SIZE))?.toInt().toString() + + (hitbox?.endPointY?.div(FeaturesDrawer.TILE_SIZE))?.toInt().toString() + ")") printLine(g, 3, "veloX reported $ccG${player?.moveDelta?.x}") @@ -95,6 +94,14 @@ class BasicDebugInfoWindow : UICanvas { printLine(g, 5, "grounded $ccG${player?.grounded}") printLine(g, 6, "noClip $ccG${player?.noClip}") + + if (player != null) { + printLine(g, 7, + "walled ${if (player.walledLeft) "$ccR" else "$ccG"}L" + + "${if (player.walledRight) "$ccR" else "$ccG"}R" + ) + } + //printLine(g, 7, "jump $ccG${player.jumpAcc}") val lightVal: String diff --git a/src/org/dyn4j/Epsilon.java b/src/org/dyn4j/Epsilon.kt similarity index 86% rename from src/org/dyn4j/Epsilon.java rename to src/org/dyn4j/Epsilon.kt index 8eca5b219..12976b93f 100644 --- a/src/org/dyn4j/Epsilon.java +++ b/src/org/dyn4j/Epsilon.kt @@ -22,32 +22,30 @@ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.dyn4j; +/* Kotlin modified code (c) 2017 Torvald (minjaesong) */ +package org.dyn4j /** * Class containing an approximation of machine epsilon. * @author William Bittle + * * * @version 2.0.0 + * * * @since 2.0.0 */ -public final class Epsilon { - /** The double precision floating point machine epsilon approximation */ - public static final double E = Epsilon.compute(); - - /** - * Hidden default constructor. - */ - private Epsilon() {} +object Epsilon { + /** The double precision floating point machine epsilon approximation */ + val E = Epsilon.compute() /** * Computes an approximation of machine epsilon. * @return double */ - public static final double compute() { - double e = 0.5; + private fun compute(): Double { + var e = 0.5 while (1.0 + e > 1.0) { - e *= 0.5; + e *= 0.5 } - return e; + return e } } \ No newline at end of file