Menu
CoddyTech

Sinais com argumentos

Parte da seção Programação orientada a objetos do Journey de GDScript da Coddy. Lição 38 de 65.

Um sinal pode transportar valores. Liste-os na declaração, como os parâmetros de uma função:

signal damaged(amount: int, hp_left: int)
signal died

Passe os valores para emit() na mesma ordem:

func take_damage(amount: int) -> void:
	hp = maxi(hp - amount, 0)
	damaged.emit(amount, hp)
	if hp == 0:
		died.emit()

Uma função conectada recebe os valores como parâmetros, então ela precisa de um parâmetro para cada valor:

hero.damaged.connect(_on_hero_damaged)

func _on_hero_damaged(amount: int, hp_left: int) -> void:
	print("-%d HP, %d left" % [amount, hp_left])

Os tipos na declaração documentam os valores: o GDScript não os verifica quando você emite. Uma incompatibilidade aparece na função que recebe o sinal. Uma função com o número errado de parâmetros, ou um parâmetro tipado que não pode conter o valor, gera um erro na linha emit(), e essa função não é executada.

bind() adiciona os próprios valores depois dos emitidos. Assim, um método pode escutar vários heróis e ainda saber qual deles foi atingido:

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

Os argumentos fornecem ao ouvinte os dados de que ele precisa, para que não tenha de obtê-los do emissor. Nunca conecte uma lambda que use o próprio objeto emissor, como hero.died.connect(func(): print(hero.hp)): a lambda mantém hero vivo, hero mantém a lambda, nenhum dos dois é liberado, e o Godot informa instâncias não liberadas quando o programa termina.

challenge icon

Desafio

Fácil

Uma carteira relata cada alteração por meio de sinais que carregam os números. Em Wallet, adicione os parâmetros aos dois sinais e escreva os dois métodos:

  • balance_changed(old_balance: int, new_balance: int) e purchase_failed(price: int, missing: int)
  • add(amount) adiciona moedas e emite balance_changed com o saldo antes e depois.
  • buy(price): quando o saldo é suficiente, subtraia o preço e emita balance_changed. Caso contrário, não altere nada e emita purchase_failed com o preço e quantas moedas estão faltando.

O código fornecido conecta uma função a cada sinal, lê quantos comandos vêm a seguir, executa cada comando (add 20, buy 15) e imprime as moedas restantes ao final. Para add 20, buy 15, buy 10, add 5, buy 10, ele imprime:

Balance: 0 -> 20
Balance: 20 -> 5
Cannot buy for 10: 5 coins missing
Balance: 5 -> 10
Balance: 10 -> 0
Coins left: 0

Seu código deve ficar em wallet.gd. main.gd contém o código de entrada/saída fornecido e não pode ser editado.

Experimente você mesmo

extends Node

func _ready():
	# Código de entrada/saída fornecido: mantenha-o como está
	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])
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação orientada a objetos

Pratique por conta própria: Compilador de GDScript online