Menu
CoddyTech

Conectando-se a sinais

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

connect() recebe a função a ser executada como um Callable. Nomeie um método sem parênteses ou escreva uma lambda:

chest.opened.connect(_on_chest_opened)          # um método deste script
chest.opened.connect(quest_log.add_entry)       # um método de outro objeto
chest.opened.connect(func(): print("Creak!"))   # uma lambda

Godot nomeia um método ouvinte com _on_, depois o emissor e, em seguida, o sinal: _on_chest_opened. Um sinal pode ter muitas funções conectadas, e elas são executadas na ordem em que foram conectadas.

Um objeto que escuta geralmente se conecta, em um método que recebe o emissor:

# quest_log.gd
class_name QuestLog
extends RefCounted

var chests_opened := 0

func track(chest: Chest) -> void:
	if not chest.opened.is_connected(_on_chest_opened):
		chest.opened.connect(_on_chest_opened)

func untrack(chest: Chest) -> void:
	if chest.opened.is_connected(_on_chest_opened):
		chest.opened.disconnect(_on_chest_opened)

func _on_chest_opened() -> void:
	chests_opened += 1

Conectar a mesma função ao mesmo sinal duas vezes é um erro, assim como desconectar uma função que não está conectada. is_connected() verifica primeiro. disconnect() para de escutar, e a próxima emissão não executa mais essa função.

Passe CONNECT_ONE_SHOT como segundo argumento, e a conexão se remove após sua primeira chamada: chest.opened.connect(_on_first_open, CONNECT_ONE_SHOT).

Uma lambda mantém o valor que uma variável local tinha quando a lambda foi criada. count += 1 dentro de uma lambda conectada altera essa cópia, e count em _ready() continua sendo 0. Mantenha um contador em uma variável membro de um objeto ouvinte, como faz QuestLog.

challenge icon

Desafio

Fácil

Um estande de tiro tem alvos que emitem hit quando são atingidos. Escreva o ScoreBoard que os escuta:

  • watch(target) conecta o sinal hit do alvo a _on_target_hit. Observar um alvo que já está sendo observado não altera nada.
  • ignore(target) desconecta o sinal. Ignorar um alvo que não está sendo observado não altera nada.
  • _on_target_hit() adiciona 10 a points e imprime Hit! Score: N.

Observar duas vezes ou ignorar um alvo que não está sendo observado não pode causar um erro, pois qualquer erro faz o teste falhar. target.gd está completo.

O código fornecido lê o número de alvos e, em seguida, comandos como watch 0, ignore 0 e shoot 0, e imprime a pontuação final. Para dois alvos e os comandos watch 0, shoot 0, shoot 1, watch 1, watch 1, shoot 1, ignore 0, shoot 0, ele imprime:

Shot target 0
Hit! Score: 10
Shot target 1
Shot target 1
Hit! Score: 20
Shot target 0
Final score: 20

Seu código deve ficar em score_board.gd e target.gd. main.gd contém o código fornecido de entrada/saída 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 board := ScoreBoard.new()
	var targets: Array[Target] = []
	for i in int(OS.read_string_from_stdin()):
		targets.append(Target.new())
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var parts := OS.read_string_from_stdin().split(" ")
		var target := targets[int(parts[1])]
		if parts[0] == "watch":
			board.watch(target)
		elif parts[0] == "ignore":
			board.ignore(target)
		else:
			print("Shot target ", parts[1])
			target.shoot()
	print("Final score: ", board.points)
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