From f464ef8c18c9f2e351098c119ee5253d962a213b Mon Sep 17 00:00:00 2001 From: minjaesong Date: Thu, 1 Jun 2017 23:07:07 +0900 Subject: [PATCH] fixed LB/RB/BR bug (actor jitters because of false positive collision?) with a hack --- .../terrarum/blockproperties/BlockCodex.kt | 13 ++++ .../terrarum/gameactors/ActorHumanoid.kt | 40 +++++----- .../terrarum/gameactors/ActorWithPhysics.kt | 75 ++++++++++++++----- .../torvald/terrarum/realestate/LandUtil.kt | 2 +- 4 files changed, 92 insertions(+), 38 deletions(-) diff --git a/src/net/torvald/terrarum/blockproperties/BlockCodex.kt b/src/net/torvald/terrarum/blockproperties/BlockCodex.kt index caca3234f..48364d141 100644 --- a/src/net/torvald/terrarum/blockproperties/BlockCodex.kt +++ b/src/net/torvald/terrarum/blockproperties/BlockCodex.kt @@ -68,6 +68,19 @@ object BlockCodex { } } + fun getOrNull(rawIndex: Int?): BlockProp? { + if (rawIndex == null || rawIndex == Block.NULL) { + return null + } + + try { + return blockProps[rawIndex] + } + catch (e: NullPointerException) { + throw NullPointerException("Blockprop with raw id $rawIndex does not exist.") + } + } + private fun setProp(prop: BlockProp, record: CSVRecord) { prop.nameKey = record.get("name") diff --git a/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt b/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt index 888662987..cbf65af91 100644 --- a/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt +++ b/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt @@ -286,7 +286,7 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null) /** * Up/Down movement */ - if (noClip) { + if (noClip || COLLISION_TEST_MODE) { if (hasController) { if (axisY != 0f) { walkVertical(axisY < 0, axisY.abs()) @@ -363,25 +363,27 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null) * @author minjaesong */ private fun walkHorizontal(left: Boolean, absAxisVal: Float) { - if ((!walledLeft && left) || (!walledRight && !left)) { - readonly_totalX = - if (absAxisVal == AXIS_KEYBOARD) - avAcceleration * applyVelo(walkCounterX) * (if (left) -1f else 1f) - else - avAcceleration * (if (left) -1f else 1f) * absAxisVal + if (left && walledLeft || !left && walledRight) return - if (absAxisVal != AXIS_KEYBOARD) - controllerMoveDelta?.x?.let { controllerMoveDelta!!.x = controllerMoveDelta!!.x.plus(readonly_totalX).bipolarClamp(avSpeedCap * absAxisVal) } - else - controllerMoveDelta?.x?.let { controllerMoveDelta!!.x = controllerMoveDelta!!.x.plus(readonly_totalX).bipolarClamp(avSpeedCap) } - if (absAxisVal == AXIS_KEYBOARD) { - walkCounterX += 1 - } + readonly_totalX = + if (absAxisVal == AXIS_KEYBOARD) + avAcceleration * applyVelo(walkCounterX) * (if (left) -1f else 1f) + else + avAcceleration * (if (left) -1f else 1f) * absAxisVal - isWalkingH = true + if (absAxisVal != AXIS_KEYBOARD) + controllerMoveDelta?.x?.let { controllerMoveDelta!!.x = controllerMoveDelta!!.x.plus(readonly_totalX).bipolarClamp(avSpeedCap * absAxisVal) } + else + controllerMoveDelta?.x?.let { controllerMoveDelta!!.x = controllerMoveDelta!!.x.plus(readonly_totalX).bipolarClamp(avSpeedCap) } + + if (absAxisVal == AXIS_KEYBOARD) { + walkCounterX += 1 } + isWalkingH = true + + // Heading flag walkHeading = if (left) LEFT else RIGHT } @@ -393,6 +395,9 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null) * @param absAxisVal (set AXIS_KEYBOARD if keyboard controlled) */ private fun walkVertical(up: Boolean, absAxisVal: Float) { + if (up && walledTop || !up && walledBottom) return + + readonly_totalY = if (absAxisVal == AXIS_KEYBOARD) avAcceleration * applyVelo(walkCounterY) * (if (up) -1f else 1f) @@ -400,14 +405,15 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null) avAcceleration * (if (up) -1f else 1f) * absAxisVal if (absAxisVal != AXIS_KEYBOARD) - controllerMoveDelta?.y?.let { controllerMoveDelta!!.y = controllerMoveDelta!!.y.plus(readonly_totalX).bipolarClamp(avSpeedCap * absAxisVal) } + controllerMoveDelta?.y?.let { controllerMoveDelta!!.y = controllerMoveDelta!!.y.plus(readonly_totalY).bipolarClamp(avSpeedCap * absAxisVal) } else - controllerMoveDelta?.y?.let { controllerMoveDelta!!.y = controllerMoveDelta!!.y.plus(readonly_totalX).bipolarClamp(avSpeedCap) } + controllerMoveDelta?.y?.let { controllerMoveDelta!!.y = controllerMoveDelta!!.y.plus(readonly_totalY).bipolarClamp(avSpeedCap) } if (absAxisVal == AXIS_KEYBOARD) { walkCounterY += 1 } + isWalkingV = true } diff --git a/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt b/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt index c8daa8023..51e76a9a7 100644 --- a/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt +++ b/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt @@ -56,14 +56,14 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean * * Unit: pixel * !! 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; + override val hitbox = Hitbox(0.0, 0.0, 0.0, 0.0) // Hitbox is implemented using Double; val tilewiseHitbox: Hitbox get() = Hitbox.fromTwoPoints( hitbox.startX.div(TILE_SIZE).floor(), hitbox.startY.div(TILE_SIZE).floor(), - hitbox.endX.div(TILE_SIZE).floor(), - hitbox.endY.div(TILE_SIZE).floor() + hitbox.endX.minus(0.00001).div(TILE_SIZE).floor(), + hitbox.endY.minus(0.00001).div(TILE_SIZE).floor() ) /** @@ -589,15 +589,20 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean val affectingTiles = ArrayList() var collidingStep: Int? = null + for (step in 1..ccdSteps) { + val stepBox = sixteenStep[step] + forEachOccupyingTilePos(stepBox) { val tileCoord = LandUtil.resolveBlockAddr(it) val tileProp = BlockCodex.getOrNull(world.getTileFromTerrain(tileCoord.first, tileCoord.second)) + if (tileProp == null || tileProp.isSolid) { affectingTiles.add(it) } } + if (affectingTiles.isNotEmpty()) { collidingStep = step break // collision found on this step, break and proceed to next step @@ -612,6 +617,8 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean var bounceX = false var bounceY = false + var zeroX = false + var zeroY = false // collision NOT detected if (collidingStep == null) { hitbox.translate(vectorSum) @@ -619,6 +626,16 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean } // collision detected else { + println("Collision step: $collidingStep") + + + affectingTiles.forEach { + val tileCoord = LandUtil.resolveBlockAddr(it) + println("affectign tile: ${tileCoord.first}, ${tileCoord.second}") + } + + + val newHitbox = hitbox.reassign(sixteenStep[collidingStep]) var selfCollisionStatus = 0 @@ -627,40 +644,46 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean if (isWalled(newHitbox, COLLIDING_TOP)) selfCollisionStatus += COLL_TOPSIDE if (isWalled(newHitbox, COLLIDING_BOTTOM)) selfCollisionStatus += COLL_BOTTOMSIDE + // fixme UP and RIGHT && LEFT and DOWN bug when (selfCollisionStatus) { 0 -> { println("[ActorWithPhysics] Contradiction -- collision detected by CCD, but isWalled() says otherwise") } - 5 -> { bounceX = true } - 10 -> { bounceY = true } - 15 -> { newHitbox.reassign(sixteenStep[0]); bounceX = true; bounceY = true } + 5 -> { zeroX = true } + 10 -> { zeroY = true } + 15 -> { newHitbox.reassign(sixteenStep[0]); zeroX = true; zeroY = true } // one-side collision - 1, 11 -> { newHitbox.translatePosX(TILE_SIZE - newHitbox.startX.modTileDelta ()); bounceX = true } - 4, 14 -> { newHitbox.translatePosX( - newHitbox.endX.modTileDelta ()) ; bounceX = true } - 8, 13 -> { newHitbox.translatePosY(TILE_SIZE - newHitbox.startY.modTileDelta ()); bounceY = true } - 2, 7 -> { newHitbox.translatePosY( - newHitbox.endY.modTileDelta ()) ; bounceY = true } + 1, 11 -> { newHitbox.translatePosX(TILE_SIZE - newHitbox.startX.modTileDelta()); bounceX = true } + 4, 14 -> { newHitbox.translatePosX( - newHitbox.endX.modTileDelta()) ; bounceX = true } + 8, 13 -> { newHitbox.translatePosY(TILE_SIZE - newHitbox.startY.modTileDelta()); bounceY = true } + 2, 7 -> { newHitbox.translatePosY( - newHitbox.endY.modTileDelta()) ; bounceY = true } // two-side collision 3 -> { - newHitbox.translatePosX(TILE_SIZE - newHitbox.startX.modTileDelta ()) - newHitbox.translatePosY( - newHitbox.endY.modTileDelta ()) + newHitbox.translatePosX(TILE_SIZE - newHitbox.startX.modTileDelta()) + newHitbox.translatePosY( - newHitbox.endY.modTileDelta()) bounceX = true; bounceY = true } 6 -> { - newHitbox.translatePosX( - newHitbox.endX.modTileDelta ()) - newHitbox.translatePosY( - newHitbox.endY.modTileDelta ()) + println(- newHitbox.endY.modTileDelta()) + newHitbox.translatePosX( - newHitbox.endX.modTileDelta()) + newHitbox.translatePosY( - newHitbox.endY.modTileDelta()) bounceX = true; bounceY = true } 9 -> { - newHitbox.translatePosX(TILE_SIZE - newHitbox.startX.modTileDelta ()) - newHitbox.translatePosY(TILE_SIZE - newHitbox.startY.modTileDelta ()) + newHitbox.translatePosX(TILE_SIZE - newHitbox.startX.modTileDelta()) + newHitbox.translatePosY(TILE_SIZE - newHitbox.startY.modTileDelta()) bounceX = true; bounceY = true } 12 -> { - newHitbox.translatePosX( - newHitbox.endX.modTileDelta ()) - newHitbox.translatePosY(TILE_SIZE - newHitbox.startY.modTileDelta ()) + newHitbox.translatePosX( - newHitbox.endX.modTileDelta()) + newHitbox.translatePosY(TILE_SIZE - newHitbox.startY.modTileDelta()) bounceX = true; bounceY = true } } + if (selfCollisionStatus in listOf(3,6,9,12)) { + println("twoside collision $selfCollisionStatus") + } + // bounce X/Y if (bounceX) { @@ -671,6 +694,14 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean externalForce.y *= elasticity controllerMoveDelta?.let { controllerMoveDelta!!.y *= elasticity } } + if (zeroX) { + externalForce.x = 0.0 + controllerMoveDelta?.let { controllerMoveDelta!!.x = 0.0 } + } + if (zeroY) { + externalForce.y = 0.0 + controllerMoveDelta?.let { controllerMoveDelta!!.y = 0.0 } + } hitbox.reassign(newHitbox) @@ -1296,6 +1327,8 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean flagDespawn = true } + + private fun forEachOccupyingTileNum(consumer: (Int?) -> Unit) { val tiles = ArrayList() for (y in tilewiseHitbox.startY.toInt()..tilewiseHitbox.endY.toInt()) { @@ -1322,8 +1355,8 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean val newTilewiseHitbox = Hitbox.fromTwoPoints( hitbox.startX.div(TILE_SIZE).floor(), hitbox.startY.div(TILE_SIZE).floor(), - hitbox.endX.div(TILE_SIZE).floor(), - hitbox.endY.div(TILE_SIZE).floor() + hitbox.endX.minus(0.00001).div(TILE_SIZE).floor(), + hitbox.endY.minus(0.00001).div(TILE_SIZE).floor() ) val tilePosList = ArrayList() @@ -1362,6 +1395,8 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean return tileProps.forEach(consumer) } + + companion object { /** diff --git a/src/net/torvald/terrarum/realestate/LandUtil.kt b/src/net/torvald/terrarum/realestate/LandUtil.kt index 53c3e4ef9..abca0a661 100644 --- a/src/net/torvald/terrarum/realestate/LandUtil.kt +++ b/src/net/torvald/terrarum/realestate/LandUtil.kt @@ -11,7 +11,7 @@ object LandUtil { fun getBlockAddr(x: Int, y: Int): BlockAddress = (Terrarum.ingame!!.world.width * y).toLong() + x - fun resolveAbsoluteBlockNumber(t: BlockAddress): Pair = + fun resolveBlockAddr(t: BlockAddress): Pair = Pair((t % Terrarum.ingame!!.world.width).toInt(), (t / Terrarum.ingame!!.world.width).toInt()) /**