Menu
CoddyTech

¿Qué es una señal?

Parte de la sección Programación orientada a objetos del Journey de GDScript de Coddy. Lección 35 de 65.

Les suceden cosas a los objetos mientras se ejecuta un juego: se recoge una moneda, se abre una puerta, los hp del héroe bajan a 0. Otras partes del programa reaccionan a estos eventos: aumenta la puntuación, suena un sonido y aparece la pantalla de fin del juego.

Una señal es un mensaje que un objeto envía cuando le sucede algo. El objeto emite la señal, y se ejecuta cada función conectada a esa señal:

# coin.gd
class_name Coin
extends RefCounted

signal collected

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

signal collected declara la señal y collected.emit() la envía. La moneda no sabe quién está escuchando. El código que se ocupa de las monedas conecta una de sus propias funciones a la señal:

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

La salida es Coin picked up, Score +1, Done. Al emitir, se ejecutan las funciones conectadas de inmediato, antes de la línea que viene después de emit(). Una señal sin funciones conectadas no hace nada cuando se emite.

Sin una señal, collect() tendría que llamar al código de puntuación por sí mismo, así que cada moneda necesitaría una referencia al marcador. Con una señal, la moneda solo anuncia el evento, y cualquier cantidad de oyentes, o ninguno, puede reaccionar ante él.

Los nodos propios de Godot funcionan de la misma manera: un Button emite pressed cuando se hace clic en él, y un Timer emite timeout cuando se agota el tiempo.

challenge icon

Desafío

Fácil

Un buzón anuncia el correo nuevo con una señal. Mailbox ya declara signal mail_arrived y tiene un contador letters. Escribe deliver(kind):

  • Cuando kind es "letter", suma 1 a letters y emite mail_arrived.
  • Cualquier otro tipo (un anuncio, un folleto) se desecha: nada cambia y no se emite nada.

El código proporcionado conecta una función que imprime You've got mail!, luego lee cuántas líneas siguen y entrega cada una. La línea away desconecta esa función y home vuelve a conectarla, así que una carta que llega mientras no estás se cuenta, pero no se anuncia. Para las líneas letter, ad, away, letter imprime:

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

Tu código va en mailbox.gd. main.gd contiene el código de entrada/salida proporcionado y no se puede editar.

Pruébalo tú mismo

extends Node

func _ready():
	# Código de entrada/salida proporcionado: déjalo tal como está
	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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación orientada a objetos

Practica por tu cuenta: Compilador de GDScript online