diff --git a/docs/gyms/cross-timeline-interactions/gym_controller.gd b/docs/gyms/cross-timeline-interactions/gym_controller.gd index 8db1780..afe3967 100644 --- a/docs/gyms/cross-timeline-interactions/gym_controller.gd +++ b/docs/gyms/cross-timeline-interactions/gym_controller.gd @@ -20,6 +20,13 @@ func _ready() -> void: # Connect to variable changes to watch for demo variables 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 Dialogic.start(start_timeline) @@ -49,6 +56,14 @@ func _on_dialogic_signal(argument: Variant) -> void: Dialogic.end_timeline() 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 diff --git a/docs/gyms/cross-timeline-interactions/gym_main.dtl b/docs/gyms/cross-timeline-interactions/gym_main.dtl index 1cda082..58d8988 100644 --- a/docs/gyms/cross-timeline-interactions/gym_main.dtl +++ b/docs/gyms/cross-timeline-interactions/gym_main.dtl @@ -50,7 +50,24 @@ Miko (neutral): Which pattern would you like to explore? Miko (joy): The variable itself is the jump target! 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! Miko (smile): Thanks for exploring! Come back anytime. Advisor (pl5): Until next time. [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 diff --git a/docs/gyms/gym09_scene_switching/README.md b/docs/gyms/gym09_scene_switching/README.md new file mode 100644 index 0000000..8595579 --- /dev/null +++ b/docs/gyms/gym09_scene_switching/README.md @@ -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 diff --git a/docs/gyms/gym09_scene_switching/gym09_congrats.dtl b/docs/gyms/gym09_scene_switching/gym09_congrats.dtl new file mode 100644 index 0000000..28f3800 --- /dev/null +++ b/docs/gyms/gym09_scene_switching/gym09_congrats.dtl @@ -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 diff --git a/docs/gyms/gym09_scene_switching/gym09_congrats.dtl.uid b/docs/gyms/gym09_scene_switching/gym09_congrats.dtl.uid new file mode 100644 index 0000000..2b0511d --- /dev/null +++ b/docs/gyms/gym09_scene_switching/gym09_congrats.dtl.uid @@ -0,0 +1 @@ +uid://b8hj1owk0somk diff --git a/docs/gyms/gym09_scene_switching/gym09_controller.gd b/docs/gyms/gym09_scene_switching/gym09_controller.gd new file mode 100644 index 0000000..84f8bad --- /dev/null +++ b/docs/gyms/gym09_scene_switching/gym09_controller.gd @@ -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) diff --git a/docs/gyms/gym09_scene_switching/gym09_controller.gd.uid b/docs/gyms/gym09_scene_switching/gym09_controller.gd.uid new file mode 100644 index 0000000..92fd68f --- /dev/null +++ b/docs/gyms/gym09_scene_switching/gym09_controller.gd.uid @@ -0,0 +1 @@ +uid://k82wjnwinxwp diff --git a/docs/gyms/gym09_scene_switching/gym09_intro.dtl b/docs/gyms/gym09_scene_switching/gym09_intro.dtl new file mode 100644 index 0000000..1bc9fd9 --- /dev/null +++ b/docs/gyms/gym09_scene_switching/gym09_intro.dtl @@ -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? diff --git a/docs/gyms/gym09_scene_switching/gym09_intro.dtl.uid b/docs/gyms/gym09_scene_switching/gym09_intro.dtl.uid new file mode 100644 index 0000000..757f72b --- /dev/null +++ b/docs/gyms/gym09_scene_switching/gym09_intro.dtl.uid @@ -0,0 +1 @@ +uid://my3sk1mu2lx6 diff --git a/docs/gyms/gym09_scene_switching/gym09_main.tscn b/docs/gyms/gym09_scene_switching/gym09_main.tscn new file mode 100644 index 0000000..dbe3e7f --- /dev/null +++ b/docs/gyms/gym09_scene_switching/gym09_main.tscn @@ -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") diff --git a/docs/gyms/gym09_scene_switching/gym09_minigame.gd b/docs/gyms/gym09_scene_switching/gym09_minigame.gd new file mode 100644 index 0000000..d7c2c22 --- /dev/null +++ b/docs/gyms/gym09_scene_switching/gym09_minigame.gd @@ -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) diff --git a/docs/gyms/gym09_scene_switching/gym09_minigame.gd.uid b/docs/gyms/gym09_scene_switching/gym09_minigame.gd.uid new file mode 100644 index 0000000..8eb3cf3 --- /dev/null +++ b/docs/gyms/gym09_scene_switching/gym09_minigame.gd.uid @@ -0,0 +1 @@ +uid://bpu7ehr2qjc1f diff --git a/docs/gyms/gym09_scene_switching/gym09_minigame.tscn b/docs/gyms/gym09_scene_switching/gym09_minigame.tscn new file mode 100644 index 0000000..04d55b3 --- /dev/null +++ b/docs/gyms/gym09_scene_switching/gym09_minigame.tscn @@ -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"] diff --git a/project.godot b/project.godot index 02ea2d8..40b3260 100644 --- a/project.godot +++ b/project.godot @@ -27,6 +27,8 @@ directories/dch_directory={ "Raptor": "res://docs/museums/dialogic/Raptor.dch" } 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_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", @@ -50,6 +52,8 @@ layout/default_style="Default" variables={ "Gym": { "demo_flag": false, +"minigame_done": false, +"minigame_return": "", "player_name": "Hero", "sub_value": 0, "time_of_day": "morning"