// var player = {
// pos: {x, y}
// vel: {x, y}
// isOnGround: whether the player is touching the isOnGround
// }
// input: {lr, ud, jump}
// dt: dt
let computeV0 = function (height) {
return Math.sqrt(height * gravity * -2.0);
};
let lerp = function(a, b, t) {
return a + (b-a)*t;
};
let clamp = function(v, min, max) {
return Math.min(Math.max(v,min),max);
};
let gravity = -9.8;
let jumpHeight = 2.0;
let moveSpeed = 3.5;
let groundAccel = 25.0;
let groundDecel = 50.0;
let airAccel = 7.0;
// cache our own idea of previous velocity so we can apply average velocity and
// still compute future values correctly
if (!this.vel)
this.vel = {x:player.vel.x, y:player.vel.y};
var pVel = {x: this.vel.x, y: this.vel.y};
if (player.isOnGround) {
this.jumpTimer = 0.0;
if (input.jump && !this.jumpInit) {
pVel.y = computeV0(jumpHeight);
this.vel.y = pVel.y + gravity * dt;
this.jumpInit = true;
}
if (!input.jump)
this.jumpInit = false;
// instant velocity change
let groundSpeed = input.lr * moveSpeed;
let useAccel = Math.sign(groundSpeed) === Math.sign(this.vel.x) && Math.abs(groundSpeed) > Math.abs(this.vel.x);
let baseAccel = useAccel ? groundAccel : groundDecel;
let accel = Math.min(baseAccel * dt, Math.abs(groundSpeed - player.vel.x));
this.vel.x += (groundSpeed > player.vel.x) ? accel : -accel;
pVel.x = this.vel.x;
} else {
this.jumpTimer+=dt;
if (this.jumpInit && !input.jump)
this.jumpInit = false;
var gravityMod = lerp(0.2, 3.6, clamp(jumpTimer-0.1, 0, 1));
if (!this.jumpInit && player.vel.y > 0.0)
gravityMod = 2.3;
else if (player.vel.y <= 0.0)
gravityMod = 2.0;
this.vel.y += gravity * dt * gravityMod;
let airSpeed = input.lr * moveSpeed;
let accel = Math.min(airAccel * dt, Math.abs(airSpeed - player.vel.x));
this.vel.x += (airSpeed > player.vel.x) ? accel : -accel;
}
player.vel.x = 0.5 * (pVel.x + this.vel.x);
player.vel.y = 0.5 * (pVel.y + this.vel.y);
return player;