Menu
CoddyTech

Sygnały z argumentami

Część sekcji Programowanie obiektowe ścieżki GDScript w Coddy. Lekcja 38 z 65.

Sygnał może przenosić wartości. Wymień je w deklaracji, tak jak parametry funkcji:

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

Przekaż wartości do emit() w tej samej kolejności:

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

Połączona funkcja otrzymuje wartości jako parametry, więc potrzebuje jednego parametru dla każdej wartości:

hero.damaged.connect(_on_hero_damaged)

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

Typy w deklaracji opisują wartości: GDScript nie sprawdza ich podczas emisji. Niezgodność ujawnia się w funkcji odbierającej. Funkcja z nieprawidłową liczbą parametrów lub parametrem z typem, który nie może przechować wartości, powoduje błąd w wierszu emit(), a ta funkcja nie zostaje uruchomiona.

bind() dodaje własne wartości po wyemitowanych wartościach. Jedna metoda może wtedy nasłuchiwać kilku bohaterów i nadal wiedzieć, który z nich został trafiony:

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")

Argumenty przekazują odbiorcy potrzebne dane, dzięki czemu nie musi ich odczytywać z obiektu emitującego sygnał. Nigdy nie łącz lambdy, która używa samego obiektu emitującego sygnał, na przykład hero.died.connect(func(): print(hero.hp)): lambda utrzymuje przy życiu hero, hero utrzymuje lambdę, żaden z nich nigdy nie zostaje zwolniony, a Godot zgłasza wycieki instancji po zakończeniu programu.

challenge icon

Wyzwanie

Łatwy

Portfel zgłasza każdą zmianę za pomocą sygnałów przenoszących liczby. W Wallet dodaj parametry do obu sygnałów i napisz dwie metody:

  • balance_changed(old_balance: int, new_balance: int) i purchase_failed(price: int, missing: int)
  • add(amount) dodaje monety i emituje balance_changed z saldem przed zmianą i po niej.
  • buy(price): gdy saldo jest wystarczające, odejmij cenę i wyemituj balance_changed. W przeciwnym razie niczego nie zmieniaj i wyemituj purchase_failed z ceną i liczbą brakujących monet.

Dostarczony kod łączy jedną funkcję z każdym sygnałem, odczytuje liczbę kolejnych poleceń, wykonuje każde polecenie (add 20, buy 15) i na koniec wyświetla liczbę pozostałych monet. Dla poleceń add 20, buy 15, buy 10, add 5, buy 10 wyświetla:

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

Umieść swój kod w pliku wallet.gd. main.gd zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.

Spróbuj swoich sił

extends Node

func _ready():
	# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
	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 iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator GDScript online