Add spine and dialogic #1
@@ -20,6 +20,13 @@ func _ready() -> void:
|
|||||||
# Connect to variable changes to watch for demo variables
|
# Connect to variable changes to watch for demo variables
|
||||||
Dialogic.VAR.variable_changed.connect(_on_variable_changed)
|
Dialogic.VAR.variable_changed.connect(_on_variable_changed)
|
||||||
|
|
||||||
|
# Check if we're returning from the gym09 minigame
|
||||||
|
if Dialogic.VAR.Gym.minigame_done:
|
||||||
|
print("[Gym Controller] Returning from minigame — starting congrats timeline.")
|
||||||
|
Dialogic.VAR.Gym.minigame_done = false
|
||||||
|
Dialogic.start("gym09_congrats")
|
||||||
|
return
|
||||||
|
|
||||||
# Start the hub timeline
|
# Start the hub timeline
|
||||||
Dialogic.start(start_timeline)
|
Dialogic.start(start_timeline)
|
||||||
|
|
||||||
@@ -49,6 +56,14 @@ func _on_dialogic_signal(argument: Variant) -> void:
|
|||||||
Dialogic.end_timeline()
|
Dialogic.end_timeline()
|
||||||
Dialogic.start_timeline("gym_pattern4_signal_target")
|
Dialogic.start_timeline("gym_pattern4_signal_target")
|
||||||
|
|
||||||
|
elif argument is String and argument == "start_minigame":
|
||||||
|
# Gym 09: Scene switching demo
|
||||||
|
# Store the return path so the minigame knows where to come back to
|
||||||
|
Dialogic.VAR.Gym.minigame_return = "hub"
|
||||||
|
print("[Gym Controller] Signal 'start_minigame' — switching to minigame scene.")
|
||||||
|
await get_tree().create_timer(0.3).timeout
|
||||||
|
get_tree().change_scene_to_file("res://docs/gyms/gym09_scene_switching/gym09_minigame.tscn")
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,24 @@ Miko (neutral): Which pattern would you like to explore?
|
|||||||
Miko (joy): The variable itself is the jump target!
|
Miko (joy): The variable itself is the jump target!
|
||||||
jump gym_pattern8_dynamic_label/start
|
jump gym_pattern8_dynamic_label/start
|
||||||
|
|
||||||
|
- More patterns...
|
||||||
|
Miko (smile): There's more to explore on the next page!
|
||||||
|
jump menu_p2
|
||||||
|
|
||||||
- I've seen enough. Goodbye!
|
- I've seen enough. Goodbye!
|
||||||
Miko (smile): Thanks for exploring! Come back anytime.
|
Miko (smile): Thanks for exploring! Come back anytime.
|
||||||
Advisor (pl5): Until next time.
|
Advisor (pl5): Until next time.
|
||||||
[end_timeline]
|
[end_timeline]
|
||||||
|
|
||||||
|
label menu_p2
|
||||||
|
|
||||||
|
Miko (neutral): More patterns to explore:
|
||||||
|
|
||||||
|
- 9. Scene switching (Dialogic ↔ gameplay)
|
||||||
|
Miko (smile): This one changes scenes — a timeline, then a minigame, then back!
|
||||||
|
Advisor (pl5): I'll take you to the intro, which will trigger the minigame.
|
||||||
|
Miko (neutral): Press the button 5 times to return.
|
||||||
|
jump gym09_intro/
|
||||||
|
|
||||||
|
- Back to first page
|
||||||
|
jump menu
|
||||||
|
|||||||
27
docs/gyms/gym09_scene_switching/README.md
Normal file
27
docs/gyms/gym09_scene_switching/README.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Gym 09 — Scene Switching
|
||||||
|
|
||||||
|
Demonstrates switching between a Dialogic timeline scene and a non-Dialogic gameplay scene.
|
||||||
|
|
||||||
|
## Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
gym09_main.tscn gym09_minigame.tscn
|
||||||
|
┌─────────────────┐ ┌──────────────────┐
|
||||||
|
│ gym09_intro.dtl │ │ Press button 5x │
|
||||||
|
│ ↓ │ │ ↓ │
|
||||||
|
│ [signal] │ ───→ │ set variable │
|
||||||
|
│ │ ←─── │ change_scene back │
|
||||||
|
│ gym09_congrats │ │ │
|
||||||
|
│ .dtl │ └──────────────────┘
|
||||||
|
└─────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## How to Run
|
||||||
|
|
||||||
|
Open `gym09_main.tscn` in the Godot editor and press **F6** (Run Current Scene).
|
||||||
|
|
||||||
|
## Key Mechanic
|
||||||
|
|
||||||
|
- `Dialogic.VAR.Gym.minigame_done` acts as a flag between scenes
|
||||||
|
- `[signal arg=start_minigame]` triggers `get_tree().change_scene_to_file()`
|
||||||
|
- The controller's `_ready()` checks the flag to know which timeline to start
|
||||||
51
docs/gyms/gym09_scene_switching/gym09_congrats.dtl
Normal file
51
docs/gyms/gym09_scene_switching/gym09_congrats.dtl
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# ============================================================
|
||||||
|
# Gym 09 — Scene Switching: Congratulations Timeline
|
||||||
|
# ============================================================
|
||||||
|
# This timeline runs AFTER the player returns from the
|
||||||
|
# minigame. It congratulates them and explains the mechanism.
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
join Miko center
|
||||||
|
join Advisor right
|
||||||
|
|
||||||
|
Miko (joy): You did it! You pressed the button 5 times!
|
||||||
|
|
||||||
|
[wait time="0.5"]
|
||||||
|
|
||||||
|
Advisor (pl5): Welcome back to a Dialogic timeline.
|
||||||
|
Advisor (pl5): Notice what just happened:
|
||||||
|
|
||||||
|
[wait time="1.0"]
|
||||||
|
|
||||||
|
Advisor (pl5): 1. You started in a Dialogic timeline (the intro).
|
||||||
|
Advisor (pl5): 2. A signal triggered a scene change to a pure\
|
||||||
|
gameplay scene with no Dialogic UI.
|
||||||
|
Advisor (pl5): 3. The minigame set a Dialogic variable:\
|
||||||
|
`Gym.minigame_done = true`
|
||||||
|
Advisor (pl5): 4. Then it called `change_scene_to_file()` back here.
|
||||||
|
Advisor (pl5): 5. This scene's controller checked the variable\
|
||||||
|
and started THIS timeline.
|
||||||
|
|
||||||
|
[wait time="2.0"]
|
||||||
|
|
||||||
|
Miko (smile): The magic is that Dialogic is an AUTOLOAD!
|
||||||
|
Miko (joy): Its variables survive scene changes because the\
|
||||||
|
autoload never gets freed.
|
||||||
|
|
||||||
|
Advisor (doubt): This pattern is essential for:
|
||||||
|
Advisor (doubt): • Minigames (fishing, crafting, lockpicking)
|
||||||
|
Advisor (doubt): • Combat encounters between dialog scenes
|
||||||
|
Advisor (doubt): • Exploration that triggers narrative beats
|
||||||
|
Advisor (doubt): • Any gameplay/dialog hybrid
|
||||||
|
|
||||||
|
[wait time="2.0"]
|
||||||
|
|
||||||
|
Miko (smile): Want to try again?
|
||||||
|
|
||||||
|
- Yes, play the minigame again!
|
||||||
|
set {Gym.minigame_done} = false
|
||||||
|
[signal arg=start_minigame]
|
||||||
|
|
||||||
|
- No, I understand the pattern. Back to hub.
|
||||||
|
set {Gym.minigame_done} = false
|
||||||
|
jump gym_main/menu
|
||||||
1
docs/gyms/gym09_scene_switching/gym09_congrats.dtl.uid
Normal file
1
docs/gyms/gym09_scene_switching/gym09_congrats.dtl.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://b8hj1owk0somk
|
||||||
37
docs/gyms/gym09_scene_switching/gym09_controller.gd
Normal file
37
docs/gyms/gym09_scene_switching/gym09_controller.gd
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# ============================================================
|
||||||
|
# Gym 09 — Scene Switching Controller
|
||||||
|
# ============================================================
|
||||||
|
# This root node handles:
|
||||||
|
# 1. Starting the right timeline on scene load
|
||||||
|
# (intro on first visit, congrats after minigame)
|
||||||
|
# 2. Catching the [signal arg=start_minigame] to change scenes
|
||||||
|
# ============================================================
|
||||||
|
extends Node2D
|
||||||
|
|
||||||
|
const MINIGAME_SCENE_PATH := "res://docs/gyms/gym09_scene_switching/gym09_minigame.tscn"
|
||||||
|
|
||||||
|
@export var intro_timeline: DialogicTimeline
|
||||||
|
@export var congrats_timeline: DialogicTimeline
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
# Connect to signal events from timelines
|
||||||
|
Dialogic.signal_event.connect(_on_dialogic_signal)
|
||||||
|
|
||||||
|
# Check if we're returning from the minigame
|
||||||
|
if Dialogic.VAR.Gym.minigame_done:
|
||||||
|
print("[Gym09 Controller] Returning from minigame — starting congrats timeline.")
|
||||||
|
Dialogic.VAR.Gym.minigame_done = false
|
||||||
|
Dialogic.start(congrats_timeline)
|
||||||
|
else:
|
||||||
|
print("[Gym09 Controller] First visit — starting intro timeline.")
|
||||||
|
Dialogic.start(intro_timeline)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_dialogic_signal(argument: Variant) -> void:
|
||||||
|
if argument is String and argument == "start_minigame":
|
||||||
|
print("[Gym09 Controller] Signal 'start_minigame' received — switching to minigame scene.")
|
||||||
|
# Tell the minigame where to return
|
||||||
|
Dialogic.VAR.Gym.minigame_return = "standalone"
|
||||||
|
await get_tree().create_timer(0.3).timeout
|
||||||
|
get_tree().change_scene_to_file(MINIGAME_SCENE_PATH)
|
||||||
1
docs/gyms/gym09_scene_switching/gym09_controller.gd.uid
Normal file
1
docs/gyms/gym09_scene_switching/gym09_controller.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://k82wjnwinxwp
|
||||||
43
docs/gyms/gym09_scene_switching/gym09_intro.dtl
Normal file
43
docs/gyms/gym09_scene_switching/gym09_intro.dtl
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# ============================================================
|
||||||
|
# Gym 09 — Scene Switching: Intro Timeline
|
||||||
|
# ============================================================
|
||||||
|
# This timeline introduces the scene-switching concept,
|
||||||
|
# then emits a signal that triggers a scene change to the
|
||||||
|
# minigame (a non-Dialogic scene).
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
join Miko center
|
||||||
|
join Advisor right
|
||||||
|
|
||||||
|
Miko (joy): Welcome to Gym 09 — Scene Switching!
|
||||||
|
Advisor (pl5): This gym demonstrates how Dialogic timelines and\
|
||||||
|
non-Dialogic gameplay scenes can flow back and forth.
|
||||||
|
|
||||||
|
[wait time="1.0"]
|
||||||
|
|
||||||
|
Miko (neutral): Here's the plan:
|
||||||
|
Miko (smile): 1. You're reading this dialog (Dialogic timeline).
|
||||||
|
Advisor (pl5): 2. I'll emit a signal that changes the scene to a\
|
||||||
|
pure minigame — no dialog, no portraits, just gameplay.
|
||||||
|
Miko (smile): 3. In the minigame, press the button 5 times!
|
||||||
|
Advisor (pl5): 4. After 5 presses, you'll automatically return here\
|
||||||
|
and I'll congratulate you with another timeline.
|
||||||
|
|
||||||
|
[wait time="1.5"]
|
||||||
|
|
||||||
|
Miko (joy): That shows the full loop:\
|
||||||
|
Dialogic scene → gameplay scene → Dialogic scene!
|
||||||
|
|
||||||
|
Advisor (pl5): The key insight: Dialogic is an autoload, so\
|
||||||
|
variables persist even in non-Dialogic scenes.
|
||||||
|
|
||||||
|
[wait time="1.0"]
|
||||||
|
|
||||||
|
Miko (smile): Ready? Let's go to the minigame!
|
||||||
|
|
||||||
|
# This signal is caught by gym09_controller.gd,
|
||||||
|
# which calls get_tree().change_scene_to_file("...minigame.tscn")
|
||||||
|
[signal arg=start_minigame]
|
||||||
|
|
||||||
|
# This line won't be reached — the scene changes immediately
|
||||||
|
Miko (surprise): Wait, shouldn't I still be here?
|
||||||
1
docs/gyms/gym09_scene_switching/gym09_intro.dtl.uid
Normal file
1
docs/gyms/gym09_scene_switching/gym09_intro.dtl.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://my3sk1mu2lx6
|
||||||
10
docs/gyms/gym09_scene_switching/gym09_main.tscn
Normal file
10
docs/gyms/gym09_scene_switching/gym09_main.tscn
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[gd_scene format=3]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://docs/gyms/gym09_scene_switching/gym09_controller.gd" id="1_ctrl"]
|
||||||
|
[ext_resource type="Resource" path="res://docs/gyms/gym09_scene_switching/gym09_intro.dtl" id="2_intro"]
|
||||||
|
[ext_resource type="Resource" path="res://docs/gyms/gym09_scene_switching/gym09_congrats.dtl" id="3_congrats"]
|
||||||
|
|
||||||
|
[node name="Gym09SceneSwitching" type="Node2D"]
|
||||||
|
script = ExtResource("1_ctrl")
|
||||||
|
intro_timeline = ExtResource("2_intro")
|
||||||
|
congrats_timeline = ExtResource("3_congrats")
|
||||||
55
docs/gyms/gym09_scene_switching/gym09_minigame.gd
Normal file
55
docs/gyms/gym09_scene_switching/gym09_minigame.gd
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# ============================================================
|
||||||
|
# Gym 09 — Minigame Scene
|
||||||
|
# ============================================================
|
||||||
|
# A pure gameplay scene with NO Dialogic UI.
|
||||||
|
# Press the button 5 times, then return to the Dialogic scene.
|
||||||
|
# ============================================================
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
@export var required_presses: int = 5
|
||||||
|
|
||||||
|
var _press_count: int = 0
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
print("[Gym09 Minigame] Ready! Press the button ", required_presses, " times.")
|
||||||
|
_update_label()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_button_pressed() -> void:
|
||||||
|
_press_count += 1
|
||||||
|
print("[Gym09 Minigame] Press ", _press_count, " of ", required_presses)
|
||||||
|
_update_label()
|
||||||
|
|
||||||
|
if _press_count >= required_presses:
|
||||||
|
_on_complete()
|
||||||
|
|
||||||
|
|
||||||
|
func _update_label() -> void:
|
||||||
|
var remaining := required_presses - _press_count
|
||||||
|
if remaining > 0:
|
||||||
|
%CounterLabel.text = "Presses remaining: " + str(remaining)
|
||||||
|
%Button.text = "Press Me! (" + str(_press_count) + "/" + str(required_presses) + ")"
|
||||||
|
else:
|
||||||
|
%CounterLabel.text = "Complete!"
|
||||||
|
%Button.text = "Returning..."
|
||||||
|
|
||||||
|
|
||||||
|
func _on_complete() -> void:
|
||||||
|
print("[Gym09 Minigame] Complete! Setting variable and switching back.")
|
||||||
|
# Dialogic is an autoload, so this works even without a Dialogic layout
|
||||||
|
Dialogic.VAR.Gym.minigame_done = true
|
||||||
|
|
||||||
|
# Disable the button so player can't spam it
|
||||||
|
%Button.disabled = true
|
||||||
|
|
||||||
|
# Brief pause so the player sees "Complete!"
|
||||||
|
await get_tree().create_timer(1.0).timeout
|
||||||
|
|
||||||
|
# Determine where to return based on who started us
|
||||||
|
var return_path := "res://docs/gyms/gym09_scene_switching/gym09_main.tscn"
|
||||||
|
if Dialogic.VAR.Gym.minigame_return == "hub":
|
||||||
|
return_path = "res://docs/gyms/cross-timeline-interactions/gym_controller.tscn"
|
||||||
|
|
||||||
|
print("[Gym09 Minigame] Returning to: ", return_path)
|
||||||
|
get_tree().change_scene_to_file(return_path)
|
||||||
1
docs/gyms/gym09_scene_switching/gym09_minigame.gd.uid
Normal file
1
docs/gyms/gym09_scene_switching/gym09_minigame.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://bpu7ehr2qjc1f
|
||||||
45
docs/gyms/gym09_scene_switching/gym09_minigame.tscn
Normal file
45
docs/gyms/gym09_scene_switching/gym09_minigame.tscn
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
[gd_scene format=3 uid="uid://p83ndnog4l2h"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://bpu7ehr2qjc1f" path="res://docs/gyms/gym09_scene_switching/gym09_minigame.gd" id="1_script"]
|
||||||
|
|
||||||
|
[node name="Gym09Minigame" type="Control" unique_id=313626257]
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
script = ExtResource("1_script")
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=419254278]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 8
|
||||||
|
anchor_left = 0.5
|
||||||
|
anchor_top = 0.5
|
||||||
|
anchor_right = 0.5
|
||||||
|
anchor_bottom = 0.5
|
||||||
|
offset_left = -150.0
|
||||||
|
offset_top = -80.0
|
||||||
|
offset_right = 150.0
|
||||||
|
offset_bottom = 80.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="TitleLabel" type="Label" parent="VBoxContainer" unique_id=529708548]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "MINIGAME"
|
||||||
|
horizontal_alignment = 1
|
||||||
|
|
||||||
|
[node name="CounterLabel" type="Label" parent="VBoxContainer" unique_id=1005168486]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Presses remaining: 5"
|
||||||
|
horizontal_alignment = 1
|
||||||
|
|
||||||
|
[node name="Button" type="Button" parent="VBoxContainer" unique_id=211036225]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 4
|
||||||
|
text = "Press Me! (0/5)"
|
||||||
|
|
||||||
|
[connection signal="pressed" from="VBoxContainer/Button" to="." method="_on_button_pressed"]
|
||||||
@@ -27,6 +27,8 @@ directories/dch_directory={
|
|||||||
"Raptor": "res://docs/museums/dialogic/Raptor.dch"
|
"Raptor": "res://docs/museums/dialogic/Raptor.dch"
|
||||||
}
|
}
|
||||||
directories/dtl_directory={
|
directories/dtl_directory={
|
||||||
|
"gym09_congrats": "res://docs/gyms/gym09_scene_switching/gym09_congrats.dtl",
|
||||||
|
"gym09_intro": "res://docs/gyms/gym09_scene_switching/gym09_intro.dtl",
|
||||||
"gym_main": "res://docs/gyms/cross-timeline-interactions/gym_main.dtl",
|
"gym_main": "res://docs/gyms/cross-timeline-interactions/gym_main.dtl",
|
||||||
"gym_pattern1_jump": "res://docs/gyms/cross-timeline-interactions/gym_pattern1_jump.dtl",
|
"gym_pattern1_jump": "res://docs/gyms/cross-timeline-interactions/gym_pattern1_jump.dtl",
|
||||||
"gym_pattern1_target": "res://docs/gyms/cross-timeline-interactions/gym_pattern1_target.dtl",
|
"gym_pattern1_target": "res://docs/gyms/cross-timeline-interactions/gym_pattern1_target.dtl",
|
||||||
@@ -50,6 +52,8 @@ layout/default_style="Default"
|
|||||||
variables={
|
variables={
|
||||||
"Gym": {
|
"Gym": {
|
||||||
"demo_flag": false,
|
"demo_flag": false,
|
||||||
|
"minigame_done": false,
|
||||||
|
"minigame_return": "",
|
||||||
"player_name": "Hero",
|
"player_name": "Hero",
|
||||||
"sub_value": 0,
|
"sub_value": 0,
|
||||||
"time_of_day": "morning"
|
"time_of_day": "morning"
|
||||||
|
|||||||
Reference in New Issue
Block a user