class_name PlayerShipController extends ShipController # Drives a Ship from the local player's input actions (see project.godot # [input] and FLIGHT_MANUAL.md). var _action := ShipAction.new() func get_action() -> ShipAction: # Full overwrite per axis (not +=/-=): _action is reused across ticks, so # fields must not depend on starting from a fresh Vector3.ZERO each call. # # Input.get_axis(negative, positive) is strength(positive) - # strength(negative), so these keep the exact sign conventions the digital # version had while becoming proportional on a controller: # get_action_strength() returns a flat 1.0 for a held key but the # normalised past-deadzone deflection for an InputEventJoypadMotion. A # half-pulled trigger is therefore half thrust, and keyboard flight is # unchanged down to the value. # Forward/Backward thrust (main engines) _action.thrust.z = Input.get_axis("move_back", "move_forward") # Strafe thrusters (left/right) _action.thrust.x = Input.get_axis("move_left", "move_right") # Vertical thrusters (up/down) _action.thrust.y = Input.get_axis("move_down", "move_up") # Yaw (turn left/right around Y axis) _action.rotation.y = Input.get_axis("turn_right", "turn_left") # Pitch (nose up/down around X axis). Positive rotation.x is nose-UP: # torque about local +X rotates the ship's up vector toward its tail by the # right-hand rule, which lifts the nose (measured, not assumed). The # argument order here used to be reversed, so "pitch_down" pitched up and # the I/K keys were each labelled as the opposite of what they did. # The default binding then gives flight-sim polarity — right stick forward # is pitch_down is nose down — and InputSettings holds the player's # preference for flipping that. _action.rotation.x = Input.get_axis("pitch_down", "pitch_up") * InputSettings.pitch_sign() # Roll (bank left/right around Z axis) _action.rotation.z = Input.get_axis("roll_right", "roll_left") _action.turbo = Input.is_action_pressed("turbo") return _action