Gamasutra: Joe Clark’s Weblog – Orkward Devlog #3: Getting Ink

0
51



The next weblog submit, until in any other case famous, was written by a member of Gamasutra’s group.
The ideas and opinions expressed are these of the author and never Gamasutra or its guardian firm.


 

Hiya, I am Joe and I am making Orkward, the area ork courting sport. I will be cross-posting this devlog from its unique house on itch.io to share my growth journey with the Gamasutra group. Orkward is completely free to play on itch.io proper now.

This third devlog was initially written again in December 2020 and has been very flippantly edited right here. Ink has seen an excellent 1.0 launch since this was written and I’ve nonetheless not caught up – so remember that some issues could have modified!

On the time of writing, Orkward is coming as much as 6000 phrases of richly interconnected interactive fiction. It is written utilizing Ink, a scripting language by Inkle which drives their very own video games – together with Pendragon, Heaven’s Vault and 80 Days.

On this devlog, I will be speaking about Ink, how I take advantage of it, and what I consider it. It’s going to begin off at fairly a conceptual stage, however get progressively extra technical as we go.

Orkward

The primary model of Orkward was a text-only sport, pure interactive fiction. It was pushed from an Ink script and a CSS stylesheet. It appeared like this:

This totally playable, browser-based interactive fiction sport was exported straight from the editor from only a few traces of Ink script (extra on that shortly).

Ink additionally supplies an API which you’ll be able to plug into your individual engine. It helps JavaScript and Unity in the present day, and we’re hoping for Unreal assist within the not-too-distant future (this appears probably as Ink simply obtained a grant from Epic).

The present model of the sport embeds Ink’s ‘native’ JavaScript renderer and runtime into my very own JavaScript (React) ‘frontend’. I can management when and the place the textual content displasy and skim/write inside sport state at my leisure. This implies I can plug-in my very own artwork property and UI overlays on high of the story, giving me a great deal of management.

Since model 0.5, Orkward has changed the pure-text menu with a visible gallery and UI overlay, giving the participant a richer, extra visible option to drive the story. This is the way it appears to be like now:

Updated Orkward menu

In a later devlog I am going to most likely discuss extra concerning the JavaScript frontend (until I feel it is too boring, which may simply occur [EDIT – hasn’t happened yet, still too boring[). For now, we’re just going to focus on the texty bit produced by Ink.

Playing with Ink

The basic idea of Ink is to print prose on the screen, interspersed with options or choices which let the player choose where to go next. Once the game is finished, you should be able to read back over all the text and have a consistent, plain-text narrative.

In other words, the pages are designed to be continuous. This is a very different model to the paged output of Twine or Ren’Py.

In Orkward, you might see a choice like this (choice in yellow text):

A screenshot of a text-choice shown in Ink

And when you click on a choice, the options are removed and replaced with the next text, so if you select ‘down the grog’, you’ll see this:

A screenshot of the previous choice resolved into text

Seamless. Lovely.

But it doesn’t have to be seamless – that’s just the default presentation. Ink is a runtime and has an API which I can call to read/write variable state, generate text, loop through choices, and so on. The HTML renderer I’m using is just a bit of very-readable JavaScript which I can modify. So I can customise the output as I like, highlighting player options or marking out ‘sections’ to imply player choice.

Writing with Ink

Ink is a scripting language is which puts text first. There’s no fiddly GUI – the idea really is that you just write out your story in prose, as natural as possible and without having to use the mouse. The dedication and focus that gives you is just lovely.

Inkle provide an editor called Inky, which is the easiest way to get started. Or there’s a range of plugins to Visual Studio Code.

If you’re familiar with Twine, it’s quite different because you don’t have the pinboard with nodes that visualise the story. I have to say, I don’t miss this at all. It’s quite nice to be able to visualise the story, but things quickly get very hard to follow. And it’s fiddly. I spend as much time moving nodes around as I do acually writing. For a time back in Twine 1, I actually wrote the serialised format directly and imported it back into the tool to test it.

If you’re familiar with Ren’Py, then Ink is pretty similar. Ink is a much thinner engine – it doesn’t give you all the fancy UI stuff that Ren’Py gives you, and makes fewer assumptions about presentation. I think Ink is a more elegant and powerful scripting language – although for some people, Ren’Py will be a better fit.

There is a bit of syntax to learn. Like markdown, it’s a mixture of arbitrary and intuitive symbols scattered across your text to drive the formatting. But once you learn that syntax – and it’s its simplest, it’s really very simple – it becomes very quick to put something together.

Simple Syntax

Here’s the basic format of an ink script, taken from Inky (the Ink editor):

Some Ink script, shown in Inky

This defines a named section of story (or a stitch, in Ink parlance), called gather_armor. Other sections are referenced in lines 187 and 189 via diverts, which are those little arrows. When the story gets to that line, it’ll go/jump/divert to that section.

The asterisks on lines 186 and 188 define choices that the player can pick. Everything on the same line as the asterisk will be displayed as a single choice (so choices are in effect single-line). When the player picks a choice, Ink will play all content between that choice and the next choice or divert.

So in the code above, selecting the first choice will trigger a divert to  the death_by_manners section (bad news for the player!), and the second will trigger divert to main_branch. Instead of diverts, we could put some inline text. Typically we’d indent this text to show that it’s “inside” an option block.

The square brackets on line 188 alter the line before and after selection. This is a little bit complicated, but basically it cuts the line into three parts around the brackets. The bit before the open bracket will always be shown. The bit in between the brackets will only be shown before the option is clicked, and the bit after the closing bracket will only be shown after the option was clicked, replacing the bit in the middle.

So before the option is clicked, Ink prints:

“Fine.”

And afterwards, it prints:

“Fine,” you say.

This is often useful because the text of a choice, without the context of other choices around it, often doesn’t read well when you read the prose back.

Indenting is immaterial, by the way, and only used for formatting. Ink mostly ignores whitespace, apart from line breaks because some syntax is line-based (for example, choices (*) and code (~) read the whole line).

Here’s how that section looks in-game:

The previous Ink source rendered in-game

Fancy Syntax

Ink is a really rich language, full of powerful features. Here are just a few neat tricks I’ve used in Orkward.

Alternatives

A very common use-case in interactive fiction is to show cycling or randomised output, typically when you get back to root menu. Like a shopkeeper. The first time you meet the shopkeeper, you need to print a description of them. But the second time, you just need a simple line to introduce the shop menu.

Alternatives are a great way to do this. Here’s a drinking game loop with Chompa (slightly simplified – this will actually loop forever):

Syntax for alternative outputs, shown in Inky

Syntax for alternative outputs, shown in Inky

This creates a section (stitch) called drink_up, which we jump (divert) back to on every choice.

The { cycle: } stuff is the alternative loop. Every line starting with – is an alternative. cycle is a keyword which tells ink to cycle through these options one by one. The <> syntax is ‘glue’, which basically ignores the line breaks. So every time we enter the drink_up section, we show a different line of text.

Here’s what the output looks like in the Inky editor:

An example of rendered alternative outputs, shown in Inky

Another twist on alternatives is to shuffle the output, meaning you can get more varied, natural dialog. This scene, in which the player tries to defuse an orky bomb, uses the single-line syntax, where shuffle is denoted by ‘~’ and each alternative is denoted by the ‘|’:

Ink source for shuffled alternative text with in-line syntax, shown in Inky

This produces a random output like “Try the red one” each time

The ‘alternative’ syntax really shows what a dedicated scripted language can do when it really understand its domain. I love it!

Tags

Ink allows me to add arbitrary ‘tags’ to any line. These are a bit like comments, in that the player won’t see them. But they are seen by the runtime engine. Tags allow me to broadcast messages to the game’s frontend from within the story. You can use this to change visual styles, synchronise art assets, play music or sound. I use tags to broadcast a return to the main menu screen (hiding the story and showing the gallery menu), trigger an ending or game over screen, and unlock trophies.

Here’s an example of unlocking a trophy by out-drinking Chompa:

Ink source showing a trophy tag, captured from Inky

The first line sets the trophy variable by incrementing a number. The second line is the tag, where ‘trophy’ is the tag name and ‘bottoms_up’ is the variable name (minus a prefix).

When the frontend sees this tag, if the variable count is 1 (ie, the first time a trophy is triggered), we’ll show a little pop-up to tell the player they’re just unlocked a trophy. Neat!

Weaves

Finally, here’s a neat trick using a thing called a weave. This is a bit tricky and maybe only makes sense when you’ve used Ink and got a feel for how it works.

The Ink I’ve shown so far uses diverts at the end of each option to go to the next section – which is a good proxy for how Twine works.

But that can mean you have very fragmented script, with little sense of structure and flow. Ideally you want the start of the story at the top of your script, and the bottom at the end, and the rest flowing in a broadly chronological order (as much as possible!). And you can do this with sticthes and diverts.

Weaves are a neat trick which helps you reduce this fragmentation and have longer sequences of prose. It’s denoted by a dash (yes,a  dash can mean a lot of things in Ink!) and it will ‘gather’ or ‘catch’ the story here unless otherwise diverted.

Here’s an example. This section of Orkward lets you pick a name for your knife:

Syntax for a weave, shown in Inky

It presents the player with three options (“Dis is Clara/Stabba/Julius”) and, whenever one is picked, it sets an internal variable which we can use later.

The weave is the dash after the choices, on line 251. It basically acts as a section break for Ink, telling it not to associate line 251 or anything after it with the previous section. It also tells Ink where to go next after any previous sections (unless they explicitly divert).

That’s a bit complicated, isn’t it? Basically, after each choice, unless there’s a divert, we jump to the next weave. So all three options above end up in the same place.

This gets really useful when you have branches which all end up in the same place, because the start and the end are in the right place in the file so you get a natural structure. It’s a bit hard to show this in a screenshot, but here’s a very brief example (you might imagine that each choice has a lot more content before joining up at the weave at the end):

An example of intented choices, gathered with a weave, from Inky

This generally works better with shorter sections, but it’s a really useful trick.

Other stuff

There’s a lot more I haven’t talked about. Stitches can be scoped a bit into knots (think sections and subsections) and accessed by paths (-> section1.subsectionb ).You can pass parameters to stitches and knots. You can even pass diverts through. You can define functions to compute values. I haven’t really talked about variables but you can see them in this blog. You can nest choices and weaves, which quickly becomes useful when inlining text.

It’s a really rich language which has helped Inkle ship some very complex interactive storytelling experiences.

A Few Stains

Working with Ink has been pretty great, but I do have a couple of criticisms.

Firstly, there’s a lot of jargon involved. Ink documentation talks about knots and weaves and diverts and tunnels. Now, there’s a pretty good reason for this because Ink introduces a lot of concepts which are pretty unique to it. But mostly I think it’s a bit of a barrier to learning and makes the language look harder than it really is. You might argue that some characters get a bit over-used too – dashes, in particular, can mean very different things in subtly different contexts. You get used to all this and it’s clear enough, but you do need to wrap your head around it. 

In the end, it’s a programming language and so it does take a bit of comprehension.

Secondly, the tools available leave a little to be desired. Inkle’s Inky editor is basically really really good. It runs the game alongside your script and instantly updates – which is just brilliant for editing while you play through.

A screenshot of the Inky editor

But it does have shortcomings. It’s only really good for editing a single file – if you’re working with several files, it quickly becomes hard work. I can’t really use it for Orkward – I have too many files, and because the structure of the game is non-standard, I often need to see things rendered in-game.

I get the sense that the community use Visual Studio Code for a lot of Inking. And I’m using it, too, because it’s a great tool for JavaScript development and vital to the frontend. There are few plugins for syntax support and stuff, but they too have many shortcomings. It’s great for large projects with multiple files, but I really miss the preview/live-reload modes.

Ink has just recently received investment from Epic, so I’m really hoping to see a better range of tools (and maybe documentation) coming out over the next year to make it easier and better to work with.

Ok I’m bored and want to get back to game dev please

So to round up, Ink is:

An elegant scripting language which reminds me very much of markdown

A runtime which exports to Unity and JavaScript and is ideal for embedding into a bigger game.

Mostly, I picked up ink for this project just for the sake of trying it out. I’ve wanted an excuse for years, so I’m pleased Orkward came along and gave me a chance to get stuck in. The runtime API means I can deeply integrate with whichever game engine I’m using, while the text-first approach to scripting the narrative means I can stay glued to the keyboard and iterate very quickly.

I’ve really enjoyed my time with Ink and would absolutely use it again to drive any text-heavy storytelling in future games.

In the next devlog, I’ll be joined by a very special guest to talk about narrative design in Orkward. See you then!



Supply hyperlink

Leave a reply