Add Procedural Map

This commit is contained in:
Matteo Sonaglioni
2026-03-11 13:05:36 +01:00
parent f7b334b21c
commit 47380d3137
29 changed files with 1568 additions and 179 deletions

View File

@@ -8,6 +8,10 @@ extends Path3D
@export var larghezza_binari: float = 1.2
@export var gruppo_camere: Node3D
@export_group("Costruzione Rotaie")
@export var distanza_traversine: float = 1.0
@export var modello_traversina: PackedScene
@export_group("Controlli Manuali")
@export var velocita_max: float = 15.0
@export var velocita_min: float = -5.0
@@ -32,10 +36,6 @@ var colori_fuochi: Array[Color] = [
@export_group("Movimento e Oscillazione")
@export_range(0.0, 1.0) var intensita_oscillazione_base: float = 0.5
@export_group("Costruzione Rotaie")
@export var distanza_traversine: float = 1.0
@export var modello_traversina: PackedScene
var treno_istanziato: Node3D
var progresso_treno: float = 0.0
var tempo_oscillazione: float = 0.0
@@ -56,6 +56,63 @@ func _ready() -> void:
else:
print("ATTENZIONE: Devi prima disegnare i punti del Path3D!")
func _costruisci_rotaie_da_zero() -> void:
var mat_legno = StandardMaterial3D.new()
mat_legno.albedo_color = Color(0.35, 0.2, 0.1)
var mat_ferro = StandardMaterial3D.new()
mat_ferro.albedo_color = Color(0.6, 0.6, 0.65)
mat_ferro.metallic = 0.8
var mesh_traversina_default = BoxMesh.new()
mesh_traversina_default.size = Vector3(larghezza_binari + 0.6, 0.1, 0.3)
var mesh_binario = BoxMesh.new()
mesh_binario.size = Vector3(0.1, 0.15, distanza_traversine + 0.05)
var lunghezza_totale = curve.get_baked_length()
var numero_pezzi = int(lunghezza_totale / distanza_traversine)
for i in range(numero_pezzi):
var distanza = i * distanza_traversine
var pezzo_binario = Node3D.new()
add_child(pezzo_binario)
var pos_attuale_locale = curve.sample_baked(distanza, true)
var distanza_avanti = distanza + 0.1
var pos_avanti_locale = Vector3.ZERO
if distanza_avanti > lunghezza_totale:
var pos_dietro = curve.sample_baked(distanza - 0.1, true)
pos_avanti_locale = pos_attuale_locale + (pos_attuale_locale - pos_dietro)
else:
pos_avanti_locale = curve.sample_baked(distanza_avanti, true)
pezzo_binario.position = pos_attuale_locale
var globale_attuale = to_global(pos_attuale_locale)
var globale_avanti = to_global(pos_avanti_locale)
if globale_attuale.distance_to(globale_avanti) > 0.001:
pezzo_binario.look_at(globale_avanti, Vector3.UP)
if modello_traversina != null:
var traversina_custom = modello_traversina.instantiate()
pezzo_binario.add_child(traversina_custom)
else:
var traversina = MeshInstance3D.new()
traversina.mesh = mesh_traversina_default
traversina.material_override = mat_legno
pezzo_binario.add_child(traversina)
var binario_sx = MeshInstance3D.new()
binario_sx.mesh = mesh_binario
binario_sx.material_override = mat_ferro
binario_sx.position = Vector3(-larghezza_binari / 2.0, 0.1, 0)
pezzo_binario.add_child(binario_sx)
var binario_dx = MeshInstance3D.new()
binario_dx.mesh = mesh_binario
binario_dx.material_override = mat_ferro
binario_dx.position = Vector3(larghezza_binari / 2.0, 0.1, 0)
pezzo_binario.add_child(binario_dx)
func _calcola_fermate() -> void:
var fermate_temp = []
for figlio in get_children():
@@ -88,10 +145,8 @@ func _test_fuochi_manuale() -> void:
var offset_x = randf_range(-6.0, 6.0)
var offset_z = randf_range(-6.0, 6.0)
# 1. POSIZIONA
fuoco_root.global_position = treno_istanziato.global_position + Vector3(offset_x, 0.5, offset_z)
# 2. COLORA E ACCENDI
if fuoco_root.has_method("imposta_colore"):
fuoco_root.imposta_colore(colori_fuochi.pick_random())
if fuoco_root.has_method("accendi"):
@@ -156,23 +211,24 @@ func _gestione_movimento_treno(delta: float) -> void:
progresso_treno += lunghezza_totale
if offsets_fermate.size() > 0: indice_prossima_fermata = offsets_fermate.size() - 1
# 1. Il centro matematico perfetto e incontrovertibile del treno
var pos_centro = to_global(curve.sample_baked(progresso_treno, true))
# 2. Il punto in cui deve guardare (abbastanza lontano per non vibrare)
var prog_davanti = wrapf(progresso_treno + 2.0, 0.0, lunghezza_totale)
var pos_davanti = to_global(curve.sample_baked(prog_davanti, true))
if pos_centro.distance_to(pos_davanti) > 0.01:
# Posizionamento esatto, zero vibrazioni laterali
treno_istanziato.global_position = pos_centro
treno_istanziato.look_at(pos_davanti, Vector3.UP)
treno_istanziato.rotate_y(PI)
if gruppo_camere:
# La telecamera segue il punto perfetto
gruppo_camere.global_position = gruppo_camere.global_position.lerp(pos_centro, delta * 12.0)
# Usiamo orthonormalized() per pulire le micro-imperfezioni matematiche
var rot_cam = gruppo_camere.global_basis.orthonormalized().get_rotation_quaternion()
var rot_treno = treno_istanziato.global_basis.orthonormalized().get_rotation_quaternion()
gruppo_camere.global_basis = Basis(rot_cam.slerp(rot_treno, delta * 8.0))
if not fermata_in_corso:
var vel_reale = abs(velocita_treno * moltiplicatore_stazione)
tempo_oscillazione += delta * vel_reale * 2.0
@@ -206,10 +262,8 @@ func _esegui_fermata(andando_avanti: bool = true) -> void:
var offset_x = randf_range(-5.0, 5.0)
var offset_z = randf_range(-5.0, 5.0)
# 1. POSIZIONA
fuoco_root.global_position = posizione_marker + Vector3(offset_x, 0.5, offset_z)
# 2. COLORA E ACCENDI
if fuoco_root.has_method("imposta_colore"):
fuoco_root.imposta_colore(colori_fuochi.pick_random())
if fuoco_root.has_method("accendi"):
@@ -230,63 +284,6 @@ func _esegui_fermata(andando_avanti: bool = true) -> void:
tween_ripartenza.tween_property(self, "moltiplicatore_stazione", 1.0, tempo_ripartenza)
tween_ripartenza.tween_callback(func(): in_ripartenza = false)
func _costruisci_rotaie_da_zero() -> void:
var mat_legno = StandardMaterial3D.new()
mat_legno.albedo_color = Color(0.35, 0.2, 0.1)
var mat_ferro = StandardMaterial3D.new()
mat_ferro.albedo_color = Color(0.6, 0.6, 0.65)
mat_ferro.metallic = 0.8
var mesh_traversina_default = BoxMesh.new()
mesh_traversina_default.size = Vector3(larghezza_binari + 0.6, 0.1, 0.3)
var mesh_binario = BoxMesh.new()
mesh_binario.size = Vector3(0.1, 0.15, distanza_traversine + 0.05)
var lunghezza_totale = curve.get_baked_length()
var numero_pezzi = int(lunghezza_totale / distanza_traversine)
for i in range(numero_pezzi):
var distanza = i * distanza_traversine
var pezzo_binario = Node3D.new()
add_child(pezzo_binario)
var pos_attuale_locale = curve.sample_baked(distanza, true)
var distanza_avanti = distanza + 0.1
var pos_avanti_locale = Vector3.ZERO
if distanza_avanti > lunghezza_totale:
var pos_dietro = curve.sample_baked(distanza - 0.1, true)
pos_avanti_locale = pos_attuale_locale + (pos_attuale_locale - pos_dietro)
else:
pos_avanti_locale = curve.sample_baked(distanza_avanti, true)
pezzo_binario.position = pos_attuale_locale
var globale_attuale = to_global(pos_attuale_locale)
var globale_avanti = to_global(pos_avanti_locale)
if globale_attuale.distance_to(globale_avanti) > 0.001:
pezzo_binario.look_at(globale_avanti, Vector3.UP)
if modello_traversina != null:
var traversina_custom = modello_traversina.instantiate()
pezzo_binario.add_child(traversina_custom)
else:
var traversina = MeshInstance3D.new()
traversina.mesh = mesh_traversina_default
traversina.material_override = mat_legno
pezzo_binario.add_child(traversina)
var binario_sx = MeshInstance3D.new()
binario_sx.mesh = mesh_binario
binario_sx.material_override = mat_ferro
binario_sx.position = Vector3(-larghezza_binari / 2.0, 0.1, 0)
pezzo_binario.add_child(binario_sx)
var binario_dx = MeshInstance3D.new()
binario_dx.mesh = mesh_binario
binario_dx.material_override = mat_ferro
binario_dx.position = Vector3(larghezza_binari / 2.0, 0.1, 0)
pezzo_binario.add_child(binario_dx)
func _costruisci_treno() -> void:
if modello_treno != null:
treno_istanziato = modello_treno.instantiate()