View Categories

Narrative Markup Language

13 min read

Narrative Markup Language (.nar) Documentation

Narrative Markup Language (.nar) Documentation #

Overview #

The .nar file format is designed to script narrative events in your Game Maker projects. With this format, you can define scenes, dialogue, choices, variable assignments, conditional branching, background transitions, and actor actions such as creation, removal, sprite changes, and animations.

This documentation is the definitive guide to writing .nar files, covering every command and option available to ensure you can create immersive and dynamic narratives.

File Structure #

A typical .nar file is a plain text document where each line represents a command or piece of narrative content. Indentation is used to indicate nested blocks (for example, within conditionals or loops).

Tips:

  • Use consistent indentation (spaces or tabs) for clarity.
  • Avoid excessive nesting to keep the file maintainable.
  • The order of lines is critical, as the parser processes them sequentially.

Comments #

Comments document your narrative and are ignored by the parser. They can be on their own line or inline with other commands.

Start a comment with the symbol # (outside of string literals):

# This is a full line comment
Some narrative text # This is an inline comment

Meta Blocks #

Meta blocks allow you to define metadata such as the title, author, or date of your narrative file. They are enclosed by the tags {start_meta} and {end_meta}. Each line inside should begin with a meta keyword (in curly braces) followed by its value and an optional comment.

Below is an expanded meta block example with syntax highlighting:

{start_meta}
{author} Name # Author name
{story_title} Title # The title of your story
{description} Description of the story # A short description of your story
{version} 1 # Version number
{date} 08/01/2025 # Creation or last modified date
{genre} Horror, Mystery # Story genre classification
{rating} 16+ # Content rating/age recommendation
{language} English # Story language
{series} Acre Shore # Series name if part of one (optional)
{episode} 1 # Episode/chapter number in series (optional)
{tags} # Content tags/themes
{copyright} © Author name 2025 # Copyright information
{credits} # Additional credits/acknowledgments (optional)
{end_meta}

Scenes #

Begin a new scene with the command @scene followed by the scene name. Scenes help segment your narrative into manageable parts.

@scene Introduction

You can also jump between scenes using destination tags and goto commands (covered below).

Dialogue #

Dialogue lines start with a character’s name enclosed in square brackets, followed by the dialogue text. This automatically sets the speaker and dialogue variables in the engine.

[Alice] Hello there, welcome to our story!
[Bob] Thanks, Alice. Glad to be here.

You can insert variables into dialogue using the syntax ${variable_name}.

Character Name Colors #

You can assign colors to character names to make them visually distinct in dialogue. Use the @name_color command:

@name_color Alice, #0000FF
  @name_color Bob, #FF0000
  
  [Alice] My name will appear in blue!
  [Bob] And mine will be red!

The syntax is: @name_color character_name, color_code

The color code should be in the format #RRGGBB (hexadecimal RGB values).

Once a color is assigned to a character name, it will be applied automatically whenever that character speaks.

Choices #

Use the command @choice to present multiple narrative options. After this command, list each option on a new line using the format:

Option text > destination_tag

Example:

@choice
Go left > left_path
Go right > right_path

This lets the player choose which narrative path to follow.

If Statements #

The .nar format supports conditional branching using if statements. Conditions can compare variables or literal values with operators like =, <, >, <=, and >=.

Example:

if ${score} > 10
    [Narrator] You have achieved a high score!
else
    [Narrator] Keep trying to beat the high score.

Important Formatting Rules:

  • The if statement must start at the beginning of the line (no indentation)
  • The content inside the if block must be indented (with spaces or tabs)
  • The else statement must be at the same indentation level as the if statement (no indentation)
  • The content inside the else block must be indented

Incorrect Format (Will Not Work):

if ${score} > 10
[Narrator] You have achieved a high score!
else
[Narrator] Keep trying to beat the high score.

Tips:

  • Logical operators such as and, or, and not can be used for compound conditions.
  • Always define your variables before referencing them in conditions.
  • The indentation must be consistent throughout your if/else blocks.

Background System #

The .nar format provides a powerful background system that supports multiple layers, animations, and transitions. This allows you to create dynamic scenes with parallax effects, scrolling elements, and other visual enhancements.

Basic Background Commands #

The simplest way to change the scene background is with the @background command:

@background scene1.png
@background scene2.png transition: true

The background images are loaded from the res/img/background/ directory. Set the transition parameter to true if you want a fade effect.

Layered Backgrounds #

For more complex scenes, you can create multiple background layers with different depths and anchor points:

@background_layer sky, sky.png, 1100
@background_layer mountains, mountains.png, 1050
@background_layer foreground, trees.png, 1000, true, 50%, 100%

The parameters for @background_layer are:

  • layer_id: A unique identifier for the layer
  • sprite_file: The filename of the background image
  • depth: Drawing depth (higher values are drawn behind lower values)
  • visible: Optional visibility parameter (true/false)
  • anchor_x: Optional horizontal anchor point (pixel value or percentage, default: “50%”)
  • anchor_y: Optional vertical anchor point (pixel value or percentage, default: “50%”)

The anchor point determines the origin of the background image. By default, backgrounds are anchored at their center (50%, 50%). You can use percentages (e.g., “0%”, “100%”) or pixel values (e.g., “150”, “200”) to set the anchor point.

Background Anchor Points #

You can change the anchor point of an existing background layer:

@background_anchor mountains, 0%, 50%
@background_anchor foreground, 100%, 100%

The parameters for @background_anchor are:

  • layer_id: The identifier of the layer to modify
  • anchor_x: Horizontal anchor point (pixel value or percentage)
  • anchor_y: Vertical anchor point (pixel value or percentage)

Changing the anchor point affects how the background is positioned and how animations are applied. For example:

  • 0%, 0%: Anchors at the top-left corner
  • 100%, 0%: Anchors at the top-right corner
  • 0%, 100%: Anchors at the bottom-left corner
  • 100%, 100%: Anchors at the bottom-right corner
  • 50%, 50%: Anchors at the center (default)

Background Animations #

You can animate background layers to create dynamic effects:

@animate_background mountains, parallax, 20
@animate_background clouds, scroll_horizontal, 1.5
@animate_background water, sway, 5
@animate_background train, train_effect, 3

The parameters for @animate_background are:

  • layer_id: The identifier of the layer to animate
  • animation_name: The type of animation to apply
  • speed_or_amount: Controls the speed or intensity of the animation

Available animations include:

  • scroll_horizontal: Scrolls the background horizontally (positive = right, negative = left)
  • scroll_vertical: Scrolls the background vertically (positive = down, negative = up)
  • parallax: Creates a parallax effect based on mouse position
  • sway: Gentle side-to-side swaying motion
  • bounce: Subtle up-and-down bouncing motion
  • shake: Random shaking effect
  • zoom_pulse: Pulsing zoom effect
  • train_effect: Specialized effect simulating train movement

To stop an animation:

@stop_background_animation clouds

Changing Background Layers #

You can change a specific background layer with optional transition:

@change_background sky, night_sky.png, true

The parameters are:

  • layer_id: The identifier of the layer to change
  • sprite_file: The new background image
  • transition: Optional fade transition (true/false)

Background Groups and Crossfading #

You can group multiple background layers and crossfade between groups:

@background_group day_scene, day_sky, day_mountains, day_foreground
@background_group night_scene, night_sky, night_mountains, night_foreground
@crossfade_backgrounds day_scene, night_scene, 3.0

The parameters for @background_group are:

  • group_id: A unique identifier for the group
  • layer_id1, layer_id2, ...: The identifiers of the layers in the group

The parameters for @crossfade_backgrounds are:

  • from_group_id: The identifier of the starting group
  • to_group_id: The identifier of the ending group
  • duration: Optional crossfade duration in seconds (default: 1.0)

Removing Background Layers #

To remove a background layer:

@remove_background mountains

Example: Train Scene with Scrolling Landscape #

@background_layer sky, blue_sky.png, 1100
@background_layer landscape, countryside.png, 1050
@background_layer train, train_interior.png, 1000

@animate_background landscape, scroll_horizontal, -2
@animate_background train, train_effect, 3

[Conductor] Welcome aboard the express train to Meadowvale!

@wait 2s

[Passenger] The countryside is beautiful this time of year.

Fading Background Layers #

You can fade individual background layers in or out:

@fade_background clouds, in, 2.0
@fade_background rain, out, 3.5

The parameters for @fade_background are:

  • layer_id: The identifier of the layer to fade
  • fade_type: Either “in” to fade in or “out” to fade out
  • duration: Optional fade duration in seconds (default: 1.0)

When fading in, the layer will be made visible but with zero opacity, then gradually increase to full opacity. When fading out, the layer will gradually decrease to zero opacity, then be hidden.

Actor Commands #

The .nar format includes several commands for managing actors in your scenes. The system supports both single-sprite actors and layered actors with multiple components.

Single-Sprite Actors #

Use the command @actor with the following parameters:

  • actor_id: A unique identifier for the actor.
  • sprite_file: The filename of the actor’s sprite.
  • x and y: The starting coordinates (can be pixels or percentages like “50%”).
  • depth: Drawing depth (actors with higher values are drawn behind those with lower values).
  • Optional: visible – either true or false (default is true).
  • Optional: breathing – a number for intensity (0.02 is default), 0 or false to disable.
@actor hero, hero_sprite.png, 50%, 80%, 10, true, 0.03
    @actor statue, statue.png, 75%, 80%, 20, true, 0

Layered Actors #

For more complex characters with multiple layers, use the @actor_begin and @actor_end block format:

@actor_begin character_id
        body_base: character_body.png
        body_layer: character_clothes.png
        head_base: character_head.png
        face: character_neutral.png
        blink: character_blink.png
        head_layer: character_hat.png
        x: 50%
        y: 80%
        depth: 0
        visible: true
        breathing: 0.03
        expressions: {happy:happy.png,sad:sad.png,angry:angry.png}
    @actor_end

All layers are optional. The system will automatically handle parent-child relationships between layers. Set breathing to 0 or false to disable the breathing animation, or set it to a number to control the intensity (default is 0.02).

Changing Expressions #

For layered actors with defined expressions, use @expression to change the face:

@expression character_id, happy

Changing Individual Layers #

Update a specific layer of a layered actor using @change_layer:

@change_layer character_id, head_layer, new_hat.png

Toggling Layer Visibility #

Show or hide specific layers with @toggle_layer:

@toggle_layer character_id, head_layer, false

Removing an Actor #

Remove an actor with the command @remove_actor followed by the actor ID:

@remove_actor hero

Changing an Actor’s Sprite #

For single-sprite actors, change the sprite with @change_sprite:

@change_sprite hero, hero_happy.png

Animating an Actor #

Animate an actor with @animate followed by the actor ID, animation name, and an optional “wait” parameter:

@animate hero, bounce
@animate villain, shake, wait

Available animations include:

  • slide_in_right, slide_in_left, slide_in_top, slide_in_bottom
  • slide_out_right, slide_out_left, slide_out_top, slide_out_bottom
  • bounce, shake
  • fade_in, fade_out
  • slide_in_right_fade, slide_out_right_fade

If the “wait” parameter is included, the narrative will pause until the animation completes.

Actor Entrance and Exit #

Simplified commands for actor entrances and exits:

@enter hero, slide_in_right, wait
@exit villain, fade_out, remove, wait

The @enter command takes an actor ID, optional animation name (default: “fade_in”), and optional “wait” parameter.

The @exit command takes an actor ID, optional animation name (default: “fade_out”), optional “remove” parameter to delete the actor after exit, and optional “wait” parameter.

Audio System #

The .nar format includes commands for playing music and sound effects to enhance your narrative experience.

Playing Music #

Use the @play_music command to play background music with the following parameters:

  • track_id: The identifier of the music track (without file extension)
  • loop: Optional boolean to specify if the music should loop (default: true)
  • volume: Optional volume level from 0.0 to 1.0 or as a percentage (default: 1.0)
  • fade_in: Optional boolean to enable fade-in effect (default: false)
  • fade_duration: Optional duration of the fade in seconds (default: 1.0)
@play_music main_theme
@play_music battle_music, true, 0.8, true, 2.0
@play_music ambient, true, 50%

Music files should be placed in the res/sound/music/ directory as WAV files.

Playing Sound Effects #

Use the @play_sound command to play sound effects:

  • sound_id: The identifier of the sound effect (without file extension)
  • loop: Optional boolean to specify if the sound should loop (default: false)
  • volume: Optional volume level from 0.0 to 1.0 or as a percentage (default: 1.0)
@play_sound door_open
@play_sound rain_ambience, true, 0.5
@play_sound explosion, false, 75%

Sound effect files should be placed in the res/sound/fx/ directory as WAV files.

Stopping Sounds #

Use the @stop_sound command to stop a specific sound effect:

@stop_sound rain_ambience
@stop_sound rain_ambience, true, 2.0

The parameters are:

  • sound_id: The identifier of the sound to stop
  • fade_out: Optional boolean to enable fade-out effect (default: false)
  • fade_duration: Optional duration of the fade in seconds (default: 0.5)

Stopping Music #

Use the @stop_music command to stop the currently playing music:

@stop_music
@stop_music true, 3.0

The parameters are:

  • fade_out: Optional boolean to enable fade-out effect (default: false)
  • fade_duration: Optional duration of the fade in seconds (default: 1.0)

Crossfading Music #

Use the @crossfade_music command to smoothly transition between music tracks:

@crossfade_music new_theme
@crossfade_music calm_music, 3.0, true, 0.7

The parameters are:

  • track_id: The identifier of the new music track
  • fade_duration: Optional duration of the crossfade in seconds (default: 2.0)
  • loop: Optional boolean to specify if the new music should loop (default: true)
  • volume: Optional volume level for the new track (default: 1.0)

Setting Volume #

Use the @set_music_volume and @set_fx_volume commands to adjust the master volume levels:

@set_music_volume 0.5
@set_fx_volume 75%

Volume can be specified as a decimal between 0.0 and 1.0, or as a percentage.

Waiting for Audio #

Use the @wait_for_audio command to pause the narrative until a sound effect completes:

@play_sound long_effect
@wait_for_audio long_effect

This is useful for synchronizing narrative progression with audio cues.

UI Commands #

The .nar format includes several commands for creating UI elements and notifications.

Toast Notifications #

Display temporary notifications that slide in from the top-right of the screen using the @toast command:

@toast This is a simple notification
@toast This will display for 5 seconds, 300
@toast This has a title, 180, Important Message
@toast This has a colored title, 180, Warning, red
@toast Custom color with hex code, 180, Custom, #FF00FF

The syntax is: @toast message, [duration], [title], [color]

  • message: The main text to display (required)
  • duration: How long the toast stays visible in steps (optional, default: 180)
  • title: An optional title displayed above the message
  • color: The color for the title, can be a named color or hex code (optional, default: white)

Named colors include: red, blue, green, yellow, orange, purple, pink, cyan, black, white, and gray/grey.

Advanced Options & Debugging #

This section covers advanced features and tips to help you debug your .nar files:

  • Debugging Output: The parser logs detailed messages for each processed line. Use these logs to troubleshoot and refine your narrative.
  • Indentation Consistency: Ensure that nested blocks (such as within if statements) use consistent indentation to avoid errors.
  • Error Handling: The parser will log errors when files are missing or commands fail. Use these messages to resolve issues.
  • Variable Replacement: Variables are replaced dynamically. Ensure variables are defined before use.
  • Conditional Branching: Test all branches of your logic. Use the else clause as a fallback.

Best Practices #

To create robust and maintainable narratives, consider these best practices:

  • Organize your files with clear scene breaks using the @scene command.
  • Document your narrative logic with comments.
  • Maintain consistent formatting and indentation.
  • Test all narrative branches and actor commands for smooth transitions.
  • Review debugging output to catch issues early.

Conclusion #

This guide is your comprehensive reference for writing .nar files in Game Maker. It covers everything from basic syntax and scene setup to advanced actor manipulation and debugging techniques. Use it to craft rich, dynamic narratives that bring your stories to life.

Happy scripting! 😊🚀

MENU

Tools