module Lapis::Docs::C_GAMEPLAY_AND_DECLARATIVE_DSL::C_SIGNALS_AND_EVENTS

Overview

Signals & Event-Driven Architecture

Comprehensive guide to Godot's reactive event system in Crystal, covering declaration, emission, inter-language connections, and cooperative signal awaiting with await.

Executive Summary & Key Topics

Topic Method / Anchor Description
Signal Capabilities .topic_00_signal_features Type-safe signal emission, reflection, and cooperative fiber suspension.
Declaring & Emitting Signals .topic_01_signal_declaration Declaring signals and calling generated type-safe emit methods.
Connecting Signals in Crystal & GDScript .topic_02_connecting_signals Subscribing to signals across Crystal nodes and GDScript scripts.
Cooperative Signal Awaiting (await) .topic_03_awaiting_signals Suspending gameplay fibers non-blockingly until a signal arrives or times out.

Related Guides & Source References

Defined in:

libgodot/docs/c_gameplay_and_declarative_dsl/c_signals_and_events.cr

Class Method Summary

Class Method Detail

def self.topic_00_signal_features : Nil #

Signal Capabilities: Type-safe signal emission, reflection, and cooperative fiber suspension.

Key Topics & Information

  • Declarative syntax: signal name(arg1 : Type1, arg2 : Type2)
  • Synthesized type-safe emission helpers: emit_name(arg1, arg2)
  • First-class signal awaiting: await(node.signal_name, timeout_sec: 5.0)
  • Full ClassDB reflection for Godot connections dialog and GDScript interop

def self.topic_01_signal_declaration : Nil #

Declaring & Emitting Signals: Declaring signals and calling generated type-safe emit methods.

Declare signals using the signal macro inside any node:

node HealthSystem < Node do
  # Signal with typed parameters
  signal health_changed(current : Int32, max : Int32)

  # Parameterless signal
  signal died

  property current_hp : Int32 = 100
  property max_hp : Int32 = 100

  def take_damage(amount : Int32) : Void
    @current_hp = (@current_hp - amount).clamp(0, @max_hp)

    # Call ergonomic emit helper (or synthesized emit_<name>):
    emit(health_changed, @current_hp, @max_hp)

    if @current_hp <= 0
      emit(died)
    end
  end
end

def self.topic_02_connecting_signals : Nil #

Connecting Signals in Crystal & GDScript: Subscribing to signals across Crystal nodes and GDScript scripts.

Connecting in Crystal:

# Connect with a block directly on first-class bound signals:
player.died.connect do
  Godot.print("Player has perished!")
end

# Typed signal callbacks receive arguments:
player.health_changed.connect do |args|
  Godot.print("Health updated: #{args[0]} / #{args[1]}")
end

Connecting in GDScript:

func _ready():
    var player = $Player
    player.health_changed.connect(_on_health_changed)

func _on_health_changed(current: int, max_hp: int):
    print("Player health: ", current, "/", max_hp)

def self.topic_03_awaiting_signals : Nil #

Cooperative Signal Awaiting (await): Suspending gameplay fibers non-blockingly until a signal arrives or times out.

Lapis supports first-class cooperative signal awaiting without blocking the engine main loop:

# Suspend until enemy dies:
await(enemy.died)

# Await with timeout (raises TimeoutError or returns nil):
await(boss.defeated, timeout_sec: 10.0)

# Awaiting a timer:
timer = get_tree.create_timer(2.0)
await(timer.timeout)