diff --git a/src/net/torvald/terrarum/StateInGame.kt b/src/net/torvald/terrarum/StateInGame.kt index aa974449f..9ffed88bd 100644 --- a/src/net/torvald/terrarum/StateInGame.kt +++ b/src/net/torvald/terrarum/StateInGame.kt @@ -194,7 +194,7 @@ constructor() : BasicGameState() { /////////////////////////// TilePropUtil.dynamicLumFuncTickClock() world.updateWorldTime(delta) - WorldSimulator(player, delta) + //WorldSimulator(player, delta) WeatherMixer.update(gc, delta) TileStats.update() if (!(CommandDict["setgl"] as SetGlobalLightOverride).lightOverride) @@ -405,12 +405,12 @@ constructor() : BasicGameState() { // velocity worldG.color = GameFontBase.codeToCol["g"] worldG.drawString( - "${0x7F.toChar()}X ${actor.velocity.x}", // doesn't work for NPCs/Player + "${0x7F.toChar()}X ${actor.moveDelta.x}", actor.hitbox.posX.toFloat(), actor.hitbox.pointedY.toFloat() + 4 + 8 ) worldG.drawString( - "${0x7F.toChar()}Y ${actor.velocity.y}", + "${0x7F.toChar()}Y ${actor.moveDelta.y}", actor.hitbox.posX.toFloat(), actor.hitbox.pointedY.toFloat() + 4 + 8 * 2 ) diff --git a/src/net/torvald/terrarum/gameactors/ActorWithSprite.kt b/src/net/torvald/terrarum/gameactors/ActorWithSprite.kt index 9a4d8becf..96730d33f 100644 --- a/src/net/torvald/terrarum/gameactors/ActorWithSprite.kt +++ b/src/net/torvald/terrarum/gameactors/ActorWithSprite.kt @@ -65,39 +65,31 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean = ) /** + * TODO external force? do we need this? we have moveDelta + * * Velocity vector for newtonian sim. * Acceleration: used in code like: * veloY += 3.0 * +3.0 is acceleration. You __accumulate__ acceleration to the velocity. */ - internal val velocity = Vector2(0.0, 0.0) - var veloX: Double - get() = velocity.x - protected set(value) { - velocity.x = value - } - var veloY: Double - get() = velocity.y - protected set(value) { - velocity.y = value - } + internal val externalForce = Vector2(0.0, 0.0) - val moveDelta = Vector2(0.0, 0.0) + val moveDelta = Vector2(0.0, 0.0) // moveDelta = velocity + controllerMoveDelta @Transient private val VELO_HARD_LIMIT = 100.0 /** * for "Controllable" actors */ - var controllerVel: Vector2? = if (this is Controllable) Vector2() else null + var controllerMoveDelta: Vector2? = if (this is Controllable) Vector2() else null var walkX: Double - get() = controllerVel!!.x + get() = controllerMoveDelta!!.x protected set(value) { - controllerVel!!.x = value + controllerMoveDelta!!.x = value } var walkY: Double - get() = controllerVel!!.y + get() = controllerMoveDelta!!.y protected set(value) { - controllerVel!!.y = value + controllerMoveDelta!!.y = value } /** @@ -155,8 +147,6 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean = } get() = 1.0 - elasticity - @Transient private val CEILING_HIT_ELASTICITY = 0.3 - var density = 1000.0 set(value) { if (value < 0) @@ -342,7 +332,7 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean = * @param acc : Acceleration in Vector2 */ fun applyForce(acc: Vector2) { - velocity += acc.times(speedMultByTile) + externalForce += acc * speedMultByTile } private val bounceDampenVelThreshold = 0.5 @@ -375,8 +365,8 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean = } // hard limit velocity - veloX = veloX.bipolarClamp(VELO_HARD_LIMIT) - veloY = veloY.bipolarClamp(VELO_HARD_LIMIT) + externalForce.x = externalForce.x.bipolarClamp(VELO_HARD_LIMIT) + externalForce.y = externalForce.y.bipolarClamp(VELO_HARD_LIMIT) // Set 'next' position (hitbox) from canonical and walking velocity setNewNextHitbox() @@ -391,8 +381,12 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean = applyNormalForce() } - setHorizontalFriction() - if (immobileBody || isPlayerNoClip) { // TODO also hanging on the rope, etc. + if (!immobileBody) { // TODO test no friction on immobileBody + setHorizontalFriction() + } + //if (immobileBody || isPlayerNoClip) { // TODO also hanging on the rope, etc. + // TODO test no friction on immobileBody + if (isPlayerNoClip) { // TODO also hanging on the rope, etc. setVerticalFriction() } @@ -429,28 +423,28 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean = if (!(isCollidingSide(hitbox, COLLIDING_LEFT) && walkX < 0) || !(isCollidingSide(hitbox, COLLIDING_RIGHT) && walkX > 0) ) { - moveDelta.x = veloX + walkX + moveDelta.x = externalForce.x + walkX } // decide whether to ignore walkY if (!(isCollidingSide(hitbox, COLLIDING_TOP) && walkY < 0) || !(isCollidingSide(hitbox, COLLIDING_BOTTOM) && walkY > 0) ) { - moveDelta.y = veloY + walkY + moveDelta.y = externalForce.y + walkY } } else { if (!isCollidingSide(hitbox, COLLIDING_LEFT) || !isCollidingSide(hitbox, COLLIDING_RIGHT) ) { - moveDelta.x = veloX + moveDelta.x = externalForce.x } // decide whether to ignore walkY if (!isCollidingSide(hitbox, COLLIDING_TOP) || !isCollidingSide(hitbox, COLLIDING_BOTTOM) ) { - moveDelta.y = veloY + moveDelta.y = externalForce.y } } } @@ -475,7 +469,7 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean = * Drag of atmosphere * D = Cd (drag coefficient) * 0.5 * rho (density) * V^2 (velocity sqr) * A (area) */ - val D: Vector2 = Vector2(veloX.magnSqr(), veloY.magnSqr()) * dragCoefficient * 0.5 * A// * tileDensityFluid.toDouble() + val D: Vector2 = Vector2(moveDelta.x.magnSqr(), moveDelta.y.magnSqr()) * dragCoefficient * 0.5 * A// * tileDensityFluid.toDouble() val V: Vector2 = (W - D) / mass * SI_TO_GAME_ACC @@ -488,7 +482,7 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean = // axis Y. Using operand >= and hitting the ceiling will lock the player to the position if (moveDelta.y > 0.0) { // was moving downward? if (isColliding(nextHitbox, COLLIDING_TOP)) { // hit the ceiling - hitAndForciblyReflectY() + hitAndReflectY() //hitAndForciblyReflectY() grounded = false } else if (isColliding(nextHitbox)) { @@ -534,7 +528,7 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean = val ccdDelta = (nextHitbox.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(velocity.magnitude * 2), 0.5) // adaptive tick + val displacement = Math.min(1.0.div(moveDelta.magnitude * 2), 0.5) // adaptive tick ccdDelta.set(ccdDelta.setMagnitude(displacement)) } @@ -551,35 +545,44 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean = } private fun hitAndReflectX() { - if ((veloX * elasticity).abs() > Epsilon.E) { - veloX *= -elasticity + if ((externalForce.x * elasticity).abs() >= MINIMUM_BOUNCE_THRESHOLD) { // > Epsilon.E) { + externalForce.x *= -elasticity if (this is Controllable) walkX *= -elasticity } else { - veloX = 0.0 + externalForce.x = 0.0 if (this is Controllable) walkX = 0.0 } } private fun hitAndReflectY() { - if ((veloY * elasticity).abs() > Epsilon.E) { - veloY *= -elasticity + if (externalForce.y.abs() >= MINIMUM_BOUNCE_THRESHOLD) { //> Epsilon.E) { + externalForce.y *= -elasticity if (this is Controllable) walkY *= -elasticity } else { - veloY = 0.0 + externalForce.y = 0.0 if (this is Controllable) walkY *= 0.0 } } + @Transient private val CEILING_HIT_ELASTICITY = 0.3 + @Transient private val MINIMUM_BOUNCE_THRESHOLD = 0.1 + /** * prevents sticking to the ceiling */ private fun hitAndForciblyReflectY() { - if (veloY.abs() * CEILING_HIT_ELASTICITY > A_PIXEL) - veloY = -veloY * CEILING_HIT_ELASTICITY - else - veloY = veloY.sign() * -A_PIXEL + // TODO HARK! I have changed veloX/Y to moveDelta.x/y + if (moveDelta.y < 0) { + if (moveDelta.y.abs() * CEILING_HIT_ELASTICITY > A_PIXEL) + moveDelta.y = -moveDelta.y * CEILING_HIT_ELASTICITY + else + moveDelta.y = moveDelta.y.sign() * -A_PIXEL + } + else { + throw Error("Check this out bitch (moveDelta.y = ${moveDelta.y})") + } } private fun isColliding(hitbox: Hitbox) = isColliding(hitbox, 0) @@ -792,13 +795,13 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean = BASE_FRICTION * if (grounded) feetFriction else bodyFriction } - if (veloX < 0) { - veloX += friction - if (veloX > 0) veloX = 0.0 // compensate overshoot + if (externalForce.x < 0) { + externalForce.x += friction + if (externalForce.x > 0) externalForce.x = 0.0 // compensate overshoot } - else if (veloX > 0) { - veloX -= friction - if (veloX < 0) veloX = 0.0 // compensate overshoot + else if (externalForce.x > 0) { + externalForce.x -= friction + if (externalForce.x < 0) externalForce.x = 0.0 // compensate overshoot } if (this is Controllable) { @@ -819,13 +822,13 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean = else BASE_FRICTION * bodyFriction - if (veloY < 0) { - veloY += friction - if (veloY > 0) veloX = 0.0 // compensate overshoot + if (externalForce.y < 0) { + externalForce.y += friction + if (externalForce.y > 0) externalForce.y = 0.0 // compensate overshoot } - else if (veloY > 0) { - veloY -= friction - if (veloY < 0) veloY = 0.0 // compensate overshoot + else if (externalForce.y > 0) { + externalForce.y -= friction + if (externalForce.y < 0) externalForce.y = 0.0 // compensate overshoot } if (this is Controllable) { diff --git a/src/net/torvald/terrarum/gameactors/ProjectileSimple.kt b/src/net/torvald/terrarum/gameactors/ProjectileSimple.kt index 201d42027..06569757c 100644 --- a/src/net/torvald/terrarum/gameactors/ProjectileSimple.kt +++ b/src/net/torvald/terrarum/gameactors/ProjectileSimple.kt @@ -53,7 +53,7 @@ open class ProjectileSimple( posPre = Point2d(fromPoint.x, fromPoint.y) // lightbox sized 8x8 centered to the bullet lightBoxList.add(Hitbox(-4.0, -4.0, 8.0, 8.0)) - this.velocity.set(velocity) + //this.externalForce.set(velocity) damage = bulletDatabase[type][OFFSET_DAMAGE] as Int displayColour = bulletDatabase[type][OFFSET_COL] as Color @@ -63,7 +63,7 @@ open class ProjectileSimple( setHitboxDimension(2, 2, 0, 0) // should be following sprite's properties if there IS one - velocity.set((fromPoint to toPoint).setMagnitude(speed.toDouble())) + externalForce.set((fromPoint to toPoint).setMagnitude(speed.toDouble())) diff --git a/src/net/torvald/terrarum/gameactors/ai/AILuaAPI.kt b/src/net/torvald/terrarum/gameactors/ai/AILuaAPI.kt index 04345f729..47f172bb7 100644 --- a/src/net/torvald/terrarum/gameactors/ai/AILuaAPI.kt +++ b/src/net/torvald/terrarum/gameactors/ai/AILuaAPI.kt @@ -60,8 +60,8 @@ internal class AILuaAPI(g: Globals, actor: ActorWithSprite) { t["posX"] = actor.hitbox.centeredX.toLua() t["posY"] = actor.hitbox.centeredY.toLua() - t["veloX"] = actor.veloX.toLua() - t["veloY"] = actor.veloY.toLua() + t["veloX"] = actor.moveDelta.x.toLua() + t["veloY"] = actor.moveDelta.y.toLua() t["width"] = actor.hitbox.width.toLua() t["height"] = actor.hitbox.height.toLua() diff --git a/src/net/torvald/terrarum/gameactors/physicssolver/CollisionSolver.kt b/src/net/torvald/terrarum/gameactors/physicssolver/CollisionSolver.kt index 9b81a67c4..fcc9f0561 100644 --- a/src/net/torvald/terrarum/gameactors/physicssolver/CollisionSolver.kt +++ b/src/net/torvald/terrarum/gameactors/physicssolver/CollisionSolver.kt @@ -150,10 +150,10 @@ object CollisionSolver { // if they actually makes collision (e.g. player vs ball), solve it if (a makesCollisionWith b) { - val ux_1 = a.veloX - val ux_2 = b.veloX - val uy_1 = a.veloY - val uy_2 = b.veloY + val ux_1 = a.moveDelta.x + val ux_2 = b.moveDelta.x + val uy_1 = a.moveDelta.y + val uy_2 = b.moveDelta.y val m1 = a.mass val m2 = b.mass