mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
fix(ship): delta-scale drag so it stays correct at any physics tick rate
drag_coefficient/angular_drag/the idle angular-drag multiplier were applied once per physics tick with no delta scaling, correct only because project.godot never pins physics/common/physics_ticks_per_second and Godot's default happens to be 60. _tick_scaled(k, state.step) makes the decay rate invariant to tick rate instead. Also promotes the previously hardcoded 0.9 idle angular-drag literal to an export, matching its sibling.
This commit is contained in:
+15
-4
@@ -18,6 +18,7 @@ extends RigidBody3D
|
||||
@export var max_angular_speed = 3.0 # Maximum rotation speed
|
||||
@export var drag_coefficient = 0.98 # Linear drag (air resistance)
|
||||
@export var angular_drag = 0.95 # Rotational drag
|
||||
@export var idle_angular_drag = 0.9 # Rotational drag when no rotation input is held
|
||||
|
||||
@export_group("Surface Pull")
|
||||
@export var wall_pull_strength = 6.0 # Wall grav-plating strength (m/s^2-equivalent)
|
||||
@@ -279,12 +280,22 @@ func apply_rotation_forces(state: PhysicsDirectBodyState3D, rotation_input: Vect
|
||||
state.apply_torque(torque)
|
||||
|
||||
|
||||
# Scales a per-tick decay multiplier `k` (defined at a 60 Hz reference rate)
|
||||
# by the actual elapsed tick time `step`, so `v *= _tick_scaled(k, step)`
|
||||
# decays at the same rate per second regardless of physics_ticks_per_second.
|
||||
func _tick_scaled(k: float, step: float) -> float:
|
||||
return pow(k, step * 60.0)
|
||||
|
||||
|
||||
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
|
||||
# This simulates air resistance reducing velocity over time.
|
||||
# _tick_scaled makes the decay rate invariant to the physics tick rate —
|
||||
# drag_coefficient/angular_drag/idle_angular_drag are all defined as the
|
||||
# per-tick multiplier at a 60 Hz reference rate.
|
||||
state.linear_velocity *= _tick_scaled(drag_coefficient, state.step)
|
||||
|
||||
# Angular drag (rotational resistance)
|
||||
# Physics: Similar to linear drag but for rotational motion
|
||||
@@ -292,10 +303,10 @@ func apply_drag_and_limits(state: PhysicsDirectBodyState3D, rotation_input: Vect
|
||||
# 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
|
||||
state.angular_velocity *= _tick_scaled(idle_angular_drag, state.step)
|
||||
else:
|
||||
# Normal drag when actively rotating
|
||||
state.angular_velocity *= angular_drag
|
||||
state.angular_velocity *= _tick_scaled(angular_drag, state.step)
|
||||
|
||||
# Limit maximum speeds
|
||||
# Physics: Terminal velocity concept - maximum achievable speed
|
||||
|
||||
Reference in New Issue
Block a user