What are action rpgs?

Writing dialog for games should be easy. Most game conversations are simple exchanges. No tricky game code is needed, it's just two or more people speaking one at a time. By making game conversations easy to write and edit, the more time we have focus on the writing itself. This article introduces a mark-up language that makes it easy for anyone to write game dialog.

Roots

Look at this excerpt from a movie script:

A script excerpt from Indiana Jones.

The formatting here is clean and easy to follow. This structure is a good starting point when thinking about ways to author game conversation.

Of course movies and games are very different:

  • Movies are director driven, games are player driven
  • Movies are linear, games can branch
  • Movies are immutable, games have state

Practically, these differences mean game dialog doesn't follow a single master-script, instead it's formed of many miniscripts that the player may or may not encounter as they play the game. Games need some mechanism to decide when to show a script to player. This is a mechanism that can be layered on top of the dialog and this article doesn't discuss this "flow-management" but it's worth being aware of.

The final chapters of the How to Make an RPG book teach you to create a small RPG and it has cutscenes and conversations. You can see one below:

How conversation is done in How to Make an RPG.

The above dialog is not as clean as the movie script but still it's readable. The dialog formatting makes it easy to use in the gamecode but it's no fun to write! We can do better.

A More Natural Way to Write

This is what I've been thinking about recently; how would I define a concise language that can be used to author dialog for games. (When I say "language" I mean something like a domain specific language / markup).

Here's a portion of the above cutscene shown above but formatted in this new language:

How conversation is done in How to Make an RPG.

That's easier to write! This language is a work in progress but it's currently useful and I want to share where I am with it.

How is this actually used? Well, when writing a game you'd write most scripts in this nice friendly language. The game then loads and parses these scripts into a data structure. As the game runs it uses the datastructures to display lines from the script. In a JRPG this means these scripts are shown as textboxes.

Goals

The goals for this language:

  • Text based.
  • Easy to write.
  • Presentation agnostic.
  • Allow things to get complicated when needed.

I'm not sure I'll be able to achieve all these goals but they're the ones I'm keeping in mind. (If it all falls apart I'll have a language that's pretty good at writing JRPG dialog).

Each script is a self contained text file. This means they can be edited by many different programs, they're simple to integrate in a tool chain and work well with source control. They're also easy to share and modify.

Until very recently XML was a incredibly popular format for human-editable data in the games industry. In fact, we may still be living in that time. XML isn't easy to edit, it's verbose, it's too easy generate a bad-XML file by missing out a closing tag or forgetting to write a /. The poor designer who has to edit these files is going to have a rough time. The hardest thing about writing dialog should be the writing itself not dealing formating and conforming to some artibary specification. Therefore this scripting language strives to get out of the authors way and let the writing flow.

The dialog language does not define how it's used, or even how it should be parsed! This is up to the game that's going to use it. Writers should to be able to add metadata to the scripts but what the data is and how it's used is left up to the presentation layer (in this case that would be the game). This means it's a format can be used widely and has a tight focus on the value it provides; allowing dialog to be written in a structured way.

Games are complicated and there will be a need for callbacks or even conditional callbacks into the game code from the conversation script. This should be possible!

Elder:
Well, now we must rebuild.
Here take this.
<script>
    if villagers_saved > 5 then
        Give("mega_potion")
    else
        Give("potion")
    end
</script>

My preference is to keep code out of scripts as much as possible. Debugging game code embedded in conversation scripts is really painful! In the above example I'd prefer the code to be predefined. Here's how we might rewrite it:

Elder:
Well, now we must rebuild.
Here take this. <script>SaveVillageReward()</script>

Predefined scripts may not always be desirable if there's a lot of iteration going on. There's even a reasonable case to be made that keeping code next to the text makes it more likely to be kept in sync.

Use

It's one thing to define a language, it's another to parse it and use it in a game. The parser I have at the moment is very simple. There two types of text; speaker identifiers and words being spoken. Each line of text separated by an empty line is a called a page of text. Pages represent chunks of speech. A page might indicate when the speaker takes a breath or moves on to a new topic. Pages stop the speaker saying everything as one long run on sentence.

Speaker Id

The speaker id starts after a new line and is formed of all text before a colon.

Name: Hello

Here the speaker-id is Name and the spoken text is Hello.

The newline requirement means a : symbol in text doesn't need escaping and it's valid to write something like this:

Student: The book was called "Understanding Comics: The Invisible Art"

Text Pages

Text separated by an empty line is considered a new page of text.

Paul:
Hello.

My name is Paul.

When parsing "Hello." and "My name is Paul." are separated into two pages of conversation, instead of one continuous thought. In Lua you might parse this into a table that looks like this:

{
    {
        speaker = "Paul",
        text =
        {
            "Hello.",
            "My name is Paul"
        }
    }
}

If you don't have the space they're considered the same page.

Paul:
Hello.
My name is Paul.

This could be parsed as:

{
    {
        speaker = "Paul",
        text = { "Hello.\nMy name is Paul." }
    }
}

At this point you might wonder how'd you add blank line to a page. Well, to do that requires an escaping method, I have a good idea about how to do this but it's not in my parser yet.

Why Pages?

In a JPRG I use pages to indicate the current textbox should be closed and a new one opened. In another game type you might use them to insert a newline, or have the player press a button to show the next bit of text.

What if I want a disembodied voice or narrator in my game?

All text must have a speaker-id, what you do with that speaker-id once you have it in game is up to you. You can ignore it. Speaker ids are useful for labelling who is speaking the text or correctly positioning it on screen.

Meta data

As it stands, the features shown above are the only ones my parser supports but there is a little more planned.

  • Tags such as <pause> or <slow>...</slow>
  • A way to inject code

Tags mark certain sections of the text as having some additional property. Tags can control text type-out speed, color and so on. The language won't define what tags do; that's left up the the presentation layer.

Tags may also be the way to inject code into the conversation. I don't want lots of raw code in the script, simple function calls would be preferred but we'll see how it pans out.

Closing

Hope you've enjoyed reading about how I'm approaching authoring game conversation. This is a work in progress, so if you have suggestions then please hit me up on twitter. The conversation language is the first layer in an architecture that ends with it being displayed in game. I'll cover how my parser and textbox display in a future article. You can get an idea of what I think about good textbox design by checking out "What Makes a Good Dialog Box" over here.

Thanks for reading.