diff --git a/Game/scripts/ship.gd b/Game/scripts/ship.gd index 2961114..cd40210 100644 --- a/Game/scripts/ship.gd +++ b/Game/scripts/ship.gd @@ -28,9 +28,13 @@ func _ready(): gravity_scale = 1.0 # Set custom inertia for better rotation + # Physics: I = m * r² (moment of inertia = mass × radius²) + # Lower inertia = easier to rotate, higher inertia = more stable inertia = Vector3(1.0, 1.0, 1.0) # Create and apply low-friction physics material + # Physics: F_friction = μ * N (friction force = coefficient × normal force) + # Lower μ (friction coefficient) = less resistance to sliding var ship_material = PhysicsMaterial.new() ship_material.friction = 0.1 # Very low friction ship_material.bounce = 0.2 # Slight bounce @@ -73,17 +77,25 @@ func _update_camera(delta): func _update_ball_cam(delta): # In ball cam, camera positions itself so the ship is between camera and ball + # Physics: Vector mathematics for 3D positioning var ship_pos = global_transform.origin var ball_pos = ball.global_transform.origin # Calculate direction from ball to ship + # Physics: Vector subtraction and normalization + # Direction vector: d̂ = (P₂ - P₁) / |P₂ - P₁| var ball_to_ship = (ship_pos - ball_pos).normalized() # Position camera behind the ship relative to the ball's position # This ensures the ship is always between the camera and ball + # Physics: Vector addition for position calculation + # P_camera = P_ship + d̂ * distance + height_offset var camera_target_pos = ship_pos + ball_to_ship * camera_distance + Vector3.UP * camera_height # Smoothly move camera to target position + # Physics: Linear interpolation (LERP) for smooth motion + # P(t) = P₀ + t * (P₁ - P₀), where t ∈ [0,1] + # This creates exponential approach to target position camera.global_transform.origin = camera.global_transform.origin.lerp(camera_target_pos, camera_smoothing * delta) # Make camera look at the ball @@ -93,11 +105,17 @@ func _update_ball_cam(delta): var to_ball = (ball_pos - camera_pos).normalized() # Create look-at transform manually + # Physics: 3D rotation matrices and basis vectors + # Uses right-hand rule: forward = -Z, up = Y, right = X + # Basis matrix transforms local coordinates to world coordinates var camera_transform = Transform3D() camera_transform.origin = camera_pos camera_transform.basis = Basis.looking_at(to_ball, Vector3.UP) # Apply the rotation smoothly + # Physics: Spherical linear interpolation (SLERP) for rotation + # SLERP provides smooth rotation along great circle on unit sphere + # Maintains constant angular velocity during interpolation camera.global_transform.basis = camera.global_transform.basis.slerp(camera_transform.basis, camera_smoothing * delta) func _update_ship_cam(delta): @@ -180,10 +198,15 @@ func apply_thruster_forces(state: PhysicsDirectBodyState3D, thrust_input: Vector return # Convert thrust input to world space forces based on ship orientation + # Physics: F = m * a (Newton's Second Law: Force = mass × acceleration) + # World force = Local force × Rotation matrix (basis transformation) var ship_basis = global_transform.basis var world_thrust = Vector3.ZERO # All thrusters should work relative to ship orientation + # Physics: Vector transformation from local to world coordinates + # F_world = R * F_local (where R is rotation matrix) + # Forward/backward thrust (main engines) world_thrust += -ship_basis.z * thrust_input.z * thrust_power @@ -199,6 +222,7 @@ func apply_thruster_forces(state: PhysicsDirectBodyState3D, thrust_input: Vector world_thrust *= turbo_multiplier # Apply the force + # Physics: Δv = F * Δt / m (change in velocity = force × time / mass) state.apply_central_force(world_thrust) func apply_rotation_forces(state: PhysicsDirectBodyState3D, rotation_input: Vector3): @@ -206,19 +230,29 @@ func apply_rotation_forces(state: PhysicsDirectBodyState3D, rotation_input: Vect return # Apply torque for rotation - simple and effective + # Physics: τ = I * α (torque = moment of inertia × angular acceleration) + # Also: α = τ / I (angular acceleration = torque / moment of inertia) + # Lower inertia = higher angular acceleration for same torque var torque = Vector3( - rotation_input.x * rotation_power, # Pitch - rotation_input.y * rotation_power, # Yaw - rotation_input.z * rotation_power # Roll + rotation_input.x * rotation_power, # Pitch (rotation around X-axis) + rotation_input.y * rotation_power, # Yaw (rotation around Y-axis) + rotation_input.z * rotation_power # Roll (rotation around Z-axis) ) + # Physics: Δω = τ * Δt / I (change in angular velocity = torque × time / inertia) state.apply_torque(torque) func apply_drag_and_limits(state: PhysicsDirectBodyState3D, rotation_input: Vector3): # Linear drag (air resistance) + # Physics: F_drag = -½ * ρ * v² * C_d * A (drag force equation) + # Simplified: v_new = v_old * drag_coefficient (exponential decay) + # This simulates air resistance reducing velocity over time state.linear_velocity *= drag_coefficient - # Angular drag (rotational resistance) - more aggressive when not rotating + # Angular drag (rotational resistance) + # Physics: Similar to linear drag but for rotational motion + # τ_drag = -C_angular * ω² (angular drag torque) + # Simplified: ω_new = ω_old * angular_drag (exponential decay) if rotation_input.length() < 0.01: # More drag when not actively rotating to stop quicker state.angular_velocity *= 0.9 @@ -227,8 +261,14 @@ func apply_drag_and_limits(state: PhysicsDirectBodyState3D, rotation_input: Vect state.angular_velocity *= angular_drag # Limit maximum speeds + # Physics: Terminal velocity concept - maximum achievable speed + # When thrust force = drag force, acceleration = 0, velocity = constant if state.linear_velocity.length() > max_speed: + # Normalize to unit vector, then scale to max speed + # Physics: v̂ = v / |v| (unit vector), v_limited = v̂ * v_max state.linear_velocity = state.linear_velocity.normalized() * max_speed if state.angular_velocity.length() > max_angular_speed: + # Same concept for angular velocity + # Physics: ω̂ = ω / |ω|, ω_limited = ω̂ * ω_max state.angular_velocity = state.angular_velocity.normalized() * max_angular_speed