Tutorial: Uso de Señales en Godot 4

I software engineer. Developer Python. I read books. I watch movies. I writer fiction. I am a black cat. And You?
1. Player recoge monedas → HUD suma puntaje
Escena:
Player(CharacterBody2D)Coin(Area2D con CollisionShape2D)HUD(Control con LabelScoreLabel)
Código de la moneda (coin.gd)
extends Area2D
signal coin_collected(points: int)
@export var points: int = 10
func _on_body_entered(body: Node) -> void:
if body.is_in_group("player"):
coin_collected.emit(points)
queue_free() # destruye la moneda
Código en el HUD (hud.gd)
extends Control
var score: int = 0
@onready var score_label: Label = $ScoreLabel
func add_points(points: int) -> void:
score += points
score_label.text = str(score)
Conexión de la señal (en Player o LevelManager)
func _ready():
for coin in get_tree().get_nodes_in_group("coins"):
coin.coin_collected.connect($HUD.add_points)
2. Player ataca → enemigo recibe daño
Escena:
Playercon unaSword(Area2D)Enemy(CharacterBody2D con scriptenemy.gd)
Código en la espada (sword.gd)
extends Area2D
signal hit_enemy(damage: int)
@export var damage: int = 25
func _on_body_entered(body: Node) -> void:
if body.is_in_group("enemy"):
hit_enemy.emit(damage)
Código en el enemigo (enemy.gd)
extends CharacterBody2D
var health: int = 100
func take_damage(amount: int) -> void:
health -= amount
print("Enemy HP:", health)
if health <= 0:
queue_free() # enemigo muere
Conexión
func _ready():
$Player/Sword.hit_enemy.connect($Enemy.take_damage)
3. Player recibe daño → HUD actualiza vida
Escena:
Player(CharacterBody2D con vida)EnemyAttack(Area2D)HUD(Control con barra de vidaHealthBar)
Código del player (player.gd)
extends CharacterBody2D
signal health_changed(new_health: int)
var max_health: int = 100
var health: int = 100
func take_damage(amount: int) -> void:
health -= amount
health = max(health, 0)
health_changed.emit(health)
if health <= 0:
print("Game Over")
Código del HUD (hud.gd)
extends Control
@onready var health_bar: ProgressBar = $HealthBar
func update_health(value: int) -> void:
health_bar.value = value
Conexión
func _ready():
$Player.health_changed.connect($HUD.update_health)
Código del ataque enemigo (enemy_attack.gd)
extends Area2D
@export var damage: int = 20
func _on_body_entered(body: Node) -> void:
if body.is_in_group("player"):
body.take_damage(damage)
4. Player cruza puerta → cambiar de escena
Escena:
Door(Area2D con CollisionShape2D)Player
Código en la puerta (door.gd)
extends Area2D
signal player_entered
@export var next_scene: String = "res://scenes/room2.tscn"
func _on_body_entered(body: Node) -> void:
if body.is_in_group("player"):
player_entered.emit()
Conexión para cambiar escena (ejemplo en LevelManager.gd)
extends Node
func _ready():
$Door.player_entered.connect(change_scene)
func change_scene():
var new_scene = load($Door.next_scene)
get_tree().change_scene_to_packed(new_scene)
Conclusiones
Emitir señal:
signal nombre(parametros)y luegoemit(parametros).Conectar señal:
nodo.signal.connect(función_receptora).Beneficio: Se evita acoplar directamente Player ↔ HUD, Enemy ↔ Player, etc.


