Kandria
The importance of speech
Dialog (dialogue?) is going to be a big part of Kandria, so it's important to have a good system in place for that, both in terms of user experience, and in terms of being able to write the dialogue in the first place. The initial system for this was actually written a year ago, but it was disabled for a long time as I had to fix up other parts of the game. Last week I started work on getting it integrated again.
Let's start top down, meaning we'll first take a look at the user interface and the behaviours on that side. A typical dialog system is going to consist of a profile picture showing the character talking, a nametag, a dialog box, and a choice list for whenever the player should make a choice. What this looks like in actuality can differ a lot depending on the game of course. Here's the mockup for Kandria as it stands right now:
The profile can play different animations depending on the mood in the text. I made a couple of those animations last week:
I'll definitely need more than those few in the end, but I can keep that for a bit later. Anyway. In terms of UX, the textbox needs several convenience features: the text should scroll out at a configurable speed, and the player should be able to skip the text to fill the box immediately with a button press. Finally, before the text scrolls to the next block, the user must press another button. Ideally conversations can be repeated so that the player can catch up in case they accidentally mashed through something, or aren't sure anymore what the entire conversation was about.
So let's flip the tables and look at how dialog should be written. I know that this is very much an "in-house" kind of thing in most studios, and from the little glimpses I've seen there's solutions that offer big user interfaces with flow charts and all that, and on the other hand there's scripting languages designed specifically for that for which you'll just need a text editor. Whatever the case, the system must give you controls to specify:
Who is speaking at any moment
What expression or animation they might have
The text that's being spoken, as well as various markup effects
A way to label sections and jump between these labels
A way to show a selection of choices to the user and how to branch depending on the choice
Displaying different text or choices depending on a condition about the current game state
Camera and character movement controls to create cutscenes.
For Kandria I went with a plaintext script system, as I already had a parser framework for a markup language that I like quite a lot, called Markless. Markless is designed to be extensible, and the parser system cl-markless offers this as well. I then set out to write a specification that describes the syntax extensions that I needed, as well as the actual semantics of the various syntactic constructs. You can read the spec here. For the purposes of this short summary, here's an example:
~ Jack
| (:confused) And who might this be?
~ The Stranger
- I don't remember
| (:puzzled) I.. can't quite remember.
- No one in particular
| (:skeptical) No one important.
| Besides, (:smirk) it's polite to introduce yourself, first.
~ Jack
? (< 10 (trust 'catherine))
| | I'm Jack. Sorry about that, I'm quite busy.
|?
| | (:annoyed) ... charming. I'm Jack.
| ! setf (trust 'jack) (- (trust 'jack) 2)
| (:normal) I make sure things run around here.
| You best make yourself useful, too... stranger.
This doesn't show off all features, of course, but it should give a good idea on how dialogue is written in general. Just a quick explanation in case you're confused on how to read it:
~
Marks a "source" and tells who is speaking.|
Marks a quote and indicates text to be spoken.-
Marks a choice. The same line notes the choice label, and the indented block afterwards what happens if the choice is taken.(:_)
Marks an expression and will cause the corresponding animation to be played.?
Marks a conditional choice. If the following expression is true – in this case, catherine's trust level is above 10 – then the following block is executed, otherwise it skips it.|?
Marks another conditional branch. Without a following expression it designates the "alternative" in case the first condition fails.! setf
causes a change in the game's global state. In this case it decreases jack's trust level by 2.
Anyway, I hope you can see how this can be used to create complex dialogue trees. This system alone isn't enough however, there has to be another system in place that controls what dialog and interaction is possible at what time in the story. This ties in closely with the global progression and quest system, which I'll hopefully talk about next week.
The dialog system above is almost entirely independent of Kandria and I hope to release it as a standalone library sometime, whenever I get some spare time to document ti and clean it up a little. It actually involves a full compiler, assembly language, and execution virtual machine. Why? Because compilers are fun.
The dialog system only handles the execution state of the dialog trees and all, the actual display and UX is left elsewhere, and is what I completely rewrote last week. I've implemented it using the UI toolkit Alloy, another big project of mine. I'm almost done with the implementation now, just need to add some more behaviours and think ahead a bit on how to implement text effects nicely.
Actually, speaking of text effects and dialog systems in general, if you've played text heavy games before, were there any particular effects or features that you enjoyed a lot? I'd be interested in gathering some more reference material for stuff like this.
Let me know if you recall anything!