add final godrays

This commit is contained in:
Matteo Sonaglioni
2026-03-11 20:01:01 +01:00
parent 609b70a114
commit 38b5933636
10 changed files with 165 additions and 289 deletions

View File

@@ -1,7 +1,5 @@
extends Node3D
@export_group("Luce Direzionale e Ambiente")
@export var color_mattina: Color = Color(1.0, 0.9, 0.8, 1.0)
@export var color_pomeriggio: Color = Color(1.0, 0.6, 0.2, 1.0)
@@ -23,10 +21,8 @@ extends Node3D
@export_range(0.0, 1.0) var energia_luce_notte: float = 0.3
@export_group("Materiali Extra")
@export var materiale_nebbia: ShaderMaterial
@export var materiale_pioggia_gocce: StandardMaterial3D
# --- NUOVA VARIABILE PER LE NUVOLE ---
@export var materiale_nuvole: ShaderMaterial
@export_group("Meteo (Pioggia & Fulmini)")
@@ -39,9 +35,27 @@ extends Node3D
@export var scala_min_fulmine: float = 1.0
@export var scala_max_fulmine: float = 3.0
# --- NUOVI PARAMETRI CINEMATIC MODE ---
@export_group("Cinematic Mode Ambiente")
@export var intervallo_eventi_meteo: float = 8.0 # Ogni quanti secondi cambia qualcosa da solo
@export var intervallo_eventi_meteo: float = 8.0
# --- NUOVO: PARAMETRI GOD RAYS ---
@export_group("God Rays")
@export var godray_scene: PackedScene
@export var max_rain_godrays: int = 8
@export var godray_spawn_radius: float = 15.0
# --- NUOVE VARIABILI PER L'ISOMETRICA ---
# Sposta il centro in cui nascono i raggi (es. più a destra e più in alto)
@export var godray_spawn_offset: Vector3 = Vector3(15.0, 5.0, -15.0)
# Incliniamo i raggi per farli spiovere dall'alto a destra.
# (X negativa li inclina in avanti, Z li fa "stendere" diagonalmente sullo schermo)
@export var godray_rotation_degrees: Vector3 = Vector3(-45.0, 45.0, -30.0)
# Quanto in alto rispetto al suolo/treno devono nascere
@export var godray_spawn_height: float = 5.0
# Quanto devono essere lunghi i raggi (scala Y) e larghi (scala X)
@export var godray_scale: Vector3 = Vector3(2.0, 6.0, 2.0)
@onready var sole: DirectionalLight3D = $DirectionalLight3D
@onready var ambiente: WorldEnvironment = $WorldEnvironment
@@ -49,7 +63,9 @@ extends Node3D
@onready var bottone_pioggia: CheckButton = $CanvasLayer/CheckButtonPioggia
@onready var particelle_pioggia: GPUParticles3D = $SubViewportContainer/SubViewport/World/Camere/PioggiaCadente
# --- NODI FULMINE ---
# --- NUOVO: RIFERIMENTO AL NODO DELLE CAMERE PER FARLI MUOVERE COL TRENO ---
@onready var nodo_camere: Node3D = $SubViewportContainer/SubViewport/World/Camere
@onready var luce_lampo: DirectionalLight3D = $LuceLampo
@onready var sprite_fulmine: Sprite3D = $SubViewportContainer/SubViewport/World/Camere/SpriteFulmine
@@ -58,10 +74,9 @@ var is_raining: bool = false
var intensita_pioggia: float = 0.0
var timer_prossimo_fulmine: float = 0.0
# Variabili Cinematic Mode
var is_cinematic_mode: bool = false
var timer_cinematic_env: float = 0.0
var sto_cambiando_in_cinematic: bool = false # Serve per non disattivare la modalità quando lo script clicca i bottoni da solo
var sto_cambiando_in_cinematic: bool = false
func _ready() -> void:
if menu_giornata:
@@ -80,28 +95,23 @@ func _ready() -> void:
_resetta_timer_fulmine()
# --- ASCOLTO TASTIERA PER CINEMATIC MODE ---
func _input(event: InputEvent) -> void:
if event is InputEventKey and event.pressed and not event.echo:
# Attiva/Disattiva con C
if event.keycode == KEY_C:
is_cinematic_mode = !is_cinematic_mode
if is_cinematic_mode:
timer_cinematic_env = intervallo_eventi_meteo # Fa scattare un evento quasi subito
timer_cinematic_env = intervallo_eventi_meteo
print("Ambiente Cinematic: ATTIVATA")
else:
print("Ambiente Cinematic: DISATTIVATA")
return
# Se premi le camere, si ferma la cinematic mode
if event.keycode in [KEY_1, KEY_2, KEY_3, KEY_4, KEY_5]:
if is_cinematic_mode:
is_cinematic_mode = false
print("Ambiente Cinematic: DISATTIVATA (Cambio camera manuale)")
func _on_giornata_selezionata(index: int) -> void:
# Se l'utente clicca la tendina a mano, spegni la cinematic mode
if not sto_cambiando_in_cinematic and is_cinematic_mode:
is_cinematic_mode = false
print("Ambiente Cinematic: DISATTIVATA (Orario cambiato manualmente)")
@@ -113,32 +123,33 @@ func _on_giornata_selezionata(index: int) -> void:
tween_giorno.set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
tween_giorno.tween_property(self, "tempo_giorno", target_tempo, durata_transizione)
# --- NUOVO: SE E' MATTINA (Index 0), SPAWNA IL GODRAY ---
if index == 0:
trigger_morning()
func _on_pioggia_toggled(toggled_on: bool) -> void:
# Se l'utente clicca il bottone della pioggia a mano, spegni la cinematic mode
if not sto_cambiando_in_cinematic and is_cinematic_mode:
is_cinematic_mode = false
print("Ambiente Cinematic: DISATTIVATA (Pioggia cambiata manualmente)")
# --- NUOVO: SALVIAMO LO STATO PRECEDENTE PER CAPIRE SE HA SMESSO ---
var stava_piovendo = is_raining
is_raining = toggled_on
if particelle_pioggia:
particelle_pioggia.emitting = is_raining
# --- NUOVO: SE STAVA PIOVENDO E ORA NON PIOVE PIÙ, SPAWNA TANTI GODRAYS ---
if stava_piovendo and not is_raining:
trigger_after_rain()
func _process(delta: float) -> void:
# --- LOGICA EVENTI CASUALI CINEMATIC MODE ---
if is_cinematic_mode:
timer_cinematic_env -= delta
if timer_cinematic_env <= 0.0:
_genera_evento_meteo_casuale()
timer_cinematic_env = randf_range(intervallo_eventi_meteo * 0.8, intervallo_eventi_meteo * 1.5)
# --- LOGICA NORMALE AMBIENTE ---
var base_tint: Color
var base_sky_top: Color
var base_sky_horizon: Color
@@ -153,9 +164,7 @@ func _process(delta: float) -> void:
else:
intensita_pioggia = move_toward(intensita_pioggia, 0.0, delta * 0.5)
# --- LOGICA NUVOLE: SI ADDENSANO CON LA PIOGGIA ---
if materiale_nuvole:
# lerp fa una transizione fluida tra 0.4 (limpido) e 1.0 (coperto) in base all'intensità della pioggia
var densita_attuale = lerp(0.4, 1.0, intensita_pioggia)
materiale_nuvole.set_shader_parameter("cloud_density", densita_attuale)
var sharpness_attuale = lerp(0.14, 0.0, intensita_pioggia)
@@ -204,7 +213,6 @@ func _process(delta: float) -> void:
materiale_nebbia.set_shader_parameter("night_intensity", night_val)
materiale_nebbia.set_shader_parameter("sun_color", final_tint)
# --- FUNZIONE GENERATORE CASUALE ---
func _genera_evento_meteo_casuale() -> void:
sto_cambiando_in_cinematic = true
@@ -231,11 +239,9 @@ func _genera_evento_meteo_casuale() -> void:
sto_cambiando_in_cinematic = false
# --- FUNZIONI FULMINI ---
func _resetta_timer_fulmine() -> void:
timer_prossimo_fulmine = randf_range(tempo_min_fulmine, tempo_max_fulmine)
# --- FUNZIONI FULMINI ---
func _scatena_fulmine() -> void:
if luce_lampo:
var tween_luce = create_tween()
@@ -254,11 +260,8 @@ func _scatena_fulmine() -> void:
var angolo_casuale = randf() * TAU
var distanza = randf_range(10.0, 40.0)
# Ho abbassato la Y da 20.0 a 10.0. Se non lo vedi ancora, abbassala a 5.0!
sprite_fulmine.position = Vector3(cos(angolo_casuale) * distanza, 10.0, sin(angolo_casuale) * distanza)
# VIA LA RIGA LOOK_AT! Ci pensa il Billboard dell'Inspector ora.
sprite_fulmine.modulate = colore_fulmine
sprite_fulmine.modulate.a = 1.0
@@ -266,11 +269,53 @@ func _scatena_fulmine() -> void:
sprite_fulmine.scale = Vector3(s, s, s)
var tween_sprite = create_tween()
# Ora rimane visibile al 100% per 0.2 secondi (il doppio)
tween_sprite.tween_interval(0.2)
# Ora ci mette 0.4 secondi a svanire dolcemente (il doppio)
tween_sprite.tween_property(sprite_fulmine, "modulate:a", 0.0, 0.4)
if numero_scariche > 1:
await get_tree().create_timer(randf_range(0.05, 0.15)).timeout
# --- FUNZIONI GOD RAYS ---
# ==========================================
# --- FUNZIONI GOD RAYS INTEGRATE ---
# ==========================================
func trigger_morning() -> void:
# Quando è mattina spara un solo godray vicino al treno
spawn_single_godray()
func trigger_after_rain() -> void:
# Evitiamo di farli spawnare se piove di notte (tempo_giorno >= 2.5)
if tempo_giorno < 2.5:
for i in range(max_rain_godrays):
spawn_single_godray()
func spawn_single_godray() -> void:
if godray_scene == null:
print("Attenzione: Manca la scena del Godray nell'Inspector!")
return
if nodo_camere == null:
print("Attenzione: Non trovo il nodo Camere per agganciare il Godray!")
return
var ray = godray_scene.instantiate()
# --- LA MAGIA È QUI ---
# Invece di aggiungerli a "nodo_camere" (che si muove),
# li aggiungiamo al genitore delle camere (il nodo "World"), che è fermo!
var nodo_mondo = nodo_camere.get_parent()
nodo_mondo.add_child(ray)
# Calcoliamo una posizione casuale
var random_x = randf_range(-godray_spawn_radius, godray_spawn_radius)
var random_z = randf_range(-godray_spawn_radius, godray_spawn_radius)
# Usiamo la GLOBAL_POSITION: Il raggio prende le coordinate globali di dov'è la
# telecamera in QUESTO preciso millisecondo, e ci aggiunge il suo offset casuale.
# Da questo momento in poi, essendo figlio del Mondo, resterà immobile lì.
ray.global_position = nodo_camere.global_position + Vector3(random_x, godray_spawn_height, random_z)
# Li incliniamo tutti uguali per farli piovere dall'angolo
ray.rotation_degrees = godray_rotation_degrees
# Li allunghiamo per farli sembrare veri fasci di luce
ray.scale = godray_scale