diff options
author | elioat <elioat@tilde.institute> | 2025-04-09 22:00:15 -0400 |
---|---|---|
committer | elioat <elioat@tilde.institute> | 2025-04-09 22:00:15 -0400 |
commit | 0b4e014792b6969a0627fcf8e651f236102027af (patch) | |
tree | 9e6087241b00f211d75192e1f2d4f6d820fb2aa3 /html/space/physics.js | |
parent | a375a8bb1084bef90967734c6ec0233fca306145 (diff) | |
download | tour-0b4e014792b6969a0627fcf8e651f236102027af.tar.gz |
*
Diffstat (limited to 'html/space/physics.js')
-rw-r--r-- | html/space/physics.js | 279 |
1 files changed, 206 insertions, 73 deletions
diff --git a/html/space/physics.js b/html/space/physics.js index 6b71601..d4dfe55 100644 --- a/html/space/physics.js +++ b/html/space/physics.js @@ -1,5 +1,6 @@ // Physics module for handling movement and collisions import { inputState } from './input.js'; +import { createProjectile } from './gameState.js'; // Constants const MAX_THRUST = 0.5; // Reduced from 2 @@ -8,113 +9,245 @@ const DECELERATION = 0.001; // Reduced from 0.01 const BASE_ROTATION_SPEED = 0.001; // Reduced from 0.005 const ROTATION_ACCELERATION = 0.0005; // Reduced from 0.002 const ROTATION_DECELERATION = 0.0002; // Reduced from 0.001 +const MOUSE_SENSITIVITY = 0.03; // Increased from 0.01 for sharper turns +const MAX_SPEED = 1.0; // Maximum speed in any direction + +// Weapon constants +export const PRIMARY_COOLDOWN = 100; // ms between primary shots +export const SECONDARY_COOLDOWN = 2000; // ms between secondary shots +export const PRIMARY_BURST_COUNT = 3; // Number of shots in primary burst +export const PRIMARY_BURST_DELAY = 50; // ms between burst shots // Player state -const player = { +let playerState = { position: { x: 0, y: 0, z: 0 }, velocity: { x: 0, y: 0, z: 0 }, - rotation: { x: 0, y: 0, z: 0 }, - rotationSpeed: { x: 0, y: 0 } // Added for smooth rotation + rotation: { x: 0, y: 0 }, + thrust: 0, + strafe: 0, + weapons: { + primary: { + lastFired: 0, + burstCount: 0, + burstTimer: 0 + }, + secondary: { + lastFired: 0 + } + } }; // Initialize physics export function initPhysics() { // Reset player state - player.position = { x: 0, y: 0, z: 0 }; - player.velocity = { x: 0, y: 0, z: 0 }; - player.rotation = { x: 0, y: 0, z: 0 }; - player.rotationSpeed = { x: 0, y: 0 }; + playerState.position = { x: 0, y: 0, z: 0 }; + playerState.velocity = { x: 0, y: 0, z: 0 }; + playerState.rotation = { x: 0, y: 0 }; + playerState.thrust = 0; + playerState.strafe = 0; } -// Helper function to apply force in a direction -function applyForce(direction, magnitude, deltaTime) { - const force = { - x: direction.x * magnitude * deltaTime, - y: direction.y * magnitude * deltaTime, - z: direction.z * magnitude * deltaTime - }; - - player.velocity.x += force.x; - player.velocity.y += force.y; - player.velocity.z += force.z; +// Helper function to limit speed in a direction +function limitSpeed(velocity, maxSpeed) { + const speed = Math.sqrt(velocity.x * velocity.x + velocity.y * velocity.y + velocity.z * velocity.z); + if (speed > maxSpeed) { + const scale = maxSpeed / speed; + velocity.x *= scale; + velocity.y *= scale; + velocity.z *= scale; + } } -// Update physics -export function updatePhysics(deltaTime) { - // Update rotation speed based on input - if (inputState.yaw !== 0) { - player.rotationSpeed.y += inputState.yaw * ROTATION_ACCELERATION * deltaTime; +// Update player controls +export function updatePlayerControls(controls) { + // Handle thrust (space bar) + if (controls.thrust) { + playerState.thrust = Math.min(playerState.thrust + THRUST_ACCELERATION, MAX_THRUST); } else { - // Smoothly decelerate rotation - player.rotationSpeed.y *= (1 - ROTATION_DECELERATION * deltaTime); + // Apply deceleration when no thrust input + if (playerState.thrust > 0) { + playerState.thrust = Math.max(playerState.thrust - DECELERATION, 0); + } } - if (inputState.pitch !== 0) { - player.rotationSpeed.x += inputState.pitch * ROTATION_ACCELERATION * deltaTime; + // Handle vertical strafing (W/S) + if (controls.up) { + playerState.verticalStrafe = Math.min(playerState.verticalStrafe + THRUST_ACCELERATION, MAX_THRUST); + } else if (controls.down) { + playerState.verticalStrafe = Math.max(playerState.verticalStrafe - THRUST_ACCELERATION, -MAX_THRUST); } else { - // Smoothly decelerate rotation - player.rotationSpeed.x *= (1 - ROTATION_DECELERATION * deltaTime); + // Apply deceleration when no vertical strafe input + if (playerState.verticalStrafe > 0) { + playerState.verticalStrafe = Math.max(playerState.verticalStrafe - DECELERATION, 0); + } else if (playerState.verticalStrafe < 0) { + playerState.verticalStrafe = Math.min(playerState.verticalStrafe + DECELERATION, 0); + } + } + + // Handle horizontal strafing (A/D) + if (controls.left) { + playerState.horizontalStrafe = Math.min(playerState.horizontalStrafe + THRUST_ACCELERATION, MAX_THRUST); + } else if (controls.right) { + playerState.horizontalStrafe = Math.max(playerState.horizontalStrafe - THRUST_ACCELERATION, -MAX_THRUST); + } else { + // Apply deceleration when no horizontal strafe input + if (playerState.horizontalStrafe > 0) { + playerState.horizontalStrafe = Math.max(playerState.horizontalStrafe - DECELERATION, 0); + } else if (playerState.horizontalStrafe < 0) { + playerState.horizontalStrafe = Math.min(playerState.horizontalStrafe + DECELERATION, 0); + } + } + + // Handle mouse-based rotation with smoothing + const targetRotationY = controls.mouseX * MOUSE_SENSITIVITY; + const targetRotationX = controls.mouseY * MOUSE_SENSITIVITY; + + // Smooth rotation using lerp with faster response + playerState.rotation.y += (targetRotationY - playerState.rotation.y) * 0.2; + playerState.rotation.x += (targetRotationX - playerState.rotation.x) * 0.2; + + // Clamp pitch rotation + playerState.rotation.x = Math.max(-Math.PI/2, Math.min(Math.PI/2, playerState.rotation.x)); + + // Handle weapons with cooldowns + const currentTime = Date.now(); + + // Primary weapon (burst fire) + if (controls.fire) { + const primary = playerState.weapons.primary; + if (currentTime - primary.lastFired >= PRIMARY_COOLDOWN && primary.burstCount === 0) { + primary.burstCount = PRIMARY_BURST_COUNT; + primary.burstTimer = currentTime; + firePrimaryWeapon(); + primary.lastFired = currentTime; + } } - // Apply rotation based on current rotation speed - player.rotation.y += player.rotationSpeed.y * BASE_ROTATION_SPEED * deltaTime; - player.rotation.x += player.rotationSpeed.x * BASE_ROTATION_SPEED * deltaTime; + // Secondary weapon (single shot with cooldown) + if (controls.secondary && currentTime - playerState.weapons.secondary.lastFired >= SECONDARY_COOLDOWN) { + fireSecondaryWeapon(); + playerState.weapons.secondary.lastFired = currentTime; + } - // Calculate forward and right vectors based on current rotation - const cosY = Math.cos(player.rotation.y); - const sinY = Math.sin(player.rotation.y); - const cosX = Math.cos(player.rotation.x); - const sinX = Math.sin(player.rotation.x); + // Handle burst fire timing + const primary = playerState.weapons.primary; + if (primary.burstCount > 0 && currentTime - primary.burstTimer >= PRIMARY_BURST_DELAY) { + firePrimaryWeapon(); + primary.burstCount--; + primary.burstTimer = currentTime; + } +} - // Forward vector (in the direction the ship is facing) +// Update physics +export function updatePhysics(deltaTime) { + // Calculate forward and right vectors based on rotation const forward = { - x: sinY * cosX, - y: sinX, - z: cosY * cosX + x: Math.sin(playerState.rotation.y) * Math.cos(playerState.rotation.x), + y: -Math.sin(playerState.rotation.x), + z: Math.cos(playerState.rotation.y) * Math.cos(playerState.rotation.x) }; - // Right vector (perpendicular to forward) const right = { - x: cosY, + x: Math.cos(playerState.rotation.y), y: 0, - z: -sinY + z: -Math.sin(playerState.rotation.y) }; - // Apply thrust in the direction the ship is facing - if (inputState.thrust !== 0) { - applyForce(forward, inputState.thrust * THRUST_ACCELERATION, deltaTime); - } + const up = { x: 0, y: 1, z: 0 }; - // Apply strafing force - if (inputState.strafe !== 0) { - applyForce(right, inputState.strafe * THRUST_ACCELERATION, deltaTime); - } + // Apply thrust in forward direction + const thrustVelocity = { + x: forward.x * playerState.thrust * deltaTime, + y: forward.y * playerState.thrust * deltaTime, + z: forward.z * playerState.thrust * deltaTime + }; - // Apply damping to simulate space friction (very slight) - const currentSpeed = Math.sqrt( - player.velocity.x * player.velocity.x + - player.velocity.y * player.velocity.y + - player.velocity.z * player.velocity.z - ); - - if (currentSpeed > 0) { - const speedDamping = 1 - (DECELERATION * deltaTime); - player.velocity.x *= speedDamping; - player.velocity.y *= speedDamping; - player.velocity.z *= speedDamping; - } + // Apply horizontal strafe + const horizontalStrafeVelocity = { + x: right.x * playerState.horizontalStrafe * deltaTime, + y: 0, + z: right.z * playerState.horizontalStrafe * deltaTime + }; + + // Apply vertical strafe + const verticalStrafeVelocity = { + x: 0, + y: up.y * playerState.verticalStrafe * deltaTime, + z: 0 + }; + + // Add velocities + playerState.velocity.x += thrustVelocity.x + horizontalStrafeVelocity.x + verticalStrafeVelocity.x; + playerState.velocity.y += thrustVelocity.y + horizontalStrafeVelocity.y + verticalStrafeVelocity.y; + playerState.velocity.z += thrustVelocity.z + horizontalStrafeVelocity.z + verticalStrafeVelocity.z; + + // Limit total speed + limitSpeed(playerState.velocity, MAX_SPEED); + + // Apply velocity to position + playerState.position.x += playerState.velocity.x * deltaTime; + playerState.position.y += playerState.velocity.y * deltaTime; + playerState.position.z += playerState.velocity.z * deltaTime; + + // Apply friction/drag + const drag = 0.99; + playerState.velocity.x *= drag; + playerState.velocity.y *= drag; + playerState.velocity.z *= drag; +} + +// Weapon firing +function firePrimaryWeapon() { + const forward = { + x: Math.sin(playerState.rotation.y) * Math.cos(playerState.rotation.x), + y: -Math.sin(playerState.rotation.x), + z: Math.cos(playerState.rotation.y) * Math.cos(playerState.rotation.x) + }; - // Update position - player.position.x += player.velocity.x * deltaTime; - player.position.y += player.velocity.y * deltaTime; - player.position.z += player.velocity.z * deltaTime; + createProjectile({ + position: { ...playerState.position }, + velocity: { + x: forward.x * 10 + playerState.velocity.x, + y: forward.y * 10 + playerState.velocity.y, + z: forward.z * 10 + playerState.velocity.z + }, + type: 'primary' + }); } -// Get player state for rendering +function fireSecondaryWeapon() { + const forward = { + x: Math.sin(playerState.rotation.y) * Math.cos(playerState.rotation.x), + y: -Math.sin(playerState.rotation.x), + z: Math.cos(playerState.rotation.y) * Math.cos(playerState.rotation.x) + }; + + createProjectile({ + position: { ...playerState.position }, + velocity: { + x: forward.x * 5 + playerState.velocity.x, + y: forward.y * 5 + playerState.velocity.y, + z: forward.z * 5 + playerState.velocity.z + }, + type: 'secondary' + }); +} + +// Get current player state export function getPlayerState() { + return playerState; +} + +// Get weapon cooldown states +export function getWeaponStates() { + const currentTime = Date.now(); return { - position: { ...player.position }, - rotation: { ...player.rotation }, - velocity: { ...player.velocity } + primary: { + cooldown: Math.max(0, PRIMARY_COOLDOWN - (currentTime - playerState.weapons.primary.lastFired)), + burstCount: playerState.weapons.primary.burstCount + }, + secondary: { + cooldown: Math.max(0, SECONDARY_COOLDOWN - (currentTime - playerState.weapons.secondary.lastFired)) + } }; } \ No newline at end of file |