Menu
CoddyTech

Was ist ein Signal?

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

Während ein Spiel läuft, passieren Dinge mit Objekten: Eine Münze wird eingesammelt, eine Tür öffnet sich, die hp des Helden sinkt auf 0. Andere Teile des Programms reagieren auf diese Ereignisse: Der Punktestand steigt, ein Ton erklingt, der Game-Over-Bildschirm erscheint.

Ein Signal ist eine Nachricht, die ein Objekt sendet, wenn etwas mit ihm geschieht. Das Objekt sendet das Signal aus, und jede mit diesem Signal verbundene Funktion wird ausgeführt:

# coin.gd
class_name Coin
extends RefCounted

signal collected

func collect() -> void:
	print("Coin picked up")
	collected.emit()

signal collected deklariert das Signal und collected.emit() sendet es. Die Münze weiß nicht, wer zuhört. Der Code, der sich für Münzen interessiert, verbindet eine seiner eigenen Funktionen mit dem Signal:

# main.gd
func _ready():
	var coin := Coin.new()
	coin.collected.connect(_on_coin_collected)
	coin.collect()
	print("Done")

func _on_coin_collected() -> void:
	print("Score +1")

Die Ausgabe lautet Coin picked up, Score +1, Done. Beim Auslösen werden die verbundenen Funktionen sofort ausgeführt, bevor die Zeile nach emit() ausgeführt wird. Ein Signal ohne verbundene Funktionen bewirkt beim Auslösen nichts.

Ohne ein Signal müsste collect() den Code für die Punktzahl selbst aufrufen, sodass jede Münze eine Referenz auf die Punktetafel bräuchte. Mit einem Signal kündigt die Münze nur das Ereignis an, und beliebig viele Listener oder auch gar keiner können darauf reagieren.

Godots eigene Knoten funktionieren genauso: Ein Button löst pressed aus, wenn er angeklickt wird, und ein Timer löst timeout aus, wenn seine Zeit abläuft.

challenge icon

Aufgabe

Einfach

Ein Briefkasten kündigt neue Post mit einem Signal an. Mailbox deklariert bereits signal mail_arrived und hat einen letters-Zähler. Schreibe deliver(kind):

  • Wenn kind "letter" ist, addiere 1 zu letters und sende mail_arrived aus.
  • Jede andere Art (eine Werbung, ein Flyer) wird weggeworfen: Nichts ändert sich und nichts wird ausgesendet.

Der bereitgestellte Code verbindet eine Funktion, die You've got mail! ausgibt, liest dann, wie viele Zeilen folgen, und stellt jede davon zu. Die Zeile away trennt die Verbindung zu dieser Funktion, und home verbindet sie wieder. Ein Brief, der ankommt, während du weg bist, wird also gezählt, aber nicht angekündigt. Für die Zeilen letter, ad, away, letter gibt der Code Folgendes aus:

Delivering: letter
You've got mail!
Delivering: ad
Delivering: letter
Letters: 2

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

Probier es selbst

extends Node

func _ready():
	# Bereitgestellter Ein-/Ausgabecode: unverändert lassen
	var mailbox := Mailbox.new()
	mailbox.mail_arrived.connect(_on_mail_arrived)
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var line := OS.read_string_from_stdin()
		if line == "away":
			mailbox.mail_arrived.disconnect(_on_mail_arrived)
		elif line == "home":
			mailbox.mail_arrived.connect(_on_mail_arrived)
		else:
			print("Delivering: ", line)
			mailbox.deliver(line)
	print("Letters: ", mailbox.letters)

func _on_mail_arrived() -> void:
	print("You've got mail!")
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