fixed LB/RB/BR bug (actor jitters because of false positive collision?) with a hack

This commit is contained in:
minjaesong
2017-06-01 23:07:07 +09:00
parent f95cc5b27d
commit f464ef8c18
4 changed files with 92 additions and 38 deletions

View File

@@ -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) { private fun setProp(prop: BlockProp, record: CSVRecord) {
prop.nameKey = record.get("name") prop.nameKey = record.get("name")

View File

@@ -286,7 +286,7 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null)
/** /**
* Up/Down movement * Up/Down movement
*/ */
if (noClip) { if (noClip || COLLISION_TEST_MODE) {
if (hasController) { if (hasController) {
if (axisY != 0f) { if (axisY != 0f) {
walkVertical(axisY < 0, axisY.abs()) walkVertical(axisY < 0, axisY.abs())
@@ -363,25 +363,27 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null)
* @author minjaesong * @author minjaesong
*/ */
private fun walkHorizontal(left: Boolean, absAxisVal: Float) { private fun walkHorizontal(left: Boolean, absAxisVal: Float) {
if ((!walledLeft && left) || (!walledRight && !left)) { if (left && walledLeft || !left && walledRight) return
readonly_totalX =
if (absAxisVal == AXIS_KEYBOARD)
avAcceleration * applyVelo(walkCounterX) * (if (left) -1f else 1f)
else
avAcceleration * (if (left) -1f else 1f) * absAxisVal
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) { readonly_totalX =
walkCounterX += 1 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 // Heading flag
walkHeading = if (left) LEFT else RIGHT 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) * @param absAxisVal (set AXIS_KEYBOARD if keyboard controlled)
*/ */
private fun walkVertical(up: Boolean, absAxisVal: Float) { private fun walkVertical(up: Boolean, absAxisVal: Float) {
if (up && walledTop || !up && walledBottom) return
readonly_totalY = readonly_totalY =
if (absAxisVal == AXIS_KEYBOARD) if (absAxisVal == AXIS_KEYBOARD)
avAcceleration * applyVelo(walkCounterY) * (if (up) -1f else 1f) 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 avAcceleration * (if (up) -1f else 1f) * absAxisVal
if (absAxisVal != AXIS_KEYBOARD) 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 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) { if (absAxisVal == AXIS_KEYBOARD) {
walkCounterY += 1 walkCounterY += 1
} }
isWalkingV = true isWalkingV = true
} }

View File

@@ -56,14 +56,14 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
* * Unit: pixel * * Unit: pixel
* !! external class should not hitbox.set(); use setHitboxDimension() and setPosition() * !! 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 val tilewiseHitbox: Hitbox
get() = Hitbox.fromTwoPoints( get() = Hitbox.fromTwoPoints(
hitbox.startX.div(TILE_SIZE).floor(), hitbox.startX.div(TILE_SIZE).floor(),
hitbox.startY.div(TILE_SIZE).floor(), hitbox.startY.div(TILE_SIZE).floor(),
hitbox.endX.div(TILE_SIZE).floor(), hitbox.endX.minus(0.00001).div(TILE_SIZE).floor(),
hitbox.endY.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<BlockAddress>() val affectingTiles = ArrayList<BlockAddress>()
var collidingStep: Int? = null var collidingStep: Int? = null
for (step in 1..ccdSteps) { for (step in 1..ccdSteps) {
val stepBox = sixteenStep[step] val stepBox = sixteenStep[step]
forEachOccupyingTilePos(stepBox) { forEachOccupyingTilePos(stepBox) {
val tileCoord = LandUtil.resolveBlockAddr(it) val tileCoord = LandUtil.resolveBlockAddr(it)
val tileProp = BlockCodex.getOrNull(world.getTileFromTerrain(tileCoord.first, tileCoord.second)) val tileProp = BlockCodex.getOrNull(world.getTileFromTerrain(tileCoord.first, tileCoord.second))
if (tileProp == null || tileProp.isSolid) { if (tileProp == null || tileProp.isSolid) {
affectingTiles.add(it) affectingTiles.add(it)
} }
} }
if (affectingTiles.isNotEmpty()) { if (affectingTiles.isNotEmpty()) {
collidingStep = step collidingStep = step
break // collision found on this step, break and proceed to next 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 bounceX = false
var bounceY = false var bounceY = false
var zeroX = false
var zeroY = false
// collision NOT detected // collision NOT detected
if (collidingStep == null) { if (collidingStep == null) {
hitbox.translate(vectorSum) hitbox.translate(vectorSum)
@@ -619,6 +626,16 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
} }
// collision detected // collision detected
else { 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]) val newHitbox = hitbox.reassign(sixteenStep[collidingStep])
var selfCollisionStatus = 0 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_TOP)) selfCollisionStatus += COLL_TOPSIDE
if (isWalled(newHitbox, COLLIDING_BOTTOM)) selfCollisionStatus += COLL_BOTTOMSIDE if (isWalled(newHitbox, COLLIDING_BOTTOM)) selfCollisionStatus += COLL_BOTTOMSIDE
// fixme UP and RIGHT && LEFT and DOWN bug
when (selfCollisionStatus) { when (selfCollisionStatus) {
0 -> { println("[ActorWithPhysics] Contradiction -- collision detected by CCD, but isWalled() says otherwise") } 0 -> { println("[ActorWithPhysics] Contradiction -- collision detected by CCD, but isWalled() says otherwise") }
5 -> { bounceX = true } 5 -> { zeroX = true }
10 -> { bounceY = true } 10 -> { zeroY = true }
15 -> { newHitbox.reassign(sixteenStep[0]); bounceX = true; bounceY = true } 15 -> { newHitbox.reassign(sixteenStep[0]); zeroX = true; zeroY = true }
// one-side collision // one-side collision
1, 11 -> { newHitbox.translatePosX(TILE_SIZE - newHitbox.startX.modTileDelta ()); bounceX = true } 1, 11 -> { newHitbox.translatePosX(TILE_SIZE - newHitbox.startX.modTileDelta()); bounceX = true }
4, 14 -> { newHitbox.translatePosX( - newHitbox.endX.modTileDelta ()) ; bounceX = true } 4, 14 -> { newHitbox.translatePosX( - newHitbox.endX.modTileDelta()) ; bounceX = true }
8, 13 -> { newHitbox.translatePosY(TILE_SIZE - newHitbox.startY.modTileDelta ()); bounceY = true } 8, 13 -> { newHitbox.translatePosY(TILE_SIZE - newHitbox.startY.modTileDelta()); bounceY = true }
2, 7 -> { newHitbox.translatePosY( - newHitbox.endY.modTileDelta ()) ; bounceY = true } 2, 7 -> { newHitbox.translatePosY( - newHitbox.endY.modTileDelta()) ; bounceY = true }
// two-side collision // two-side collision
3 -> { 3 -> {
newHitbox.translatePosX(TILE_SIZE - newHitbox.startX.modTileDelta ()) newHitbox.translatePosX(TILE_SIZE - newHitbox.startX.modTileDelta())
newHitbox.translatePosY( - newHitbox.endY.modTileDelta ()) newHitbox.translatePosY( - newHitbox.endY.modTileDelta())
bounceX = true; bounceY = true bounceX = true; bounceY = true
} }
6 -> { 6 -> {
newHitbox.translatePosX( - newHitbox.endX.modTileDelta ()) println(- newHitbox.endY.modTileDelta())
newHitbox.translatePosY( - newHitbox.endY.modTileDelta ()) newHitbox.translatePosX( - newHitbox.endX.modTileDelta())
newHitbox.translatePosY( - newHitbox.endY.modTileDelta())
bounceX = true; bounceY = true bounceX = true; bounceY = true
} }
9 -> { 9 -> {
newHitbox.translatePosX(TILE_SIZE - newHitbox.startX.modTileDelta ()) newHitbox.translatePosX(TILE_SIZE - newHitbox.startX.modTileDelta())
newHitbox.translatePosY(TILE_SIZE - newHitbox.startY.modTileDelta ()) newHitbox.translatePosY(TILE_SIZE - newHitbox.startY.modTileDelta())
bounceX = true; bounceY = true bounceX = true; bounceY = true
} }
12 -> { 12 -> {
newHitbox.translatePosX( - newHitbox.endX.modTileDelta ()) newHitbox.translatePosX( - newHitbox.endX.modTileDelta())
newHitbox.translatePosY(TILE_SIZE - newHitbox.startY.modTileDelta ()) newHitbox.translatePosY(TILE_SIZE - newHitbox.startY.modTileDelta())
bounceX = true; bounceY = true bounceX = true; bounceY = true
} }
} }
if (selfCollisionStatus in listOf(3,6,9,12)) {
println("twoside collision $selfCollisionStatus")
}
// bounce X/Y // bounce X/Y
if (bounceX) { if (bounceX) {
@@ -671,6 +694,14 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
externalForce.y *= elasticity externalForce.y *= elasticity
controllerMoveDelta?.let { controllerMoveDelta!!.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) hitbox.reassign(newHitbox)
@@ -1296,6 +1327,8 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
flagDespawn = true flagDespawn = true
} }
private fun forEachOccupyingTileNum(consumer: (Int?) -> Unit) { private fun forEachOccupyingTileNum(consumer: (Int?) -> Unit) {
val tiles = ArrayList<Int?>() val tiles = ArrayList<Int?>()
for (y in tilewiseHitbox.startY.toInt()..tilewiseHitbox.endY.toInt()) { 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( val newTilewiseHitbox = Hitbox.fromTwoPoints(
hitbox.startX.div(TILE_SIZE).floor(), hitbox.startX.div(TILE_SIZE).floor(),
hitbox.startY.div(TILE_SIZE).floor(), hitbox.startY.div(TILE_SIZE).floor(),
hitbox.endX.div(TILE_SIZE).floor(), hitbox.endX.minus(0.00001).div(TILE_SIZE).floor(),
hitbox.endY.div(TILE_SIZE).floor() hitbox.endY.minus(0.00001).div(TILE_SIZE).floor()
) )
val tilePosList = ArrayList<BlockAddress>() val tilePosList = ArrayList<BlockAddress>()
@@ -1362,6 +1395,8 @@ open class ActorWithPhysics(renderOrder: RenderOrder, val immobileBody: Boolean
return tileProps.forEach(consumer) return tileProps.forEach(consumer)
} }
companion object { companion object {
/** /**

View File

@@ -11,7 +11,7 @@ object LandUtil {
fun getBlockAddr(x: Int, y: Int): BlockAddress = fun getBlockAddr(x: Int, y: Int): BlockAddress =
(Terrarum.ingame!!.world.width * y).toLong() + x (Terrarum.ingame!!.world.width * y).toLong() + x
fun resolveAbsoluteBlockNumber(t: BlockAddress): Pair<Int, Int> = fun resolveBlockAddr(t: BlockAddress): Pair<Int, Int> =
Pair((t % Terrarum.ingame!!.world.width).toInt(), (t / Terrarum.ingame!!.world.width).toInt()) Pair((t % Terrarum.ingame!!.world.width).toInt(), (t / Terrarum.ingame!!.world.width).toInt())
/** /**