player now walks again, still stick to wall if key is kept down, but gravity is no longer accumulated (because the walking velocity is now separated)

Former-commit-id: f9394abe6230a4e60f2f7a42e81f7e85264a60c5
Former-commit-id: 1cd5b78c5800aef082d5eeec13a0a0a50ccea35b
This commit is contained in:
Song Minjae
2016-05-08 01:29:52 +09:00
parent 12876a5ce2
commit 127e6344cf
5 changed files with 94 additions and 65 deletions

View File

@@ -52,7 +52,7 @@ constructor() : BasicGameState() {
lateinit var consoleHandler: UIHandler
lateinit var debugWindow: UIHandler
lateinit var notifinator: UIHandler
lateinit var notifier: UIHandler
lateinit internal var player: Player
@@ -123,10 +123,10 @@ constructor() : BasicGameState() {
debugWindow = UIHandler(BasicDebugInfoWindow())
debugWindow.setPosition(0, 0)
notifinator = UIHandler(Notification())
notifinator.setPosition(
(Terrarum.WIDTH - notifinator.UI.width) / 2, Terrarum.HEIGHT - notifinator.UI.height)
notifinator.setVisibility(true)
notifier = UIHandler(Notification())
notifier.setPosition(
(Terrarum.WIDTH - notifier.UI.width) / 2, Terrarum.HEIGHT - notifier.UI.height)
notifier.setVisibility(true)
if (Terrarum.gameConfig.getAsBoolean("smoothlighting") == true)
KeyToggler.forceSet(KEY_LIGHTMAP_SMOOTH, true)
@@ -164,7 +164,7 @@ constructor() : BasicGameState() {
debugWindow.update(gc, delta)
notifinator.update(gc, delta)
notifier.update(gc, delta)
Terrarum.appgc.setVSync(Terrarum.appgc.fps >= Terrarum.VSYNC_TRIGGER_THRESHOLD)
}
@@ -250,7 +250,7 @@ constructor() : BasicGameState() {
uiContainer.forEach { ui -> ui.render(gc, g) }
debugWindow.render(gc, g)
consoleHandler.render(gc, g)
notifinator.render(gc, g)
notifier.render(gc, g)
}
private fun getGradientColour(row: Int): Color {
@@ -311,20 +311,21 @@ constructor() : BasicGameState() {
g.fill(skyBox, skyColourFill)
}
/** Send message to notifier UI and toggle the UI as opened. */
fun sendNotification(msg: Array<String>) {
(notifinator.UI as Notification).sendNotification(Terrarum.appgc, update_delta, msg)
notifinator.setAsOpening()
(notifier.UI as Notification).sendNotification(Terrarum.appgc, update_delta, msg)
notifier.setAsOpening()
}
fun wakeDormantActors() {
// determine whether the inactive actor should be re-active
// determine whether the dormant actor should be re-activated
var actorContainerSize = actorContainerInactive.size
var i = 0
while (i < actorContainerSize) { // loop thru actorContainerInactive
val actor = actorContainerInactive[i]
val actorIndex = i
if (actor is Visible && actor.inUpdateRange()) {
addActor(actor)
addActor(actor) // duplicates are checked here
actorContainerInactive.removeAt(actorIndex)
actorContainerSize -= 1
i-- // array removed 1 elem, so also decrement counter by 1
@@ -336,14 +337,14 @@ constructor() : BasicGameState() {
fun updateAndInactivateDistantActors(gc: GameContainer, delta: Int) {
var actorContainerSize = actorContainer.size
var i = 0
// determine whether the actor should be active or dormant by its distance from the player
// will put dormant actors to list specifically for them
// determine whether the actor should be active or dormant by its distance from the player.
// If the actor must be dormant, the target actor will be put to the list specifically for them.
// if the actor is not to be dormant, update it
while (i < actorContainerSize) { // loop thru actorContainer
while (i < actorContainerSize) { // loop through the actorContainer
val actor = actorContainer[i]
val actorIndex = i
if (actor is Visible && !actor.inUpdateRange()) {
actorContainerInactive.add(actor) // duplicates are checked when the actor is re-activated
actorContainerInactive.add(actor) // naïve add; duplicates are checked when the actor is re-activated
actorContainer.removeAt(actorIndex)
actorContainerSize -= 1
i-- // array removed 1 elem, so also decrement counter by 1
@@ -359,6 +360,7 @@ constructor() : BasicGameState() {
get() = getGradientColour(2).getRGB24().rgb24ExpandToRgb30()
fun Color.getRGB24(): Int = (this.redByte shl 16) or (this.greenByte shl 8) or (this.blueByte)
/** Remap 8-bit value (0.0-1.0) to 10-bit value (0.0-4.0) by prepending two bits of zero for each R, G and B. */
fun Int.rgb24ExpandToRgb30(): Int = (this and 0xff) or
(this and 0xff00).ushr(8).shl(10) or
(this and 0xff0000).ushr(16).shl(20)
@@ -382,11 +384,16 @@ constructor() : BasicGameState() {
actorContainer.binarySearch(ID) >= 0
fun removeActor(actor: Actor) = removeActor(actor.referenceID)
/**
* get index of the actor and delete by the index.
* we can do this as the list is guaranteed to be sorted
* and only contains unique values.
*
* Any values behind the index will be automatically pushed to front.
* This is how remove function of [java.util.ArrayList] is defined.
*/
fun removeActor(ID: Int) {
if (ID == player.referenceID) throw RuntimeException("Attempted to remove player.")
// get index of the actor and delete by the index.
// we can do this as the list is guaranteed to be sorted
// and only contains unique values
val indexToDelete = actorContainer.binarySearch(ID)
if (indexToDelete >= 0) actorContainer.removeAt(indexToDelete)
}
@@ -418,7 +425,6 @@ constructor() : BasicGameState() {
}
private fun insertionSortLastElem(arr: ArrayList<Actor>) {
// 'insertion sort' last element
var x: Actor
var j: Int
var index: Int = arr.size - 1

View File

@@ -35,13 +35,16 @@ open class ActorWithBody constructor() : Actor(), Visible {
* veloY += 3.0
* +3.0 is acceleration. You __accumulate__ acceleration to the velocity.
*/
internal val positioningDelta = Vector2(0.0, 0.0)
internal val velocity = Vector2(0.0, 0.0)
var veloX: Double
get() = positioningDelta.x
private set(value) { positioningDelta.x = value }
get() = velocity.x
private set(value) { velocity.x = value }
var veloY: Double
get() = positioningDelta.y
private set(value) { positioningDelta.y = value }
get() = velocity.y
private set(value) { velocity.y = value }
var walkX: Double = 0.0
var walkY: Double = 0.0
val moveDelta = Vector2(0.0, 0.0)
@Transient private val VELO_HARD_LIMIT = 10000.0
var grounded = false
@@ -118,7 +121,7 @@ open class ActorWithBody constructor() : Actor(), Visible {
*/
@Transient private val SI_TO_GAME_VEL = METER / Terrarum.TARGET_FPS
@Transient private var gravitation: Vector2 = map.gravitation
@Transient private val gravitation: Vector2 = map.gravitation
@Transient val DRAG_COEFF_DEFAULT = 1.2
/** Drag coeffisient. Parachutes have much higher value than bare body (1.2) */
private var DRAG_COEFF: Double
@@ -157,8 +160,8 @@ open class ActorWithBody constructor() : Actor(), Visible {
@Transient private val MASS_DEFAULT: Double = 60.0
internal val physSleep: Boolean
get() = veloX.abs() < 0.5 && veloY.abs() < 0.5
internal var physSleep: Boolean = false
private set
/**
* for collide-to-world compensation
@@ -176,10 +179,6 @@ open class ActorWithBody constructor() : Actor(), Visible {
private val CCD_THRE = 1.0
private val CCD_TICK = 0.125
val movementDelta = Vector2(0.0, 0.0)
val externalDelta = Vector2(0.0, 0.0)
private val gravityDelta = Vector2(0.0 , 0.0)
init {
}
@@ -226,6 +225,18 @@ open class ActorWithBody constructor() : Actor(), Visible {
override fun run() = update(Terrarum.appgc, Terrarum.game.DELTA_T)
/**
* Add vector value to the velocity, in the time unit of single frame.
*
* Since we're adding some value every frame, the value is equivalent to the acceleration.
* Find about Newton's second law for the background knowledge.
* @param vec : Acceleration in Vector2
*/
fun applyForce(vec: Vector2) {
velocity += vec
physSleep = false
}
override fun update(gc: GameContainer, delta_t: Int) {
if (isUpdate) {
@@ -251,12 +262,13 @@ open class ActorWithBody constructor() : Actor(), Visible {
//applyBuoyancy()
}
positioningDelta.set(movementDelta + externalDelta + gravityDelta)
// hard limit velocity
if (veloX > VELO_HARD_LIMIT) veloX = VELO_HARD_LIMIT
if (veloY > VELO_HARD_LIMIT) veloY = VELO_HARD_LIMIT
moveDelta.x = veloX + walkX
moveDelta.y = veloY + walkY
if (!physSleep) {
// Set 'next' position (hitbox) to fiddle with
setNewNextHitbox()
@@ -309,16 +321,17 @@ open class ActorWithBody constructor() : Actor(), Visible {
* Drag of atmosphere
* D = Cd (drag coefficient) * 0.5 * rho (density) * V^2 (velocity) * A (area)
*/
val D: Vector2 = (gravityDelta + movementDelta) * DRAG_COEFF * 0.5 * A * tileDensityFluid.toDouble()
val D: Vector2 = velocity * DRAG_COEFF * 0.5 * A * tileDensityFluid.toDouble()
val V: Vector2 = (W - D) / mass * SI_TO_GAME_ACC
gravityDelta += V
applyForce(V)
}
}
private fun setHorizontalFriction() {
val friction = BASE_FRICTION * tileFriction.tileFrictionToMult()
if (veloX < 0) {
veloX += friction
if (veloX > 0) veloX = 0.0 // compensate overshoot
@@ -327,18 +340,37 @@ open class ActorWithBody constructor() : Actor(), Visible {
veloX -= friction
if (veloX < 0) veloX = 0.0 // compensate overshoot
}
if (walkX < 0) {
walkX += friction
if (walkX > 0) walkX = 0.0
}
else if (walkX > 0) {
walkX -= friction
if (walkX < 0) walkX = 0.0
}
}
private fun setVerticalFriction() {
val friction = BASE_FRICTION * tileFriction.tileFrictionToMult()
if (veloY < 0) {
veloY += friction
if (veloY > 0) veloY = 0.0 // compensate overshoot
if (veloY > 0) veloX = 0.0 // compensate overshoot
}
else if (veloY > 0) {
veloY -= friction
if (veloY < 0) veloY = 0.0 // compensate overshoot
}
if (walkY < 0) {
walkY += friction
if (walkY > 0) walkY = 0.0
}
else if (walkY > 0) {
walkY -= friction
if (walkY < 0) walkY = 0.0
}
}
private fun updateVerticalCollision() {
@@ -347,13 +379,11 @@ open class ActorWithBody constructor() : Actor(), Visible {
if (isColliding(CONTACT_AREA_BOTTOM)) { // the ground has dug into the body
adjustHitBottom()
veloY = 0.0 // reset veloY, simulating normal force
gravityDelta.zero()
hitAndReflectY()
grounded = true
}
else if (isColliding(CONTACT_AREA_BOTTOM, 0, 1)) { // the actor is standing ON the ground
veloY = 0.0 // reset veloY, simulating normal force
gravityDelta.zero()
hitAndReflectY()
grounded = true
}
@@ -566,7 +596,7 @@ open class ActorWithBody constructor() : Actor(), Visible {
private fun hitAndReflectX() {
if ((veloX * elasticity).abs() > SLEEP_THRE) {
veloX = -veloX * elasticity
veloX *= -elasticity
}
else {
veloX = 0.0
@@ -575,7 +605,7 @@ open class ActorWithBody constructor() : Actor(), Visible {
private fun hitAndReflectY() {
if ((veloY * elasticity).abs() > SLEEP_THRE) {
veloY = -veloY * elasticity
veloY *= -elasticity
}
else {
veloY = 0.0
@@ -774,8 +804,8 @@ open class ActorWithBody constructor() : Actor(), Visible {
private fun setNewNextHitbox() {
nextHitbox.set(
(hitbox.posX + veloX)
, (hitbox.posY + veloY)
(hitbox.posX + moveDelta.x)
, (hitbox.posY + moveDelta.y)
, (baseHitboxW * scale)
, (baseHitboxH * scale)
)

View File

@@ -133,24 +133,19 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
(if (left) -1 else 1).toFloat() *
absAxisVal
// veloX = readonly_totalX
movementDelta += Vector2(readonly_totalX, 0.0)
//applyForce(Vector2(readonly_totalX, 0.0))
walkX += readonly_totalX
walkX = absClamp(walkX, actorValue.getAsDouble(AVKey.SPEED)!! * actorValue.getAsDouble(AVKey.SPEEDMULT)!!)
walkCounter += 1
// Clamp veloX
movementDelta.x = absClamp(movementDelta.x,
actorValue.getAsDouble(AVKey.SPEED)!!
* actorValue.getAsDouble(AVKey.SPEEDMULT)!!
* Math.sqrt(scale))
// Heading flag
if (left)
walkHeading = LEFT
else
walkHeading = RIGHT
println("$walkCounter: ${movementDelta.x}")
println("$walkCounter: ${readonly_totalX}")
}
/**
@@ -168,15 +163,9 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
(if (up) -1 else 1).toFloat() *
absAxisVal
movementDelta.set(Vector2(0.0, readonly_totalY))
applyForce(Vector2(0.0, readonly_totalY))
if (walkCounter <= WALK_FRAMES_TO_MAX_ACCEL) walkCounter += 1
// Clamp veloX
movementDelta.y = absClamp(movementDelta.y,
actorValue.getAsDouble(AVKey.SPEED)!! *
actorValue.getAsDouble(AVKey.SPEEDMULT)!! *
Math.sqrt(scale))
}
private fun applyAccel(x: Int): Double {
@@ -214,7 +203,6 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
//veloX = 0f
walkCounter = 0
movementDelta.zero()
}
// stops; let the friction kick in by doing nothing to the velocity here
@@ -241,7 +229,6 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
///veloY = 0f
walkCounter = 0
movementDelta.zero()
}
/**
@@ -260,9 +247,9 @@ class Player : ActorWithBody, Controllable, Pocketed, Factionable, Luminous, Lan
var timedJumpCharge = init - init / len * jumpCounter
if (timedJumpCharge < 0) timedJumpCharge = 0.0
val jumpAcc = pwr * timedJumpCharge * JUMP_ACCELERATION_MOD * Math.sqrt(scale)
val jumpAcc = pwr * timedJumpCharge * JUMP_ACCELERATION_MOD * Math.sqrt(scale) // positive value
movementDelta.y -= jumpAcc
applyForce(Vector2(0.0, -jumpAcc))
}
// for mob ai:

View File

@@ -85,8 +85,8 @@ class BasicDebugInfoWindow:UICanvas {
+ (hitbox.pointedY / MapDrawer.TILE_SIZE).toInt().toString()
+ ")")
printLine(g, 3, "veloX reported $ccG${if (player.physSleep) "(sleep)" else player.veloX}")
printLine(g, 4, "veloY reported $ccG${if (player.physSleep) "(sleep)" else player.veloY}")
printLine(g, 3, "veloX reported $ccG${if (player.physSleep) "(sleep)" else player.moveDelta.x}")
printLine(g, 4, "veloY reported $ccG${if (player.physSleep) "(sleep)" else player.moveDelta.y}")
printLineColumn(g, 2, 3, "veloX measured $ccG${xdelta}")
printLineColumn(g, 2, 4, "veloY measured $ccG${ydelta}")

View File

@@ -542,12 +542,18 @@ class Vector2 {
*/
operator fun not() = negate()
/**
* Negates this [Vector2].
* @return [Vector2] this vector
*/
operator fun unaryMinus() = negate()
/**
* Negates this [Vector2].
* @return [Vector2] this vector
*/
fun negate(): Vector2 {
return Vector2(x * -1.0, y * -1.0)
return Vector2(-x, -y)
}
/**