Files
experiment-adventure-ai/sample_cutscene_example.md
2025-07-30 21:52:27 -07:00

7.7 KiB

Sample Cutscene Example

Overview

This document provides a complete example of how to use the cutscene system to create a complex sequence as described in the requirements.

Example Scenario

The example implements this sequence:

  1. Character1 moves to position (234, 591)
  2. At the same time, Character2 moves to position (912, 235)
  3. When both arrive, Character2 turns to face Character1
  4. Character2 says a dialogue line to Character1
  5. A special animation (shocked) is played for Character1

Sample Implementation

# Sample cutscene implementation
extends Node2D

# Character nodes (would be set in the editor or loaded)
var character1: Node2D
var character2: Node2D

# Cutscene manager
var cutscene_manager: CutsceneManager

func _ready() -> void:
    # Initialize the cutscene system
    setup_cutscene()
    
    # Start the cutscene
    cutscene_manager.start()

func setup_cutscene() -> void:
    # Create the cutscene manager
    cutscene_manager = CutsceneManager.new()
    add_child(cutscene_manager)
    
    # Create the action sequence as described in requirements
    
    # 1. & 2. Characters move simultaneously
    var parallel_moves = [
        MoveAction.new(character1, Vector2(234, 591), 150.0),  # Character1 moves
        MoveAction.new(character2, Vector2(912, 235), 150.0)   # Character2 moves
    ]
    cutscene_manager.add_parallel_actions(parallel_moves)
    
    # 3. Character2 turns to face Character1
    var turn_action = TurnAction.new(character2, character1, 3.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
    var animation_action = AnimationAction.new(character1, "shocked", false)
    cutscene_manager.add_action(animation_action)
    
    # Set up cutscene callbacks
    cutscene_manager.on_completed = func():
        print("Cutscene completed!")
        # Return to gameplay or next scene

# Alternative implementation with more complex chaining
func setup_advanced_cutscene() -> void:
    cutscene_manager = CutsceneManager.new()
    add_child(cutscene_manager)
    
    # Create actions
    var move1 = MoveAction.new(character1, Vector2(234, 591), 150.0)
    var move2 = MoveAction.new(character2, Vector2(912, 235), 150.0)
    var turn = TurnAction.new(character2, character1, 3.0)
    var dialogue = DialogueAction.new(character2, "Hello there, friend!", 2.0)
    var animation = AnimationAction.new(character1, "shocked", false)
    
    # Add parallel actions
    cutscene_manager.add_parallel_actions([move1, move2])
    
    # Add sequential actions
    cutscene_manager.add_action(turn)
    cutscene_manager.add_action(dialogue)
    cutscene_manager.add_action(animation)
    
    # Set completion callback
    cutscene_manager.on_completed = _on_cutscene_finished
}

func _on_cutscene_finished() -> void:
    print("The cutscene has finished playing")
    # Handle post-cutscene logic here
    # For example, transition to gameplay state

More Complex Example with Conditional Logic

# Advanced example with conditional actions
func setup_conditional_cutscene() -> void:
    cutscene_manager = CutsceneManager.new()
    add_child(cutscene_manager)
    
    # Move characters into position
    var move_group = [
        MoveAction.new(character1, Vector2(300, 400)),
        MoveAction.new(character2, Vector2(500, 400))
    ]
    cutscene_manager.add_parallel_actions(move_group)
    
    # Conditional dialogue based on game state
    var dialogue_action = DialogueAction.new(
        character1, 
        get_dialogue_text(), 
        3.0
    )
    cutscene_manager.add_action(dialogue_action)
    
    # Play different animation based on dialogue response
    var animation_action = AnimationAction.new(
        character2, 
        get_reaction_animation(), 
        false
    )
    cutscene_manager.add_action(animation_action)
    
    # Wait for a moment
    cutscene_manager.add_action(WaitAction.new(1.0))
    
    # Final action
    var final_dialogue = DialogueAction.new(
        character2, 
        "That was interesting!", 
        2.0
    )
    cutscene_manager.add_action(final_dialogue)

func get_dialogue_text() -> String:
    # This could be based on game state, player choices, etc.
    return "What do you think about this situation?"

func get_reaction_animation() -> String:
    # This could be based on game state, player choices, etc.
    return "thoughtful"

Integration with Game Systems

# Example of integrating with a game state manager
class_name GameCutsceneManager
extends Node

var cutscene_manager: CutsceneManager
var game_state: GameStateManager

func play_story_cutscene(story_key: String) -> void:
    # Pause gameplay
    game_state.set_state(GameState.CUTSCENE)
    
    # Create cutscene based on story key
    var cutscene_data = load_cutscene_data(story_key)
    cutscene_manager = create_cutscene_from_data(cutscene_data)
    
    # Set up completion callback to resume gameplay
    cutscene_manager.on_completed = func():
        game_state.set_state(GameState.PLAYING)
        # Clean up
        cutscene_manager.queue_free()
        cutscene_manager = null
    
    # Start the cutscene
    cutscene_manager.start()

func load_cutscene_data(key: String) -> Dictionary:
    # Load cutscene data from a file or database
    # This could be JSON, CSV, or custom format
    return {
        "actions": [
            {"type": "move", "character": "player", "position": [100, 200]},
            {"type": "dialogue", "character": "npc", "text": "Hello!"},
            {"type": "animation", "character": "player", "name": "wave"}
        ]
    }

func create_cutscene_from_data(data: Dictionary) -> CutsceneManager:
    var manager = CutsceneManager.new()
    add_child(manager)
    
    # Convert data to actions
    for action_data in data["actions"]:
        var action = create_action_from_data(action_data)
        if action:
            manager.add_action(action)
    
    return manager

func create_action_from_data(data: Dictionary) -> Action:
    match data["type"]:
        "move":
            var character = get_character_by_name(data["character"])
            var position = Vector2(data["position"][0], data["position"][1])
            return MoveAction.new(character, position)
        "dialogue":
            var character = get_character_by_name(data["character"])
            return DialogueAction.new(character, data["text"])
        "animation":
            var character = get_character_by_name(data["character"])
            return AnimationAction.new(character, data["name"])
        _:
            return null

Performance Considerations

# Example of optimizing cutscene performance
func setup_optimized_cutscene() -> void:
    cutscene_manager = CutsceneManager.new()
    add_child(cutscene_manager)
    
    # Pre-load any resources needed for actions
    preload_animations()
    preload_dialogue_textures()
    
    # Use object pooling for frequently created actions
    var move_action_pool = []
    for i in range(10):
        move_action_pool.append(MoveAction.new(null, Vector2.ZERO))
    
    # Reuse actions when possible
    var action1 = get_pooled_move_action(character1, Vector2(100, 100))
    var action2 = get_pooled_move_action(character2, Vector2(200, 200))
    
    cutscene_manager.add_parallel_actions([action1, action2])
    
    # Clean up when done
    cutscene_manager.on_completed = func():
        release_pooled_actions()
        # Other cleanup

This sample demonstrates how to use the cutscene system to create complex, dynamic sequences that can handle both sequential and parallel actions while maintaining clean, readable code.