Feature/Add movement interpolation (#5)
All checks were successful
Build and Publish Docker Image / Build and Validate (push) Successful in 7s
Build and Publish Docker Image / Publish to Registry (push) Successful in 7s

- 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: #5
Co-authored-by: Juan Sebastian Montoya <juansmm@outlook.com>
Co-committed-by: Juan Sebastian Montoya <juansmm@outlook.com>
This commit is contained in:
Juan Sebastián Montoya 2025-11-26 09:36:39 -05:00 committed by Juan Sebastián Montoya
parent dfe87d63cc
commit c5a7f160bc

View file

@ -153,7 +153,10 @@
class Player extends GameObject { class Player extends GameObject {
constructor(scene, groundSize) { constructor(scene, groundSize) {
super(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() { createMesh() {
@ -170,31 +173,69 @@
} }
initialize() { initialize() {
// Initialize velocity (needed because initialize is called from parent constructor)
if (!this.velocity) {
this.velocity = new THREE.Vector3(0, 0, 0);
}
this.reset(); this.reset();
} }
reset() { reset() {
this.setPosition(0, 0.5, 0); this.setPosition(0, 0.5, 0);
this.mesh.rotation.y = 0; this.mesh.rotation.y = 0;
if (this.velocity) {
this.velocity.set(0, 0, 0);
}
} }
update(keys) { 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['w'] || keys['arrowup']) targetVelocity.z -= this.maxSpeed;
if (keys['s'] || keys['arrowdown']) moveVector.z += this.speed; if (keys['s'] || keys['arrowdown']) targetVelocity.z += this.maxSpeed;
if (keys['a'] || keys['arrowleft']) moveVector.x -= this.speed; if (keys['a'] || keys['arrowleft']) targetVelocity.x -= this.maxSpeed;
if (keys['d'] || keys['arrowright']) moveVector.x += this.speed; 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 // Boundary checks
const boundary = this.groundSize / 2 - 0.5; const boundary = this.groundSize / 2 - 0.5;
this.mesh.position.x = Math.max(-boundary, Math.min(boundary, this.mesh.position.x)); 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)); 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 // Rotate player based on movement
if (moveVector.length() > 0) { if (this.velocity.length() > 0.01) {
this.mesh.rotation.y += 0.1; this.mesh.rotation.y += 0.1;
} }
} }