Skip to main content

Command Palette

Search for a command to run...

Tutorial: Uso de Señales en Godot 4

Published
2 min read
Tutorial: Uso de Señales en Godot 4
J

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 Label ScoreLabel)

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:

  • Player con una Sword (Area2D)

  • Enemy (CharacterBody2D con script enemy.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 vida HealthBar)

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 luego emit(parametros).

  • Conectar señal: nodo.signal.connect(función_receptora).

  • Beneficio: Se evita acoplar directamente Player ↔ HUD, Enemy ↔ Player, etc.