Skip to content

Tutorial Writing Text

johnjohto edited this page Jul 28, 2026 · 3 revisions

Tutorial: Writing Text

Write prose. The engine wraps. Every box in the engine — dialogue, battle messages, the narration band, Pokédex descriptions — renders through one text pipeline that word-wraps to the classic 18-column measure and pages automatically. You never hand-break lines to fit the screen.

{"cmd": "say", "text": "The old keeper looks up from the ledger and studies you for a long moment before speaking."}

That's one sentence, no line breaks — the box wraps it to 18 columns, shows two lines at a time, and pages with the ▼ prompt, exactly like the classics did.

Deliberate breaks

Two escapes remain for when you want control:

Escape Meaning
\n force a line break here
\f force a page break here (the ▼ pause)
{"cmd": "say", "text": "I have three rules.\fNo running.\nNo shouting.\nNo shortcuts."}

The first page ends at the \f; the second page lists the rules on their own lines (two visible at a time).

Where it applies

  • say / notice / ask / show_text — the dialogue box: 18 columns, 2 lines per page.
  • Battle messages — same box, same measure.
  • narrate — the walk-through band wraps to the same 18 columns but shows at most 2 lines and never pages (the player is walking; there is no ▼). Keep narration short. If it wraps past two lines, the rest is cut — and --validate warns you before a player ever sees it.
  • Pokédex descriptions (desc in a species file) — 18 columns, 3 lines per page, and long prose now pages automatically: write the whole flavor text as one string and the dex screen deals it out.

The safety net

Three things can still go wrong in text, and all of them are loud at --validate time instead of silent on screen:

  • A single word wider than 18 characters can't wrap (words are never hyphenated). It draws clamped at the box border, and text.unbreakable_word warns naming the word.
  • A character with no glyph in your project's charmap draws nothing. lang.missing_glyph warns naming the exact characters — this now covers all your text, not just language packs.
  • A narrate longer than two wrapped lines truncates; text.narrate_overflow warns with the offending text.

Each warning is reviewable: if it's deliberate, suppress it with a reason in data/lint_suppressions.json and your project validates clean.

Translations get it free

Language packs ride the same pipeline: a translated string re-wraps to the measure on its own, so translators write natural prose too — no mirroring the source's line breaks. See Language Packs.

Clone this wiki locally