Señales con argumentos
Parte de la sección Programación orientada a objetos del Journey de GDScript de Coddy. Lección 38 de 65.
Una señal puede transportar valores. Enuméralos en la declaración, como los parámetros de una función:
signal damaged(amount: int, hp_left: int)
signal diedPasa los valores a emit() en el mismo orden:
func take_damage(amount: int) -> void:
hp = maxi(hp - amount, 0)
damaged.emit(amount, hp)
if hp == 0:
died.emit()Una función conectada recibe los valores como parámetros, así que necesita un parámetro por 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])Los tipos en la declaración documentan los valores: GDScript no los comprueba cuando emites. Una discrepancia aparece en la función receptora. Una función con un número incorrecto de parámetros, o un parámetro tipado que no puede contener el valor, produce un error en la línea de emit(), y esa función no se ejecuta.
bind() añade tus propios valores después de los emitidos. Así, un método puede escuchar a varios héroes y seguir sabiendo cuál recibió el golpe:
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")Los argumentos proporcionan a un receptor los datos que necesita, para que no tenga que leerlos del emisor. Nunca conectes una lambda que use el propio objeto emisor, como hero.died.connect(func(): print(hero.hp)): la lambda mantiene vivo a hero, hero mantiene la lambda, ninguno de los dos se libera nunca y Godot informa de instancias filtradas cuando termina el programa.
Desafío
FácilUna cartera informa de cada cambio mediante señales que incluyen los números. En Wallet, añade los parámetros a ambas señales y escribe los dos métodos:
balance_changed(old_balance: int, new_balance: int)ypurchase_failed(price: int, missing: int)add(amount)añade monedas y emitebalance_changedcon el saldo anterior y el posterior.buy(price): cuando el saldo es suficiente, resta el precio y emitebalance_changed. De lo contrario, no cambia nada y emitepurchase_failedcon el precio y la cantidad de monedas que faltan.
El código proporcionado conecta una función a cada señal, lee cuántos comandos siguen, ejecuta cada comando (add 20, buy 15) e imprime las monedas restantes al final. Para add 20, buy 15, buy 10, add 5, buy 10, imprime:
Balance: 0 -> 20
Balance: 20 -> 5
Cannot buy for 10: 5 coins missing
Balance: 5 -> 10
Balance: 10 -> 0
Coins left: 0Tu código va en wallet.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 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])
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
1Fundamentos de la programación orientada a objetos
Archivos externosIntroducción a la programación orientada a objetosClases vs. objetosLa palabra clave selfMétodosPropiedadesConstructor (_init)Repaso: calculadora sencilla4Polimorfismo
Repaso de la sobrescritura de métodosTipado patoClases y métodos abstractosDiseño de interfacesRepaso: calculadora de formas7Señales
¿Qué es una señal?Declarar y emitirConectarse a las señalesSeñales con argumentosRepaso: sistema de salud10Patrones de diseño, parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón Composite2Propiedades de clase
Variables de instancia y estáticasFunciones estáticasMétodos setter de propiedadesMétodos getter de propiedadesPrivado por convenciónRepaso: administrador de cuentas bancarias5Encapsulación
Miembros públicos y privadosValidación con settersOcultación de informaciónPropiedades de solo lecturaRepaso: sistema de registros de estudiantes8Conceptos avanzados de POO
Composición frente a herenciaClases internasNodos como componentesRefCounted frente a NodeEnums en clases3Herencia
Herencia básicaLa palabra clave superSobrescritura de métodosCadenas de herenciaComprobaciones de tipo con isRepaso: jerarquía de empleados6Métodos especiales
Introducción a los métodos virtualesEl método _to_stringIteradores personalizadosRepaso: lista personalizada9Patrones de diseño, parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón StrategyPractica por tu cuenta: Compilador de GDScript online