Сигналы с аргументами
Часть раздела Объектно-ориентированное программирование путешествия по GDScript на Coddy. Урок 38 из 65.
Сигнал может передавать значения. Перечисли их в объявлении, как параметры функции:
signal damaged(amount: int, hp_left: int)
signal diedПередай значения в emit() в том же порядке:
func take_damage(amount: int) -> void:
hp = maxi(hp - amount, 0)
damaged.emit(amount, hp)
if hp == 0:
died.emit()Подключённая функция получает значения в качестве параметров, поэтому для каждого значения ей нужен отдельный параметр:
hero.damaged.connect(_on_hero_damaged)
func _on_hero_damaged(amount: int, hp_left: int) -> void:
print("-%d HP, %d left" % [amount, hp_left])Типы в объявлении документируют значения: GDScript не проверяет их при отправке сигнала. Несоответствие обнаруживается в принимающей функции. Функция с неправильным количеством параметров или типизированным параметром, который не может содержать это значение, вызывает ошибку в строке с emit(), и эта функция не выполняется.
bind() добавляет ваши собственные значения после переданных сигналом. Тогда один метод может слушать нескольких героев и при этом знать, кого из них ударили:
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")Аргументы передают слушателю необходимые данные, поэтому ему не нужно считывать их у отправителя сигнала. Никогда не подключай лямбда-функцию, которая использует сам объект, отправляющий сигнал, например hero.died.connect(func(): print(hero.hp)): лямбда-функция удерживает hero в памяти, hero удерживает лямбда-функцию, ни один из них никогда не освобождается, и Godot сообщает об утёкших экземплярах при завершении программы.
Задание
ЛегкоКошелёк сообщает о каждом изменении с помощью сигналов, которые передают числовые значения. В Wallet добавь параметры к обоим сигналам и напиши два метода:
balance_changed(old_balance: int, new_balance: int)иpurchase_failed(price: int, missing: int)add(amount)добавляет монеты и отправляет сигналbalance_changedс балансом до и после изменения.buy(price): если баланса достаточно, вычти стоимость и отправь сигналbalance_changed. Иначе ничего не меняй и отправь сигналpurchase_failed, передав стоимость и количество недостающих монет.
Предоставленный код подключает по одной функции к каждому сигналу, считывает количество следующих команд, выполняет каждую команду (add 20, buy 15) и в конце выводит оставшееся количество монет. Для add 20, buy 15, buy 10, add 5, buy 10 он выводит:
Balance: 0 -> 20
Balance: 20 -> 5
Cannot buy for 10: 5 coins missing
Balance: 5 -> 10
Balance: 10 -> 0
Coins left: 0Твой код нужно написать в wallet.gd. В main.gd находится предоставленный код ввода/вывода, и его нельзя редактировать.
Попробуйте сами
extends Node
func _ready():
# Предоставленный код ввода/вывода: оставьте его без изменений
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])
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово selfМетодыСвойстваКонструктор (_init)Повторение: простой калькулятор4Полиморфизм
Переопределение методов: повторениеУтиная типизацияАбстрактные классы и методыПроектирование интерфейсовПовторение — калькулятор фигур7Сигналы
Что такое сигнал?Объявление и отправкаПодключение к сигналамСигналы с аргументамиПовторение — система здоровья10Паттерны проектирования. Часть 2
Паттерн «Команда»Паттерн «Адаптер»Паттерн «Декоратор»Паттерн «Шаблонный метод»Паттерн «Состояние»Паттерн «Компоновщик»2Свойства классов
Переменные экземпляра и классаСтатические функцииСеттеры свойствГеттеры свойствПриватность по соглашениюПовторение — менеджер банковского счёта5Инкапсуляция
Открытые и закрытые членыПроверка данных с помощью сеттеровСокрытие информацииСвойства только для чтенияПовторение — система учета студентов8Продвинутые концепции ООП
Композиция и наследованиеВнутренние классыУзлы как компонентыRefCounted и NodeПеречисления в классах11Проект: Управление библиотекой
Обзор проектаКлассы книг и пользователей3Наследование
Основы наследованияКлючевое слово superПереопределение методовЦепочки наследованияПроверка типов с помощью isПовторение — иерархия сотрудников6Специальные методы
Введение в виртуальные методыМетод _to_stringПользовательские итераторыПовторение: пользовательский список9Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн «Одиночка»Паттерн «Фабрика»Паттерн «Наблюдатель»Паттерн «Стратегия»Потренируйтесь самостоятельно: Онлайн-компилятор GDScript