From 9efcb1684f9e29dbef209e0e873072f3330f1944 Mon Sep 17 00:00:00 2001 From: Song Minjae Date: Thu, 19 Jan 2017 03:25:22 +0900 Subject: [PATCH] proper impl of walk friction control (WIP submerged case) Former-commit-id: cf8c11dee3eed491893bbfa61167e47863524366 Former-commit-id: 30a8fbedcc05cb6aee5f131708152d4db1fd9415 --- .../terrarum/gameactors/ActorHumanoid.kt | 21 ++--- .../terrarum/gameactors/ActorWithBody.kt | 79 +++++++++++++++---- 2 files changed, 69 insertions(+), 31 deletions(-) diff --git a/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt b/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt index bf7d42de5..2e60cec02 100644 --- a/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt +++ b/src/net/torvald/terrarum/gameactors/ActorHumanoid.kt @@ -22,6 +22,10 @@ import java.util.* open class ActorHumanoid(birth: GameDate, death: GameDate? = null) : HistoricalFigure(birth, death), Controllable, Pocketed, Factionable, Luminous, LandHolder { + + // FIXME disable all water-related movement mods (slow ESDF velo while submerged)ssssst + + /** Must be set by PlayerFactory */ override var inventory: ActorInventory = ActorInventory() @@ -74,7 +78,7 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null) @Transient val BASE_DENSITY = 980.0 companion object { - @Transient internal const val ACCEL_MULT_IN_FLIGHT: Double = 0.21 + //@Transient internal const val ACCEL_MULT_IN_FLIGHT: Double = 0.21 @Transient internal const val WALK_ACCEL_BASE: Double = 0.67 @Transient const val BASE_HEIGHT = 40 @@ -144,7 +148,6 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null) // don't put this into keyPressed; execution order is important! updateGamerControlBox(gc.input) - updateMovementControl() updateSprite(delta) if (noClip) { @@ -218,20 +221,6 @@ open class ActorHumanoid(birth: GameDate, death: GameDate? = null) } } - private fun updateMovementControl() { - if (!noClip) { - if (grounded) { - actorValue[AVKey.ACCELMULT_MOVEMENT] = 1.0 - } - else { - actorValue[AVKey.ACCELMULT_MOVEMENT] = ACCEL_MULT_IN_FLIGHT - } - } - else { - actorValue[AVKey.ACCELMULT_MOVEMENT] = 1.0 - } - } - private val hasController: Boolean get() = if (isGamer) Terrarum.controller != null else true diff --git a/src/net/torvald/terrarum/gameactors/ActorWithBody.kt b/src/net/torvald/terrarum/gameactors/ActorWithBody.kt index 96712d203..e2db6c38a 100644 --- a/src/net/torvald/terrarum/gameactors/ActorWithBody.kt +++ b/src/net/torvald/terrarum/gameactors/ActorWithBody.kt @@ -24,6 +24,9 @@ import java.util.* open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) { + // FIXME disable all water-related movement mods (slow ESDF velo while submerged) + + /** !! ActorValue macros are on the very bottom of the source !! **/ override var actorValue: ActorValue = ActorValue() @@ -248,6 +251,8 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) { protected val updateDelta: Int get() = Terrarum.ingame.UPDATE_DELTA + @Transient private var accelMultMovement = 1.0 + /** * true: This actor had just made collision */ @@ -355,6 +360,7 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) { * Actual physics thing (altering velocity) starts from here */ + updateMovementControl() // Combine velo and walk applyMovementVelocity() @@ -384,8 +390,9 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) { } setHorizontalFriction() - if (isPlayerNoClip) // or hanging on the rope, etc. + if (isPlayerNoClip) { // or hanging on the rope, etc. setVerticalFriction() + } // apply our compensation to actual hitbox updateHitbox() @@ -404,6 +411,30 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) { } } + /** about get going + * for about stopping, see setHorizontalFriction */ + private fun updateMovementControl() { + /* if not submerged: + if grounded: + feetTileFriction + else: + bodyTileFriction + else: + linearMix(not submerged, fluidViscosity, submergedRatio) + */ + if (!isPlayerNoClip) { + if (grounded) { + accelMultMovement = feetFriction.frictionToMult() + } + else { + accelMultMovement = bodyFriction.frictionToMult() + } + } + else { + accelMultMovement = 1.0 + } + } + private fun applyMovementVelocity() { if (this is Controllable) { // decide whether to ignore walkX @@ -756,11 +787,15 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) { return contactAreaCounter } + /** about stopping + * for about get moving, see updateMovementControl */ private fun setHorizontalFriction() { val friction = if (isPlayerNoClip) - BASE_FRICTION * TileCodex[Tile.STONE].friction.tileFrictionToMult() - else - BASE_FRICTION * bodyFriction.tileFrictionToMult() + BASE_FRICTION * TileCodex[Tile.STONE].friction.frictionToMult() + else { + // TODO status quo if !submerged else linearBlend(feetFriction, bodyFriction, submergedRatio) + BASE_FRICTION * (if (grounded) feetFriction else bodyFriction).frictionToMult() + } if (veloX < 0) { veloX += friction @@ -785,9 +820,9 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) { private fun setVerticalFriction() { val friction = if (isPlayerNoClip) - BASE_FRICTION * TileCodex[Tile.STONE].friction.tileFrictionToMult() + BASE_FRICTION * TileCodex[Tile.STONE].friction.frictionToMult() else - BASE_FRICTION * bodyFriction.tileFrictionToMult() + BASE_FRICTION * bodyFriction.frictionToMult() if (veloY < 0) { veloY += friction @@ -827,24 +862,23 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) { } }*/ - /*private val submergedVolume: Double + private val submergedRatio: Double + get() = submergedHeight / hitbox.height + + private val submergedVolume: Double get() = submergedHeight * hitbox.width * hitbox.width private val submergedHeight: Double get() = Math.max( getContactingAreaFluid(COLLIDING_LEFT), getContactingAreaFluid(COLLIDING_RIGHT) - ).toDouble()*/ + ).toDouble() - /** - * Get highest friction value from surrounding tiles - * @return - */ internal val bodyFriction: Int get() { var friction = 0 - forEachFeetTile { + forEachOccupyingTile { // get max friction if (it?.friction ?: TileCodex[Tile.AIR].friction > friction) friction = it?.friction ?: TileCodex[Tile.AIR].friction } @@ -852,7 +886,22 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) { return friction } - fun Int.tileFrictionToMult(): Double = this / 16.0 + /** + * Get highest friction value from surrounding tiles + * @return + */ + internal val feetFriction: Int // FIXME sharp turn on ice is still possible as on soil/rocks + get() { + var friction = 0 + forEachFeetTile { // get max friction + if (it?.friction ?: TileCodex[Tile.AIR].friction > friction) + friction = it?.friction ?: TileCodex[Tile.AIR].friction + } + + return friction + } + + fun Int.frictionToMult(): Double = this / 16.0 /** * Get highest tile density from occupying tiles, fluid only @@ -1177,7 +1226,7 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) { val avAcceleration: Double get() = actorValue.getAsDouble(AVKey.ACCEL)!! * actorValue.getAsDouble(AVKey.ACCELBUFF)!! * - (actorValue.getAsDouble(AVKey.ACCELMULT_MOVEMENT) ?: 1.0) * + accelMultMovement * scale.sqrt() val avSpeedCap: Double get() = actorValue.getAsDouble(AVKey.SPEED)!! *