Skip to content

dialogue

dialogue

Branching dialogue with a typewriter reveal, choices and rich text.

This is an opt-in module, imported on its own with import nim2d/dialogue. The core engine does not pull it in.

A conversation is a Script: nodes keyed by id, each with a speaker, an optional portrait, one or more pages of text, and choices that branch to other nodes. You build a script as plain Nim data (a parser for a file format could target the same shape later), hand it to newDialogue, and start it. Each frame the game calls update and draw, and routes keys through handleKey.

Text is rich. A page is a string with a small markup the renderer understands: *italic* and **bold** as in markdown, plus bracket tags closed with [/] and nestable: [b] bold, [i] italic, [o] a per-character outline (a border on the glyphs, not the box), [#ffcc00] a hex color and [gold] a palette name. So "The [#ff5555]dragon[/] **roars**. *You* feel [o]afraid[/]." works.

Two ways to render. The simple path is a Style record (a font set, a box, colors, padding) feeding the built-in renderer. The advanced path sets Hooks to take over the box, the text or the choices, any left nil falling back to the default, so a game can lay the message out however it likes while keeping the markup.

Choice

type Choice = object

Fields

  • text string – the label shown
  • goto string – the node it leads to ("" ends the dialogue)
  • cond proc (): bool – when set, the choice is hidden while it returns false
  • action proc () – when set, runs as the choice is picked

Node

type Node = object

Fields

  • id string
  • speaker string – optional name label
  • portrait Image – optional image drawn beside the text
  • pages seq[string] – one or more screens of text, shown before the choices
  • choices seq[Choice] – empty means a plain line
  • next string – where a choiceless node goes on advance ("" ends)
  • onEnter proc () – optional side effect when the node becomes current

Script

type Script = ref object

Fields

  • nodes Table[string, Node]

RevealKind

type RevealKind = enum

Values

  • rvTypewriter – one character at a time
  • rvWord – one word at a time
  • rvFade – all at once, fading in
  • rvInstant – shown immediately

Reveal

type Reveal = object

Fields

  • kind RevealKind
  • cps float – characters (or words for rvWord) per second
  • punctuationPause float – extra seconds after . ! ? , ; :
  • fadeTime float – seconds for rvFade
  • onGlyph proc (r: Rune) – called for each character as it appears
  • custom proc (d: Dialogue; dt: float): bool – a fully custom reveal: advance it by `dt`, set `d.shown` (out of `d.totalRunes`), and return true when complete. Used when set, whatever `kind` is.

Align

type Align = enum

Values

  • alLeft
  • alCenter
  • alRight

Style

type Style = object

Fields

  • fonts tuple[regular, bold, italic, boldItalic: Font] – the regular font is required; the others are used for bold/italic when set, and faked otherwise (bold by a double draw, italic by a shear)
  • box tuple[x, y, w, h: float] – where the box sits; leave w at 0 for an automatic strip across the bottom of the window
  • padding float
  • roundness float
  • lineSpacing float
  • align Align
  • boxColor Color
  • textColor Color
  • speakerColor Color
  • choiceColor Color
  • choiceHighlight Color
  • outlineColor Color
  • outlineWidth float – border thickness for outlined text (0 uses 1.5)
  • outlineText bool – outline every character, not only `[o]` spans

Hooks

type Hooks = object

Fields

  • drawBox proc (nim2d: Nim2d; d: Dialogue)
  • drawText proc (nim2d: Nim2d; d: Dialogue)
  • drawChoices proc (nim2d: Nim2d; d: Dialogue)

DialogueState

type DialogueState = enum

Values

  • dsRevealing – text is still appearing
  • dsWaiting – a page is fully shown, waiting to advance
  • dsChoosing – the last page is shown and choices are up
  • dsDone – the conversation has ended

Dialogue

type Dialogue = ref object

Fields

  • script Script
  • style Style
  • reveal Reveal
  • hooks Hooks
  • current string – current node id
  • page int – current page within the node
  • state DialogueState
  • cursor int – highlighted choice (index into the visible choices)
  • shown int – revealed rune count
  • totalRunes int
  • onFinish proc () – called once when the conversation ends

newScript

proc newScript(): Script

An empty script.

Returns

Script

add

proc add(s: Script; node: Node)

Add a node, or replace one with the same id.

Parameters

  • s (Script)
  • node (Node)

has

proc has(s: Script; id: string): bool

Whether the script has a node with this id.

Parameters

  • s (Script)
  • id (string)

Returns

bool

choice

proc choice(text, goto: string; cond: proc (): bool = nil; action: proc () = nil): Choice

A choice leading to goto, optionally gated by cond and with the side

effect action that runs when it is picked.

Parameters

  • text (string)
  • goto (string)
  • cond (proc (): bool)
  • action (proc ())

Returns

Choice

defaultReveal

proc defaultReveal(): Reveal

A typewriter reveal at a readable speed with a small pause on punctuation.

Returns

Reveal

defaultStyle

proc defaultStyle(font: Font): Style

A dark rounded box with light text, ready to use. Set box for a custom

position, or leave it for an automatic strip across the bottom of the window.

Parameters

  • font (Font)

Returns

Style

currentNode

proc currentNode(d: Dialogue): Node

The node being shown, or an empty node if the current id is unknown.

Parameters

  • d (Dialogue)

Returns

Node

visibleChoices

proc visibleChoices(d: Dialogue): seq[Choice]

The choices on the current node whose cond allows them.

Parameters

  • d (Dialogue)

Returns

seq[Choice]

start

proc start(d: Dialogue; nodeId: string)

Begin (or jump to) a node, from its first page. Runs the node's onEnter.

Parameters

  • d (Dialogue)
  • nodeId (string)

update

proc update(d: Dialogue; nim2d: Nim2d; dt: float)

Advance the reveal. Call once a frame while the dialogue is active. Takes

nim2d because the text is laid out against the window and the box.

Parameters

  • d (Dialogue)
  • nim2d (Nim2d)
  • dt (float)

active

proc active(d: Dialogue): bool

Whether a conversation is currently up.

Parameters

  • d (Dialogue)

Returns

bool

isRevealing

proc isRevealing(d: Dialogue): bool

Whether the current page is still appearing.

Parameters

  • d (Dialogue)

Returns

bool

select

proc select(d: Dialogue)

Confirm the highlighted choice.

Parameters

  • d (Dialogue)

choose

proc choose(d: Dialogue; index: int)

Pick a visible choice directly by index (for mouse selection).

Parameters

  • d (Dialogue)
  • index (int)

advance

proc advance(d: Dialogue)

The single "continue" action. While revealing it skips to the full text;

while waiting it moves to the next page or ends the line; while choosing it confirms the highlighted choice.

Parameters

  • d (Dialogue)

moveCursor

proc moveCursor(d: Dialogue; delta: int)

Move the choice highlight, wrapping around.

Parameters

  • d (Dialogue)
  • delta (int)

handleKey

proc handleKey(d: Dialogue; key: Key)

Route a key: space or enter advances and confirms, the arrows move the

choice highlight. Call from the engine's keydown.

Parameters

  • d (Dialogue)
  • key (Key)

draw

proc draw(d: Dialogue; nim2d: Nim2d)

Draw the box, the revealed text and any choices. A no-op when the dialogue

is done. Call inside the engine's draw, after the world.

Parameters

  • d (Dialogue)
  • nim2d (Nim2d)

choiceAt

proc choiceAt(d: Dialogue; nim2d: Nim2d; mx, my: float): int

The index of the visible choice under (mx, my) with the default choice

layout, or -1. Useful for mouse selection.

Parameters

  • d (Dialogue)
  • nim2d (Nim2d)
  • mx (float)
  • my (float)

Returns

int

newDialogue

proc newDialogue(script: Script; style: Style; reveal: Reveal = defaultReveal()): Dialogue

A dialogue player over script, drawn with style. Call start to begin.

Parameters

  • script (Script)
  • style (Style)
  • reveal (Reveal)

Returns

Dialogue

DialogueScene

type DialogueScene = ref object

A Scene wrapping a Dialogue, forwarding update, draw and input. Push it

on a SceneManager and set dlg.onFinish to pop it when the talk ends.

Fields

  • dlg Dialogue

newDialogueScene

proc newDialogueScene(dlg: Dialogue): DialogueScene

Wrap a dialogue as a scene.

Parameters

  • dlg (Dialogue)

Returns

DialogueScene

Generated with mkdocstrings-nim