Logo Header


(currently cinetraverse1, conforms to Cinetraverse v1.0.2)

If you are going to make your own verses, consider reading this page.

See also "demo" verse in "verses/demo" as an example, and "cinetraverse/play/verse/verse.go", "cinetraverse/play/verse/verse_load.go" from the source, in particular loadVerse() function.

...Actually, you have the entire engine source to read and clarify the player⇆verse interaction.

You will need programs to work with text, image, sound, and video files. Among the others, there are Sublime, GIMP, Audacity, OpenShot, and ffmpeg.

In .json-s, the fields that can be localized are maps (also called associative arrays or hashtables). Their keys are 3-letter language codes from ISO 639-2, and their values are localized strings. For example, {"eng" : "Old rope", "rus": "Старая верёвка", "ukr" : "Стара мотузка"}. Below these are called «langmaps».

All places must have unique Ids, as well as portals and things (see below). However, it is allowed (confusing though) to have e.g. place and thing with the same Id.

Each verse's state is saved in "states/<verseId>" dir; <verseId> is the name of verse's dir from "verses". There are few .json-s inside where Ids of current place, found places, unlocked portals, and acquired things are stored in plaintext.

The root dir of a verse contains the following dirs (enclosed in "[]") and files:










Let's look into these one by one.

[ambients], [cinemas], [musics]

Contain ambient sounds, videos, and musics for the places respectively. Since they are played in looped mode, they have to be looped on their own, that is, the transition from the end to the beginning should be seamless, without «leaps» or «clicks». Search for sound loops or make your own, the usual way is to crossfade the end with the beginning. As for videos, the simplest approach is probably the aforementioned crossfading, however more sophisticated methods exist, e.g. J. Liao, M. Finch, H. Hoppe: Fast computation of seamless video loops. 2015, ACM Trans. Graph. 34(6):197:1–197:10. As a last resort, use our Fourier Video Loop utility.

Greater framerate of a video increases loading time and memory consumption. 30 FPS should be enough.

Of course, different places can use the same music, ambient, or even video (see below).

[picture] or picture.png

256x256 image of the verse that is displayed in the main menu. More precisely, this is an animage (animated image, see "cinetraverse/core/video/animage.go"), that may consist of many frames. If so, the corresponding files, named "0001.png", "0002.png", ..., reside in "[picture]" dir; the duration of the (looped) animation is set to 3 sec. If it's static (single frame), then it's a single file "picture.png".


This is where places and their internals are defined. They are arranged in layers, or «circles» in Cinetraverse terms, thus when you open this dir, you see






"hidden.png" is a 64x64 image for the places not found by the player yet.

The dir "[i]" contains the places on i-th circle. 0-th circle is the center of the map and should contain only 1 place; the verse as a puzzle is «solved» when the player has reached this central place. Now, within each "[i]", there are place dirs:





First 2 digits define the order in which the places reside on i-th circle at Circles map, starting from the top («North») and then clockwise. Remove first 3 symbols, including "_", to obtain the Id of this place, used e.g. in "Destination" property of a portal (see below). So, for example, the Id of the place in "02_forest" dir is "forest".

At the beginning the player is at the "01_" place of the outermost circle, all other places are hidden.

Finally, the definition of a given place within "xy_placeId":







Again, we consider them one by one.

[here] or here.png

64x64 looped animage of the place at Circles map when the player is at this place (hence «here»). The duration of the animation is set to 2 sec. Single file "here.png" is for static image.


Analogously, 64x64 image of the place at Circles map when the player is at another place.

How the «here» and «there» images differ, is up to you: animated/static, color/greyscale etc.


The dimensions of this image (width and height) must be equal to that of the video of this place, because they are scaled (preserving the aspect ratio) to fill the screen.

You use this image to define zones — things and portals (see below). Each zone must have a unique color, though it doesn't have to be a connected set of pixels. Black color means «no zone». Typically, few distinct colors (bright saturated ones, e.g. red, green, cyan, yellow etc.) are enough. Hint: to position zones accurately, use layers in your image editor, with a frame from place's video as a background layer and zones image as an active layer.


Mostly defines the place audiovisually. Its fields are

Title : langmap. Yup, it's the title of the place (displayed at Circles map and as destination of unlocked portals leading there). Title and Id are different properties.

Cinema : string. Name of video file (including extension) in "cinemas" dir that is played at this place.

Ambient : string. Name of audio file (including extension) in "ambients" dir that is played. If empty, there will be no ambient.

Music : string. Name of audio file (including extension) in "musics". Empty means no music.

HexColor2Thing : string → string map. Keys are colors in HTML format (6 hexadecimal digits, RRGGBB) of the zones from "zones.png", values are Ids of things that are acquired when the player clicks on the zone (after that, the zone becomes inactive).

[portals] (optional) ▲

If it is present, there are portals at this place. They are defined by .json files inside this dir. The Id of the portal is the short filename of .json: "forest_brook_sea.json" defines the portal with Id "forest_brook_sea". The fields of portal-defining .json:

Destination : string. Id of destination place.

HexColor : string. HTML-color of the zone that corresponds to this portal from "zones.png" of this place.

RectCenter : array of 2 integers. X and Y, from the top left corner, in pixels of this place's video/zones image, of the center of the portal rectangle where the video of destination place appears during transition to that place.

RectWidth : integer. Width of the portal rectangle, in pixels of this place's video/zones image.

In other words, during the transition from current place to destination place, this rectangle (and the destination place's video in it) will be smoothly «zoomed out» to fill the screen.

Now, the «interactive» part of a portal:

Phrases : array of, well, Phrase-s. Each phrase is defined by its initial, «incomplete», content, and its «completes», that is, how its content changes when the player uses certain thing on this phrase. For the portal to become unlocked, the player has to guess the right combination of things. So, each Phrase has the following fields:

Content : langmap. Original, incomplete phrase, where "..." mark missed parts. The presence and the number of "..." aren't checked, that is left to you; what is «missed» is the meaning, the intention, maybe the feeling, — not a «strict» sequence of words, like a thing's name.

Completes : array of Complete-s. In turn, each Complete consists of

Thing : string. Id of the thing.

Content : langmap. The phrase completed by this thing. Again, there is no strict rule that only "..." parts may be modified. Quite opposite: the thing is able to change the entire phrase, the order of its parts, its style, and so on.

The 1st Complete is «correct», it is the one the player has to guess in order to unlock the portal. If the player uses a thing for which there is no complete, the phrase returns to incomplete state. A thing can be used many times to complete the phrases of the same portal.

Back to the root dir of a verse.


Currently, there is only "portals" dir here, and within it, in turn, there are "loop" and "open" dirs. The former one contains the sounds that are played in looped mode while the player tries to unlock a portal (each time the sound is chosen randomly), and the latter one contains the sounds that are played at once when the player starts to move through the portal for the first time (again, chosen randomly).


Contains dirs whose names are 3-letter language codes from ISO 639-2. Inside such dir there is a single dir whose name should be familiar to you by now: "portals". In there, put the .ogg files named after the corresponding portals ("forest_brook_sea.ogg"), they are played at once when the player has unlocked the portal. If such file doesn't exist, then simply nothing is played for that portal.

The rightly completed phrases, pronounced with intonation that brings some additional meaning, are the most obvious content of such speech, however you may try something else.


Contains 72x72 images of things (displayed in inventory) and "things.json" file, where the things are defined by the array of the following 3-element records:

Id : string. Id of thing.

Title : langmap. Name of thing.

Pic : string. Filename of the thing's image (in this very dir).


Verse info. Fields:

Title : langmap. In the main menu, the verses are sorted in alphabetical order by title.

Description : langmap. The brief description of the verse.

Version : string.

Date : string.

Authors : string.

Languages : array of strings. Each element is a 3-letter language code from ISO 639-2. When the code of certain language is present here, it means that all translatable strings have been actually translated to this language... well, that's how it should be. Also, the language Cinetraverse is set to ("Lang" in "config.json") must be present in this array, otherwise the engine will not play the verse.

Comments : string. Use "\n" for newlines.

Format : string. Reserved.


There are some sanity checks, but you can simply make the verse that will crash the engine circumventing these checks. Moreover, you are probably able to achieve buffer overflow, arbitrary code execution, privilege escalation, rootkit installation etc. etc. Or, you may get the verse made by someone else that includes such surprises. Therefore, be careful with verses obtained from untrusted sources.

Also, there is no automatic «solvability» check, — nothing stops you from making a very complex verse where central place is unreachable (things required to unlock portals are in places where only these portals lead, correct completes require non-existent things, and so on). In other words, such check is manual and up to you.

Copyright © 2014–2021 Sunkware
Style:  NightWinterSea
VisitIPs is 👁watching👁 you⟩