Developer Update: Dialogue Dialogue Dialogue

Welcome Hey everybody - M. James Short here. I handle systems, tools, and general programming duties on Bill Hates Videogames. I wanted to provide an update about some recent overhauling we’ve done to one of our most essential systems in the game: the dialogue system.


In early 2017, when Saam first approached me to help with Bill Hates Videogames, it was a simple ask: “Do you know how to make a dialogue system?”

I had just completed a Proof-of-concept effort to build a small game in various 2d engines (Unity, Paper 2D (UE), Construct 2, etc.) and had settled on using Gamemaker Studio 2 (GMS2) going forward. I was in the process of migrating the B.R.I.G.A.D.E Force prototype to GMS2 while learning the ins-and-outs of GML/GMS2, and Saam was also using GMS2 for his prototype. Perfect match.

“Sure, I could knock something out for you over a weekend.” (Spoiler: It took a lot longer than a weekend)

First Iteration

Saam’s needs for a dialogue system were pretty simple in the first pass:

  • Dialogue needs to live in a speech bubble emanating from the characters
  • Saam needed to be able to add dialogue and edit dialogue pretty easily


When I sat down and prepared to put together a dialogue system for Bill Hates Videogames I grouped my various needs into five problems to solve:

alt text

Now that I knew my focus areas, I set out to understand how other devs were solving these problems in GMS2.

It turns out there’s a lot of great solutions.

Friendlycosmonaut has an excellent dialogue system that’s been around since GMS1. While it’s deeply customizable for experienced devs, it’s also perfect for new devs that need something that works, is easy to understand, and provides a classic dialogue box at the bottom of the screen. It’s also free, well documented, and continually supported, which is probably the most important thing when choosing to use someone else’s code. Evaluating the system against my focus areas, it solves these problems:

alt text

I also checked out Advanced Dialogue Box by diestware. It’s a simple but effective dialogue box generator that will handle the boxes, portraits, text effects, and more. At the time (2017), it worked in GMS2, even though it’s for GMS1.4. I don’t know if it currently works, so try at your own risk.

HappyTear Text-Dialogue Engine by HappyTearParakoopa is another system that I checked-out. It has tons of features (including text bubbles - one of my requirements!), and it’s pretty easy to customize, but it hadn’t received updates in three years (six years now), which made me wary of consuming it. It also was built for GMS1.4.

As I checked out how other people were solving these problems in GMS2, I started putting together the dialogue system’s framework (assuming I would just write my own code that solved all five problems). I decided that for the first pass, I was only going to solve these three problems:

alt text

Commit e0a9e82, checked-in on April 19, 2017, featured obj_controller_dialogue, the beginning of dialogue in Bill Hates Videogames. Shortly afterward, the first conversation occurred:

alt text

I was still learning the ropes of GMS/GML as I fleshed out BHV’s dialogue system, so I spent many hours down Google rabbit-holes trying to understand the “intricacies” of GMS2. During one of those spirals, I ran across this thread from 2015: Thread

I downloaded Frilly Knickers and checked it out.

alt text

In reviewing Frilly Knickers, I realized it solved all five problems:

alt text

I wasn’t a big fan of the way text was formatted in the external .csv so I decided to use my own implementation. What I did love about Frilly Knickers, though, was that you could tell the developer thought about how other devs would use their code. The developer modularized each problem the code solved, so it was easy to customize.

It was effortless to take the things I needed from the system and slot them into my current, custom solution.

alt text

There were a lot of other positives about Frilly Knickers: it already supported tags in strings (and was easily extensible), there was a clean separation between dialogue box code and string parsing/rendering prep, and the developer was swift to answer questions/update the code.

A day or two later, I had the first full end-to-end dialogue system up-and-running in BHV that solved all five problems:

Branching dialogue

alt text

One thing to note: Frilly Knickers uses Gamemaker’s default drawing functions to render text on the screen. Those drawing functions are incredibly inefficient and have a shockingly high overhead. Not the fault of Frilly Knickers, but it’s essential to understand because something better is coming.

For reference, this is the first .csv format I used for BHV’s dialogue:

alt text

It’s pretty self-explanatory, but the character field tells the dialogue controller which character to put the dialogue bubble on. I had this complicated way of supporting multiple character dialogue that required an array with the characters involved to be initialized before starting the dialogue.

This dialogue system solved the original need, but over the next couple of years, we added more features:

Dynamically expanding dialogue bubbles

alt text

Dialogue bubbles that “pop” into existence

alt text

Walking around dialogue

alt text

Text effects

alt text

Dynamic controller buttons that change based on real-time input

alt text

Dynamic dialogue zoom that ensures the characters look at each other when they talk, characters are placed in the center of the screen and dialogue bubbles won’t go off-screen

alt text

Slightly hard to read but we added cinematic cuts to the dialogue system. Dialogue pauses to run a timeline. This timeline dynamically jumps the camera around the room focusing on different points a proof-of-concept. When the timeline is complete, the dialogue picks back up. Currently moving this to sequences in GMS2.3

alt text

Towards the end of 2019, I realized that I needed to overhaul the dialogue system to fully account for the new features and, more importantly, to allow Saam to create & manage branching dialogue more efficiently.

At the same time, Bill Hates Videogames got accepted to the PAX South Indie area, and we focused our attention on getting the demo cleaned-up for showing.

alt text

Recent Updates

PAX South was a smashing success for Bill Hates Videogames, and we came back energized to hit feature complete.

I started investigating the best way to handle branching dialogue and found two solutions:

Quack Dialogue System, created by Quack, is an incredibly robust system to develop and manage branching dialogue in your game. It features an online editor and works effortlessly with some of the significant GMS2 Dialogue Systems (such as the FC Dialogue System mentioned above). When I initially checked it out, it did not have the branching pathway visualization.

Chatterbox, by Juju Adams - also the creator of Frilly Knickers, is “a Gamemaker implementation of the Yarn language.” It allows you to create Yarn files using your favorite text editor but I recommend using Yarnspinner and is easy to use for writers or non-devs.

Since I was already using Juju’s Frilly Knickers and knew the code was well implemented and supported, I chose to move forward with Chatterbox. As part of that decision, I also decided to use Juju’s Scribble library to handle all text rendering in the dialogue system. You should also use it anytime you want to draw text on a screen.

By itself, hooking up new parts of a dialogue system and replacing the text renderer would have been a lift, but at the same time, GMS 2.3 launched, and we needed to migrate to support Sequences.

The last couple of months have been a lot of low-level work migrating Bill Hates Videogames to GMS 2.3 (not too bad actually, just had to deal with the array changes), and tearing out the old dialogue system parts and replacing them with Chatterbox and Scribble.

The first iteration is complete (with a healthy dose of visual bugs to still clean-up), and we’re already noticing a difference in how fast Saam can create and implement dialogue in the game.

One last cool thing to note: the biggest problem we faced migrating to Yarn was how we were going to do conversations with multiple characters in a scene. Not just from a controller perspective but I wanted to make it easy for Saam to add characters to a room, or scene and easily hook them to Yarn so dynamic dialogue bubbles could be created on the instance. After beating my head against the wall for a week, asking multiple people for advice in various GMS dev discord, and starting/scratching two different solutions I reached out to sp202, who had helped me with some tricky vfx programming on B.R.I.G.A.D.E Force. His solution was eloquent:

Add the ability to add characters to a map in GM through Yarn. This map would track the character index, the instance id in the room and their friendly name.

After some trial-and-error, here’s what the final code looks like:

add_character function

alt text

character function

alt text

Saam is able to add this function to the create event for any new objects he puts in the room.


alt text

Then in Yarn, he can just write this: alt text

The dialogue controller matches up “Bill” to the map and knows exactly where to put the dialogue box and generate the dialogue.

sp202’s original solution still works also. So if Saam wants to change the name of a character in the map or add a new character through the map, he can do this in Yarn: alt text

When Nagi is added to the game through GMS2, the character runs this code in their Create event: alt text

Combining them together gives Saam a large amount of flexibility in Chatterbox to update and manage characters through dialogue.

And here’s what it looks like in-game:

Na’gi’s name gets dynamically updated through Yarn. (excuse all the UI/various bugs)

alt text

alt text

Pretty neat!

Here’s what the final dialogue system looks like: alt text

That’s it for now. Next time we’ll dig a little deeper into the ins-and-outs of building tools for other people vs building them for yourself.

Michael (Listened to Locrian - Return to Annihilation on repeat while writing this)