Menu
CoddyTech

Signaux avec arguments

Fait partie de la section Programmation orientée objet du Journey GDScript de Coddy. Leçon 38 sur 65.

Un signal peut transporter des valeurs. Indique-les dans la déclaration, comme les paramètres d’une fonction :

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

Transmets les valeurs à emit() dans le même ordre :

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

Une fonction connectée reçoit les valeurs en tant que paramètres. Elle a donc besoin d’un paramètre par valeur :

hero.damaged.connect(_on_hero_damaged)

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

Les types dans la déclaration documentent les valeurs : GDScript ne les vérifie pas lors de l’émission. Une incompatibilité apparaît dans la fonction réceptrice. Une fonction qui n’a pas le bon nombre de paramètres, ou un paramètre typé qui ne peut pas contenir la valeur, provoque une erreur à la ligne emit(), et cette fonction ne s’exécute pas.

bind() ajoute vos propres valeurs après celles émises. Une méthode peut alors écouter plusieurs héros tout en sachant lequel a été touché :

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

Les arguments fournissent à un écouteur les données dont il a besoin, afin qu’il n’ait pas à les lire depuis l’émetteur. Ne connectez jamais une lambda qui utilise l’objet émetteur lui-même, comme hero.died.connect(func(): print(hero.hp)) : la lambda maintient hero en vie, hero maintient la lambda, aucun des deux n’est jamais libéré, et Godot signale des instances ayant fui lorsque le programme se termine.

challenge icon

Défi

Facile

Un portefeuille signale chaque changement au moyen de signaux qui transportent les nombres. Dans Wallet, ajoute les paramètres aux deux signaux et écris les deux méthodes :

  • balance_changed(old_balance: int, new_balance: int) et purchase_failed(price: int, missing: int)
  • add(amount) ajoute des pièces et émet balance_changed avec le solde avant et après.
  • buy(price) : lorsque le solde est suffisant, soustrais le prix et émets balance_changed. Sinon, ne change rien et émets purchase_failed avec le prix et le nombre de pièces manquantes.

Le code fourni connecte une fonction à chaque signal, lit le nombre de commandes à suivre, exécute chaque commande (add 20, buy 15) et affiche les pièces restantes à la fin. Pour add 20, buy 15, buy 10, add 5, buy 10, il affiche :

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

Ton code va dans wallet.gd. main.gd contient le code d’entrée/sortie fourni et ne peut pas être modifié.

Essayez vous-même

extends Node

func _ready():
	# Code d'entrée/sortie fourni : conservez-le tel quel
	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 iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation orientée objet

Entraînez-vous par vous-même : Compilateur GDScript en ligne