JavaScript + Ink: Part 2: Story API

JavaScript + Ink:

ink is a scripting language for creating interactive narratives. It can be written using the editor Inky. The inkjs NPM module is a JavaScript port of the ink engine.


Story API

In the last part, the “Ink for Web” functionality was used as part of Inky to make make three JavaScript files: ink.js, main.js, and the story.js. In reviewing the inkjs NPM module, the connection was made between the module and ink.js file created by “Ink for Web”. They were the same.

In reviewing the main.js, there were were usages of a story object to check if the story could continue, what the next chunk of text was, and what any of the choices were.

Runtime API

There isn’t direct documentation for the JavaScript API. However, the C# documentation shows the API for using the Story object.

NameTypeDescription
canContinuePropertyReturns true if the story can continue to run or false otherwise.
Continue()FunctionReturns the next text block and loads the next choices, if any.
currentChoicesPropertyAn array of the current choices. Each entry’s text property contains their text.
ChooseChoiceIndex()FunctionSupplying a valid index matching the length of the array of currentChoices will consider that entry “clicked.”
currentTagsProperty.An array of any tags as part of current block
globalTagsPropertyAn array of all tags used in the story

Creating a JSON Story file

The Story API is created from reading a JSON file with a compiled story. In order to get that, an Ink file must be run through either inklecate, a command-line tool, or via the Inky editor using the File -> “Export to JSON..” option.

Browser and Node.js Differences

The difference between the story.js and the JSON file is actually only that the story.js has its JSON contents set as the value for variable called storyContent. It is often easier to simply load this file into the global namespace via a SCRIPT tag and then parse the object when working in a browser. For node.js, the JSON file can be loaded via a require() as shown in the inkjs README.

Using the Story API

It was our first date and we hadn't made dinner plans.
-> Pizza_Choices
=== Pizza_Choices ===
He turned to me. "What should we eat?"
+ [Pizza?]
-> Pizza
+ [Sushi?]
-> Sushi
+ [Salad?]
-> Salad
+ [Nothing?]
-> Nothing
=== Pizza ===
He shook his head. "I don't like pizza."
-> Pizza_Choices
=== Sushi ===
"Sushi sounds good!"
-> DONE
=== Salad ===
"Not a salad"
-> Pizza_Choices
=== Nothing ===
"We have to eat something!"
-> Pizza_Choices

index.js


var Story = require('inkjs').Story;
var json = require('./ExampleStory.json');

var inkStory = new Story(json);

console.log(inkStory.Continue());

Calling the Continue() function on the above example story will produce the following:

It was our first date and we hadn’t made dinner plans.

Calling Continue() again would produce the following:

He turned to me. “What should we eat?”

Finally, checking currentChoices would produce and array of four entries with properties text and index.

Revised index.js


var Story = require('inkjs').Story;
var json = require('./ExampleStory.json');

var inkStory = new Story(json);

inkStory.Continue();

/*
  It was our first date and we hadn't made dinner plans.
*/

inkStory.Continue();

/*
  He turned to me. "What should we eat?"
*/


for(var choice of inkStory.currentChoices) {
  console.log("Text: " + choice.text + " : Index: " + choice.index);
}
/*
  Text: Pizza? : Index: 0
  Text: Sushi? : Index: 1
  Text: Salad? : Index: 2
  Text: Nothing? : Index: 3
*/