improvements

This commit is contained in:
2025-08-01 20:07:40 -07:00
parent cfb4aa874b
commit 5cde8be9a7
9 changed files with 581 additions and 0 deletions

View File

@@ -0,0 +1,149 @@
# Acceptance Criteria: Base Character with Dialogue System
## Overview
This document defines the acceptance criteria for implementing a base character scene with dialogue functionality in Godot. The implementation should allow characters to have dialogue lines that can be triggered programmatically.
## Requirements
### 1. Base Character Scene
- **Feature**: Create a base character scene with Polygon2D sprite
- **Acceptance Criteria**:
- Scene file `scenes/base_character.tscn` exists
- Contains a Polygon2D node as the character sprite
- Character has appropriate positioning and scaling
- Scene can be instantiated in other scenes
- Scene includes necessary child nodes for dialogue system integration
### 2. Dialogue Entity
- **Feature**: Implement dialogue entity that can be triggered programmatically
- **Acceptance Criteria**:
- Dialogue entity can be attached to any character node
- Can be triggered via a public method call
- Accepts text content and duration parameters
- Supports programmatic triggering without user input
### 3. Visual Dialogue Box
- **Feature**: White dialogue box that animates in when triggered
- **Acceptance Criteria**:
- Dialogue box appears above character when triggered
- Animates in with smooth transition (fade/slide)
- Has white background with appropriate styling
- Properly positioned relative to character
- Resizes based on text content
### 4. Text Reveal Animation
- **Feature**: Text revealed one character at a time
- **Acceptance Criteria**:
- Text appears character-by-character with delay
- Each character reveal has consistent timing
- Text is properly formatted and readable
- Animation can be configured with different speeds
### 5. Duration Handling
- **Feature**: Dialogue box closes after specified duration
- **Acceptance Criteria**:
- Dialogue automatically closes after duration ends
- Smooth animation out when closing
- Duration parameter is configurable
- Can handle zero or negative durations appropriately
### 6. API Interface
- **Feature**: Clean public API for dialogue interaction
- **Acceptance Criteria**:
- Public method to trigger dialogue: `trigger_dialogue(text, duration)`
- Method returns immediately after triggering
- No blocking operations during animation
- Proper error handling for invalid parameters
### 7. Test Scene
- **Feature**: Single character automatically triggering a single dialogue line
- **Acceptance Criteria**:
- Test scene file `scenes/test_dialogue.tscn` exists
- Contains one base character instance
- Dialogue is automatically triggered on scene load
- Demonstrates complete functionality (show, reveal, hide)
- Scene runs without errors
## Technical Specifications
### File Structure
```
scenes/
├── base_character.tscn
└── test_dialogue.tscn
scripts/
├── dialogue_system.gd
└── base_character.gd
```
### Dialogue System Components
1. **DialogueBox**: Visual UI element for displaying dialogue
2. **TextRevealer**: Handles character-by-character text animation
3. **AnimationController**: Manages show/hide animations
4. **CharacterDialog**: Interface for character-to-dialogue communication
### API Methods
```gdscript
# In base_character.gd or similar
func trigger_dialogue(text: String, duration: float) -> void:
# Triggers dialogue with specified text and duration
# In dialogue_system.gd
func show_dialogue(text: String, duration: float) -> void:
# Internal method to display dialogue UI
```
### Animation Requirements
- **Show Animation**: 0.3 second fade/slide in
- **Text Reveal**: 0.05 second per character
- **Hide Animation**: 0.2 second fade out
- **Duration**: Default 3 seconds if not specified
## Success Metrics
### Functional Tests
1. [ ] Base character scene loads without errors
2. [ ] Dialogue box appears when `trigger_dialogue()` is called
3. [ ] Text reveals character-by-character with correct timing
4. [ ] Dialogue box closes automatically after duration
5. [ ] Test scene demonstrates complete workflow
6. [ ] API methods can be called from other scripts
### Performance Tests
1. [ ] No frame drops during animation sequences
2. [ ] Memory usage remains stable
3. [ ] Animation timing is consistent across different hardware
### Compatibility Tests
1. [ ] Works with existing Godot 4.x projects
2. [ ] Compatible with different character positioning
3. [ ] Handles various text lengths appropriately
4. [ ] Works with different duration values
## Non-Functional Requirements
### Code Quality
- [ ] Well-documented code with comments
- [ ] Clean, maintainable code structure
- [ ] Follows Godot coding conventions
- [ ] Proper error handling and validation
### User Experience
- [ ] Smooth animations without jank
- [ ] Clear visual feedback during dialogue
- [ ] Responsive interface
- [ ] Accessible text formatting
## Dependencies
- Godot 4.x engine
- Standard Godot 2D node types (Node2D, Control, Label)
- AnimationPlayer or Tween for UI animations
- Timer for duration handling
## Acceptance Process
1. Review code implementation against these criteria
2. Run test scene to verify functionality
3. Confirm all acceptance tests pass
4. Validate API usability and documentation
5. Ensure no breaking changes to existing systems

View File

@@ -0,0 +1,93 @@
# Dialogue System Architecture
```mermaid
graph TD
A[Base Character Scene] --> B(DialogueSystem)
B --> C(DialogueBox UI)
B --> D(TextRevealer)
B --> E(AnimationController)
B --> F(Timer)
C --> G[Visual Display]
D --> H[Character-by-Character Reveal]
E --> I[Show/Hide Animations]
F --> J[Duration Management]
subgraph "Dialogue Flow"
B --> K{Trigger Dialogue}
K -->|Text + Duration| L[Show Dialogue Box]
L --> M[Start Text Reveal]
M --> N[Wait for Duration]
N --> O[Hide Dialogue Box]
end
subgraph "Components"
C --> C1[White Background]
C --> C2[Positioning]
D --> D1[Character Timing]
D --> D2[Text Display]
E --> E1[Animation Playback]
F --> F1[Timer Management]
end
style A fill:#e1f5fe
style B fill:#f3e5f5
style C fill:#e8f5e9
style D fill:#fff3e0
style E fill:#fce4ec
style F fill:#f1f8e9
```
## Component Descriptions
### Base Character Scene (A)
- Contains the character sprite (Polygon2D)
- Acts as the entry point for dialogue triggering
- Manages the dialogue system interface
### DialogueSystem (B) - Main Controller
- Coordinates all dialogue functionality
- Interfaces with UI components
- Handles timing and state management
- Provides public API for triggering dialogue
### DialogueBox UI (C)
- Visual representation of dialogue
- White background container
- Proper positioning relative to character
- Handles visibility states
### TextRevealer (D)
- Manages character-by-character text display
- Controls reveal timing
- Updates text label content incrementally
- Handles text formatting and wrapping
### AnimationController (E)
- Manages show/hide animations
- Controls timing of UI transitions
- Ensures smooth visual experience
- Handles animation cleanup
### Timer (F)
- Manages dialogue duration
- Triggers automatic closure
- Provides timing feedback to system
- Handles edge cases (zero/negative durations)
## Flow Description
1. **Trigger**: Base character calls `trigger_dialogue(text, duration)`
2. **Show**: DialogueSystem initiates show animation for DialogueBox
3. **Reveal**: TextRevealer starts character-by-character text display
4. **Wait**: Timer waits for specified duration
5. **Hide**: AnimationController triggers hide animation
6. **Complete**: System returns to idle state
## Integration Points
- Base Character Scene: Public API interface
- DialogueBox UI: Visual rendering component
- TextRevealer: Text animation logic
- AnimationController: UI transition handling
- Timer: Duration management

3
main.tscn Normal file
View File

@@ -0,0 +1,3 @@
[gd_scene format=3 uid="uid://dihuaoy6htse6"]
[node name="Node2D" type="Node2D"]

View File

@@ -0,0 +1,82 @@
# Base Character Scene with Dialogue System Design Plan
## Overview
Create a base character scene with:
1. A sprite/shape (using Polygon2D for now)
2. A dialogue entity that can be triggered programmatically
3. Visual dialogue box with animation and character-by-character text reveal
4. Test scene to demonstrate the behavior
## Implementation Steps
### 1. Base Character Scene Design
- Create a new scene file `scenes/base_character.tscn`
- Add a Polygon2D node as the character sprite
- Add necessary child nodes for dialogue system integration
- Set up proper positioning and scaling
### 2. Dialogue UI System
- Create dialogue box UI with:
- Background rectangle (white)
- Text display area
- Animation for showing/hiding
- Implement character-by-character text reveal
- Handle timing and duration logic
### 3. Dialogue Action Integration
- Extend or modify DialogueAction to use new UI system
- Ensure compatibility with existing cutscene manager
- Add proper signal handling for animation completion
### 4. Test Scene
- Create test scene `scenes/test_dialogue.tscn`
- Add base character instance
- Automatically trigger dialogue on scene load
- Demonstrate the complete functionality
## Technical Details
### Base Character Scene Structure
```
Node2D (root)
├── Polygon2D (character sprite)
└── DialogueSystem (script for handling dialogue UI)
```
### Dialogue System Components
1. **DialogueBox**: Visual element that appears when dialogue is triggered
2. **TextRevealer**: Handles character-by-character text display
3. **AnimationController**: Manages show/hide animations
4. **Timer**: Controls duration of dialogue display
### DialogueAction Integration Points
- `start()` method should trigger UI display
- Text and duration parameters should be passed to UI system
- Completion signal should be properly emitted
## File Structure
```
scenes/
├── base_character.tscn
└── test_dialogue.tscn
scripts/
├── dialogue_system.gd
└── base_character.gd
cutscene/
└── actions/
└── DialogueAction.gd (modified)
```
## Implementation Approach
1. First, create the base character scene with Polygon2D
2. Implement the dialogue UI system in a separate script
3. Modify DialogueAction to integrate with new UI system
4. Create test scene that demonstrates functionality
5. Ensure all components work together within existing cutscene framework
## Animation Requirements
- Dialogue box should animate in (fade/slide)
- Text should reveal character-by-character with delay
- Dialogue box should animate out after duration ends

View File

@@ -0,0 +1,10 @@
[gd_scene format=3 uid="uid://basecharacter"]
[node name="BaseCharacter" type="Node2D"]
[node name="Sprite" type="Polygon2D" parent="."]
color = Color(0.2, 0.6, 1, 1)
antialiased = true
polygon = PackedVector2Array(10, -20, 20, 0, 10, 20, -10, 20, -20, 0, -10, -20)
[node name="DialogueSystem" type="Node" parent="."]

23
scenes/test_dialogue.tscn Normal file
View File

@@ -0,0 +1,23 @@
[gd_scene load_steps=4 format=3 uid="uid://testdialogue"]
[ext_resource type="Script" path="res://scripts/test_dialogue.gd" id="1_f305o"]
[ext_resource type="Script" path="res://scripts/base_character.gd" id="2_00bif"]
[ext_resource type="Script" path="res://scripts/dialogue_system.gd" id="3_11ynk"]
[node name="TestScene" type="Node2D"]
position = Vector2(-1, 0)
script = ExtResource("1_f305o")
[node name="Character" type="Node2D" parent="."]
position = Vector2(407, 206)
[node name="BaseCharacter" type="Node2D" parent="Character"]
script = ExtResource("2_00bif")
[node name="Sprite" type="Polygon2D" parent="Character/BaseCharacter"]
color = Color(0.2, 0.6, 1, 1)
antialiased = true
polygon = PackedVector2Array(10, -20, 20, 0, 10, 20, -10, 20, -20, 0, -10, -20)
[node name="DialogueSystem" type="Node2D" parent="Character/BaseCharacter"]
script = ExtResource("3_11ynk")

35
scripts/base_character.gd Normal file
View 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
View 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
View 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)