progress
This commit is contained in:
@@ -76,25 +76,6 @@ func add_action(action: Action) -> void:
|
||||
|
||||
sequential_actions.append(action)
|
||||
|
||||
func add_parallel_actions(actions: Array) -> void:
|
||||
# Add a group of actions to run in parallel
|
||||
if state != State.IDLE:
|
||||
print("Warning: Cannot add actions while cutscene is running")
|
||||
return
|
||||
|
||||
if actions.size() == 0:
|
||||
return
|
||||
|
||||
# Create a parallel action group
|
||||
var group = {
|
||||
"actions": actions,
|
||||
"completed_count": 0,
|
||||
"total_count": actions.size()
|
||||
}
|
||||
|
||||
# Add to sequential actions as a single item
|
||||
sequential_actions.append(group)
|
||||
|
||||
# Internal methods
|
||||
func _process(delta: float) -> void:
|
||||
# Main update loop
|
||||
@@ -120,7 +101,7 @@ func _execute_next_action() -> void:
|
||||
|
||||
var action_item = sequential_actions[action_index]
|
||||
action_index += 1
|
||||
|
||||
print(action_item)
|
||||
# Check if this is a parallel group or single action
|
||||
if typeof(action_item) == TYPE_DICTIONARY and action_item.has("actions"):
|
||||
# This is a parallel group
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Cutscene System for Godot 4.3
|
||||
|
||||
## Overview
|
||||
This is a flexible cutscene system for 2D point-and-click adventure games in Godot 4.3. It supports both sequential and parallel action execution, with a focus on extensibility and dynamic behavior.
|
||||
This is a flexible cutscene system for 2D point-and-click adventure games in Godot 4.3. It supports both sequential and parallel action execution, with a focus on extensibility and dynamic behavior. The system can be used directly with code or with the visual Cutscene Editor plugin that manages cutscene resources.
|
||||
|
||||
## Features
|
||||
- Sequential action execution
|
||||
@@ -9,6 +9,7 @@ This is a flexible cutscene system for 2D point-and-click adventure games in God
|
||||
- Extensible action system
|
||||
- Signal-based completion system
|
||||
- Error handling and recovery
|
||||
- Resource-based cutscene management (with Cutscene Editor plugin)
|
||||
|
||||
## System Components
|
||||
|
||||
@@ -25,7 +26,7 @@ This is a flexible cutscene system for 2D point-and-click adventure games in God
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Setup
|
||||
### Basic Setup (Code-based)
|
||||
```gdscript
|
||||
# Create a cutscene manager
|
||||
var cutscene_manager = CutsceneManager.new()
|
||||
@@ -39,7 +40,7 @@ cutscene_manager.add_action(DialogueAction.new(character, "Hello, world!"))
|
||||
cutscene_manager.start()
|
||||
```
|
||||
|
||||
### Parallel Actions
|
||||
### Parallel Actions (Code-based)
|
||||
```gdscript
|
||||
# Create parallel actions
|
||||
var parallel_actions = [
|
||||
@@ -49,6 +50,20 @@ var parallel_actions = [
|
||||
cutscene_manager.add_parallel_actions(parallel_actions)
|
||||
```
|
||||
|
||||
### Resource-based Setup (With Cutscene Editor)
|
||||
```gdscript
|
||||
# Load a cutscene resource created with the visual editor
|
||||
var cutscene_resource = preload("res://path/to/your/cutscene.tscn")
|
||||
|
||||
# Generate actions from the resource
|
||||
var generator = CutsceneGenerator.new()
|
||||
var cutscene_manager = generator.generate_cutscene(cutscene_resource)
|
||||
|
||||
# Add to scene and start
|
||||
add_child(cutscene_manager)
|
||||
cutscene_manager.start()
|
||||
```
|
||||
|
||||
### The Example Scenario
|
||||
The system supports complex sequences like the one described in the requirements:
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ func _init(character_node: Node2D, target: Vector2, move_speed: float = 100.0) -
|
||||
name = "MoveAction"
|
||||
|
||||
func start() -> void:
|
||||
print("started", character)
|
||||
if character == null:
|
||||
self._set_failed("Character is null")
|
||||
return
|
||||
@@ -29,6 +30,7 @@ func start() -> void:
|
||||
self._set_running()
|
||||
|
||||
func update(delta: float) -> void:
|
||||
print ("updating")
|
||||
if state != State.RUNNING:
|
||||
return
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
[gd_scene format=3 uid="uid://animatedcharacter"]
|
||||
|
||||
[ext_resource type="Script" path="res://cutscene/examples/animated_character.gd" id="1"]
|
||||
|
||||
[node name="AnimatedCharacter" type="Node2D"]
|
||||
script = ExtResource( "1" )
|
||||
|
||||
[node name="Sprite2D" type="Sprite2D" parent="."]
|
||||
|
||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
||||
@@ -1,80 +0,0 @@
|
||||
extends Node2D
|
||||
|
||||
# Character nodes
|
||||
@onready var character1: Node2D = $Character1
|
||||
@onready var character2: Node2D = $Character2
|
||||
|
||||
# Cutscene manager
|
||||
var cutscene_manager: CutsceneManager
|
||||
|
||||
func _ready() -> void:
|
||||
# Initialize the cutscene system
|
||||
setup_cutscene()
|
||||
|
||||
# Start the cutscene after a short delay to see the initial positions
|
||||
var start_timer = Timer.new()
|
||||
start_timer.wait_time = 1.0
|
||||
start_timer.one_shot = true
|
||||
start_timer.connect("timeout", start_cutscene)
|
||||
add_child(start_timer)
|
||||
start_timer.start()
|
||||
|
||||
func setup_cutscene() -> void:
|
||||
# Create the cutscene manager
|
||||
cutscene_manager = CutsceneManager.new()
|
||||
add_child(cutscene_manager)
|
||||
|
||||
# Connect to cutscene signals
|
||||
cutscene_manager.connect("cutscene_started", _on_cutscene_started)
|
||||
cutscene_manager.connect("cutscene_completed", _on_cutscene_completed)
|
||||
cutscene_manager.connect("action_started", _on_action_started)
|
||||
cutscene_manager.connect("action_completed", _on_action_completed)
|
||||
|
||||
# Create the action sequence as described in requirements
|
||||
|
||||
# 1. & 2. Characters move simultaneously
|
||||
var parallel_moves = [
|
||||
MoveAction.new(character1, Vector2(234, 591), 100.0), # Character1 moves
|
||||
MoveAction.new(character2, Vector2(912, 235), 100.0) # Character2 moves
|
||||
]
|
||||
cutscene_manager.add_parallel_actions(parallel_moves)
|
||||
|
||||
# 3. Character2 turns to face Character1
|
||||
var turn_action = TurnAction.new(character2, character1, 1.0)
|
||||
cutscene_manager.add_action(turn_action)
|
||||
|
||||
# 4. Character2 says dialogue
|
||||
var dialogue_action = DialogueAction.new(character2, "Hello there, friend!", 2.0)
|
||||
cutscene_manager.add_action(dialogue_action)
|
||||
|
||||
# 5. Character1 plays shocked animation (simulated with a wait since we don't have an actual animation)
|
||||
var animation_action = WaitAction.new(1.0) # Simulate animation with wait
|
||||
cutscene_manager.add_action(animation_action)
|
||||
|
||||
# Add a final dialogue from character1
|
||||
var final_dialogue = DialogueAction.new(character1, "That was surprising!", 2.0)
|
||||
cutscene_manager.add_action(final_dialogue)
|
||||
|
||||
func start_cutscene() -> void:
|
||||
print("Starting cutscene...")
|
||||
cutscene_manager.start()
|
||||
|
||||
func _on_cutscene_started() -> void:
|
||||
print("Cutscene started!")
|
||||
|
||||
func _on_cutscene_completed() -> void:
|
||||
print("Cutscene completed!")
|
||||
print("Final positions:")
|
||||
print("Character1: %s" % character1.position)
|
||||
print("Character2: %s" % character2.position)
|
||||
|
||||
func _on_action_started(action: Action) -> void:
|
||||
print("Action started: %s" % action.name)
|
||||
|
||||
func _on_action_completed(action: Action) -> void:
|
||||
print("Action completed: %s" % action.name)
|
||||
|
||||
# Clean up when the node is removed
|
||||
func _exit_tree() -> void:
|
||||
if cutscene_manager:
|
||||
cutscene_manager.queue_free()
|
||||
@@ -1,16 +0,0 @@
|
||||
[gd_resource type="VisualShader" load_steps=2 format=3 uid="uid://bqjt0um0vbxs7"]
|
||||
|
||||
[sub_resource type="VisualShaderNodeDerivativeFunc" id="VisualShaderNodeDerivativeFunc_n7wl4"]
|
||||
|
||||
[resource]
|
||||
code = "shader_type canvas_item;
|
||||
render_mode blend_mix;
|
||||
|
||||
|
||||
|
||||
"
|
||||
mode = 1
|
||||
flags/light_only = false
|
||||
nodes/fragment/0/position = Vector2(700, 140)
|
||||
nodes/fragment/2/node = SubResource("VisualShaderNodeDerivativeFunc_n7wl4")
|
||||
nodes/fragment/2/position = Vector2(196, 138)
|
||||
@@ -1,18 +0,0 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://bx826fm1kd3wk"]
|
||||
|
||||
[ext_resource type="Script" path="res://cutscene/examples/sample_cutscene.gd" id="1"]
|
||||
|
||||
[node name="SampleCutscene" type="Node2D"]
|
||||
script = ExtResource("1")
|
||||
|
||||
[node name="Character1" type="Node2D" parent="."]
|
||||
position = Vector2(100, 100)
|
||||
|
||||
[node name="Polygon2D" type="Polygon2D" parent="Character1"]
|
||||
polygon = PackedVector2Array(-5, -19, -27, 2, 2, 15, 15, 6, 9, -19)
|
||||
|
||||
[node name="Character2" type="Node2D" parent="."]
|
||||
position = Vector2(200, 100)
|
||||
|
||||
[node name="Polygon2D" type="Polygon2D" parent="Character2"]
|
||||
polygon = PackedVector2Array(10, -25, -43, 1, -14, 40, 48, 13)
|
||||
@@ -1,95 +0,0 @@
|
||||
extends Node2D
|
||||
|
||||
# Test the cutscene system
|
||||
func _ready() -> void:
|
||||
print("Testing cutscene system...")
|
||||
|
||||
# Create test characters
|
||||
var char1 = Node2D.new()
|
||||
char1.name = "TestCharacter1"
|
||||
add_child(char1)
|
||||
|
||||
var char2 = Node2D.new()
|
||||
char2.name = "TestCharacter2"
|
||||
add_child(char2)
|
||||
|
||||
# Create animation player for char1
|
||||
var anim_player = AnimationPlayer.new()
|
||||
anim_player.name = "AnimationPlayer"
|
||||
char1.add_child(anim_player)
|
||||
|
||||
# Create a simple animation
|
||||
var animation = Animation.new()
|
||||
animation.name = "test_animation"
|
||||
animation.length = 1.0
|
||||
anim_player.add_animation("test_animation", animation)
|
||||
|
||||
# Test the cutscene system
|
||||
test_sequential_actions(char1, char2)
|
||||
|
||||
# After a delay, test parallel actions
|
||||
var timer = Timer.new()
|
||||
timer.wait_time = 3.0
|
||||
timer.one_shot = true
|
||||
timer.connect("timeout", test_parallel_actions.bind(char1, char2))
|
||||
add_child(timer)
|
||||
timer.start()
|
||||
|
||||
func test_sequential_actions(char1: Node2D, char2: Node2D) -> void:
|
||||
print("\n=== Testing Sequential Actions ===")
|
||||
|
||||
# Create cutscene manager
|
||||
var manager = CutsceneManager.new()
|
||||
add_child(manager)
|
||||
|
||||
# Connect signals
|
||||
manager.connect("cutscene_completed", _on_test_completed.bind("sequential"))
|
||||
|
||||
# Add sequential actions
|
||||
manager.add_action(MoveAction.new(char1, Vector2(100, 100), 50.0))
|
||||
manager.add_action(WaitAction.new(0.5))
|
||||
manager.add_action(TurnAction.new(char1, Vector2(200, 200), 1.0))
|
||||
manager.add_action(DialogueAction.new(char1, "Hello, world!", 1.0))
|
||||
manager.add_action(AnimationAction.new(char1, "test_animation", false))
|
||||
|
||||
# Start the cutscene
|
||||
manager.start()
|
||||
|
||||
func test_parallel_actions(char1: Node2D, char2: Node2D) -> void:
|
||||
print("\n=== Testing Parallel Actions ===")
|
||||
|
||||
# Create cutscene manager
|
||||
var manager = CutsceneManager.new()
|
||||
add_child(manager)
|
||||
|
||||
# Connect signals
|
||||
manager.connect("cutscene_completed", _on_test_completed.bind("parallel"))
|
||||
|
||||
# Add parallel actions
|
||||
var parallel_group = [
|
||||
MoveAction.new(char1, Vector2(300, 300), 100.0),
|
||||
MoveAction.new(char2, Vector2(400, 400), 100.0)
|
||||
]
|
||||
manager.add_parallel_actions(parallel_group)
|
||||
|
||||
# Add sequential actions after parallel
|
||||
manager.add_action(TurnAction.new(char1, char2, 2.0))
|
||||
manager.add_action(DialogueAction.new(char1, "We moved together!", 1.5))
|
||||
|
||||
# Start the cutscene
|
||||
manager.start()
|
||||
|
||||
func _on_test_completed(test_type: String) -> void:
|
||||
print("Test %s completed successfully!" % test_type)
|
||||
|
||||
# Clean up after a delay
|
||||
var cleanup_timer = Timer.new()
|
||||
cleanup_timer.wait_time = 1.0
|
||||
cleanup_timer.one_shot = true
|
||||
cleanup_timer.connect("timeout", clean_up)
|
||||
add_child(cleanup_timer)
|
||||
cleanup_timer.start()
|
||||
|
||||
func clean_up() -> void:
|
||||
print("\n=== All tests completed ===")
|
||||
print("Cutscene system is working correctly!")
|
||||
Reference in New Issue
Block a user