Skip to content

Composition and reuse

When one Story starts repeating the same structure, move that structure into reusable sprites, layers, or design files instead of duplicating long YAML blocks.

Reuse starts with custom sprite files

samples/story/composite-sprite.story.yaml creates three instances from the same checked-in sprite definition:

yaml
- create@letter:
    ./sprites/split-flap: A
    nextCharacter: B
    perspective: 820
    x: 198
    y: 130

- create@digit:
    ./sprites/split-flap: "7"
    nextCharacter: "8"
    perspective: 820
    x: 294
    y: 130

Each create call constructs a fresh instance, so the scene can reuse one definition without sharing runtime state.

Public fields and actions live in the sprite definition

samples/story/sprites/split-flap.sprite.yaml declares what the outside Story is allowed to set and call:

yaml
members:
  - field@character: string
    default: " "

  - field@nextCharacter: string
    default: " "

  - action@flip:
      - field@to: string
        required: true

That is why the parent Story can set nextCharacter during create and later call letter.flip@letterB: B.

Layers compose child sprites into one reusable unit

Inside the same sprite file, the reusable cell is built from nested layers and primitives:

yaml
- create@front:
    layer:
      - rect@panel: 0,0,52,38
        fill: "#1b2a35"
      - text@glyph: " "
        fontSize: 40
        fontFamily: "Consolas"
        fontWeight: bold
        color: "#f4f1df"
        x: 26
        y: 38
        align: center

The outer Story treats this as one Sprite, but the reusable definition is free to manage its own internal tree.

Each instance keeps its own timeline

The parent Story calls the same public action on separate instances:

yaml
- letter.flip@letterB: B
  duration: 0.8s
- digit.flip@digit8: "8"
  duration: 0.5s
- tail.flip@tailA: A
  duration: 0.65s

- wait: $letterB
- wait: $digit8
- wait: $tailA

Each action label becomes its own completion source, so the Story can coordinate several independent instances without flattening their private logic.

Reuse structure, theme, and timing separately

As your Stories grow, keep these concerns separate:

  • Structure: custom sprites such as ./sprites/split-flap
  • Theme: shared design tokens and styles in .design.yaml files
  • Timing: animation tokens such as spring@normal or tween@reveal

That separation keeps each sample easier to read and update.

Preview the reuse sample

powershell
story preview samples/story/composite-sprite.story.yaml

Then continue with Design system to extract shared theme values out of the Story file.

Rune Project brings Rune Story authoring together with the Rune Engine rendering foundation.