Files
experiment-adventure-ai/scripts/dialogue_system.gd
2025-08-01 21:41:59 -07:00

127 lines
3.2 KiB
GDScript

extends Node2D
# Dialogue system for Godot 4.x
# Handles displaying dialogue with animations and text reveal
# Signals
signal dialogue_started()
signal dialogue_completed()
# Configuration
@export var text_reveal_speed: float = 0.05 # seconds per character
@export var show_animation_duration: float = 0.3 # seconds
@export var hide_animation_duration: float = 0.2 # seconds
# Private variables
@onready var dialogue_box = $PanelContainer
@onready var text_label: Label = $PanelContainer/Label
var timer: Timer = null
var current_text: String = ""
var current_duration: float = 0.0
var text_index: int = 0
var is_showing: bool = false
var is_revealing: bool = false
func _ready():
# Initialize the dialogue system
pass
func trigger_dialogue(text: String, duration: float = 3.0) -> void:
"""Trigger dialogue with specified text and duration"""
if is_showing:
return
current_text = text
current_duration = duration
text_index = 0
is_showing = true
is_revealing = false
# Show the dialogue box with animation
show_dialogue_box()
# Start revealing text after a short delay to allow animation to complete
await get_tree().create_timer(show_animation_duration)
# Start revealing text immediately
start_text_reveal()
func show_dialogue_box():
"""Show dialogue box with animation"""
dialogue_box.visible = true
# Animate in using Tween
var tween = create_tween()
tween.set_ease(Tween.EASE_OUT)
tween.set_trans(Tween.TRANS_SINE)
tween.tween_property(dialogue_box, "modulate:a", 1.0, show_animation_duration)
# Emit signal when animation completes
await tween.finished
emit_signal("dialogue_started")
func hide_dialogue_box():
"""Hide dialogue box with animation"""
# Animate out using Tween
var tween = create_tween()
tween.set_ease(Tween.EASE_IN)
tween.set_trans(Tween.TRANS_SINE)
tween.tween_property(dialogue_box, "modulate:a", 0.0, hide_animation_duration)
# Wait for animation to complete
await tween.finished
dialogue_box.visible = false
is_showing = false
is_revealing = false
emit_signal("dialogue_completed")
func start_text_reveal():
"""Start revealing text character by character"""
if is_revealing:
return
is_revealing = true
text_label.text = ""
text_index = 0
# If duration is 0 or negative, don't auto-hide
if current_duration <= 0:
# Just reveal all text immediately
text_label.text = current_text
is_revealing = false
return
# Start timer for automatic hiding
timer = Timer.new()
timer.wait_time = current_duration
timer.one_shot = true
timer.connect("timeout", self._on_dialogue_timeout)
add_child(timer)
timer.start()
# Start the character-by-character reveal
reveal_next_character()
func reveal_next_character():
"""Reveal the next character in the text"""
if text_index >= current_text.length():
# Finished revealing all characters
is_revealing = false
return
# Add the next character to the text label
text_label.text += current_text[text_index]
text_index += 1
# Schedule next character reveal
await get_tree().create_timer(text_reveal_speed).timeout
reveal_next_character()
func _on_dialogue_timeout():
"""Handle dialogue timeout"""
if is_showing and not is_revealing:
hide_dialogue_box()