Menu
CoddyTech

Segnali con argomenti

Fa parte della sezione Programmazione orientata agli oggetti del percorso GDScript di Coddy. Lezione 38 di 65.

Un segnale può trasportare valori. Elencali nella dichiarazione, come i parametri di una funzione:

signal damaged(amount: int, hp_left: int)
signal died

Passa i valori a emit() nello stesso ordine:

func take_damage(amount: int) -> void:
	hp = maxi(hp - amount, 0)
	damaged.emit(amount, hp)
	if hp == 0:
		died.emit()

Una funzione connessa riceve i valori come parametri, quindi ha bisogno di un parametro per ogni valore:

hero.damaged.connect(_on_hero_damaged)

func _on_hero_damaged(amount: int, hp_left: int) -> void:
	print("-%d HP, %d left" % [amount, hp_left])

I tipi nella dichiarazione documentano i valori: GDScript non li controlla quando emetti. Una mancata corrispondenza si manifesta nella funzione ricevente. Una funzione con un numero errato di parametri, o un parametro tipizzato che non può contenere il valore, genera un errore alla riga emit(), e quella funzione non viene eseguita.

bind() aggiunge i tuoi valori dopo quelli emessi. Un metodo può quindi ascoltare diversi eroi e sapere comunque quale è stato colpito:

ada.damaged.connect(_on_damaged.bind("Ada"))
bo.damaged.connect(_on_damaged.bind("Bo"))

func _on_damaged(amount: int, hp_left: int, who: String) -> void:
	print(who, " lost ", amount, " HP")

Gli argomenti forniscono a un listener i dati di cui ha bisogno, così non deve leggerli dall'emettitore. Non collegare mai una lambda che usa l'oggetto emittente stesso, come hero.died.connect(func(): print(hero.hp)): la lambda mantiene in vita hero, hero mantiene la lambda, nessuno dei due viene mai liberato e Godot segnala istanze non liberate quando il programma termina.

challenge icon

Sfida

Facile

Un portafoglio segnala ogni modifica con segnali che trasportano i numeri. In Wallet, aggiungi i parametri a entrambi i segnali e scrivi i due metodi:

  • balance_changed(old_balance: int, new_balance: int) e purchase_failed(price: int, missing: int)
  • add(amount) aggiunge monete ed emette balance_changed con il saldo prima e dopo.
  • buy(price): quando il saldo è sufficiente, sottrai il prezzo ed emetti balance_changed. Altrimenti non modificare nulla ed emetti purchase_failed con il prezzo e il numero di monete mancanti.

Il codice fornito collega una funzione a ciascun segnale, legge quanti comandi seguono, esegue ogni comando (add 20, buy 15) e stampa le monete rimaste alla fine. Con add 20, buy 15, buy 10, add 5, buy 10 stampa:

Balance: 0 -> 20
Balance: 20 -> 5
Cannot buy for 10: 5 coins missing
Balance: 5 -> 10
Balance: 10 -> 0
Coins left: 0

Il tuo codice va in wallet.gd. main.gd contiene il codice di input/output fornito e non può essere modificato.

Provalo tu

extends Node

func _ready():
	# Codice di input/output fornito: lascialo così com'è
	var wallet := Wallet.new()
	wallet.balance_changed.connect(_on_balance_changed)
	wallet.purchase_failed.connect(_on_purchase_failed)
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var parts := OS.read_string_from_stdin().split(" ")
		if parts[0] == "add":
			wallet.add(int(parts[1]))
		else:
			wallet.buy(int(parts[1]))
	print("Coins left: ", wallet.balance)

func _on_balance_changed(old_balance: int, new_balance: int) -> void:
	print("Balance: %d -> %d" % [old_balance, new_balance])

func _on_purchase_failed(price: int, missing: int) -> void:
	print("Cannot buy for %d: %d coins missing" % [price, missing])
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore GDScript online