extends MeshInstance3D class_name TrainBody signal speed_changed(new_speed: float) signal rail_switched(old_rail: Path3D, new_rail: Path3D) @export_group("Train") @export var base_speed: float = 15.0 @export var max_speed: float = 50.0 @export var min_speed: float = 3.0 @export var acceleration: float = 12.0 @export var rail_a: Path3D @export var rail_b: Path3D var current_follower: PathFollow3D var current_rail: Path3D var current_speed: float = 15.0 func _ready() -> void: current_speed = base_speed switch_to_rail(rail_a) func _process(delta: float) -> void: _handle_input(delta) current_follower.progress += current_speed * delta func _handle_input(delta: float) -> void: if Input.is_action_pressed("speed_up"): current_speed = min(current_speed + acceleration * delta, max_speed) speed_changed.emit(current_speed) elif Input.is_action_pressed("speed_down"): current_speed = max(current_speed - acceleration * delta, min_speed) speed_changed.emit(current_speed) func get_speed() -> float: return current_speed func switch_to_rail(new_rail: Path3D) -> void: if new_rail == current_rail: return current_rail = new_rail current_follower = new_rail.get_node("TrainEngine") as PathFollow3D var closest_offset = find_closest_point_on_path(new_rail, global_position) current_follower.progress = closest_offset func find_closest_point_on_path(path: Path3D, point: Vector3) -> float: var curve = path.curve var closest_offset = 0.0 var min_distance = INF var length = curve.get_baked_length() var steps = 100 # Più alto = più preciso ma più lento for i in range(steps + 1): var offset = (float(i) / steps) * length # Trasforma il punto locale della curva in coordinate globali var path_point = path.global_transform * curve.sample_baked(offset) var dist = point.distance_to(path_point) if dist < min_distance: min_distance = dist closest_offset = offset return closest_offset