From c5a7f160bc84db003ffd834e0ed135af2447c938 Mon Sep 17 00:00:00 2001 From: Juan Sebastian Montoya Date: Wed, 26 Nov 2025 09:36:39 -0500 Subject: [PATCH] Feature/Add movement interpolation (#5) - Updated Player class to use maxSpeed, acceleration, and deceleration for smoother movement. - Introduced velocity vector for more responsive control and smoother diagonal movement. - Enhanced update method to calculate target velocity based on input and apply easing for acceleration and deceleration. - Implemented boundary checks to stop movement when hitting the edges of the play area. Reviewed-on: https://git.jusemon.com/jusemon/threejs-test/pulls/5 Co-authored-by: Juan Sebastian Montoya Co-committed-by: Juan Sebastian Montoya --- index.html | 57 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/index.html b/index.html index be499cd..9a8bfd3 100644 --- a/index.html +++ b/index.html @@ -153,7 +153,10 @@ class Player extends GameObject { constructor(scene, groundSize) { super(scene, groundSize); - this.speed = 0.15; + this.maxSpeed = 0.15; + this.acceleration = 0.08; + this.deceleration = 0.12; + this.velocity = new THREE.Vector3(0, 0, 0); } createMesh() { @@ -170,31 +173,69 @@ } initialize() { + // Initialize velocity (needed because initialize is called from parent constructor) + if (!this.velocity) { + this.velocity = new THREE.Vector3(0, 0, 0); + } this.reset(); } reset() { this.setPosition(0, 0.5, 0); this.mesh.rotation.y = 0; + if (this.velocity) { + this.velocity.set(0, 0, 0); + } } update(keys) { - const moveVector = new THREE.Vector3(); + // Calculate target velocity based on input + const targetVelocity = new THREE.Vector3(0, 0, 0); - if (keys['w'] || keys['arrowup']) moveVector.z -= this.speed; - if (keys['s'] || keys['arrowdown']) moveVector.z += this.speed; - if (keys['a'] || keys['arrowleft']) moveVector.x -= this.speed; - if (keys['d'] || keys['arrowright']) moveVector.x += this.speed; + if (keys['w'] || keys['arrowup']) targetVelocity.z -= this.maxSpeed; + if (keys['s'] || keys['arrowdown']) targetVelocity.z += this.maxSpeed; + if (keys['a'] || keys['arrowleft']) targetVelocity.x -= this.maxSpeed; + if (keys['d'] || keys['arrowright']) targetVelocity.x += this.maxSpeed; - this.mesh.position.add(moveVector); + // Smoothly interpolate velocity towards target + const isMoving = targetVelocity.length() > 0; + const accelRate = isMoving ? this.acceleration : this.deceleration; + + // Calculate velocity difference for each axis + const velDiffX = targetVelocity.x - this.velocity.x; + const velDiffZ = targetVelocity.z - this.velocity.z; + + // Apply easing to each axis independently for smoother diagonal movement + if (Math.abs(velDiffX) > 0.001) { + this.velocity.x += velDiffX * accelRate; + } else { + this.velocity.x = targetVelocity.x; + } + + if (Math.abs(velDiffZ) > 0.001) { + this.velocity.z += velDiffZ * accelRate; + } else { + this.velocity.z = targetVelocity.z; + } + + // Apply velocity to position + this.mesh.position.add(this.velocity); // Boundary checks const boundary = this.groundSize / 2 - 0.5; this.mesh.position.x = Math.max(-boundary, Math.min(boundary, this.mesh.position.x)); this.mesh.position.z = Math.max(-boundary, Math.min(boundary, this.mesh.position.z)); + // Stop velocity if hitting boundary + if (Math.abs(this.mesh.position.x) >= boundary) { + this.velocity.x = 0; + } + if (Math.abs(this.mesh.position.z) >= boundary) { + this.velocity.z = 0; + } + // Rotate player based on movement - if (moveVector.length() > 0) { + if (this.velocity.length() > 0.01) { this.mesh.rotation.y += 0.1; } }