About
Introduction to Vorple
Vorple is a user interface library for interactive literature. Its goal is to let online hypertext fiction and parser interactive fiction systems break out of their sandboxes and let story authors use the full scale of the vast possibilities of technologies that are commonly used in the World Wide Web.
An author might use Vorple just to theme their story with one of the provided custom themes, or make a multimedia spectacle with pictures, video, sound effects and interactive elements, or anything in between.
A web developer might ask if we really need Yet Another JavaScript Library. There are many general-purpose libraries, like jQuery which Vorple uses extensively, but there are none made specifically for this purpose. Libraries for "normal" web sites work usually by modifying the page elements directly, which is the best choice when you are building on top of an existing structure, but interactive fiction is different in that the content is continuously being pushed from an engine that runs the story.
The project's headquarters are at www.vorple-if.com where you'll find all the official material and downloads. JavaScript developers who want to dig into the innards of the system can find the source code at Github.
The library and all official material are open source and free for anyone to use for any purpose. (Mandatory footnote: Do still read all the licenses if you want to use it commercially or as a part of a closed system. Some third party themes, for example, are subject to slightly more restrictive licenses.)
Introduction to Undum
Undum is a JavaScript framework for creating works of hypertext and CYOA games. It is completely browser-based and provides beautiful visual design and smooth interaction out of the box. Undum is created and maintained by I D Millington.
Undum is programmed purely in JavaScript, the native language of all modern web browsers. The framework is very loose, providing only the basic functionality, which makes it easy to add more elements if so needed.
Here are some examples of stories authored with Undum:
- The official Undum tutorial by I D Millington
- The Matter of the Monster by Andrew Plotkin
- Cavity of Time by "Ed Packer" (adult content)
- Leaks by Jeremias Babini, Eva Bisceglia and Sebastian Garcia
- The Play by Deirdra Kiai
As mentioned before, it's relatively easy to modify Undum's functionality and The Matter of the Monster and Leaks both use this possibility to add more features to the stories. The official Undum tutorial uses only the basic features, as do Cavity of Time and The Play.
As a contrast to "vanilla" Undum stories, Starborn is a story that uses Vorple to add multimedia features and e.g. an interactive map.
- Starborn by Juhana Leinonen
How to read this manual
This manual does not teach how to
write hypertext fiction with Undum. At the moment the tutorial game
at undum.com is the best way to learn the
basics. From now on we'll assume that the reader knows at least how to create
situations and actions and the difference between Situation
and SimpleSituation.
Here's how the rest of this manual is structured:
- Getting started instructs on how to install and set up the system.
- Developing with Vorple tells how to actually use the system and warns of some caveats.
- Modules is a reference for the included features.
- Complete examples introduces Vorple stories that can be studied to see how different features are used in actual scenarios.
The manual does not try to be a comprehensive reference. When looking for information about a certain feature, these are the primary learning resources:
Different coding practices
If you have followed the official Undum tutorial you'll notice that this manual uses slightly different conventions to structure the code.
The official tutorial builds the situations in a single block:
undum.game.situations = {
start: new undum.SimpleSituation( "..." ),
foo: new undum.SimpleSituation( "..." ),
bar: new undum.SimpleSituation( "..." )
};
This manual, and the accompanying examples, create one situation at a time independent of each other.
undum.game.situations.start = new undum.SimpleSituation( "..." );
undum.game.situations.foo = new undum.SimpleSituation( "..." );
undum.game.situations.bar = new undum.SimpleSituation( "..." );
There's a small caveat associated with the latter method: Undum allows hyphens in situation names. If a situation's name contains a hyphen, it must be created using again a slightly different syntax:
undum.game.situations[ "end-scene" ] = new undum.SimpleSituation( "..." );
Both approaches are functionally equal. The reason why this manual takes a different approach is mainly because by creating the situations independently there's no need to include a complete story for each code snippet, and secondarily because it reduces the amount of required punctuation and therefore reduces the possibility of mistakes.
Another difference is that long lines of text are split to multiple lines by concatenating smaller strings instead of using backslashes at the end of lines. That is, the Undum tutorial does this:
"<p>Now we're almost at the end of the road. But so\ far you have moved through this tutorial linearly - from one\ situation to the next, without any choice. Undum is designed to\ support narratives that branch and merge.</p>"
...but we do this instead:
"<p>Now we're almost at the end of the road. But so " + "far you have moved through this tutorial linearly - from one " + "situation to the next, without any choice. Undum is designed to " + "support narratives that branch and merge.</p>"
Again there's no practical difference, but since Vorple functions must
be concatenated with + characters it's simpler to use
the same method with normal text as well.
Quick start for the impatient
People have different ways of learning new things. For those who learn best by getting their hands dirty from the start and not by reading a book from cover to cover, here's how to pick the important parts:
- Get the system installed and running using instructions in either Starting a new project or Migrating an existing project, depending on whether you're starting from a clean slate or from an existing Undum project.
- Skim through the subchapters in Developing with Vorple. You can probably grasp the syntax from looking at the examples later. If not, you can always come back and read the Using the library functions chapter. The API is at vorple.if/doc/API, remember to keep it at hand. Pay closer attention to the Of functions and strings chapter so that you don't get bitten by unexpected behavior later.
- Look at the source codes of the example stories: One With Everything and Down the Rabbit-Hole.
- When you find some element that you want to use, look it up from this manual (under the Modules chapter) and from the API.
Getting started
Starting a new project
The download page at vorple-if.com has ready made packages for different themes. Choose a theme that pleases your eye the most, download the package and unpack.
Each theme package has at least these files and directories:
- css
- lib
- media
- audio
- image
- music
- video
- vorple.game.en.js
- index.html
The media folder and its subfolders are meant for story-specific multimedia files.
You can verify that everything works ok by opening
the index.html file with your browser.
You should see an extremely minimal but functioning Undum story.
Go through the index.html file and replace the placeholder
texts like story title and description.
(You can also do this at any point later.)
vorple.game.en.js is an empty story file.
If you want to call it something else, rename it
to whatever you wish and change the filename in index.html
so that it gets loaded properly.
Finally, open vorple.game.en.js and go through
it, there are more instructions there on how to complete the story's basic setup.
Migrating an existing project
If you already have an existing Undum project
where you want to use Vorple, download any theme package from the
download page.
You only need the library files so if you don't want to change your existing
theme it doesn't matter which package you download.
Unpack it and copy the library directory lib/ to
the same directory where the story's HTML file is.
If you want to change the layout as well, skip the rest of this chapter and read Migrating to a new theme for further instructions.
Modify your existing main HTML file
(usually storyname.en.html) and add Vorple's libraries
and resources after the line that loads Undum.
In the standard Undum template the line is almost at the end of the file.
<!-- Find this line... -->
<script type="text/javascript" src="media/js/undum.js"></script>
<!-- ...and add these lines below it: -->
<script type="text/javascript" src="lib/jquery.qtip.min.js"></script>
<script type="text/javascript" src="lib/jquery.jplayer.min.js"></script>
<script type="text/javascript" src="lib/vorple.min.js"></script>
<!-- Make sure those lines come before the line that loads your story file,
for example: -->
<script type="text/javascript"
src="media/games/tutorial/tutorial.game.en.js"></script>
If you plan for the story to feature sounds or music, see chapter Mute controls for instructions on how to add the controls to the layout.
Vorple is designed to be fully compatible with stories created for standard Undum. If you have a story that works with vanilla Undum but not with Vorple, please file a bug report.
Migrating to a new theme
If you want to start using one of the Vorple-provided themes,
download the theme package, unpack it and copy your
storyname.game.en.js story file to its main directory.
The theme's index.html file becomes the new main HTML file.
You'll need to manually edit index.html to match the contents of your
old HTML file (titles, descriptions, other custom content you've added).
At the same time when you go through index.html, check
if the theme requires other attention as well. Special instructions will be
given as comments where necessary.
Before you can start using Vorple's features, you have to make the following changes to the story file:
- Add
vorple.core.init( system );to theundum.game.init()function. - If you're using
undum.game.afterEnter()orundum.game.afterAction()global event hooks, you have to make sure that they runvorple.undum.afterEnterTrigger( character, system, from, to );andvorple.undum.afterActionTrigger( character, system, situation, action );respectively by adding them to the beginning of the event hooks.
Without these additions some of Vorple's features might not work
correctly or at all. Refer to the vorple.game.en.js
file for an example.
Developing with Vorple
Initializing the library
Some of Vorple's features are initialized by calling
vorple.core.init()API.
undum.game.init() is a good place to do so. The Undum engine
must be given as the first parameter to the initialization function. The engine
is the undum.game.init()'s second parameter, system.
undum.game.init = function( character, system ) {
// other Undum initialization
// ...
vorple.core.init( system );
};
Using the library functions
Vorple adds enhancements to Undum's basic functionality (with the core module) and extends its capabilities (with the Undum module). The setup and usage of these features are covered in the respective module chapters.
To help write the HTML contents of an Undum story, the HTML module has helper functions that create HTML tags. For example, here's the (abbreviated) starting situation from the Undum tutorial game:
start: new undum.SimpleSituation(
"<h1>Starting Out with Undum</h1>\
<img src='media/games/tutorial/woodcut1.png' class='float_right'>\
<p>Welcome to the Undum tutorial. Undum is a tool for writing\
hypertext interactive fiction. It has some unique features\
and a visual design that encourages narrative games.</p>\
\
<p class='transient'>For now, lets move on with the tutorial.\
<a href='rooms'>Click this link</a> to move on.</p>"
)
Using Vorple's HTML helpers it would be written like this:
undum.situations.start = new undum.SimpleSituation(
vorple.html.tag( "h1", "Starting Out with Undum" )
+ vorple.media.image( 'woodcut1.png', { classes: 'float_right' } )
+ vorple.html.p(
"Welcome to the Undum tutorial. Undum is a tool for writing "
+ "hypertext interactive fiction. It has some unique features "
+ "and a visual design that encourages narrative games."
) + vorple.html.p(
"For now, lets move on with the tutorial. "
+ vorple.html.link( "rooms", "Click this link" )
+ " to move on.", { classes: 'transient' }
)
)
Using the helpers reduces the chance of typos and missing end tags and they make the code more structured and readable (although your mileage may vary).
Other functions that don't create story text but do something else like play sounds or create tooltips are called inside functions.
undum.situations.maze = new undum.SimpleSituation( function() {
vorple.media.playMusic({ mp3: "background.mp3", oga: "background.ogg" });
return vorple.html.p( "You are in a maze of twisty passages, all alike." );
});
The exact syntax is described in each feature's documentation in this manual and in the API.
Reading the API
Vorple's modules and functions are documented in detail in the API. The API is included in the zip package and a link to the online version is in the main menu of the Vorple project website.
Functions mentioned in this manual have a link appended to them that
takes you to the corresponding place in the API:
vorple.core.init()API
In the API you'll find a list of modules in the left hand side of the page. Clicking on a module's name opens a page that details the fields (variables) and methods (functions) included in the module.
Here's an example documentation of
vorple.core.requireRelease()API:
The first line tells that this method:
- is a static method (all Vorple's public methods are static, so this is not meaningful information)
- returns a boolean datatype (
trueorfalse) - is called
vorple.core.requireRelease - accepts two parameters
The following paragraph describes the use and behavior of the method.
Next there's a description of accepted parameters. The accepted type or types are inside the square brackets. The parameter's name corresponds to the name shown in the first line and the text "optional" means that this parameter can be left out. If the parameter defaults to some value if it's left out, it's also shown here.
Finally there's the description of the return value (if any). There might also be links to other parts of the API or to external resources.
At the top of the page there's a link to the source code of the module. If reading the manual and the API still leaves you wondering what a function does or how it's used, you can always look at its source code and try to figure it out from there.
Remember that Vorple uses the jQuery library that has its own api. Other included libraries have their own documentation, but the API has links to them when necessary.
Of functions and strings
We need to go through some JavaScript theory for this one. Let's say we want to make a situation where we show "Hello world!" to the reader. There are three ways to do it:
// SimpleSituation with a string argument
new undum.SimpleSituation( "<p>Hello world!</p>" );
// SimpleSituation with a function argument
new undum.SimpleSituation( function() {
return "<p>Hello world!</p>";
});
// Situation
new undum.Situation({
enter: function( character, system, from ) {
system.write( "<p>Hello world!</p>" );
}
});
The end result is always the same, words "Hello world!" displayed on the screen. The difference is that the first method uses a string argument which is evaluated on initialization and the two others use functions whose contents are evaluated when they are called.
What does this fancy tech jargon mean and why is it important? Let's look at a practical example where we want to play a sound effect when the reader enters a situation:
// This won't work:
new undum.SimpleSituation(
"<p>You hear a loud bang.</p>"
+ vorple.media.playSound({ mp3: "gunshot.mp3" })
);
// Do this instead:
new undum.SimpleSituation( function() {
vorple.media.playSound({ mp3: "gunshot.mp3" });
return "<p>You hear a loud bang.</p>";
});
What happens with the first (incorrect) method is that the string contents are evaluated when the story loads and therefore you hear the sound effect right away, not when the reader enters the situation. In the latter version the sound playing function call is inside a function that's called only when the situation is entered so the sound plays at the correct time.
Vorple's functions can be divided into two categories: active functions that do something the moment they're called, and passive functions that return a string of HTML code.
The following modules or functions are always passive and therefore safe
to use in undum.SimpleSituation as a string argument:
- everything in the
htmlmodule vorple.media.image()vorple.media.youtube()
For everything else it's safer to use them in functions only.
Modules
Button
TBA
Cookie
Cookies are small snippets of text web pages can save to the user's computer. Cookies can be used to identify a returning user or save data across sessions.
Cookies can be set using the
vorple.cookie.write()API
method and read with
vorple.cookie.read()API.
Cookies can be deleted using
vorple.cookie.remove()API.
A cookie has text content and a name that's used to identify the cookie.
vorple.cookie.write( 'greeting', 'Hello!' ); // sets a cookie called "greeting" vorple.cookie.read( 'greeting' ); // returns "Hello!" vorple.cookie.remove( 'greeting' ); // removes the cookie
The cookie's contents can be updated by overwriting it with
vorple.cookie.write().
By default cookies are set to expire in one year. The expiration period
can be set using an expires option while writing the cookie,
as a number of days the cookie is valid or as a JavaScript Date
object:
vorple.cookie.write( 'greeting', 'Hello!', { expires: 7 } );
The specification says that a browser should accept at least 20 cookies per web site, each with maximum content length of 4096 bytes (characters). Most browsers allow much more than this, but it's safest to stay within these boundaries. Some browsers also limit the total length of all cookies per web site to 4096 bytes or some other value.
- Wikipedia: HTTP cookie
Core
The core module has mainly helper functions for other modules and general settings and features.
Settings
vorple.core.settings contains two variables:
vorple.core.settings.confirmWindowClose (default false)
and vorple.core.settings.debug (default false).
vorple.core.settings.confirmWindowClose defines whether or not
the browser should alert the reader that they're leaving the page when they
close the browser window or try to navigate to another page.
The purpose is to prevent the reader from accidentally leaving the page and
inadvertently erasing their progress at the same time.
If the variable is set to true a default message will be used:
"You are about to leave the story. Any unsaved progress will be lost.
Are you sure you want to continue?"
If the variable is a string, it will be used as the message:
vorple.core.settings.confirmWindowClose = "Are you sure you want to
leave the game?"
The variable vorple.core.settings.debug can be set to true
while developing the story. The flag can be used to add code used for debugging
so that they don't accidentally appear in the released version of the story:
if( vorple.core.settings.debug ) { ... }
Setting the debug flag disables
confirmWindowClose so that you don't have to dismiss the confirmation
dialog every time you reload the page.
The setting variables can be set at the beginning of the story file so that they're immediately active.
Version numbers
vorple.core.version and vorple.core.release contain the Vorple library's version numbers.
Release is incremented every time a new release is made, and version increments when the new release
includes a major feature or a significant rewrite of existing features. The full version number is displayed as version.release,
for example version 2 release 15
is denoted as 2.15.
A plugin or another library can require a certain release of the Vorple library
by calling vorple.core.requireRelease()API.
An error is thrown if the library is not recent enough. The release number will always increment between releases,
even when the version number increments, so it's safe to check only the release number.
If the page layout contains an element with class vorple-version, the contents of the element are replaced
by the Vorple's version number in the version.release format. The default Vorple themes have this
in the page footer:
Powered by <a href="http://undum.com">Undum</a> and <a href="http://vorple-if.com">Vorple <span class="vorple-version"></span></a>.
In the page itself it will look like this:
Initialization event
vorple.core.init()API
triggers a init.vorple event that
can be used to add custom initialization methods:
$( document ).on( 'init.vorple', function() {
// custom initialization here
});
This is mostly useful for plugins. Individual stories can just add any
initialization they need to undum.game.init() which runs
at the time Undum has been initialized.
HTML
In all HTML module functions that create HTML tags you can add tag attributes as the last parameter. The attributes are given as an object that has the attributes' names as keys and contents as values:
vorple.html.p(
"Test",
{
id: "foo",
classes: "bar",
title: "baz"
}
);
// → <p id="foo" class="bar" title="baz">Test</p>
Note how the class attribute must be named classes
because "class" is a reserved word in JavaScript.
Paragraphs
vorple.html.p()API
wraps given contents inside <p> tags.
The following are equal:
// the "pure" Undum method
new undum.SimpleSituation( "<p>Hello World!</p>" );
// with the HTML helper
new undum.SimpleSituation( vorple.html.p( "Hello World!" ) );
// with a custom class
vorple.html.p( "Hello World!", { classes: "transient" } );
// → <p class="transient">Hello World!</p>
);
Links
Links can be added with
vorple.html.link()API.
The first parameter is the link target, the second parameter the contents,
and the third the <a> tag options.
vorple.html.link( "./book", "Open the book", { classes: 'unique' } );
// → <a href="./book" class="unique">Open the book</a>
The parameters can be given as a single object that has keys for at least the url and the contents:
vorple.html.link({
url: "./book",
content: "Open the book",
options: { classes: 'unique' }
});
If an array of multiple links is given as the first parameter, a choice popup is created. A choice popup is a list of choices that appears when the main link is clicked.
The popup is hidden when any of the choices are selected or if the reader clicks on outside the popup.
vorple.html.link([
{
url: "http://vorple-if.com",
content: 'Vorple'
},
{
url: "http://undum.com",
content: 'Undum'
}],
'useful links'
);
Quotes
vorple.html.quote()API
can be used to wrap contents inside quotes.
The reason you might want to use this helper instead of just writing the
quotes is that this way you can't forget to add the closing quote and
you don't have to escape the quotes as in the example below.
// vanilla Undum
new undum.SimpleSituation( "<p>\"Hello,\" she said.</p>" );
// HTML helper
new undum.SimpleSituation(
vorple.html.p( vorple.html.quote( "Hello," ) + " she said." )
);
Double quotes (") are used by default but another character or
characters can be given as the second parameter, or an array with two members
where the first member is the opening quote and the second character
the closing quote.
If you assign a character to the vorple.html.defaults.quotemarks
variable, it's used as a default from there on.
vorple.html.quote( "Hello", "'" ); // → 'Hello' vorple.html.quote( "Hello", [ "«", "»" ] ); // → «Hello»
(Character entity references were used to create the arrow quotes.)
Other tags
You can add any HTML tags using
vorple.html.tag()API.
The first parameter is the tag's name, the second is the contents inside the tag
and the third parameter the options and attributes.
vorple.html.tag(
"div",
"Hello World!",
{
classes: "transient",
title: "Greeting"
}
);
// → <div class="transient" title="greeting">Hello World!</div>
The end tag is added automatically if text content is given, and the tag is self-closed if the content is not a string.
vorple.html.tag( "br" ); // → <br />
vorple.html.tag( "div", "" ); // → <div></div>
vorple.html.tag( // → <hr class="wide" />
"hr",
null,
{ classes: "wide" }
);
If you want to make sure the end tag is always added,
use endTag: "always" option:
vorple.html.tag(
"div",
contents,
{ endTag: "always" }
);
vorple.html.tag() use
-
vorple.html.p()for<p>tags -
vorple.html.link()for<a>tags and -
vorple.media.image()for<img>tags.
Media
Images
vorple.media.image()API
creates an <img> tag. The first parameter is the
picture's file name and the second optional parameter an object with tag attribute options.
vorple.media.image( 'pic.png', { classes: 'once', title: 'A nice picture' } );
// result: <img src="media/image/pic.png" class="once" title="A nice picture" />
Unless an absolute path to the file is given
(/other/folder/pic.png or http://example.com/pic.png),
a path specified by vorple.media.defaults.imagePath is used.
The default is the media/image/ directory that comes pre-made in
all theme packages. It can be changed by assigning a new path to the variable.
vorple.media.image( 'pic.png' ); // → media/image/pic.png vorple.media.defaults.imagePath = '/resources/pics/'; vorple.media.image( 'pic.png' ); // → /resources/pics/pic.png
Preloading images
By default the web browser loads images included in the story only when they are first encountered. The reader might see the image appear on the page slightly after the text, or they might see the image slowly loading, depending on their Internet connection and the size of the image.
This can be countered by preloading the image files.
vorple.media.preloadImage()API
makes the browser load the images beforehand so that they can be displayed
immediately when the story actually needs them. Multiple images can be given
to the function as an array at the same time.
vorple.media.preloadImage([ 'image1.png', 'image2.jpg' ]);
undum.game.init() is a good place to preload the images.
The default image path is assumed, just like with
vorple.media.image().
The downside is that preloading consumes bandwith unnecessarily if the reader doesn't actually come to the point in the story where the image is needed. You might consider preloading images only at some point during the story, for example one situation before the one that shows the image or at the point when the reader enters a branch in the story that leads to the situation that has the image.
Sound effects
Audio and local video files are played using the jPlayer library.
Sound effects can be played by using
vorple.media.playSound()API.
Since the support for audio files in browsers varies quite a bit, for best compatibility you can supply the same sound file in several different formats.
vorple.media.playSound({
mp3: "sound.mp3",
oga: "sound.ogg"
});
Audio files are loaded from the project's media/audio directory
unless other path is given, just like with images.
The default path is stored in vorple.media.defaults.audioPath.
vorple.media.stopSounds()API
stops all currently playing sounds. If you need to stop or pause
a single sound, you have to manipulate the player object directly.
vorple.media.playSound() returns a jPlayer object.
If you assign the return value to a variable, you can use any
jPlayer methods to manipulate the player.
Music
For music these functions can be used:
-
vorple.media.playMusic()API to start a music track -
vorple.media.stopMusic()API to stop playing music
They work identically to vorple.media.playSound() and
vorple.media.stopSounds(). There's also
vorple.media.stopAll()API
that will stop both sound effects and music.
The default directory for music files is media/music.
It can be changed by assigning the new directory to
vorple.media.defaults.musicPath.
Why not just play background music the same way you'd play sound effects? There are a couple of key differences:
- You can play only one music track at the same time. When you start playing a new music track, you don't have to stop the existing track. Starting a music track will automatically stop the previous track from playing.
- You can easily stop or mute only music or only sound effects.
- When loading a saved story, sound effects will not be played again (remember that Undum replays the whole story from the start when it's loading from a save). The last played music track will start playing when the story is loaded unless it was manually stopped.
YouTube videos
YouTube videos can be embedded with
vorple.embed.youtube()API.
The function takes as the first parameter the id of the video to embed
and as the second parameter the options.
| Option | Type | Default | Description |
|---|---|---|---|
| height | integer | 390 | Height of the video player |
| width | integer | 640 | Width of the video player |
| parameters | object | see below | YouTube embedding parameters |
All available embedding parameters are listed in the YouTube API documentation. Default parameters are:
autoplay: '1', controls: '0', disablekb: '1', modestbranding: '1', rel: '0'
That is, start playing the video immediately, hide controls, disable keyboard controls, hide YouTube logos and don't show related videos at the end.
When the story is being reloaded from a save position, the video player is
embedded but parameters.autoplay is set to 0 so that it won't start
playing automatically.
An example of usage where we show a video in an Undum situation:
undum.game.situations.livingroom = new undum.SimpleSituation(
vorple.html.p(
"You find yourself in a living room where a film has just "
+ "started playing on the DVD player."
) + vorple.html.p(
vorple.embed.youtube(
'bsGEWHNJ3s8',
{
width: '500',
height: '280',
parameters: {
controls: '1', // allow the user to control the video
loop: '1' // start again from the beginning when playback ends
}
}
)
)
);
Mute controls
<!-- --> tags around the checkboxes to enable them.
If the story uses audio, it's polite to offer the reader a possibility to
mute sounds. If you put the following piece of code into the story's
HTML file, that is, checkboxes with class mute and
value sound, music or all,
Vorple will automatically make them function as you'd expect.
<div>
<input type="checkbox" id="muteMusic" class="mute" value="music" />
<label for="muteMusic">Mute music</label>
</div>
<div>
<input type="checkbox" id="muteSound" class="mute" value="sound" />
<label for="muteSound">Mute sound effects</label>
</div>
<div>
<input type="checkbox" id="muteAll" class="mute" value="all" />
<label for="muteAll">Mute all</label>
</div>
If you want to use the opposite scheme where a checked box means that sounds are enabled, you can use the "unmute" class instead. The functionality is identical but reversed.
<div>
<input type="checkbox" id="unmuteMusic" class="unmute" value="music" />
<label for="unmuteMusic">Music</label>
</div>
<div>
<input type="checkbox" id="unmuteSound" class="unmute" value="sound" />
<label for="unmuteSound">Sound effects</label>
</div>
<div>
<input type="checkbox" id="unmuteAll" class="unmute" value="all" />
<label for="unmuteAll">All sounds</label>
</div>
The mute status is written to a browser cookie every time it changes. In other words if the reader mutes audio, the preference is automatically remembered the next time they load the story.
To toggle the mute state manually you can use
vorple.media.mute()API
to mute or unmute sounds, music or videos, or
vorple.media.muteAll()API
to mute or unmute all sounds. vorple.media.muteAll() is a shortcut for
vorple.media.mute({ sound: true, music: true }).
vorple.media.mute() uses an object that describes what elements
to mute or unmute:
vorple.media.mute( { music: true } ); // mute music
vorple.media.mute( { music: true, sound: false } ); // mute music and unmute sound
vorple.media.muteAll() is used by giving the mute status as a parameter:
vorple.media.muteAll( true ); // mute everything vorple.media.muteAll( false ); // unmute everything
The mute checkboxes are automatically toggled to reflect the current mute status even when the muting is done manually.
Mute status can be toggled with
vorple.media.toggleMute()API.
It will unmute muted media and vice versa. The return value is true if the
new status of the media is muted and false if it's now unmuted.
Here's an example of a button that toggles sounds on and off and changes its own text to reflect the current status from "Sounds on" to "Sounds off".
<button onclick="$( this ).html( vorple.media.toggleMute( 'sound' ) ? 'Sounds off' : 'Sounds on' );">
Sounds on
</button>
Limitations
Native audio and video support in web browsers is still far from standard. Some browsers can play only MP3 files, some only OGG files, some both, some neither. (The current situation is covered in the jPlayer documentation.) jPlayer tries to use the browser's native playback capabilities and falls back to a Flash solution if it doesn't work.
For this reason, to make sure the reader gets to see the videos and hear the sounds you should provide two versions of all files: an MP3 and an OGG file for sounds, and an M4V and an OGG file for videos. This will cover practically all modern desktop browsers and many of the mobile browsers.
If you don't want to make two or more versions of each media file, the safest alternative is to use only MP3 and M4V files. Some readers will then not be able to see or hear the media, but the percentage is probably very low (Firefox or Opera users who don't have Flash installed).
YouTube videos always require Flash (with some exceptions; iOS browsers (iPhone, iPod, iPad) can launch YouTube videos in a separate player).
Mobile Safari (iPhone, iPad, iPod) supports only one sound channel. If you start a new sound while another is playing, the other sound will be stopped. If you target mobile devices, it's best to disable either background music or sound effects (if you have them), otherwise any sound effect during the story will make background music stop abruptly.
Notify
Vorple uses the noty library to create notifications. They can be used to e.g. inform the reader of important events or acknowledge their actions.
Notifications are created using
vorple.notify.show()API
with the content of the notification as the first parameter.
The notification's behavior can be altered with options given as
the second parameter. All the available options can be found on
noty's web site.
vorple.notify.show(
'Note this!',
{
speed: 2000, // animations take 2 seconds (2000 ms)
closeOnSelfClick: false // don't close the notification on click
}
);
The notification's position can be given with the layout
option. The available positions are the four corners
of the screen (topLeft,
topRight,
bottomLeft and
bottomRight),
as a wide bar on the top or the bottom of the screen
(top or
bottom),
in the center on top
(topCenter),
or in the middle of the screen
(center).
The default is bottom right.
Multiple notifications in the four corners of the screen are displayed
simultaneously. In every other position the notifications are put into
a common queue and displayed sequentially. The queue can be emptied with
vorple.notify.clearQueue()API.
The oldest notification can be dismissed with
vorple.notify.close()API
and all notifications dismissed with
vorple.notify.closeAll()API,
which will also empty the queue.
In the noty library the default duration of notifications is 5 seconds (5000 ms), but Vorple's default is that the notifications are automatically hidden after seven seconds. The average reading speed is about three words per second so 7 seconds is good for messages of about 20 words. In addition to the default location (bottom right) this is the only change to noty's defaults.
vorple.notify.defaults contains the story-specific defaults.
vorple.notify.defaults.textAlign = 'left';
vorple.notify.defaults.timeout = false;
vorple.notify.show( "This notification's text is aligned left "
+ "and it must be clicked to dismiss." );
Tooltip
Creating tooltips
Vorple comes bundled with the qTip2 tooltip library.
To add a tooltip to every link in the game, we'll add the
vorple.tooltip.enable( 'a' )API
to undum.game.init():
vorple.tooltip.enable( 'a' );
As simple as that! Now every link that has the title attribute
will show the contents of the title as a tooltip when the mouse is put over them.
<a href="foo" title="This is the tooltip's text!">Link</a>
Or using the HTML module:
vorple.html.link(
'foo',
'Link',
{ title: "This is the tooltip's content!" }
);
The parameter is a jQuery selector. If you need to add tooltips more accurately or to other elements, refer to the jQuery documentation.
All qTip2 options are supported. The documentation is at http://craigsworks.com/projects/qtip2/docs/ (look under "Options").
Manually triggered tooltips
Sometimes we might want to display a tooltip in response to an unrelated event
or as part of the story's plot.
vorple.tooltip.show()API
creates a tooltip and shows it after a delay, then hides it again
after another delay.
vorple.tooltip.show(
'.targetClass',
'Tooltip content',
{
delay: 1000, // 1 second
duration: 5000 // 5 seconds
}
);
The first parameter is the element's jQuery selector, the second the text to be displayed in the tooltip, and the third is the options, including the delay before showing the tooltip and the duration how long the tooltip is displayed in milliseconds. The defaults for the delay and duration are 3000 milliseconds and 10000 milliseconds respectively.
Undum
Disposable links
Undum's once-links disable themselves after they've been clicked, but the effect is temporary. If the reader encounters the same link later, it's active again.
Disposable links are similar to once-links, but the effect is permanent:
after the reader has clicked on a disposable link,
it will never be shown during the same story again. (Links with the same target
(href-attribute) are considered being the same link.)
There are two ways to define disposable links: either give them as a list, or specify that all links should be disposable and list only the exceptions.
The disposable link list should be assigned as an array to
vorple.undum.settings.disposableLinks:
vorple.undum.settings.disposableLinks = [ 'discard', 'these', 'links' ];
To use the latter method and specify that all links should be disposable,
set vorple.undum.settings.allDisposable to true
and, if necessary, list the exceptions as an array in
vorple.undum.settings.disposableExceptions.
vorple.undum.settings.allDisposable = true; vorple.undum.settings.disposableExceptions = [ 'non-disposable', 'links' ];
If vorple.undum.settings.allDisposable is true,
vorple.undum.settings.disposableLinks will be ignored.
Disposable links don't make a difference between situations and actions.
Links to actions should be listed without the ./ prefix.
Disposable links can be defined anywhere in the story file.
Using undum.game.init() is recommended.
A link's status can be checked with
vorple.undum.isDisposed()API
which will return true if the link has been disposed.
Disposing links manually
Links can be disposed manually by calling
vorple.undum.dispose()API.
The function can dispose any number of links at the same time,
given either as separate arguments or as an array.
vorple.undum.dispose( 'name' ); vorple.undum.dispose( 'first', 'second', 'third' ); vorple.undum.dispose( [ 'first', 'second', 'third' ] );
You can dispose even links that are not in the
vorple.undum.settings.disposableLinks list.
Reactivating disposed links
To reactivate a link call
vorple.undum.reactivate()API.
You can reactivate one or multiple links at the same time, just like with
vorple.undum.dispose().
vorple.undum.reactivate( 'name' ); vorple.undum.reactivate( 'first', 'second', 'third' ); vorple.undum.reactivate( [ 'first', 'second', 'third' ] );
Reactivation applies only to future links. Any inactive links currently visible on the screen will not be activated. Reactivated links are not automatically removed from the list of disposable links, so clicking on them later will again dispose of them.
Unique links
If a link has class unique applied to it, all other instances of the same link will be automatically disabled. This can be used to make sure that only one instance of a link will be visible at the same time.
Here's a <a href="name" class="unique">link</a> and <a href="name">another</a> but only the former one will be active because it's marked as unique and the latter links to the same place.
Or, using Vorple's HTML helpers:
vorple.html.link( 'name', 'link', { classes: 'unique' } );
// → <a href="name" class="unique">link</a>
- The Outgribe: More Undum link types
doClick() and doLink() exposures
undum.doClick() and undum.doLink() are exposed as
vorple.undum.doClick()API
and
vorple.undum.doLink()API.
This lets the author use them outside Undum's own methods, when the
undum object is not available.
Complete examples
The examples can be downloaded separately from the download page.
One With Everything
The example story One With Everything uses all standard Vorple features. It's not really a story or a game by itself, but if you want to see a real-life code example of any of the features you can probably find it in the story's source code.
Down the Rabbit-Hole
Down the Rabbit-Hole showcases Vorple's features. It doesn't include every feature like One With Everything does and it uses some more advanced techniques to e.g. show custom popup windows.
Starborn
Starborn is an Undum/Vorple adaptation of an Inform 7 keyword-based story. The adaptation adds background music, an interactive map, clickable buttons and other eye candy. Some of the features are straight-up Vorple, some are custom-made for the story.
