I'm a laid-off senior software dev who decided to make a weird art-piece while between jobs.
The game I'm about to ship, "A talk beneath the tree", has 27 endings, with a pretty complex branching system underneath.
The logistics of creating this were intense:
- chunking writing and staying organized about planning, writing, and editing
- visual asset prioritization & production
- sequencing text pacing, layout, & visuals throughout the body of the game & the epilogues.
So I brought my backend-dev organizational modality to visual novel making.
Let me walk you through the philosophy I used.
What kind of game am I talking about?
Narrative games are a highly varied medium.
At one far end of the spectrum, you have stories told through cause and effect and mechanics - for instance, text adventures or parser games, like Anchorhead.
At the other end, there are games that play almost like a static story - kinetic novels like Narcissu.
There are several potential points between. You could create a narrative progressed by logistics management and minigames, like Consume Me.
Or -
You could create a game progressed by explicit player choices at key points.
Most non-kinetic visual novels fall under this category, as does choice-based interactive fiction.
I'd also argue that many RPGs - Bioware games like Mass Effect are a good example of this - are using what's essentially a high granularity, micro-branching visual novel backend as the core business logic of their social simulation.
Only this last category - stories progressed by choosing options from lists - is what this thinking framework is designed for.
There are pieces of this idea that could certainly be applied elsewhere, but the abstraction needs to match the goal and, as we've discussed, narrative gaming is a diverse space.
Now that we're clear what we're talking about, lets talk about it.
The brute-force approach to branching games
Visual novels and text games are often written off as "simple."
It may be tempting to think that you can build one without needing to think about "data". Writer/Artist teams without a skilled programmer do this all the time.
And it is feasible, up to a point. But approaching the problem of your branching game without a clear system of abstractions puts a complexity ceiling on your project.
This manifests in many ways, but two stand out to me:
- Without a consistent system of words to talk about things and rules about what those things can and can't do, it's difficult to reason about your game's structure. This will hurt you starting from early planning, and it will keep hurting you all the way through development. If you don't know what pieces you have and what they're for, you cannot grow beyond spaghetti code, nor, generally, beyond structurally messy writing.
- A clear set of abstractions usually lends itself quite well to helping break down a nebulous project into a series of clear tasks. As anyone who's attempted a complex project of any kind knows, organization can make or break you.
"But wait!" you are perhaps now protesting. "I have a lot of that already."
I hope that's what you're thinking, at least.
Maybe you have a gigantic flowchart you're working from, and you're going box by box.
Maybe you have a script marked up with branch points.
If you do, I'm pleased to inform you that you've probably developed the start of a data model. I'd like to invite you to formalize it a little.
Proposing some ground rules for branching narrative data
I'll preface this by saying that it is a proposal. I'm about to start speaking in authoritative, prescriptive terms, but I'm just some dev who likes narrative games, at the end of the day.
You know your project better than I ever will.
But I hope you'll entertain this as a thought experiment, at least.
1. Is your story a linked list, or an ordered array?
First, let me define what I mean:
Linked list: A collection of items where each one …
- contains a chunk of information, and
- tells which item comes next.
Ordered array: A collection of items abstracted such that order is assigned within the outer data structure.
… annnnd I just lost all the writers.
In this context, when I say "linked list", I mean, "we ask each thing what we should do next after we're done with it." And by ordered array, I mean, "We just read the things in order."
Both of these ways of thinking are entirely reasonable for narrative games …
But narrative games being diverse …
The sweet spot for what works for your game is unlikely to be exactly what worked for mine.
Game A
Game B
Which flowchart looks more like yours?
In Game A, most of the branches quickly converge again after diverging. We can look at the story as "linear with little tangents" for large sections of gameplay at a time. Of course, there are also major branches. But those are saved for something special, and largely, they're such big branches that you pretty well divide one story into two parallel ones. And on either side, we're back to "linear with little tangents". Do that for however many words, then we calculate what the end is. Bam. Choice based game.
In Game B, the choices are a complex, tangled web. There are convergences and divergences. The rationale of these is artistic more than structural. The branching is pervasive, and granular, and complicated.
"A talk beneath the tree" is toward the side of Game B.
Let's loop back to the "linked list vs. ordered array" question.
You do not want to build Game B with any data paradigm that assumes "things go in order by default."
The smarter bet is to use a paradigm that says, "each thing can send us to the next thing." Linked list, not ordered array.
But for Game A, "things go in order by default" might help you a lot.
Look at the Game B flowchart. Look how hard to parse that is. If that's the way your game is shaped, then that's just how it is - but if you have enough clear, forward directionality to lay out a flowchart that goes cleanly left to right, then you should absolutely look for ways for your game code to do the same.
Building the "linked list" structure from the bottom up looks like …
label my_item: e thoughtful "The chunk of information in question is the scene." jump next_item
… writing Ren'Py files where labels are all short and every single one has at least 1 jump statement.
It's hard for a human to parse. There's no way around that short of using a visual node graph. But if you need it, you need it. Don't waste your time doing something else.
But speaking of building an entire game in a visual node graph, Twine uses this "linked list" type thinking as its fundamental paradigm.
+----------------+ | Item Title | |----------------| ---> [Next Scene] | The scene text | +----------------+
Writing "ordered arrays" in a Ren'Py game usually looks like loooooooong label sections with short if/else blocks in the middle, but could also be a bunch of shorter labels that read in order.
So, think about your game, and decide if one of these abstractions fits more cleanly than the other.
Do you want your code to decide the sequence of events mostly from the top down, or mostly from the bottom up?
You can do a hybrid approach, as well.
"A talk beneath the tree", for instance, is less one type B Game, and more 4 type B Games in a sequence. That outer sequence being a linear progression, defined in a literal ordered list.
The point I'm getting at is that you need to know what your chunks are, and where the responsibility of choosing and ordering them lies.
And while we're thinking about what the chunks are, let's get pragmatic about it.
2. How does a writer divide up a story?
Usually, it's something like …
Books > parts > chapters > scenes
and maybe, depending what you're writing,
> lines
These are the lines you should be thinking along when you start chunking your story into a game.
But - since we're talking about a branching game, this particular set of abstractions might not be quite up to the task.
Let me throw another one at you.
Days > interactions > conversation topics
Hmm. That one's neat. Sounds great for a mechanically driven narrative game, but it might be overkill for a choice based game, unlesss there's a strong repeating structure.
Rewind.
The writing words used for static narratives are falling a bit short. Inventing something from scratch is causing a complexity explosion.
How do we get our terms straight so we can delineate our chunks?
My recommendation:
Use a subset of the everyday writing words … and stretch the definitions slightly … and then be really strict about sticking to those new definitions for the purpose of your project.
The whole purpose of this excercise is to create abstractions that reduce friction. So choose one that's an easy leap
Days > focus points ("scenes")
A focus point ("scene") is every time the narrative shifts its attention from one thing, to the next, including going from one room to another, starting to talk to somebody, the topic changing, etc.
I like this abstraction a lot. I think you should consider using it as is, unless you have something better.
I trust you to find what works for your project, but from here on out, I'm going to write as if you're using my "scenes."
3. "Scene" delineation should always be 1:1 between the code structure, and the writing structure
If you have to choose between doing this …
| "Scene" Node 1 |
|---|
| 1 scene the way we divided it above |
[100% linear progression]
| "Scene" Node 2 |
|---|
| 1 scene the way we divided it above |
[100% linear progression]
| "Scene" Node 3 |
|---|
| 1 scene the way we divided it above |
… and this …
| "Scene" Node 1 |
|---|
| 3 scenes the way we divided them above but |
| grouped together because they're 1 box on |
| the flowchart |
… do the first.
Don't just build code to "make things work" - write code that expresses meaning.
This is often a good philosophy of programming generally. (Not always - performance constraints, for instance, can sometimes necessitate an architecture that's so procedural this flies out the window.)
The need to encode meaning in your structure is even greater when it comes to "tech art" code.
If the shape of the data matches the way an artist or writer thinks … then you can reduce the friction of organization between the writing team and the programmers.
Every "chunk" of writing that your game requires, should be a "chunk" that makes sense as a grouping, in writer logic.
4. Be explicit about your structure
Ren'Py lets you do this:
label my_scene: "Text, text, text" label scene_after_my_scene: "and then more text right after."
Hot take, but don't. Not in a game with heavy branching.
Do this instead.
label my_scene: "Text, text, text" jump scene_after_my_scene # see what I added here? label scene_after_my_scene: "and then more text right after."
Technically necessary? No. But sanity preserving.
Your game is big. Things are going to get jumbled up and reorganized as you go. If you let your scene progression be dependent on something as brittle as ordering of blocks that sometimes get read in order with none skipped and sometimes don't? You'll be in for a debugging nightmare the moment you need to edit the base structure.
So just get in the habit of making the structural pieces explicit, every time.
5. Encode the flowchart before you write a word of prose
You have a flowchart in your notebook that looks like this:
+------------------------+ +------------------------------+
|Kevin arrives at school |------ |He stops to check the chem lab|
+------------------------+ +------------------------------+
\
+----------------------------------+
|He goes straight to English class |
+----------------------------------+
\
+-----+
| ... |
+-----+
That's awesome.
You need to go into your game engine and build a "visual novel" that contains that exact text, and the branch points. Visuals optional.
Make sure to name your labels or nodes clearly and systematically.
Recommendation: you want to find a happy medium between names that encode structure and names that bring to mind what's happening. Verbose is OK.
day_3_mica_mid_approval_ask_about_father
for instance.
As soon as you've started to get things hooked together you should run your game and play around for a little while.
And then when that starts to feel OK, you should expand the nodes into sequences of "scenes the way a writer would think about scenes."
But before we get ahead of ourselves, let's talk about the highest level structure of your game.
It's all well and good to picture a game as a cloud of interconnected scenes, but I'm guessing you've got an overarching plot as well, right?
Just like we wanted to be explicit about "scenes the way a writer would think of them", we also want to be explicit about "chapters" or "parts" or "days" the way a writer would think of them.
You probably want a system of some kind to … for instance … loop back to at the end of every chapter and take care of the setup and routing for the next one.
Maybe you have something like this:
CHAPTERS = [
{"default": ch1},
{"maria": ch2_maria, "mica": ch2_mica},
{"maria": ch3_maria, "mica": ch3_mica},
# ...
]
default chapter = 0
def end_chapter():
chapter += 1
ch_type = get_leading_girl()
if ch_type not in CHAPTERS[chapter]:
ch_type = "default"
jump(CHAPTERS[chapter][ch_type])
In this case, we'd call "end_chapter" at the end of the last scene in a chapter, and get automatically routed.
Here, chapters is an ordered list - just like chapters in a book.
We're able to do some simple checks, and route the game to the different versions.
You could also do something like this:
# chapters.rpy
label ch_1:
jump ch1_intro
label ch_2:
if maria_score > 3:
jump ch_2_maria
else:
jump ch_2_mica
label ch3:
...
Notice how in either case, we've pulled the chapter progression logic out into its own, dedicated location - and separated chapter progression logic from everything else.
This keeps the levels of abstraction in the game clearly delineated, which creates something that's much easier to reason about, structurally.
Now, with the structure cemented in place and testable, it should be easy to create your plan of attack.
6. Prose todo list should be flat, granular, and simple
At this point, you should be able to collect up every scene label or scene node and make them into a flat list.
Congratulations! You've collapsed the worst of the logistical complexity of building a narrative game.
You can turn this into a todo list or a Kanban board and start drafting scenes.
Maybe you have a "prose" column and a "visual sequencing" column.
You can parallelize between people to get it done in a way that would have been incredibly difficult with less structure.
You can divide scenes done by scenes pending and track your progress percent through your first draft - precisely.
If there's one thing you take away from this whole article, it's that you need to find a way to organize the work so that the task list is flat and well tracked.
Closing thoughts
None of this is really about tech.
You can be an excellent programmer and find breaking down a narrative into data non-obvious.
You can be a very organized writer, and get most of the way here on pure instinct.
Whatever your discipline, and whatever your skill level, I just want to invite you to step back, and think about your org systems deliberately for a couple minutes.
If what you've got is working, far be it from me to insist you change it.
But it's certainly the case that data model in narrative games is under-discussed, and I'd like to change that.
Good luck with your game! Rooting for you.
No comments:
Post a Comment