visual-novel

Category: Design Risk: Low risk ★ 4.6 · Rating 4.6/5 (804) gamedev-skills/awesome-gamedev-agent-skills Apache-2.0

Rating is derived from the repo's GitHub stars and shown for reference.


name: visual-novel
description: >
Build a visual novel: a branching script, character and background display, a text box with choices,
save/load, backlog, and skip/auto. Use for a VN, dating sim, or branching story game.

Visual Novel

A playbook for visual novels — the branching script, the presentation (text box, characters,
backgrounds), choices, and the quality-of-life systems players expect (save anywhere, backlog,
skip, auto). This is a compositional skill: it drives a dialogue engine and a UI layer. It
does not re-teach the dialogue engine or UI nodes; it defines the script model and the player
conveniences that make a VN pleasant to read.

When to use

  • Use when the game is mostly reading branching text with character art and backgrounds:
    visual novel, dating sim, branching interactive fiction, story-choice game.
  • Use when designing a choice/route structure, story flags, or VN conveniences (backlog,
    skip, auto-advance, save-anywhere).

When not to use: dialogue as one feature inside a larger game → rpg consuming
dialogue-systems. Card/board play → other genres. For the branching-script engine itself,
use dialogue-systems (Ink / Yarn Spinner).

Core loop

Read a line → advance → (at a branch) make a choice → the story branches on flags/choices →
read on → reach an ending.
The "game" is the shape of the branching and whether choices
feel consequential; everything else is presentation and convenience.

Must-have systems

  1. Branching script — ordered lines + choices + jumps, with conditions and variables (Ink/Yarn).
  2. Text box — speaker name, body text, typewriter reveal, advance on click/key.
  3. Characters — sprites with expressions/poses, positions, show/hide transitions.
  4. Backgrounds + transitions — scene images, fades/dissolves.
  5. Choices — present options, gate some on flags, record the pick.
  6. Story state — flags/variables that branch the script and unlock content.
  7. Save/load (save-anywhere) — full script position + state; multiple slots; quick save.
  8. VN conveniences — backlog/history, skip (read text), auto-advance, text-speed setting.
  9. Audio — music per scene, SFX, optional voice clips.

Design knobs

Knob Effect Notes
Text speed / instant reading comfort Always allow instant + a skip.
Auto-advance delay hands-free reading Tunable; pause on choices.
Skip scope re-reading Skip read text only by default.
Branch breadth/depth replay value vs. cost Branches multiply writing/art work.
Flag-gated content reactivity Lines/choices that check past decisions.
Route structure story shape Branch-and-merge vs. distinct routes (refs).
Choice visibility fairness Show locked choices vs. hide them.
Backlog length convenience Keep enough to re-read recent context.

Patterns

1. Script as data the engine walks

# Pseudocode. Lines, choices, and jumps as data — usually authored in Ink/Yarn and stepped
# through by that runtime. The engine asks the script for "the next thing to show".
node = script.current()
if node.kind == "line":
    show_text(node.speaker, node.text)        # wait for advance input
elif node.kind == "choice":
    options = [o for o in node.options if condition_met(o.condition, flags)]  # gate by flags
    show_choices(options)                      # wait for selection
elif node.kind == "set":
    flags[node.var] = eval_expr(node.expr, flags)
script.advance(selected_option_or_none)

2. Typewriter reveal + advance (skippable)

# Pseudocode. Reveal characters over time; a click first completes the line, then advances.
def show_text(speaker, text):
    name_label.text = speaker
    revealed = 0
    while revealed < len(text):
        if advance_pressed():                  # first press: reveal the whole line instantly
            revealed = len(text); break
        revealed += chars_per_second * dt
        body_label.text = text[:int(revealed)]
        push_to_backlog_when_complete(speaker, text)
    wait_for_advance()                          # second press: go to the next line

3. Choice sets a flag that branches later content

# Pseudocode. Choices write flags; later conditions read them — that is "reactivity".
def on_choice(option):
    if option.set: flags[option.set] = True     # e.g. flags["helped_npc"] = True
    script.jump(option.target)                   # follow the branch

# Elsewhere, a line/choice/ending checks the flag:
if flags.get("helped_npc"): play_route("good_ending") else: play_route("neutral_ending")

Pitfalls / failure modes

  • Save that only stores a checkpoint → VNs need save-anywhere. Persist the exact script
    position and all flags/variables (and seen-text data) so a load resumes the same line.
  • Presentation logic baked into the script → unmaintainable. Keep content (text, choices)
    in the script and how it looks (sprites, transitions) in the engine layer.
  • No skip/auto/backlog → readers feel trapped, especially on replays. These are expected
    baseline features, not extras.
  • Skipping unread text → players miss content. Skip should fast-forward read text only.
  • Choices with no consequence → branches that reconverge instantly feel fake. Set flags that
    visibly change later lines, choices, or endings.
  • Combinatorial branch explosion → unshippable. Prefer branch-and-merge with a few flagged
    variations over fully distinct trees (refs).
  • Lost reading context → no backlog to re-read the last lines. Keep a history buffer.
  • Hardcoded language → no localization path. Keep text in data keyed for translation.

Composition (build it from these skills)

  • Script engine: dialogue-systems (Ink / Yarn Spinner) — branching, conditions, variables, localization hooks.
  • Presentation: game-ui-ux for text-box/choice-menu layout, scaling, and safe areas; godot-ui-control for the concrete text box, choice menu, name plate, and backlog UI.
  • Persistence: save-systems for save-anywhere slots, seen-text/skip data, and settings.
  • Audio: audio-design for per-scene music, SFX, and voice playback.
  • Visuals: the engine animation/Tween skill for sprite/background transitions; shader-programming for dissolves.
  • Process: prototype-fast to test the branch structure in plain text before adding art.

References

  • For the branching data model, route structures (branch-and-merge vs. routes), flags/variables,
    save-anywhere + backlog/skip data, and the content/presentation split, read
    references/script-and-flow.md.