Add spine and dialogic #1

Open
m.rossi wants to merge 10 commits from spine into main
18 changed files with 509 additions and 0 deletions
Showing only changes of commit f8d3d19849 - Show all commits

View File

@@ -69,5 +69,10 @@ Miko (neutral): More patterns to explore:
Miko (neutral): Press the button 5 times to return. Miko (neutral): Press the button 5 times to return.
jump gym09_intro/ jump gym09_intro/
- 10. Character & Portrait Gym
Miko (joy): Positions, emotions, transforms, and spine animations!
Advisor (pl5): The visual half of the visual novel.
jump gym10_main/
- Back to first page - Back to first page
jump menu jump menu

View File

@@ -0,0 +1,25 @@
# Gym 10 — Character & Portrait Gym
Tests every aspect of Dialogic's character/portrait system.
## Demos
| # | Timeline | What it covers |
|---|----------|---------------|
| 1 | `gym10_positions` | Preset positions (left/center/right/leftmost/rightmost), manual pos=, z-index stacking |
| 2 | `gym10_portrait_switch` | `[portrait=name]` mid-text switching, emotional arcs, variable-driven portraits |
| 3 | `gym10_multichar` | 3+ characters on screen, z-index layering, dynamic leave/rejoin flow |
| 4 | `gym10_transforms` | mirror, scale, offset, rotation, smooth move transitions |
| 5 | `gym10_spine` | Raptor's spine-animated portraits (walk/jump/roar) vs static PNG portraits |
## Characters Used
- **Miko** — portraits: neutral, smile, joy, anger, shock
- **Advisor** — portraits: pl5, blink, doubt, surprise
- **Merchant** — portraits: happy, blink, surprise, confusion
- **Raptor** — spine-animated portraits: walk, jump, roar
## How to Run
- **From hub:** Pick option 10 in the main gym hub
- **Standalone:** Open `gym10_main.tscn` → F6

View File

@@ -0,0 +1,11 @@
# ============================================================
# Gym 10 — Character & Portrait Gym Controller
# ============================================================
extends Node2D
@export var start_timeline: DialogicTimeline
func _ready() -> void:
Dialogic.start(start_timeline)
print("[Gym10] Character & Portrait Gym ready.")

View File

@@ -0,0 +1 @@
uid://pdl00kv4n5q1

View File

@@ -0,0 +1,48 @@
# ============================================================
# Gym 10 — Character & Portrait Gym
# ============================================================
# Systematic exploration of Dialogic's character/portrait system:
# positions, mid-text switching, multi-character scenes,
# transforms (mirror/scale/offset), and spine animations.
# ============================================================
join Miko (joy) center [animation="Bounce In"]
Miko (joy): Welcome to the Character & Portrait Gym!
[wait time="0.5"]
join Advisor (pl5) right [animation="Fade In"]
Advisor (pl5): This is the VISUAL half of the visual novel.
Miko (smile): Characters, portraits, expressions — all the things\
that bring a VN to life!
[wait time="1.0"]
label menu
Miko (neutral): What would you like to explore?
- 1. Positions & Presets
Miko (smile): Left, center, right, manual positioning, and z-index!
jump gym10_positions/
- 2. Portrait Switching (mid-text emotions)
Miko (joy): Watch my expression change in real-time as I speak!
jump gym10_portrait_switch/
- 3. Multi-Character Scenes
Miko (neutral): 3+ characters on screen — who's in front?
jump gym10_multichar/
- 4. Transforms (mirror, scale, offset)
Miko (smile): Flip, resize, and reposition characters.
jump gym10_transforms/
- 5. Spine-Animated Portraits (Raptor)
Miko (joy): The dinosaur with moving portraits!
jump gym10_spine/
- Back to main hub
jump gym_main/menu

View File

@@ -0,0 +1 @@
uid://br6emd84bsphi

View File

@@ -0,0 +1,8 @@
[gd_scene format=3]
[ext_resource type="Script" path="res://docs/gyms/gym10_character_portraits/gym10_controller.gd" id="1_ctrl"]
[ext_resource type="Resource" path="res://docs/gyms/gym10_character_portraits/gym10_main.dtl" id="2_main"]
[node name="Gym10CharacterPortraits" type="Node2D"]
script = ExtResource("1_ctrl")
start_timeline = ExtResource("2_main")

View File

@@ -0,0 +1,70 @@
# ============================================================
# Gym 10.3 — Multi-Character Scenes
# ============================================================
# Demonstrates managing 3+ characters on screen:
# join orchestration, z-index stacking, leave/rejoin flow.
# ============================================================
leave --All--
# ---- Build up a full scene ----
join Miko (neutral) center [animation="Fade In"]
join Advisor (pl5) right [animation="Fade In" wait="true"]
join Merchant (happy) left [animation="Fade In" wait="true"]
Miko (neutral): Three characters on screen!
Advisor (pl5): This is a full conversation scene.
Merchant (happy): I feel included!
[wait time="1.0"]
# ---- Demonstrate z-index with 3 overlapping chars ----
leave --All--
join Miko (joy) center [animation="Fade In" z_index="2"]
Miko (joy): Center with z_index 2.
join Advisor (pl5) pos=x0.45y0.5 size=y400px rot=0 [animation="Fade In" z_index="1"]
Advisor (pl5): Moved slightly left, behind Miko (z_index 1).
join Merchant (surprise) pos=x0.55y0.5 size=y400px rot=0 [animation="Fade In" z_index="3"]
Merchant (surprise): Moved slightly right, with highest z_index (3)!
[wait time="1.5"]
Miko (smile): Notice the stacking — Merchant is on top, then me, then Advisor.
Advisor (doubt): This is how you control who appears in front.
[wait time="1.5"]
# ---- Leave and rejoin (dynamic cast) ----
leave Merchant [animation="Fade Down"]
Miko (neutral): The merchant left. Now it's just the two of us.
[wait time="0.5"]
join Merchant (happy) left [animation="Bounce In"]
Merchant (happy): I'm back! And I moved to the left.
[wait time="1.0"]
Advisor (pl5): Characters can leave and rejoin at different positions.
Advisor (doubt): This is essential for scene direction — characters\
enter and exit the conversation naturally.
[wait time="1.5"]
# ---- Leave all at once ----
Miko (smile): And with one command...
leave --All-- [animation="Fade Down"]
[wait time="1.0"]
Advisor (pl5): `leave --All--` clears the stage instantly.
Miko (neutral): Useful for scene transitions!
[wait time="1.0"]
jump gym10_main/menu

View File

@@ -0,0 +1 @@
uid://bqy80a0et22t4

View File

@@ -0,0 +1,64 @@
# ============================================================
# Gym 10.2 — Portrait Switching (Mid-Text Emotions)
# ============================================================
# Demonstrates changing a character's portrait expression
# in the middle of a text event using [portrait=name].
# Also: variable-driven portrait selection.
# ============================================================
leave --All--
join Miko (neutral) center [animation="Fade In"]
Advisor (pl5): Portrait switching is what makes characters feel alive.
Advisor (pl5): Watch Miko's expression change as she speaks.
[wait time="1.0"]
# ---- Single emotion change ----
Miko (neutral): I'll start calm...[portrait=joy] and suddenly I'm happy!
[wait time="1.0"]
# ---- Emotional arc in one line ----
Miko (neutral): Watch this:[portrait=shock] Whoa![portrait=anger] That makes me mad!\
[portrait=smile] But I'm a forgiving person.[portrait=joy] And now I'm happy!
[wait time="1.5"]
# ---- With pauses between emotions ----
Miko (joy): Let me tell you a story.[pause=0.8][portrait=neutral] It starts normally.\
[pause=0.8][portrait=shock] Then something shocking happens!\
[pause=0.8][portrait=smile] But it has a happy ending.
[wait time="2.0"]
Advisor (pl5): The [portrait=name] tag switches the current speaker's portrait.
Advisor (doubt): It happens instantly when the text reveal reaches that point.
# ---- Variable-driven portrait ----
leave Miko
[wait time="0.5"]
set {Gym.demo_flag} = true
if {Gym.demo_flag}:
join Miko (joy) center [animation="Fade In"]
Miko (joy): The variable was TRUE, so I'm happy!
else:
join Miko (anger) center [animation="Fade In"]
Miko (anger): The variable was FALSE, so I'm angry!
[wait time="1.0"]
Miko (smile): You can also use variables directly in portrait expressions.
Advisor (pl5): In a character event, use curly braces and parentheses.
Advisor (doubt): But that needs to be set up in the character event, not in text.
[wait time="1.0"]
# ---- Clean up ----
leave --All--
[wait time="0.5"]
jump gym10_main/menu

View File

@@ -0,0 +1 @@
uid://8sk057i7sjgh

View File

@@ -0,0 +1,81 @@
# ============================================================
# Gym 10.1 — Positions & Presets
# ============================================================
# Demonstrates all preset positions and manual positioning.
# ============================================================
# ---- Clear the stage ----
leave --All--
Advisor (pl5): Let's start with the basics — character positions.
# ---- Join at each preset position ----
join Miko (neutral) left [animation="Fade In"]
Miko (neutral): I'm on the left.
join Advisor (pl5) center [animation="Fade In"]
Advisor (pl5): I'm in the center.
join Merchant (happy) right [animation="Fade In"]
Merchant (happy): And I'm on the right!
[wait time="1.0"]
Advisor (pl5): Those are the three main presets: left, center, right.
# ---- Show leftmost/rightmost ----
leave --All--
join Miko (smile) leftmost [animation="Fade In"]
Miko (smile): Now I'm at leftmost — further to the edge!
join Advisor (pl5) rightmost [animation="Fade In"]
Advisor (pl5): And I'm at rightmost — the far right edge.
[wait time="1.5"]
Advisor (pl5): Available presets: leftmost, left, center, right, rightmost.
# ---- Manual positioning ----
leave --All--
join Miko (joy) pos=x0.15y0.5 [animation="Fade In"]
Miko (joy): I'm manually positioned at x=0.15!
join Advisor (pl5) pos=x0.85y0.5 [animation="Fade In"]
Advisor (pl5): And I'm at x=0.85 — no preset needed.
[wait time="1.5"]
Advisor (pl5): Use pos=xY for precise control over x/y coordinates.
Advisor (doubt): Values are relative to viewport: 0=left, 0.5=center, 1=right.
# ---- Z-Index (stacking order) ----
leave --All--
Miko (neutral): Next up — z-index controls who appears in front.
join Miko (neutral) center [animation="Fade In" z_index="2"]
Miko (neutral): My z_index is 2 — I should be on top.
join Advisor (pl5) center [animation="Fade In" z_index="1"]
Advisor (pl5): My z_index is 1 — I'm behind Miko.
[wait time="1.5"]
Advisor (doubt): Higher z_index = visually in front. Important when\
characters overlap.
join Merchant (happy) center [animation="Fade In" z_index="3"]
Merchant (happy): z_index 3! I'm on top of everyone!
[wait time="1.5"]
Merchant (happy): Z-index is Dialogic's own sorting — not Godot's native z_index.
# ---- Clean up and return ----
leave --All--
[wait time="0.5"]
jump gym10_main/menu

View File

@@ -0,0 +1 @@
uid://145553b16tyc

View File

@@ -0,0 +1,86 @@
# ============================================================
# Gym 10.5 — Spine-Animated Portraits (Raptor)
# ============================================================
# Raptor uses spine animation portraits instead of static
# images: walk, jump, roar. Each plays a looping animation.
# ============================================================
leave --All--
# ---- Intro ----
join Advisor (pl5) center
Advisor (pl5): Raptor uses SPINE-ANIMATED portraits.
Advisor (doubt): Unlike static PNG portraits, these play looping animations.
[wait time="1.0"]
# ---- Show the walk portrait ----
leave Advisor
join Raptor (walk) center [animation="Fade In"]
Raptor (walk): This is my WALK portrait. I'm animated!
[wait time="3.0"]
# ---- Switch to jump ----
update Raptor (jump) center
Raptor (jump): Now I'm JUMPING! Notice the animation change.
[wait time="3.0"]
# ---- Switch to roar ----
update Raptor (roar) center
Raptor (roar): ROOOAAR! My roar animation is fierce!
[wait time="3.0"]
# ---- Demonstrate fade transition ----
update Raptor (walk) center
Raptor (walk): You can also crossfade between spine portraits.
[wait time="1.0"]
# ---- Compare with static portraits ----
leave Raptor
join Miko (neutral) center [animation="Fade In"]
Miko (neutral): I use static PNG portraits — they don't move.
Miko (smile): Each of my expressions is a separate still image.
[wait time="1.0"]
join Advisor (pl5) left [animation="Fade In"]
Advisor (pl5): Spine portraits are great for characters that need\
continuous motion — creatures, robots, or expressive characters.
[wait time="1.5"]
# ---- Bring Raptor back with both ----
leave Miko
leave Advisor
join Raptor (walk) center [animation="Fade In"]
Raptor (walk): Spine portraits are configured in the character resource.
Raptor (walk): Each portrait points to a custom portrait scene\
with a SpineSprite node instead of a TextureRect.
[wait time="2.0"]
# ---- Key difference ----
join Advisor (pl5) right [animation="Fade In"]
Advisor (pl5): Key difference: spine animations loop forever.
Advisor (pl5): Static portraits stay on one frame until you switch them.
Advisor (pl5): Both use the same join/update/leave commands!
[wait time="2.0"]
# ---- Clean up ----
leave --All--
[wait time="0.5"]
jump gym10_main/menu

View File

@@ -0,0 +1 @@
uid://bh4bv8cb644be

View File

@@ -0,0 +1,98 @@
# ============================================================
# Gym 10.4 — Transforms (Mirror, Scale, Offset)
# ============================================================
# Demonstrates visual manipulation: mirroring (flip),
# scaling, offset, and manual positioning with size/rotation.
# ============================================================
leave --All--
# ---- Baseline ----
Miko (neutral): Let's explore transforms — mirror, scale, and offset.
join Miko (neutral) center [animation="Fade In"]
Miko (neutral): Here I am at default: scale=1, no mirror, no offset.
[wait time="1.5"]
# ---- Mirror (flip horizontally) ----
update Miko (neutral) center [animation="Tada" wait="true" mirrored="true"]
Miko (smile): And now I'm mirrored! I'm facing the other way.
[wait time="1.0"]
update Miko (neutral) center [animation="Tada" wait="true" mirrored="false"]
Miko (smile): And back to normal. Mirror is great for characters\
facing each other.
[wait time="1.5"]
# ---- Scale ----
leave Miko
join Miko (joy) center [animation="Fade In"]
Miko (joy): This is scale=1 — the default size.
[wait time="1.0"]
leave Miko
# Scale is set on the character resource, but we can demonstrate via update
# with manual size
join Miko (shock) pos=x0.5y0.5 size=x0.4y0.4 [animation="Bounce In"]
Miko (shock): Now I'm bigger! size=x0.4 y0.4 — 40% of viewport!
[wait time="1.5"]
join Advisor (pl5) pos=x0.2y0.5 size=x0.2y0.2 [animation="Fade In"]
Advisor (pl5): And I'm smaller — only 20% of the viewport.
[wait time="1.5"]
Miko (smile): Size differences create visual hierarchy.
Advisor (pl5): The main speaker can be larger; background characters smaller.
[wait time="1.5"]
# ---- Offset ----
leave --All--
join Miko (neutral) center [animation="Fade In"]
Miko (neutral): Offset shifts a character from their position origin.
[wait time="1.0"]
# Offset is set on the character resource, not via timeline syntax
# But we can use manual pos for the same effect
update Miko (smile) pos=x0.5y0.7 [move_time="0.8" move_trans="Sine" move_ease="In Out"]
Miko (smile): I used pos= to shift downward smoothly!
[wait time="1.0"]
update Miko (joy) pos=x0.5y0.5 [move_time="0.5"]
Miko (joy): And back to center. The move_time made it animate smoothly.
[wait time="1.5"]
# ---- Rotation ----
leave Miko
join Miko (joy) pos=x0.5y0.5 rot=15 [animation="Fade In"]
Miko (joy): I'm tilted! rot=15 degrees.
[wait time="1.0"]
update Miko (smile) pos=x0.5y0.5 rot=0 [move_time="0.5"]
Miko (smile): And back to straight. Rotate for dramatic effect!
[wait time="1.5"]
# ---- Summary ----
leave --All--
Advisor (pl5): Quick reference:
Advisor (pl5): • mirroed=true/false — flip horizontally
Advisor (doubt): • size=x1 y1 — scale from viewport (0-1)
Advisor (doubt): • pos=x1 y1 — manual position
Advisor (doubt): • rot=degrees — rotation
Advisor (doubt): • move_time=X — smooth tween for position changes
[wait time="2.0"]
jump gym10_main/menu

View File

@@ -0,0 +1 @@
uid://dcd782k6ho422

View File

@@ -29,6 +29,12 @@ directories/dch_directory={
directories/dtl_directory={ directories/dtl_directory={
"gym09_congrats": "res://docs/gyms/gym09_scene_switching/gym09_congrats.dtl", "gym09_congrats": "res://docs/gyms/gym09_scene_switching/gym09_congrats.dtl",
"gym09_intro": "res://docs/gyms/gym09_scene_switching/gym09_intro.dtl", "gym09_intro": "res://docs/gyms/gym09_scene_switching/gym09_intro.dtl",
"gym10_main": "res://docs/gyms/gym10_character_portraits/gym10_main.dtl",
"gym10_multichar": "res://docs/gyms/gym10_character_portraits/gym10_multichar.dtl",
"gym10_portrait_switch": "res://docs/gyms/gym10_character_portraits/gym10_portrait_switch.dtl",
"gym10_positions": "res://docs/gyms/gym10_character_portraits/gym10_positions.dtl",
"gym10_spine": "res://docs/gyms/gym10_character_portraits/gym10_spine.dtl",
"gym10_transforms": "res://docs/gyms/gym10_character_portraits/gym10_transforms.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",