Menu
CoddyTech

Signale mit Argumenten

Teil des Abschnitts Objektorientierte Programmierung der GDScript-Journey von Coddy. Lektion 38 von 65.

Ein Signal kann Werte übertragen. Liste sie in der Deklaration auf, wie die Parameter einer Funktion:

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

Übergib die Werte in derselben Reihenfolge an emit():

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

Eine verbundene Funktion erhält die Werte als Parameter und benötigt daher einen Parameter pro Wert:

hero.damaged.connect(_on_hero_damaged)

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

Die Typen in der Deklaration dokumentieren die Werte: GDScript prüft sie beim Auslösen nicht. Eine Typabweichung zeigt sich in der empfangenden Funktion. Eine Funktion mit der falschen Anzahl von Parametern oder einem typisierten Parameter, der den Wert nicht aufnehmen kann, verursacht einen Fehler an der Zeile mit emit(), und die Funktion wird nicht ausgeführt.

bind() fügt nach den ausgegebenen Werten eigene Werte hinzu. Eine Methode kann dann mehreren Helden zuhören und trotzdem wissen, welcher getroffen wurde:

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

Argumente liefern einem Listener die benötigten Daten, sodass er sie nicht vom Emitter auslesen muss. Verbinde niemals eine Lambda-Funktion, die das auslösende Objekt selbst verwendet, zum Beispiel hero.died.connect(func(): print(hero.hp)): Die Lambda-Funktion hält hero am Leben, hero hält die Lambda-Funktion, keines von beiden wird jemals freigegeben, und Godot meldet beim Beenden des Programms Speicherlecks.

challenge icon

Aufgabe

Einfach

Eine Wallet meldet jede Änderung mit Signalen, die die Zahlen enthalten. Füge in Wallet die Parameter zu beiden Signalen hinzu und schreibe die beiden Methoden:

  • balance_changed(old_balance: int, new_balance: int) und purchase_failed(price: int, missing: int)
  • add(amount) fügt Münzen hinzu und sendet balance_changed mit dem Kontostand davor und danach aus.
  • buy(price): Wenn der Kontostand ausreicht, ziehe den Preis ab und sende balance_changed aus. Andernfalls ändere nichts und sende purchase_failed mit dem Preis und der Anzahl der fehlenden Münzen aus.

Der bereitgestellte Code verbindet jeweils eine Funktion mit jedem Signal, liest ein, wie viele Befehle folgen, führt jeden Befehl aus (add 20, buy 15) und gibt am Ende die übrigen Münzen aus. Für add 20, buy 15, buy 10, add 5, buy 10 gibt er Folgendes aus:

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

Dein Code gehört in wallet.gd. main.gd enthält den bereitgestellten Ein-/Ausgabecode und kann nicht bearbeitet werden.

Probier es selbst

extends Node

func _ready():
	# Vorgegebener Ein-/Ausgabecode: unverändert lassen
	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 iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-GDScript-Compiler