Menu
CoddyTech

Объявление и отправка

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

Объяви сигнал с помощью ключевого слова signal и укажи его имя в начале класса рядом с переменными. Имя сигнала описывает уже произошедшее событие и записывается в формате snake_case: died, door_opened, leveled_up. В классе можно объявить столько сигналов, сколько нужно:

# player.gd
class_name Player
extends RefCounted

signal leveled_up
signal max_level_reached

const MAX_LEVEL := 3
var level := 1
var xp := 0

func add_xp(amount: int) -> void:
	xp += amount
	while xp >= 100 and level < MAX_LEVEL:
		xp -= 100
		level += 1
		leveled_up.emit()
		if level == MAX_LEVEL:
			max_level_reached.emit()

Отправляй сигнал в момент наступления события и только тогда. add_xp(50) для нового игрока ничего не отправляет. add_xp(250) после этого доводит xp до 300: сигнал leveled_up отправляется дважды, по одному разу за каждый полученный уровень, а max_level_reached — один раз, при повышении уровня до 3.

Сеттер свойства — хорошее место для вызова сигнала, потому что тогда сигнал срабатывает при любом изменении значения:

signal died

var hp: int = 10:
	set(value):
		var was_alive := hp > 0
		hp = maxi(value, 0)
		if was_alive and hp == 0:
			died.emit()

was_alive не позволяет событию died сработать повторно, когда героя с 0 HP снова поражают.

К сигналу также можно обратиться по его имени в виде текста: emit_signal("died") отправляет его, hero.connect("died", _on_hero_died) подключается к нему, а hero.has_signal("died") возвращает true. Подключение к имени, которое объект не объявляет, приводит к ошибке при выполнении этой строки.

challenge icon

Задание

Легко

Напиши Bomb, который отсчитывает время и сообщает о каждом шаге с помощью сигналов.

  • Объяви два сигнала: beeped и exploded.
  • tick() уменьшает fuse на 1. Если значение fuse всё ещё больше 0, вызови сигнал beeped; если оно достигло 0, вызови сигнал exploded.
  • Когда значение fuse станет 0, бомба взорвётся: последующие тики ничего не делают и не вызывают сигналов.

Предоставленный код считывает начальное значение fuse и количество тиков, подключается к обоим сигналам по имени и выводит Beep и BOOM! из подключённых функций, а затем выводит оставшееся значение fuse. Для значения fuse 3 и 5 тиков он выводит:

Beep
Beep
BOOM!
Fuse: 0

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

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

extends Node

func _ready():
	# Предоставленный код ввода-вывода: оставьте его без изменений
	var bomb := Bomb.new(int(OS.read_string_from_stdin()))
	# connect() с именем сигнала в виде текста
	bomb.connect("beeped", _on_beeped)
	bomb.connect("exploded", _on_exploded)
	var ticks := int(OS.read_string_from_stdin())
	for i in ticks:
		bomb.tick()
	print("Fuse: ", bomb.fuse)

func _on_beeped() -> void:
	print("Beep")

func _on_exploded() -> void:
	print("BOOM!")
quiz iconПроверьте себя

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

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

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