correct actor walk velo/accel control even when submerged; new tileprop Viscosity

Former-commit-id: 164238c9e5e0b33f9291cb09d804e2ce2f2e1721
Former-commit-id: ec07a206dd980b9ee73530f0beab876393030656
This commit is contained in:
Song Minjae
2017-01-19 04:05:57 +09:00
parent 9efcb1684f
commit 190c596f7d
5 changed files with 202 additions and 168 deletions

View File

@@ -19,7 +19,6 @@ object AVKey {
const val ACCEL = "accel"
const val ACCELBUFF = "$ACCEL$BUFF"
/** internal value used by ActorHumanoid to implement friction in walkfunction */
const val ACCELMULT_MOVEMENT = "__accelmultmvmt"
const val SCALE = "scale"
const val SCALEBUFF = "$SCALE$BUFF" // aka PHYSIQUE
/** pixels */

View File

@@ -251,8 +251,6 @@ 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
*/
@@ -360,7 +358,6 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
* Actual physics thing (altering velocity) starts from here
*/
updateMovementControl()
// Combine velo and walk
applyMovementVelocity()
@@ -411,30 +408,6 @@ 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
@@ -885,12 +858,7 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
return friction
}
/**
* Get highest friction value from surrounding tiles
* @return
*/
internal val feetFriction: Int // FIXME sharp turn on ice is still possible as on soil/rocks
internal val feetFriction: Int
get() {
var friction = 0
forEachFeetTile { // get max friction
@@ -903,6 +871,57 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
fun Int.frictionToMult(): Double = this / 16.0
internal val bodyViscosity: Int
get() {
var viscosity = 0
forEachOccupyingTile { // get max viscosity
if (it?.viscosity ?: 0 > viscosity)
viscosity = it?.viscosity ?: 0
}
return viscosity
}
internal val feetViscosity: Int
get() {
var viscosity = 0
forEachFeetTile { // get max viscosity
if (it?.viscosity ?: 0 > viscosity)
viscosity = it?.viscosity ?: 0
}
return viscosity
}
fun Int.viscosityToMult(): Double = 16.0 / (16.0 + this)
internal val speedCapByTile: Double
get() {
val notSubmergedCap = if (grounded)
feetViscosity.viscosityToMult()
else
bodyViscosity.viscosityToMult()
val normalisedViscocity = bodyViscosity.viscosityToMult()
return interpolateLinear(submergedRatio, notSubmergedCap, normalisedViscocity)
}
/** about get going
* for about stopping, see setHorizontalFriction */
internal val accelMultMovement: Double
get() {
if (!isPlayerNoClip) {
val notSubmergedAccel = if (grounded)
feetFriction.frictionToMult()
else
bodyFriction.frictionToMult()
val normalisedViscocity = bodyViscosity.viscosityToMult()
return interpolateLinear(submergedRatio, notSubmergedAccel, normalisedViscocity)
}
else {
return 1.0
}
}
/**
* Get highest tile density from occupying tiles, fluid only
*/
@@ -1231,6 +1250,7 @@ open class ActorWithBody(renderOrder: ActorOrder) : Actor(renderOrder) {
val avSpeedCap: Double
get() = actorValue.getAsDouble(AVKey.SPEED)!! *
actorValue.getAsDouble(AVKey.SPEEDBUFF)!! *
speedCapByTile *
scale.sqrt()
}
@@ -1269,3 +1289,16 @@ fun absMax(left: Double, right: Double): Double {
fun Double.magnSqr() = if (this >= 0.0) this.sqr() else -this.sqr()
fun Double.sign() = if (this > 0.0) 1.0 else if (this < 0.0) -1.0 else 0.0
fun interpolateLinear(scale: Double, startValue: Double, endValue: Double): Double {
if (startValue == endValue) {
return startValue
}
if (scale <= 0f) {
return startValue
}
if (scale >= 1f) {
return endValue
}
return (1f - scale) * startValue + scale * endValue
}