mirror of
https://github.com/lise-henry/crowbook
synced 2024-09-29 03:51:17 +02:00
129 lines
4.8 KiB
Markdown
129 lines
4.8 KiB
Markdown
# Interactive fiction
|
|
|
|
Version [`v0.12.0`](https://github.com/lise-henry/crowbook/tree/v0.12.0) added experimental support for writing interactive fiction.
|
|
|
|
> Since this support is experimental, it means it can change at
|
|
> anytime, and there is no guarentee that the interactive fiction you
|
|
> write for the current version of `crowbook` will work with the next
|
|
> release, even if it isn't a major release.
|
|
|
|
## Basics
|
|
|
|
If you want to have a non-linear story, you can simply use Markdown links just as you would for any other link:
|
|
|
|
```markdown
|
|
* [Open the treasure chest](open_chest.md)
|
|
* [It might be trapped, stay away from it](stay_away.md)
|
|
```
|
|
|
|
All `crowbook` renderers should render this correctly, allowing the reader to "choose her adventure".
|
|
Note, however, that you still need to include all these Markdown files in you book configuration files.
|
|
|
|
## The interactive fiction renderer
|
|
|
|
While the above allows you to generate correct EPUB and PDF files, it will still display all the content if the reader chooses to read your book linearly.
|
|
While this may not be a problem, you might want to only display the part of the book that the reader is actually exploring.
|
|
|
|
In order to do so, you can use the interactive fiction html renderer:
|
|
|
|
```yaml
|
|
output.html.if: my_book.html
|
|
```
|
|
|
|
This output is similar to the standalone HTML output, except the option to display only a chapter at a time is always true, and there is no way to display the table of contents.
|
|
|
|
## Using Javascript in your interactive fiction
|
|
|
|
While the above allows the reader to choose his own path, its interactivity is quite limited.
|
|
With the interactive fiction renderer, it is possible to include Javascript code in your Markdown files, using a code block element:
|
|
|
|
```markdown
|
|
You open the chest, and you find a shiny sword. Yay!
|
|
|
|
user_has_sword = true;
|
|
```
|
|
|
|
This Javascript code can return a string value, which will be displayed inside the document according to the reader's previous choices:
|
|
|
|
```markdown
|
|
You encounter a goblin, armed with a knife!
|
|
|
|
if (user_has_sword) {
|
|
return "You kill him with your sword, congratulations!";
|
|
} else {
|
|
return "You don't have any weapon, you die :(";
|
|
}
|
|
```
|
|
|
|
> Note that *only* the interactive fiction renderer supports this way
|
|
> of embedding Javascript code. If you try to render a document
|
|
> containing such code blocks to EPUB, PDF, or the "normal" HTML
|
|
> renderer, they will be displayed as regular code blocks.
|
|
|
|
## Embedding Makdown in your Javascript code embedded in your Markdown
|
|
|
|
If you want to include Markdown formatting in the Javascript code (to display a passage or another without having to write HTML code), you can use the `@"..."@` syntax:
|
|
|
|
```markdown
|
|
@"You face a troll!"@
|
|
if (user_has_sword) {
|
|
@"* [Attack him with your sword](fight_troll.md)"@
|
|
} else {
|
|
@"* [Better run away](run_away.md)"@
|
|
}
|
|
```
|
|
|
|
Note that in this case you don't need to return a value, this is done behind your back.
|
|
Similarly, `@"..."@` blocks don't require semicolons.
|
|
|
|
If you need to access the value of a Javascript variable inside this Markdown code, you can use the `{{...}}` syntax:
|
|
|
|
```markdown
|
|
var name = prompt("Enter your name", "world");
|
|
@"Hello, {{name}}"@
|
|
```
|
|
|
|
## Conditional blocks
|
|
|
|
Sometimes, you want some text (or Javascript code) to only be displayed (or run) when the reader reads this passage the first time, or alternatively when she goes back to it.
|
|
While it is trivial to add some code to check that, it is a common enough pattern to justify its
|
|
own variant:
|
|
you'll juste have to insert a named code block with the number:
|
|
|
|
```1
|
|
@"Only displayed at first passage"@
|
|
```
|
|
|
|
```2
|
|
@"Only displayed at second passage"@
|
|
```
|
|
|
|
```>2
|
|
@"Displayed at passage 3, 4 and so on.
|
|
```
|
|
|
|
## Interactive fiction options
|
|
|
|
As other renderers, there are options specific to the interactive fiction.
|
|
|
|
**html.if.new_game** allows you to specify the path to a Javascript that will be run at the beginning of the game.
|
|
Since this code is not embedded in a function and is at the root (and the beginning) of the document, it is a good place to declare all the functions and the global variables you might need for your interactive fiction mechanics.
|
|
|
|
E.g.:
|
|
|
|
```yaml
|
|
html.if.new_game: some_file.js
|
|
```
|
|
|
|
**html.if.new_turn** and **html.if.end_turn** allow you to specify some Javascript code that will be executed at the beginning and the end of each segment.
|
|
Unlike `html.if.new_game`, the (usually shorter) code is specified inline, and can return a string value that will be displayed at the beginning and the end of each segment.
|
|
This is exactly like including code blocks at the beginning or the end of each of your Markdown file.
|
|
E.g.:
|
|
|
|
```yaml
|
|
html.if.new_turn: "nb_turns += 1;"
|
|
html.end_turn: "return 'Turn: ' + nb_turns;"
|
|
```
|
|
|
|
**html.if.script** allows you to specify the name of a Javascript file to override the default script.
|