diff --git a/assets/core/interactables/ship-helm/ship_helm.gd b/assets/core/interactables/ship-helm/ship_helm.gd index 282889a..f9e2235 100644 --- a/assets/core/interactables/ship-helm/ship_helm.gd +++ b/assets/core/interactables/ship-helm/ship_helm.gd @@ -12,4 +12,4 @@ func interact(): elif parent_ship.ship_is_piloted: player_reference.set_is_piloting(false) parent_ship.remove_piloting_player() - + \ No newline at end of file diff --git a/assets/core/ships/ship_script.gd b/assets/core/ships/ship_script.gd index ba78f42..abd5420 100644 --- a/assets/core/ships/ship_script.gd +++ b/assets/core/ships/ship_script.gd @@ -9,27 +9,28 @@ extends RigidBody3D @export var base_lift_speed: float = 50.0 @export var top_speed: float = 50.0 @export var move_speed: float = 50.0 -@export var acceleration: float = 50.0 +@export var acceleration: float = 5.0 # Increased acceleration for smoother interpolation +@export var interpolation_damp: float = 0.1 # Damping for smoother rotation var piloting_player: Player = null var ship_is_piloted: bool = false var target_position: Vector3 = Vector3.ZERO var target_rotation: Quaternion = Quaternion() -var previous_position: Vector3 -var previous_rotation: Quaternion +var predicted_position: Vector3 +var predicted_rotation: Quaternion +var last_input_time: float = 0.0 var network_uuid: String = "" func _ready(): - network_uuid = NetworkManager.register_node(self) NetworkManager.property_update_received.connect(_on_property_update) - + # Preserve current position and rotation at the start target_position = global_position target_rotation = global_transform.basis.get_rotation_quaternion() - previous_position = global_position - previous_rotation = global_transform.basis.get_rotation_quaternion() + predicted_position = global_position + predicted_rotation = global_transform.basis.get_rotation_quaternion() player_detection_area.body_entered.connect(_on_player_entered) player_detection_area.body_exited.connect(_on_player_exited) @@ -47,8 +48,7 @@ func _process(delta: float): # No one is piloting, just interpolate interpolate_position_and_rotation(delta) - -func handle_input(_delta: float): +func handle_input(delta: float): var forward_input = 0.0 var turn_input = 0.0 var vertical_input = 0.0 @@ -61,9 +61,9 @@ func handle_input(_delta: float): # Left and right turning if Input.is_action_pressed("move_left"): - turn_input -= 1 - if Input.is_action_pressed("move_right"): turn_input += 1 + if Input.is_action_pressed("move_right"): + turn_input -= 1 # Up and down movement if Input.is_action_pressed("jump"): @@ -75,13 +75,12 @@ func handle_input(_delta: float): if turn_input != 0: var torque = Vector3.UP * turn_input * base_turn_speed apply_torque(torque) - + # Clamp the angular velocity to the maximum turn speed if angular_velocity.length() > max_turn_speed: angular_velocity = angular_velocity.normalized() * max_turn_speed - -# Apply force for forward and backward movement + # Apply force for forward and backward movement if forward_input != 0: var forward_direction = -global_transform.basis.z.normalized() var forward_force = forward_direction * forward_input * move_speed @@ -92,14 +91,58 @@ func handle_input(_delta: float): var vertical_force = Vector3.UP * vertical_input * base_lift_speed apply_central_force(vertical_force) + # Update predicted state + predicted_position = predict_position(delta) + predicted_rotation = predict_rotation(delta) + last_input_time = Time.get_ticks_msec() + +func predict_position(delta: float): + var velocity = linear_velocity + return global_position + velocity * delta + +func predict_rotation(delta: float): + var angular_velocity_quat = Quaternion(Vector3.UP, angular_velocity.y * delta) + return global_transform.basis.get_rotation_quaternion() * angular_velocity_quat func interpolate_position_and_rotation(delta: float): - global_position = lerp(global_position, target_position, min(acceleration * delta, 1.0)) + # Smooth interpolation with damping + global_position = lerp(global_position, target_position, 1.0 - exp(-acceleration * delta)) + global_transform.basis = Basis(slerp_damp(global_transform.basis.get_rotation_quaternion(), target_rotation, interpolation_damp, 1.0)) - var current_rotation = global_transform.basis.get_rotation_quaternion().normalized() - var interpolated_rotation = current_rotation.slerp(target_rotation, min(acceleration * delta, 1.0)) - global_transform.basis = Basis(interpolated_rotation) +func slerp_damp(from: Quaternion, to: Quaternion, damping: float, dt: float): + var t = 1.0 - exp(-damping * dt) + return from.slerp(to, t) +func send_network_update(): + if NetworkManager.is_host and ship_is_piloted and piloting_player.steam_id == NetworkManager.steam_id: + # Host is piloting, synchronize with clients + NetworkManager.sync_property_to_all_except_host(network_uuid, "global_position", predicted_position) + NetworkManager.sync_property_to_all_except_host(network_uuid, "global_rotation", predicted_rotation) + + elif !NetworkManager.is_host and ship_is_piloted and piloting_player.steam_id == NetworkManager.steam_id: + # Client is piloting, send updates to the host + NetworkManager.sync_property_to_all_except_host(network_uuid, "global_position", predicted_position) + NetworkManager.sync_property_to_all_except_host(network_uuid, "global_rotation", predicted_rotation) + +func receive_global_position_update(value: Vector3): + target_position = value + +func receive_global_rotation_update(value: Quaternion): + target_rotation = value + +func _on_player_entered(body): + if body is Player and body.get_parent() != self: + if !body.is_network_authority: return + body.call_deferred("reparent", self, true) + body.ship_entered(self) + print("Player entered the ship area.") + +func _on_player_exited(body): + if body is Player and body.get_parent() != get_node("/root/DevLevel/"): + if !body.is_network_authority: return + body.call_deferred("reparent", get_node("/root/DevLevel/"), true) + body.ship_exited() + print("Player exited the ship area.") func set_piloting_player(player: Player): piloting_player = player @@ -114,51 +157,6 @@ func remove_piloting_player(): ship_is_piloted = false print("The ship is no longer piloted.") -# When a player enters the ship's detection area -func _on_player_entered(body): - if body is Player and body.get_parent() != self: - if !body.is_network_authority: return - body.call_deferred("reparent", self, true) - body.ship_entered(self) - print("Player entered the ship area.") - -# When a player exits the ship's detection area -func _on_player_exited(body): - if body is Player and body.get_parent() != get_node("/root/DevLevel/"): - if !body.is_network_authority: return - body.call_deferred("reparent", get_node("/root/DevLevel/"), true) - body.ship_exited() - print("Player exited the ship area.") - - -func send_network_update(): - if NetworkManager.is_host and ship_is_piloted and piloting_player.steam_id == NetworkManager.steam_id: - # Host is piloting, synchronize with clients - if global_position.distance_to(previous_position) > 0.1 or global_transform.basis.get_rotation_quaternion().dot(previous_rotation) < 0.995: - NetworkManager.sync_property_to_all_except_host(network_uuid, "global_position", global_position) - NetworkManager.sync_property_to_all_except_host(network_uuid, "global_rotation", global_transform.basis.get_rotation_quaternion()) - previous_position = global_position - previous_rotation = global_transform.basis.get_rotation_quaternion() - - elif !NetworkManager.is_host and ship_is_piloted and piloting_player.steam_id == NetworkManager.steam_id: - # Client is piloting, send updates to the host - if global_position.distance_to(previous_position) > 0.1 or global_transform.basis.get_rotation_quaternion().dot(previous_rotation) < 0.995: - NetworkManager.sync_property_to_all_except_host(network_uuid, "global_position", global_position) - NetworkManager.sync_property_to_all_except_host(network_uuid, "global_rotation", global_transform.basis.get_rotation_quaternion()) - previous_position = global_position - previous_rotation = global_transform.basis.get_rotation_quaternion() - - - - -func receive_global_position_update(value: Vector3): - target_position = value - - -func receive_global_rotation_update(value: Quaternion): - target_rotation = value - - func _on_property_update(node_id: String, property_name: String, value: Variant) -> void: if NetworkManager.node_map.has(node_id) and node_id == network_uuid: if property_name == "global_position": @@ -167,4 +165,4 @@ func _on_property_update(node_id: String, property_name: String, value: Variant) receive_global_rotation_update(value) else: var node = NetworkManager.node_map[node_id] - node.set(property_name, value) + node.set(property_name, value) \ No newline at end of file