Skip to content
valvolt edited this page Jan 23, 2020 · 8 revisions

Welcome to the storiz wiki!

The story of Storiz

When I was young, I was a big fan of 'choose your own story' books. As an adult, I discovered amazing visual novels, my favourite being Steins;Gate.

I've wanted to create interactive stories for a long time, but nothing I've found was really what I was looking for. ChoiceOfGames is great but does not support videos. Ren'py and the like are amazing but require a lot of time and dedication.

What I wanted was the following:

  • I make videos with my phone
  • I drop them to a folder
  • I quickly write a few lines of text
  • and bam, I have a running game.

That's the concept behind Storiz. And since nobody developed it for me, I decided to code it myself.

On top of that, I wanted to develop an engine which could be used in a 'competitive' environment. In essence, add 'flags' to be collected by reaching certain ends and prevent cheating such as trying one path, seeing it's not going into the right direction, backtrack and use another one.

This goal is now achieved. I am thinking at making cheating even harder as most of my players are actual hackers, but as a story engine it's already very usable.

How-to guide

Storiz comes with a tutorial story containing the equivalent of this how-to guide and demonstrating its features.

Basics

Tile

Each of the story pages is called a Tile. A story is made of several tiles, linked to each other. When you click on a button, you are sent to the next tile. All tiles are declared in a single file. In its basic form, it looks like this.

"Tiles": [
  {
    "id": "1",
    "title": "my first tile",
    "text": "my tile text",
    "picture": "my_folder/picture.jpg",
    "choices": [
      {
        "text": "first choice",
        "to_tile": "2"
      },
      {
        "text": "second choice",
        "to_tile": "3"
      }
    ]
  }
]

Title

The title is a simple string, which will be displayed at the top of the tile. A title is optional.

text

The text part is what you are reading right now. It is optional, for example for stories based only on pictures and videos. The text part supports HTML tags such as <b> to make the text bold, for example. For more info on HTML tags, have a look here.

picture

A picture is also optional. To add one to the tile, you have to do the following:

  • On your computer, go to the folder where you have downloaded the Storiz engine, then enter the /public sub-folder.
  • It is recommended to create a sub-folder for your story if one does not exist already, for example my_folder.
  • Store in this subfolder the picture you want for your tile. You may want to rename your picture if its name contains spaces or special characters.
  • If your picture is named my_picture.png and is stored in /public/my_story, then the "picture" element of your tile should contain "my_folder/my_picture.png"

The picture will be resized to a height of 300 pixels. You can find free to use pictures on Pixabay.com.

choices

The choices are the heart of Storiz. It is where the story branches to alternative paths. The 'choices' element is optional, but if not provided, there will be no button to click.

Each choice is composed of a text and a to_tile elements Both elements are required.

  • The text element is a string, which will be displayed as a clickable button.
  • The to_tile element corresponds to the id of the target tile. If no tile corresponds, you will get an error when you click.

id

An identifier for the tile. It is required to link tiles together. One tile MUST have the id "1", this is the tile which will be rendered first. Other tiles can have any id, as long as it matches the to_tile of a choice. It can be a number (such as "2" or "56"), but it can be any string (such as "encounter" or "game over").

The JSON file

All tiles are stored within a single file, in the JSON format. This file must be stored in the /private sub-folder and have a name, such as my_story.json. You may want to look at other files stored in /private to see how other stories work. It is recommended to have the same name for your filename and for the /public sub-folder where you stored your pictures.

It may happen when you write your tiles to get a syntax error, for example if you miss a curly bracket or a comma. To help you, you can use a JSON Beautifier which will tell you where the error is, such as this one.

To add your story to the catalogue of available stories on the server, you need to edit the file /private/stories.json and to add an entry for your story there. The filename must be the name of your .json file. The description can be any text you want, the description supports HTML tags.

To test your story, run the server by doing the following:

  • open a terminal window
  • go to the storiz directory
  • type 'meteor' and hit enter

We have now covered the basics. You are already armed for creating some cool interactive stories !

Medias

Adding sound and video is a great way to make your stories even more immersive. Let's walk through the available options.

"Tiles": [
  {
    "id": "1",
    "title": "my first tile",
    "text": "my tile text",
    "music": "my_folder/cool_music.mp3",
    "sound": "my_folder/bang.mp3",
    "video": "my_folder/my_video.mp4",
    "choices": [
      {
        "text": "first choice",
        "to_tile": "2"
      },
      {
        "text": "second choice",
        "to_tile": "3"
      }
    ]
  }
]

sound

You can add a "sound" element to your tile. The sound file shall be stored in the /public folder, in the same way you are already storing pictures. The sound will be played once, when the tile is rendered on-screen. If you want to surprise your audience, you may want to add a few seconds of silence before playing the sound for a surprise effect.

music

The "music" element works in the same way as the "sound" one: the file to be played must be in the /public folder and will play as soon as the tile is rendered. There are however two major differences with the "sound" element:

  • the "music" will be played in an endless loop
  • if the next tile rendered on-screen has the same "music" value, then the music will continue playing. In other words, the music will play until the player renders a tile which has no "music" element or a different "music" value.

It is possible to have both music and sound elements for the same tile.

video

The "video" element works in the same way as the "picture" element. The video file must be stored in the /public folder and will play automatically as soon as the tile is rendered on-screen. The video will be resized to have a height of 300 pixels. The sound of the video will play, keep that in mind if you have a sound or music element already set.

You cannot have a "video" and "picture" at the same time: if that's the case, only the video will be rendered. You can find free to use videos on Pexels.com.

Image maps

An image map is an image on which you can click. These zones work as extra choices and are defined with the "map" element. You can decide to have only choices, or only a map, or both for your tile. Be careful not to confuse your players as nothing will tell them the picture is clickable if you don't tell them.

"Tiles": [
  {
    "id": "1",
    "title": "my first tile",
    "text": "my tile text",
    "picture": "my_folder/picture.png",
    "map": [
      {
        "shape": "poly",
        "coords": "373,253,163,134,71,62,179,99,375,213",
        "to_tile": "3"
      },
      {
        "shape": "poly",
        "coords": "18,299,151,233,111,158,3,207,3,297",
        "to_tile": "4"
      }
    ]
  }
]

Each clickable zone is composed of a shape, coordinates, and a to_tile.

  • The "to_tile" defines the target tile id, like for a choice.
  • The "shape" is the shape of the zone which can be clicked, and the "coords" corresponds to the related coordinates.

To create an image map, you have to do the following:

  • First, resize the picture so that its height is exactly 300 pixels
  • Upload your image to image-map.net
  • Edit your clickable zones on the website, then click "show me the code"
  • Copy the "shape" and "coords" values to your map element

Congratulations, you have created a clickable picture !

Inventory

Storiz supports the management of items, which open-up interesting possibilities. Items can be collected and used for unlocking certain choices. Let's see how this works.

"Stuff": [
  {
    "key": "my_item_1",
    "name": "Name of item",
    "description": "Description of item"
  },
  {
    "key": "my_item_2",
    "name": "Name of item",
    "description": "Description of item"
  }
]


"choices": [
  {
    "text": "first choice",
    "to_tile": "2",
    "item": "my_item_2"
  },
  {
    "text": "second choice",
    "to_tile": "3",
    "requires": "my_item_1",
    "uses": "my_item_1",
    "disable": "invisible"
  }
]

Stuff

All the items of the story shall be declared in the Stuff section. Each item in this section is defined by a key, a name and a description.

  • The "name" and the "description" are simple strings which will appear as such to the player.
  • The "key" must be a unique identifier for the item. This key will never be displayed on screen and is used for binding the item to the choices or maps.

These elements are called 'items' but they can be used any way you like. They can represent objects, such as a sword, or something else, such as the name of a contact, or the current mood of the character. What matters is that these elements will have an impact in the choices the player can make by enabling otherwise unavailable options.

item

This element can be added to a choice or map option. Its value shall be corresponding to a "key" declared in the Stuff section. If the player takes this choice, the item will be added to the inventory of the player. The "item" element can be declared in two ways:

  • if the option gives a single item, you can declare it in the following way: "item": "my_item"
  • if the option gives two or more items, you can declare them in an array structure like this: "item": "[my_item_1,my_item_2,my_item_3]"

uses

This element is the counterpart of the "item" element. It can be added to a choice or a map option. If the player takes this choice, and if the player had the corresponding item, then the item will be removed. If no such item was obtained, nothing will happen. The "item" element can be declared in two ways:

  • if the option removes a single item, you can declare it in the following way: "uses": "my_item"
  • if the option removes two or more items, you can declare them in an array structure like this: "uses": "[my_item_1,my_item_2,my_item_3]"

Note that an option can both give items and use (other) items.

requires

This element can be added to a choice or map option. If the player did not collect the corresponding item(s), then the option will be disabled. That is, the player won't be able to choose the option. If it is a choice option, it will be grayed-out. If it is a map option, it will disappear entirely.

  • if the option requires a single item, you can declare it in the following way: "requires": "my_item"
  • if the option requires two or more items, you can declare them in an array structure like this: "requires": "[my_item_1,my_item_2,my_item_3]"

The "requires" element is useful for branching the story based on which elements the player picked up.

disable

This element can be added to a choice option. It complements the "requires" element and controls the behavior of the corresponding choice button.

  • "disable": "grey" - This is the default option. If the player misses at least one of the "required" items, the button will be greyed-out. It will still be visible but the player won't be able to click on it. It is useful to tell the player that there are other options which he could try to unlock when replaying the game.
  • "disable": "invisible" - If specified, then if the player misses at least one of the "required" items, the button will be completely removed. It is useful to keep some branches as a surprise or to avoid having too many greyed-out buttons.

Advanced

These are advanced topics which can let you design even more complex stories.

clue collection scene

When you write tile id "x", you can let player find items (in a clickable image, for example) and stay on the same tile (to search for more items maybe) by setting the target to_tile to "x", that is, to the current id. This will trigger the attached "item" keyword but will keep the player on the same tile.

randomness

It is possible to assign the same "id" to several tiles. When this is the case, the engine will choose at random which tile to render. If you have 4 tiles with the same id, then each of these tiles will have a 25% chance to be rendered each time the player chooses to visit this id.

It is possible to add some randomness to your stories this way, which is nice for replay value, but be careful not to alienate the player. It is recommended to have only slight changes between two tiles having the same id (such as giving a different object upon visit, making the player encounter a different character, or just see a similar picture with different colors or hear a different background music).

flags

Story flags are a powerful means to control which branch the player visits. For example the player could be free to visit 5 places in any order, and could visit a 6th one once all the other places were visited. To do this, simply use the "item" and "requires" elements, but don't declare the items as keys in the Stuff section. In other words, flags are objects which are invisible to the player. Back to our example, visiting place 1 will give item flag_1 to the player, place 2 will give item flag_2 etc. And place 6 will require all six flags to unlock.

disabling a choice with an item

The "requires" let you disable a choice if you are missing an object. Now how to do the opposite? For example, imagine the following: the player can pick a heavy armor or ignore it. Later, the player is given the choice to swim across a river. If the player has picked-up the armor, you want this to lead to the player to drown. To achieve this result, you can do the following:

  1. create an item called "armor"
  2. upon starting, assign the player the flag "no_armor"
  3. when the player picks the choice to take the armor, define it as "item": "armor", "uses": "no_armor"

This means that the player will at any point in time either have the flag "no_armor" or the item "armor" but not both.

Now when the choice to swim is given, do the following:

  1. create an option where the player can swim, as "requires": "no_armor", "disable": "invisible"
  2. add an option where the player drowns, as "requires": "armor", "disable": "invisible"

What this will do is the following: the player will only see one option, never both. If he has the armor he will be forced to drown, and if he ignored it, he will be forced to pick the option where he can swim.

It gets more complex if more than one object is involved. For example, to handle the case where a player can have found a floating spell, it could be solved by assigning a corresponding "no_floating_spell" flag to the player at the beginning, and defining an option where the player drowns if he has an armor and no floating spell:

  • option 1: "requires": ["armor","no_floating_spell"]
  • option 2: "requires": "no_armor"

Misc

{
  "Name": "sample",
  "Credits": "<b>Bold credits</b>",
  "Tiles": [
  ],
  "Stuff": [
  ]
}

Name

The "Name" of your story will appear in the story menu, along with the description set in the stories.json file.

Credits

The "Credits" can contain text as well as HTML tags, like for any "text" element. Its purpose is to say something about the story, for example who is its inventor. It is also a good way to credit the people whose pictures, movies and sounds you borrowed for creating your story. Some artists are ok to let you use their work and only ask to be credited in exchange, so please play by their rules.

Wrapping up

You are now aware of all the current features of Storiz. All there is left to tell is how to run your story. To help you, the template.json file was created as a minimal structure containing all the supported keywords. You can use it as a reference. Have fun writing your next story !