improvements
This commit is contained in:
35
scripts/base_character.gd
Normal file
35
scripts/base_character.gd
Normal file
@@ -0,0 +1,35 @@
|
||||
extends Node2D
|
||||
|
||||
# Base character class that can display dialogue
|
||||
# This extends Node2D to be compatible with Godot's scene system
|
||||
|
||||
# Reference to the dialogue system
|
||||
var dialogue_system: Node = null
|
||||
|
||||
# Signals
|
||||
signal dialogue_started()
|
||||
signal dialogue_completed()
|
||||
|
||||
func _ready():
|
||||
# Find and setup dialogue system
|
||||
dialogue_system = get_node_or_null("DialogueSystem")
|
||||
if dialogue_system:
|
||||
dialogue_system.connect("dialogue_started", self._on_dialogue_started)
|
||||
dialogue_system.connect("dialogue_completed", self._on_dialogue_completed)
|
||||
else:
|
||||
print("Warning: No dialogue system found on character")
|
||||
|
||||
func trigger_dialogue(text: String, duration: float = 3.0) -> void:
|
||||
"""Public method to trigger dialogue on this character"""
|
||||
if dialogue_system:
|
||||
dialogue_system.trigger_dialogue(text, duration)
|
||||
else:
|
||||
print("Warning: No dialogue system found on character")
|
||||
|
||||
func _on_dialogue_started():
|
||||
"""Handle dialogue start signal"""
|
||||
emit_signal("dialogue_started")
|
||||
|
||||
func _on_dialogue_completed():
|
||||
"""Handle dialogue completion signal"""
|
||||
emit_signal("dialogue_completed")
|
||||
176
scripts/dialogue_system.gd
Normal file
176
scripts/dialogue_system.gd
Normal file
@@ -0,0 +1,176 @@
|
||||
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
|
||||
var dialogue_box: Control = null
|
||||
var text_label: Label = null
|
||||
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
|
||||
_create_dialogue_ui()
|
||||
|
||||
func _create_dialogue_ui():
|
||||
# Create dialogue box UI
|
||||
dialogue_box = Control.new()
|
||||
dialogue_box.name = "DialogueBox"
|
||||
|
||||
# Create background
|
||||
var background = ColorRect.new()
|
||||
background.name = "Background"
|
||||
background.color = Color(1, 1, 1, 1) # White background
|
||||
background.size = Vector2(300, 80)
|
||||
background.anchor_left = 0.5
|
||||
background.anchor_top = 1.0
|
||||
background.anchor_right = 0.5
|
||||
background.anchor_bottom = 1.0
|
||||
background.position = Vector2(-150, -40) # Positioned above character
|
||||
background.pivot_offset = Vector2(150, 40) # Center pivot
|
||||
|
||||
# Create text label
|
||||
text_label = Label.new()
|
||||
text_label.name = "TextLabel"
|
||||
text_label.text = ""
|
||||
text_label.size = Vector2(280, 60)
|
||||
text_label.anchor_left = 0.5
|
||||
text_label.add_theme_color_override("font_color", Color.BLACK)
|
||||
text_label.anchor_top = 0.5
|
||||
text_label.anchor_right = 0.5
|
||||
text_label.anchor_bottom = 0.5
|
||||
text_label.position = Vector2(-140, -30) # Centered in background
|
||||
text_label.pivot_offset = Vector2(140, 30) # Center pivot
|
||||
text_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_LEFT
|
||||
text_label.vertical_alignment = VERTICAL_ALIGNMENT_TOP
|
||||
text_label.autowrap_mode = 2 # TextServer.AUTOWRAP_WORD_SMART
|
||||
#text_label.custom_styles.normal.font_size = 16
|
||||
|
||||
# Add to dialogue box
|
||||
dialogue_box.add_child(background)
|
||||
dialogue_box.add_child(text_label)
|
||||
|
||||
# Set initial state - hidden and transparent
|
||||
dialogue_box.visible = false
|
||||
dialogue_box.modulate.a = 0.0
|
||||
|
||||
# Add to scene tree (should be added to parent character)
|
||||
add_child(dialogue_box)
|
||||
|
||||
# Position the dialogue box above the character
|
||||
# This ensures it's positioned correctly relative to the character
|
||||
if get_parent() != null:
|
||||
var parent_pos = get_parent().position
|
||||
dialogue_box.position = Vector2(parent_pos.x, parent_pos.y - 50) # Position above character
|
||||
|
||||
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)
|
||||
reveal_next_character()
|
||||
|
||||
func _on_dialogue_timeout():
|
||||
"""Handle dialogue timeout"""
|
||||
if is_showing and not is_revealing:
|
||||
hide_dialogue_box()
|
||||
10
scripts/test_dialogue.gd
Normal file
10
scripts/test_dialogue.gd
Normal file
@@ -0,0 +1,10 @@
|
||||
extends Node2D
|
||||
|
||||
func _ready():
|
||||
# Find the character and trigger dialogue after a short delay
|
||||
var character = $Character/BaseCharacter
|
||||
print("HELLO AND HERE")
|
||||
if character:
|
||||
# Wait a bit to let the scene load properly, then trigger dialogue
|
||||
await get_tree().create_timer(1.0).timeout
|
||||
character.trigger_dialogue("Hello! This is a test dialogue line that will reveal character by character.", 5.0)
|
||||
Reference in New Issue
Block a user