class_name Ship extends RigidBody3D @export_group("Movement") var max_speed = 15.0 var acceleration = 50.0 var air_resistance = 0.98 var turn_speed = 2.0 @export_group("Camera") var camera_distance = 8.0 var camera_height = 4.0 var camera_smoothing = 10.0 @onready var camera : Camera3D = get_node("Camera3D") @onready var ball = get_parent().get_node("Ball") @onready var timer_label = get_node("HUD/Control/TimerLabel") var ball_cam_enabled = true func _ready(): var game_scene = get_parent() if game_scene and game_scene.has_signal("timer_updated"): game_scene.timer_updated.connect(_on_timer_updated) print("Connected to game scene timer signal") else: print("Game scene not found or doesn't have timer_updated signal") func _input(event): if event.is_action_pressed("ui_accept"): # Enter key ball_cam_enabled = !ball_cam_enabled func _on_timer_updated(minutes: int, seconds: int): timer_label.text = "%02d:%02d" % [minutes, seconds] func _physics_process(delta): if camera: _update_camera(delta) func _update_camera(delta): if ball_cam_enabled and ball: _update_ball_cam(delta) else: _update_ship_cam(delta) func _update_ball_cam(delta): # In ball cam, camera positions itself so the ship is between camera and ball var ship_pos = global_transform.origin var ball_pos = ball.global_transform.origin # Calculate direction from ball to ship 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 var camera_target_pos = ship_pos + ball_to_ship * camera_distance + Vector3.UP * camera_height # Smoothly move camera to target position camera.global_transform.origin = camera.global_transform.origin.lerp(camera_target_pos, camera_smoothing * delta) # Make camera look at the ball if camera.global_transform.origin.distance_to(ball_pos) > 0.1: # Calculate direction to ball var camera_pos = camera.global_transform.origin var to_ball = (ball_pos - camera_pos).normalized() # Create look-at transform manually var camera_transform = Transform3D() camera_transform.origin = camera_pos camera_transform.basis = Basis.looking_at(to_ball, Vector3.UP) # Apply the rotation smoothly camera.global_transform.basis = camera.global_transform.basis.slerp(camera_transform.basis, camera_smoothing * delta) func _update_ship_cam(delta): # In ship cam, camera follows and looks in the same direction as the ship var ship_pos = global_transform.origin var ship_forward = -global_transform.basis.z # Position camera behind and above the ship var camera_target_pos = ship_pos - ship_forward * camera_distance + Vector3.UP * camera_height # Smoothly move camera camera.global_transform.origin = camera.global_transform.origin.lerp(camera_target_pos, camera_smoothing * delta) # Make camera look in the same direction as the ship var look_target = ship_pos + ship_forward * 10.0 # Look ahead of the ship camera.look_at(look_target, Vector3.UP) func _integrate_forces(state): # Get input in ship's local coordinate system var input = get_ship_input() # Apply forces based on ship's orientation if input.length() > 0.01: var ship_forward = -global_transform.basis.z var ship_right = global_transform.basis.x # Calculate movement direction based on ship orientation var movement_dir = Vector3.ZERO movement_dir += ship_forward * input.z # Forward/backward movement_dir += ship_right * input.x # Left/right movement_dir.y += input.y # Up/down # Apply acceleration force var target_velocity = movement_dir.normalized() * max_speed var velocity_diff = target_velocity - state.linear_velocity var force = velocity_diff * acceleration * mass state.apply_central_force(force) # Turn the ship to face movement direction (only if moving horizontally) var horizontal_movement = Vector3(movement_dir.x, 0, movement_dir.z) if horizontal_movement.length() > 0.1: var target_transform = global_transform.looking_at(global_transform.origin + horizontal_movement, Vector3.UP) state.transform.basis = state.transform.basis.slerp(target_transform.basis, turn_speed * state.step) # Apply air resistance state.linear_velocity *= air_resistance func get_ship_input() -> Vector3: var input = Vector3.ZERO # Get input as if controlling a ship (forward/backward/left/right relative to ship) if Input.is_action_pressed("move_forward"): input.z += 1.0 if Input.is_action_pressed("move_backward"): input.z -= 1.0 if Input.is_action_pressed("move_left"): input.x -= 1.0 if Input.is_action_pressed("move_right"): input.x += 1.0 if Input.is_action_pressed("move_up"): input.y += 1.0 if Input.is_action_pressed("move_down"): input.y -= 1.0 return input