Mit Signalen verbinden
Teil des Abschnitts Objektorientierte Programmierung der GDScript-Journey von Coddy. Lektion 37 von 65.
connect() erwartet als Callable die auszuführende Funktion. Gib den Namen einer Methode ohne Klammern an oder schreibe eine Lambda-Funktion:
chest.opened.connect(_on_chest_opened) # eine Methode dieses Skripts
chest.opened.connect(quest_log.add_entry) # eine Methode eines anderen Objekts
chest.opened.connect(func(): print("Creak!")) # ein Lambda-AusdruckGodot benennt eine empfangende Methode mit _on_, dann dem Auslöser und anschließend dem Signal: _on_chest_opened. Ein Signal kann mit mehreren Funktionen verbunden sein, die in der Reihenfolge ausgeführt werden, in der sie verbunden wurden.
Ein Objekt, das auf ein Signal wartet, verbindet sich normalerweise selbst in einer Methode, die den Sender entgegennimmt:
# quest_log.gd
class_name QuestLog
extends RefCounted
var chests_opened := 0
func track(chest: Chest) -> void:
if not chest.opened.is_connected(_on_chest_opened):
chest.opened.connect(_on_chest_opened)
func untrack(chest: Chest) -> void:
if chest.opened.is_connected(_on_chest_opened):
chest.opened.disconnect(_on_chest_opened)
func _on_chest_opened() -> void:
chests_opened += 1Dieselbe Funktion zweimal mit demselben Signal zu verbinden, ist ein Fehler, ebenso wie das Trennen einer Funktion, die nicht verbunden ist. is_connected() prüft dies zuerst. disconnect() beendet das Lauschen, und beim nächsten Auslösen wird diese Funktion nicht mehr ausgeführt.
Übergib CONNECT_ONE_SHOT als zweites Argument, und die Verbindung entfernt sich nach ihrem ersten Aufruf selbst: chest.opened.connect(_on_first_open, CONNECT_ONE_SHOT).
Eine Lambda-Funktion behält den Wert, den eine lokale Variable hatte, als die Lambda-Funktion erstellt wurde. count += 1 innerhalb einer verbundenen Lambda-Funktion ändert diese Kopie, und count in _ready() bleibt 0. Führe einen Zähler in einer Member-Variable eines Listener-Objekts, wie es QuestLog tut.
Aufgabe
EinfachEin Schießstand hat Ziele, die beim Treffer hit auslösen. Schreibe das ScoreBoard, das auf sie hört:
watch(target)verbindet das Signalhitdes Ziels mit_on_target_hit. Ein Ziel zu beobachten, das bereits beobachtet wird, ändert nichts.ignore(target)trennt die Verbindung. Ein Ziel zu ignorieren, das nicht beobachtet wird, ändert nichts._on_target_hit()addiert10zupointsund gibtHit! Score: Naus.
Ein Ziel zweimal zu beobachten oder ein nicht beobachtetes Ziel zu ignorieren darf keinen Fehler verursachen, da jeder Fehler den Test fehlschlagen lässt. target.gd ist vollständig.
Der bereitgestellte Code liest die Anzahl der Ziele und anschließend Befehle wie watch 0, ignore 0 und shoot 0 und gibt die Endpunktzahl aus. Bei zwei Zielen und den Befehlen watch 0, shoot 0, shoot 1, watch 1, watch 1, shoot 1, ignore 0, shoot 0 gibt er Folgendes aus:
Shot target 0
Hit! Score: 10
Shot target 1
Shot target 1
Hit! Score: 20
Shot target 0
Final score: 20Dein Code gehört in score_board.gd und target.gd. main.gd enthält den bereitgestellten Eingabe-/Ausgabecode und kann nicht bearbeitet werden.
Probier es selbst
extends Node
func _ready():
# Vorgegebener Ein-/Ausgabecode: unverändert lassen
var board := ScoreBoard.new()
var targets: Array[Target] = []
for i in int(OS.read_string_from_stdin()):
targets.append(Target.new())
var count := int(OS.read_string_from_stdin())
for i in count:
var parts := OS.read_string_from_stdin().split(" ")
var target := targets[int(parts[1])]
if parts[0] == "watch":
board.watch(target)
elif parts[0] == "ignore":
board.ignore(target)
else:
print("Shot target ", parts[1])
target.shoot()
print("Final score: ", board.points)
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in die OOPKlassen vs. ObjekteDas Schlüsselwort selfMethodenEigenschaftenKonstruktor (_init)Wiederholung – Einfacher Taschenrechner4Polymorphie
Methodenüberschreibung erneut betrachtetDuck-TypisierungAbstrakte Klassen und MethodenSchnittstellendesignRückblick – Formrechner7Signale
Was ist ein Signal?Deklarieren und AuslösenMit Signalen verbindenSignale mit ArgumentenRückblick – Gesundheitssystem2Klassenattribute
Instanz- vs. statische VariablenStatische FunktionenProperty-SetterProperty-GetterPrivat nach KonventionWiederholung – Bankkontenverwaltung5Kapselung
Öffentliche und private MemberValidierung mit SetternInformationsverbergenSchreibgeschützte EigenschaftenRückblick – System zur Schülerverwaltung8Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungInnere KlassenNodes als KomponentenRefCounted vs. NodeEnums in Klassen11Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen3Vererbung
Grundlegende VererbungDas Schlüsselwort superMethodenüberschreibungVererbungskettenTypprüfungen mit isWiederholung – Mitarbeiterhierarchie6Spezielle Methoden
Einführung in virtuelle MethodenDie _to_string-MethodeBenutzerdefinierte IteratorenRückblick – Benutzerdefinierte Liste9Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterBeobachter-MusterStrategie-Muster12Abschließende Herausforderungen
E-Learning-PlattformBankensystemEntwicklung von SpielfigurenFahrzeugvermietungÜbe selbstständig: Online-GDScript-Compiler