Menu
CoddyTech

Что такое сигнал?

Часть раздела Объектно-ориентированное программирование путешествия по GDScript на Coddy. Урок 35 из 65.

Пока игра работает, с объектами происходят разные события: монету подбирают, дверь открывается, hp героя снижается до 0. Другие части программы реагируют на эти события: счёт увеличивается, звучит звук, появляется экран окончания игры.

Сигнал — это сообщение, которое объект отправляет, когда с ним что-то происходит. Объект испускает сигнал, и выполняется каждая функция, подключённая к этому сигналу:

# coin.gd
class_name Coin
extends RefCounted

signal collected

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

signal collected объявляет сигнал, а collected.emit() отправляет его. Монета не знает, кто её слушает. Код, которому важны монеты, подключает к сигналу одну из собственных функций:

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

Вывод — Coin picked up, Score +1, Done. При отправке сигнала связанные функции выполняются сразу, до строки после emit(). Сигнал без связанных функций ничего не делает при отправке.

Без сигнала collect() пришлось бы самому вызывать код подсчёта очков, поэтому каждой монете понадобилась бы ссылка на табло счёта. При использовании сигнала монета лишь объявляет о событии, и на него может реагировать любое количество слушателей или никто.

Собственные узлы Godot работают так же: Button испускает сигнал pressed при нажатии, а Timer испускает сигнал timeout, когда время истекает.

challenge icon

Задание

Легко

Почтовый ящик сообщает о новой почте с помощью сигнала. В Mailbox уже объявлен signal mail_arrived и есть счётчик letters. Напиши deliver(kind):

  • Если kind равен "letter", прибавь 1 к letters и отправь сигнал mail_arrived.
  • Любая другая почта (реклама, листовка) выбрасывается: ничего не меняется, и сигнал не отправляется.

Предоставленный код подключает функцию, которая выводит You've got mail!, затем считывает количество следующих строк и обрабатывает каждую из них. Строка away отключает эту функцию, а home подключает её снова, поэтому письмо, пришедшее, пока тебя нет дома, учитывается, но о нём не сообщается. Для строк letter, ad, away, letter выводится:

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

Твой код нужно поместить в mailbox.gd. В main.gd находится предоставленный код ввода/вывода, и его нельзя редактировать.

Попробуйте сами

extends Node

func _ready():
	# Предоставленный код ввода/вывода: оставьте его без изменений
	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 iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор GDScript