Introduction

In this series, you will get to create a visual novel engine.

We will code the system from scratch and cover the following features:

And much more. These features break down into many little things we’ll have to be careful with, as it is very easy to introduce visual bugs when you have to sequence scenes and animations.

While this series shows you how to build the foundations for a visual novel, the techniques you will learn also apply to all kinds of dialogue systems, as you see very similar presentations for conversation in role-playing games, rogue-lites, platformers, and so on.

Celeste, a platformer, uses a dialogue box like most visual novels.

So you will learn to code a dialogue system and a data format to represent and play little scenes.

The controls

In this demo, the scene starts automatically with whatever animation you decide to playback, like a fade-in.

The player has limited controls as they’re mostly reading a story. They can press enter to fast forward text currently displaying and press enter when some reply is fully visible to trigger the next one.

When a choice appears, they can use the up-and-down arrow keys to select an option and press enter to confirm their selection.

Code structure

Despite the picture looking a little full, this project has one of the simpler structures you will see in Godot 2D Secrets, as the bulk of the action is happening in the scene player and the text box.

The Main node stores a list of scenes and requests a ScenePlayer to play them one after the other.

The ScenePlayer loads a file containing data, a dictionary of dictionaries, and reads them in sequence.

Depending on each node’s data, it delegates some action to a subsystem: mainly the TextBox and CharacterDisplayer.

The idea is to allow you to put any instructions in every step of the scene, like playing animation, displaying a character, or showing some text.

If you defined the corresponding dictionary keys, the scene player will ensure that something happens. We’ll see how dictionaries allow us to do that.

In the picture, you can notice a dependency between ResourceDB and other nodes. That resource database is an autoloaded node that takes care of preloading resources, like the game’s characters and backgrounds. You could use it to load audio files and more.

While it’s a singleton and it creates dependencies in the source code, it’s a singleton without mutable state: it only provides functions to access resources, allowing you to refactor your code moving forward: the nodes that use the ResourceDB singleton only request and expect to get a Character, a Background, etc.

Using data for scenes

Dialogue and scene director systems often rely on data representing a sequence of changes or actions.

The use of data allows us to either operate directly or to code an editor that will write it down to the disk for us.

Unlike using GDScript code for scripting our scenes, using data prevents players from injecting malicious code in the scene files: if the data is invalid, we ignore it. GDScript also provides us with a handy str2var() function to parse files and safely turn them into values like dictionaries, arrays, or any built-in Godot type.

Using data also allows you to use any external program to edit your game’s dialogues, then export a JSON file, load it, and convert it into your game’s expected format.

We won’t cover using an external editor in this series, but we will see how to load scenes from text files.

Suppose you decide on a particular dialogue editor you want to use from the start, like YarnEditor. In that case, you can use its exported JSON as a starting point to code your game. You don’t have to first code your dialogue system and later translate the editor’s data into your game’s format.

But if you’re going to code a unique game from scratch, you’ll want to write prototypes without relying on a specific tool first, so you can freely experiment with your gameplay. You can start using an editor that fits your project’s needs later.

Yarn Editor is a web-based, engine-agnostic and nonlinear dialogue editor.

Note that we’ll focus on coding the dialogue system and reading the data to play scenes. We will not be creating an editor plug-in, which would be a time-consuming endeavor.

There are great third-party open-source programs available already, so I would recommend using them, like Twine. If you’d like a Godot-specific tool, you can check out the open-source add-on Dialogic.

Dialogic is a Godot plugin to write dialogues with optional conditional branches. You edit everything from within Godot.

With all that in mind, it’s time to get started.

You can find the start project, which contains some sprites, in the course’s files. I invite you to open it in Godot.

In the next lesson, we’ll create our game’s text box and display animated text on it.