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 diedPassa 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.
Sfida
FacileUn 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)epurchase_failed(price: int, missing: int)add(amount)aggiunge monete ed emettebalance_changedcon il saldo prima e dopo.buy(price): quando il saldo è sufficiente, sottrai il prezzo ed emettibalance_changed. Altrimenti non modificare nulla ed emettipurchase_failedcon 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: 0Il 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])
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
1Fondamenti della programmazione orientata agli oggetti
File esterniIntroduzione alla programmazione orientata agli oggettiClassi e oggetti a confrontoLa parola chiave selfMetodiProprietàCostruttore (_init)Riepilogo - Calcolatrice semplice4Polimorfismo
Ripasso dell'override dei metodiDuck typingClassi e metodi astrattiProgettazione delle interfacceRiepilogo - Calcolatore di forme7Segnali
Che cos'è un segnale?Dichiarare ed emettereCollegarsi ai segnaliSegnali con argomentiRipasso - Sistema della salute10Pattern di progettazione, parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern Composite2Proprietà delle classi
Variabili di istanza e staticheFunzioni staticheSetter delle proprietàGetter delle proprietàPrivato per convenzioneRiepilogo - Gestore di conti bancari5Incapsulamento
Membri pubblici e privatiValidazione con i setterNascondimento delle informazioniProprietà di sola letturaRiepilogo - Sistema di gestione dei dati degli studenti8Concetti avanzati di OOP
Composizione vs ereditarietàClassi interneNodi come componentiRefCounted vs NodeEnum nelle classi11Progetto: Gestione della biblioteca
Panoramica del progettoClassi Libro e Utente3Ereditarietà
Ereditarietà di baseLa parola chiave superOverride dei metodiCatene di ereditarietàControlli di tipo con isRipasso - Gerarchia dei dipendenti6Metodi speciali
Introduzione ai metodi virtualiIl metodo _to_stringIteratori personalizzatiRiepilogo - Lista personalizzata9Modelli di progettazione, parte 1
Introduzione ai modelli di progettazionePattern SingletonPattern FactoryPattern ObserverPattern StrategyEsercitati da solo: Compilatore GDScript online