extends Node3D class_name Train signal speed_changed(new_speed: float) @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 wagon_spacing: float = 5.5 var num_wagons: int var group_name: String = "" var locomotive_model_resources: Array[String] = [ "train-diesel-a.obj", "train-diesel-b.obj", "train-diesel-box-a.obj", "train-diesel-c.obj" ] var wagon_model_resources: Array[String] = [ "train-carriage-container-blue.obj", "train-carriage-flatbed-wood.obj", "train-carriage-lumber.obj", "train-carriage-tank-large.obj", "train-diesel-box-b.obj", "train-diesel-box-c.obj" ] # Riferimento al generatore (settato da main.gd) var track_generator: TrackGenerator # Stato var current_speed: float = 15.0 var distance_traveled: float = 0.0 var locomotive: Node3D var wagons: Array = [] var wagon_distances: Array = [] func _ready() -> void: # Aspetta un frame per assicurarsi che track_generator sia settato await get_tree().process_frame await get_tree().process_frame _create_train() current_speed = base_speed func _on_button_pressed() -> void: _create_train() current_speed = base_speed func _remove_train(): for node in get_tree().get_nodes_in_group(group_name): node.queue_free() func _create_train() -> void: _remove_train() _create_locomotive() wagons = [] wagon_distances = [] num_wagons = randi_range(1, 10) _create_wagons() func _create_locomotive() -> void: var locomotive_model = locomotive_model_resources.pick_random() locomotive = load_model("res://resources/train kit/" + locomotive_model, "Locomotive") locomotive.transform.rotated(Vector3(1, 0, 0), 180.0) group_name = "locomotive" + str(Time.get_unix_time_from_system()) locomotive.add_to_group(group_name) add_child(locomotive) func _create_wagons() -> void: var loco_length = 0 for child in locomotive.get_children(): if child is MeshInstance3D: var aabb = child.get_aabb() loco_length = aabb.size.z for i in range(num_wagons): var wagon_model = wagon_model_resources.pick_random() var wagon = load_model("res://resources/train kit/" + wagon_model, "Wagon_%d" % i) wagon.transform.rotated(Vector3(1, 0, 0), 180.0) wagon.add_to_group(group_name) add_child(wagon) wagons.append(wagon) wagon_distances.append(loco_length if num_wagons == 1 else 0 * 0.5 + (i + 1) * wagon_spacing) _position_wagons_initial() func _position_wagons_initial() -> void: # Posiziona i vagoni sul tracciato all'avvio if not track_generator: return for i in range(wagons.size()): var wagon_dist = distance_traveled - wagon_distances[i] # All'inizio i vagoni potrebbero essere "prima" della partenza # quindi li posizioniamo dove possibile if wagon_dist < 0: wagon_dist = 0 var wagon_data = track_generator.get_position_on_track(wagon_dist) if wagon_data["valid"]: _apply_transform(wagons[i], wagon_data["position"], wagon_data["direction"]) func load_model(path: String, node_name: String) -> Node3D: var mesh = OBJLoader.load_obj(path) if mesh == null: return null # Crea un nodo contenitore var newobj = Node3D.new() newobj.name = node_name # Crea il mesh instance come figlio var mesh_instance = MeshInstance3D.new() mesh_instance.mesh = mesh newobj.add_child(mesh_instance) return newobj func _process(delta: float) -> void: if not track_generator or not locomotive: return _handle_input(delta) _update_movement(delta) _update_track() 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 _update_movement(delta: float) -> void: distance_traveled += current_speed * delta # Locomotiva var loco_data = track_generator.get_position_on_track(distance_traveled) if loco_data["valid"]: _apply_transform(locomotive, loco_data["position"], loco_data["direction"]) # Vagoni for i in range(wagons.size()): var wagon_dist = distance_traveled - wagon_distances[i] if wagon_dist < 0: wagon_dist = 0 var wagon_data = track_generator.get_position_on_track(wagon_dist) if wagon_data["valid"]: _apply_transform(wagons[i], wagon_data["position"], wagon_data["direction"]) func _apply_transform(node: Node3D, pos: Vector3, direction: Vector3) -> void: node.global_position = pos if direction.length_squared() > 0.001: var target = pos - direction var up = Vector3.UP if abs(direction.dot(up)) > 0.99: up = Vector3.RIGHT node.look_at(target, up) func _update_track() -> void: track_generator.update_track(distance_traveled) func get_locomotive_position() -> Vector3: if locomotive: return locomotive.global_position return Vector3.ZERO func get_speed() -> float: return current_speed