about summary refs log tree commit diff stats
path: root/html/space/physics.js
diff options
context:
space:
mode:
Diffstat (limited to 'html/space/physics.js')
-rw-r--r--html/space/physics.js253
1 files changed, 253 insertions, 0 deletions
diff --git a/html/space/physics.js b/html/space/physics.js
new file mode 100644
index 0000000..d4dfe55
--- /dev/null
+++ b/html/space/physics.js
@@ -0,0 +1,253 @@
+// 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
+const THRUST_ACCELERATION = 0.01;  // Reduced from 0.05
+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
+let playerState = {
+    position: { x: 0, y: 0, z: 0 },
+    velocity: { x: 0, y: 0, z: 0 },
+    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
+    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 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 player controls
+export function updatePlayerControls(controls) {
+    // Handle thrust (space bar)
+    if (controls.thrust) {
+        playerState.thrust = Math.min(playerState.thrust + THRUST_ACCELERATION, MAX_THRUST);
+    } else {
+        // Apply deceleration when no thrust input
+        if (playerState.thrust > 0) {
+            playerState.thrust = Math.max(playerState.thrust - DECELERATION, 0);
+        }
+    }
+
+    // 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 {
+        // 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;
+        }
+    }
+
+    // Secondary weapon (single shot with cooldown)
+    if (controls.secondary && currentTime - playerState.weapons.secondary.lastFired >= SECONDARY_COOLDOWN) {
+        fireSecondaryWeapon();
+        playerState.weapons.secondary.lastFired = currentTime;
+    }
+
+    // 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;
+    }
+}
+
+// Update physics
+export function updatePhysics(deltaTime) {
+    // Calculate forward and right vectors based on rotation
+    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)
+    };
+
+    const right = {
+        x: Math.cos(playerState.rotation.y),
+        y: 0,
+        z: -Math.sin(playerState.rotation.y)
+    };
+
+    const up = { x: 0, y: 1, z: 0 };
+
+    // 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 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)
+    };
+
+    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'
+    });
+}
+
+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 {
+        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