diff --git a/src/index.html b/src/index.html index 1926a48..a26da8d 100644 --- a/src/index.html +++ b/src/index.html @@ -23,7 +23,7 @@

✌️ Two finger drag: Pan around scene


🚶 (or press F key to toggle)

-

In FPV: WASD to move, mouse to look, F or ESC to exit

+

In FPV: WASD to move, mouse to look, SPACE to jump, SHIFT to crouch, F or ESC to exit

diff --git a/src/index.js b/src/index.js index efdb191..df57e26 100644 --- a/src/index.js +++ b/src/index.js @@ -16,10 +16,15 @@ let fpvControls = { moveBackward: false, moveLeft: false, moveRight: false, - canJump: false, + jump: false, + crouch: false, + canJump: true, velocity: new THREE.Vector3(), direction: new THREE.Vector3(), - rotation: { x: 0, y: 0 } + rotation: { x: 0, y: 0 }, + verticalVelocity: 0, + isJumping: false, + isCrouching: false }; let modelBounds = null; let groundLevel = 0; @@ -871,6 +876,20 @@ function onKeyDown(event) { case 'KeyD': if (fpvMode) fpvControls.moveRight = true; break; + case 'Space': + if (fpvMode) { + event.preventDefault(); + fpvControls.jump = true; + } + break; + case 'ShiftLeft': + case 'ShiftRight': + if (fpvMode) { + event.preventDefault(); + fpvControls.crouch = true; + fpvControls.isCrouching = true; + } + break; } } @@ -888,6 +907,16 @@ function onKeyUp(event) { case 'KeyD': if (fpvMode) fpvControls.moveRight = false; break; + case 'Space': + if (fpvMode) fpvControls.jump = false; + break; + case 'ShiftLeft': + case 'ShiftRight': + if (fpvMode) { + fpvControls.crouch = false; + fpvControls.isCrouching = false; + } + break; } } @@ -928,10 +957,13 @@ function enterFPVMode() { const centerZ = modelBounds.center.z; camera.position.set(centerX, eyeHeight, centerZ); - // Reset rotation + // Reset rotation and movement fpvControls.rotation.x = 0; fpvControls.rotation.y = 0; fpvControls.velocity.set(0, 0, 0); + fpvControls.verticalVelocity = 0; + fpvControls.isJumping = false; + fpvControls.isCrouching = false; // Update button text const fpvBtn = document.getElementById('fpv-btn'); @@ -973,6 +1005,11 @@ function exitFPVMode() { fpvControls.moveBackward = false; fpvControls.moveLeft = false; fpvControls.moveRight = false; + fpvControls.jump = false; + fpvControls.crouch = false; + fpvControls.verticalVelocity = 0; + fpvControls.isJumping = false; + fpvControls.isCrouching = false; console.log('Orbit controls restored'); }, 50); @@ -982,7 +1019,10 @@ function updateFPVMovement() { if (!fpvMode) return; const delta = 0.016; // Approximate 60fps - const moveSpeed = 500.0; // Units per second (1000x faster) + const moveSpeed = 100.0; // Units per second (1000x faster) + const jumpSpeed = 120.0; // Jump initial velocity (4x higher) + const gravity = 120.0; // Gravity strength (4x faster) + const crouchHeight = eyeHeight * 0.6; // Crouch height (60% of normal eye height) // Reset direction fpvControls.direction.set(0, 0, 0); @@ -1010,9 +1050,31 @@ function updateFPVMovement() { camera.position.add(fpvControls.direction); } - // Keep camera at eye height (simple ground collision - no falling through) - // But allow walking off edges (no invisible walls) - camera.position.y = eyeHeight; + // Handle jumping + if (fpvControls.jump && fpvControls.canJump && !fpvControls.isJumping) { + fpvControls.verticalVelocity = jumpSpeed; + fpvControls.isJumping = true; + fpvControls.canJump = false; + } + + // Apply gravity and vertical movement + if (fpvControls.isJumping) { + fpvControls.verticalVelocity -= gravity * delta; + camera.position.y += fpvControls.verticalVelocity * delta; + + // Check if landed back on ground + const targetHeight = fpvControls.isCrouching ? crouchHeight : eyeHeight; + if (camera.position.y <= targetHeight) { + camera.position.y = targetHeight; + fpvControls.verticalVelocity = 0; + fpvControls.isJumping = false; + fpvControls.canJump = true; + } + } else { + // Handle crouching when not jumping + const targetHeight = fpvControls.isCrouching ? crouchHeight : eyeHeight; + camera.position.y = targetHeight; + } // Apply rotation to camera camera.rotation.set(fpvControls.rotation.x, fpvControls.rotation.y, 0, 'YXZ');