// 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;