├── .ruby-version ├── web ├── build │ ├── CNAME │ ├── stylesheets │ │ └── all.css │ ├── javascripts │ │ ├── all.js │ │ └── bootstrap.min.js │ ├── favicon.ico │ ├── images │ │ ├── notepad.png │ │ ├── twee2-logo.png │ │ └── escape-from-earth.png │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ ├── install.html │ ├── escape-from-earth.tw2 │ ├── index.html │ ├── tutorial.html │ └── documentation.html ├── source │ ├── CNAME │ ├── stylesheets │ │ └── all.css │ ├── javascripts │ │ └── all.js │ ├── favicon.ico │ ├── images │ │ ├── notepad.png │ │ ├── twee2-logo.png │ │ └── escape-from-earth.png │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ ├── layouts │ │ └── layout.haml │ ├── install.html.haml │ ├── tutorial.html.haml │ ├── escape-from-earth.tw2 │ ├── index.html.haml │ └── documentation.html.haml ├── .gitignore └── config.rb ├── examples └── grunt │ ├── Gemfile │ ├── sections │ ├── section1.tw2 │ └── section2.tw2 │ ├── javascripts │ └── main.js.tw2 │ ├── package.json │ ├── stylesheets │ └── main.sass.tw2 │ ├── story.tw2 │ ├── README.md │ └── Gruntfile.js ├── .gitignore ├── lib ├── twee2 │ ├── version.rb │ ├── build_config.rb │ ├── story_format.rb │ ├── decompiler.rb │ └── story_file.rb └── twee2.rb ├── Gemfile ├── doc └── usage.txt ├── storyFormats ├── Paperthin │ ├── format.js │ └── icon.svg ├── SugarCube │ ├── LICENSE │ └── icon.svg ├── SugarCube2 │ ├── LICENSE │ └── icon.svg ├── Harlowe │ └── icon.svg └── Harlowe2 │ └── icon.svg ├── Rakefile ├── bin └── twee2 ├── twee2.gemspec ├── README.md └── LICENSE /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.1.5 -------------------------------------------------------------------------------- /web/build/CNAME: -------------------------------------------------------------------------------- 1 | twee2.danq.me -------------------------------------------------------------------------------- /web/source/CNAME: -------------------------------------------------------------------------------- 1 | twee2.danq.me -------------------------------------------------------------------------------- /examples/grunt/Gemfile: -------------------------------------------------------------------------------- 1 | gem 'twee2' 2 | -------------------------------------------------------------------------------- /web/build/stylesheets/all.css: -------------------------------------------------------------------------------- 1 | //= require_tree . -------------------------------------------------------------------------------- /web/source/stylesheets/all.css: -------------------------------------------------------------------------------- 1 | //= require_tree . -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | pkg/ 2 | testdata/ 3 | Gemfile.lock 4 | *~ -------------------------------------------------------------------------------- /lib/twee2/version.rb: -------------------------------------------------------------------------------- 1 | module Twee2 2 | VERSION = "0.5.0" 3 | end 4 | -------------------------------------------------------------------------------- /web/build/javascripts/all.js: -------------------------------------------------------------------------------- 1 | //= require jquery-2.1.4.min 2 | //= require_tree . 3 | -------------------------------------------------------------------------------- /web/source/javascripts/all.js: -------------------------------------------------------------------------------- 1 | //= require jquery-2.1.4.min 2 | //= require_tree . 3 | -------------------------------------------------------------------------------- /web/build/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dan-Q/twee2/HEAD/web/build/favicon.ico -------------------------------------------------------------------------------- /web/source/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dan-Q/twee2/HEAD/web/source/favicon.ico -------------------------------------------------------------------------------- /examples/grunt/sections/section1.tw2: -------------------------------------------------------------------------------- 1 | ::Game 2 | 3 | You can go to [[Room 1]] or [[Room 2]] 4 | -------------------------------------------------------------------------------- /web/build/images/notepad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dan-Q/twee2/HEAD/web/build/images/notepad.png -------------------------------------------------------------------------------- /examples/grunt/javascripts/main.js.tw2: -------------------------------------------------------------------------------- 1 | ::Boring Javascript [script] 2 | 3 | console.log('it works!') 4 | -------------------------------------------------------------------------------- /web/source/images/notepad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dan-Q/twee2/HEAD/web/source/images/notepad.png -------------------------------------------------------------------------------- /web/build/images/twee2-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dan-Q/twee2/HEAD/web/build/images/twee2-logo.png -------------------------------------------------------------------------------- /web/source/images/twee2-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dan-Q/twee2/HEAD/web/source/images/twee2-logo.png -------------------------------------------------------------------------------- /web/build/images/escape-from-earth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dan-Q/twee2/HEAD/web/build/images/escape-from-earth.png -------------------------------------------------------------------------------- /web/source/images/escape-from-earth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dan-Q/twee2/HEAD/web/source/images/escape-from-earth.png -------------------------------------------------------------------------------- /web/build/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dan-Q/twee2/HEAD/web/build/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /web/build/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dan-Q/twee2/HEAD/web/build/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /web/build/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dan-Q/twee2/HEAD/web/build/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /web/build/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dan-Q/twee2/HEAD/web/build/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /web/source/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dan-Q/twee2/HEAD/web/source/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /web/source/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dan-Q/twee2/HEAD/web/source/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /web/source/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dan-Q/twee2/HEAD/web/source/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /web/source/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dan-Q/twee2/HEAD/web/source/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /examples/grunt/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "grunt": "^1.0.1", 4 | "grunt-contrib-watch": "^1.0.0", 5 | "grunt-run": "^0.8.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/grunt/sections/section2.tw2: -------------------------------------------------------------------------------- 1 | ::Room 1 2 | You Win! 3 | 4 | [[Start Over->Start]] 5 | 6 | ::Room 2 7 | Sorry, You Lose! 8 | 9 | [[Start Over->Start]] 10 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'thor' 4 | gem 'builder' 5 | gem 'filewatcher' 6 | gem 'haml' 7 | gem 'coffee-script' 8 | gem 'nokogiri' 9 | gem 'sass' -------------------------------------------------------------------------------- /examples/grunt/stylesheets/main.sass.tw2: -------------------------------------------------------------------------------- 1 | ::Main Stylesheet [sass stylesheet] 2 | 3 | body 4 | background-color: blue 5 | 6 | tw-story 7 | font-size: 2rem 8 | color: white 9 | 10 | tw-link 11 | color: red 12 | -------------------------------------------------------------------------------- /examples/grunt/story.tw2: -------------------------------------------------------------------------------- 1 | ::StoryTitle 2 | War Games 3 | 4 | ::StoryIncludes 5 | stylesheets/main.sass.tw2 6 | javascripts/main.js.tw2 7 | sections/section1.tw2 8 | sections/section2.tw2 9 | 10 | ::Start 11 | Shall We Play A [[Game]]? 12 | -------------------------------------------------------------------------------- /web/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile ~/.gitignore_global 6 | 7 | # Ignore bundler config 8 | /.bundle 9 | 10 | # Ignore cache 11 | /.sass-cache 12 | /.cache 13 | 14 | # Ignore .DS_store file 15 | .DS_Store 16 | -------------------------------------------------------------------------------- /examples/grunt/README.md: -------------------------------------------------------------------------------- 1 | # Grunt Example 2 | 3 | You way wish to use grunt to give you a wider variety of build/compile/watch options. The following shows a basic grunt setup where all folders are watched for changes to files, twee2 builds the main `story.html` file automatically on every change, and it is live-reloaded in your browser. 4 | 5 | ## SETUP 6 | 7 | `bundle install` 8 | 9 | `npm install` 10 | 11 | `grunt watch` 12 | 13 | ## References 14 | * [Grunt](https://gruntjs.com/getting-started) 15 | 16 | * [LiveReload extensions](https://github.com/livereload/livereload-extensions) 17 | -------------------------------------------------------------------------------- /examples/grunt/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | grunt.initConfig({ 4 | run: { 5 | twee2: { 6 | exec: 'bundle exec twee2 build story.tw2 story.html' 7 | } 8 | }, 9 | watch: { 10 | files: ['*.tw2', 'stylesheets/*.tw2', 'javascripts/*.tw2', 'sections/*.tw2'], 11 | tasks: ['run:twee2'], 12 | livereload: { 13 | options: { livereload: true }, 14 | files: ['story.html'], 15 | }, 16 | }, 17 | }); 18 | 19 | grunt.loadNpmTasks('grunt-contrib-watch'); 20 | grunt.loadNpmTasks('grunt-run'); 21 | 22 | }; 23 | -------------------------------------------------------------------------------- /lib/twee2/build_config.rb: -------------------------------------------------------------------------------- 1 | require 'singleton' 2 | require 'securerandom' 3 | 4 | module Twee2 5 | class BuildConfig 6 | include Singleton 7 | 8 | attr_accessor :story_format, :story_file, :story_name 9 | attr_reader :story_ifid, :story_ifid_specified 10 | 11 | # Set defaults 12 | def initialize 13 | @story_name = 'An unnamed story' 14 | @story_ifid, @story_ifid_specified = SecureRandom.uuid, false 15 | end 16 | 17 | # Set the IFID - we track when this occurs so that the user can be 18 | # nagged for not manually setting it 19 | def story_ifid=(value) 20 | @story_ifid = value 21 | @story_ifid_specified = true 22 | end 23 | end 24 | 25 | def self.build_config 26 | BuildConfig::instance 27 | end 28 | end -------------------------------------------------------------------------------- /doc/usage.txt: -------------------------------------------------------------------------------- 1 | Command-line compiler turning Twee-like files into Twine2-like output. 2 | ------------------------------------------------------------------------------- 3 | Usage: 4 | 5 | twee2 build [input.tw2] [output.html] [[--format=story_format]] 6 | Compiles the specified twee-like file into an output file. optionally 7 | specify the format (Harlowe, Paperthin, Snowman, SugarCube, etc.). 8 | 9 | twee2 watch [input.tw2] [output.html] [[--format=story_format]] 10 | Syntax is the same as build, but twee2 will automatically watch for 11 | changes to your input file and recompile dynamically. 12 | 13 | twee2 formats 14 | Lists the output formats that are understood. 15 | 16 | twee2 decompile [URL] [output.tw2] 17 | Decompiles a Twee2/Twine 2 HTML output file at a specified URL into 18 | a Twee2 source file. 19 | NOT AVAILABLE ON MICROSOFT WINDOWS. 20 | 21 | twee2 version 22 | Reports what version of Twee2 you're using, and checks what the 23 | latest-available version is. 24 | 25 | twee2 help 26 | Displays this message. 27 | -------------------------------------------------------------------------------- /storyFormats/Paperthin/format.js: -------------------------------------------------------------------------------- 1 | window.storyFormat({"name":"Paperthin","version":"1.0","description":"The default proofing format for Twine 2. Icon designed by Simon Child from the Noun Project","author":"Chris Klimas","image":"icon.svg","url":"http://twinery.org/","license":"ZLib/Libpng","proofing":true,"source":"\n\n
\n52 | Twee2 requires 53 | Ruby 54 | version 2.0 or higher. You can check whether Ruby is installed and what version it is 55 | by opening up a command prompt or terminal and running: 56 |
57 |ruby -v58 |
59 | If you don't have Ruby installed, there are several ways to easily install it. Here are some quick ways: 60 |
61 |68 | Download RubyInstaller 69 |
70 |71 | Note that the 'decompile' feature, which turns Twine 2 story files into Twee2 source code, is not supported on Windows. 72 |
73 |79 | MacOS comes with Ruby, but it's usually out-of-date. 80 | 81 | Install a modern version 82 | 83 | using RVM. 84 |
85 |91 | Many Linux distributions have packages for Ruby, but it's often out-of-date. 92 | Install 93 | RVM 94 | and use it to get Ruby 2.1.6 by running: 95 |
96 |gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
\curl -sSL https://get.rvm.io | bash -s stable --ruby=2.1.6
rvm use 2.1.6 --default
97 | 104 | To install Twee2, open a command prompt or terminal and type: 105 |
106 |gem install twee2107 |
108 | You can check that it's installed correctly by running: 109 |
110 |twee2111 |
112 | Now you're ready to dive into the 113 | two-minute tutorial 114 | or the 115 | full documentation. 116 |
117 |123 | If you ever want to uninstall Twee2, simply run: 124 |
125 |gem uninstall twee2126 |
130 | Twee2 is open-source, which means you can read and change its code for yourself. 131 | Get the code on GitHub. 132 |
133 |91 | Twee2 is a system for writing web-based interactive fiction in the 92 | "Choose Your Own Adventure" 93 | style (but it can do a lot more than that, too). It's built on top of 94 | Twine, 95 | but instead of Twine's graphical editing system Twee2 works with your favourite text editor and 96 | tools, making it more-suitable for power users, advanced Twine authors, and those with a programming background. 97 |
98 |::StoryTitle Choosing Your Own CYOA ::Start ### Choose Your Own CYOA #### A demonstrative adventure You sit at your computer and contemplate how you're going to write your next HTML adventure game. You wrote your last one [using Twine->Twine], but you've heard good things about [Twee2], as well. ::Twine You decide to stick with what you know and use Twine. That's fine: it's a great system and it's easy to use, especially for beginners. Maybe next time you'll be ready to try Twee2! **THE END** [Play again?->Start] ::Twee2 You decide to write your latest adventure using Twee2. You find that you're able to use all of the things you're familiar with from Twine, but you also get to use your favourite text editor, break up your work into multiple files, mark up content using modern languages, and preview in a separate browser while you work. **THE END** [Play again?->Start]107 |
125 | Twee2 and Twine 2 produce 126 | the same 127 | output. They differ only in how you, the author, work to produce that output: 128 |
129 || 133 | Feature 134 | | 135 |136 | Twine 2 137 | | 138 |139 | Twee2 140 | | 141 |
|---|---|---|
| Editor | 146 |Web-based "drag-and-drop" editor | 147 |Your favourite text editor | 148 |
| Story formats supported | 151 |Harlowe, Paperthin, Snowman, SugarCube, and any custom ones you add | 152 |Harlowe, Paperthin, Snowman, SugarCube, and any custom ones you add | 153 |
| Files saved to... | 156 |Twine 2's own store (can be exported elsewhere) | 157 |Wherever you like | 158 |
| Inputs | 161 |Twine 2 files | 162 |Twee2 files, Twee files, Twine 2 files (except on Windows) | 163 |
| Outputs | 166 |Twine 2 web pages | 167 |Twine 2 web pages | 168 |
| Supported formatting languages | 171 |Markdown | 172 |Markdown, HAML | 173 |
| Supported additional languages | 176 |CSS, Javascript | 177 |CSS, Javascript, SASS/SCSS, Coffeescript | 178 |
| Simultaneous working | 181 |No | 182 |Yes, using includes and/or source control | 183 |
| Source control support | 186 |No/barely | 187 |Yes, use your favourite source control | 188 |
| Can split work into multiple files | 191 |No | 192 |Yes | 193 |
| Regeneration-on-save | 196 |No | 197 |Yes, with 'watch' command | 198 |
51 | You can write your first piece of interactive fiction in just two minutes, after you've installed 52 | Twee2. Just follow the steps below. When you're ready to move on to more-complicated adventures, 53 | see the 54 | full documentation. 55 |
56 |62 | If you haven't 63 | installed Twee2 64 | yet, do that first. 65 |
66 |78 | You can write code in any text editor: your computer will almost-certainly already have one installed. 79 | On Windows, you can use Notepad. On MacOS, TextEdit is available (be sure to select "Make Plain Text" 80 | from the Format menu). On Linux, you might use GEdit, Kate, Emacs, Vim, Pico, or something else entirely. 81 |
82 |83 | If you have a favourite text editor, you can use that: personally, I like 84 | Sublime Text, 85 | which is available for a variety of platforms and supports 86 | source code highlighting for Twee2. 87 |
88 |
91 | 97 | To begin with, copy-paste the code 98 | below 99 | on the right 100 | into your text editor (or 101 | download it here 102 | - you might need to right-click and select "Save as..."). 103 | Later, you can experiment with changing this file. 104 |
105 |
106 | Notice that the file is broken up into several
107 | passages,
108 | each of which is preceeded by a title - the titles each begin with two colons (::).
109 | Two of the passages in this code are special. The
110 | ::StoryTitle
111 | passage contains the name of our story and by convention it appears at or near the top
112 | of the file. The
113 | ::Start
114 | passage is
115 | usually
116 | the one that the player reads first, when they play your game.
117 |
119 | Save your file as
120 | escape-from-earth.tw2.
121 | You can use any file extension you like, but conventionally Twee2 files have a
122 | .tw2
123 | suffix to differentiate them from other types of files. If you're using Notepad for
124 | Windows, you might need to select "All files" from the "Save as Type" drop-down while
125 | saving, or else Windows will put
126 | .txt
127 | on the end of the filename.
128 |
130 | To compile your code, open a command prompt or terminal in the same directory as your code file, and run: 131 |
132 |133 |
twee2 build escape-from-earth.tw2 escape-from-earth.html134 | 135 |
136 | Twee2 will compile a HTML output file based on the code. Open this HTML file in your preferred web browser 137 | e.g. by double-clicking on it, and you can play your new story. Or 138 | play it online 139 | to discover what you might expect to see. 140 |
141 |142 | This short story is a very simple adventure. It might be easiest to describe in terms of a flowchart: 143 |
144 |
145 |
146 |
148 | In each passage, the player may click a link to be taken to a different passage. Links appear in the code
149 | as some text, an arrow
150 | (->),
151 | and the name of the passage that the player will be taken to upon clicking it. So the code
152 | [[Read the book->Read Book]]
153 | would show the text "Read the book" to the player, and if they click it they'll be taken to the passage that
154 | begins with
155 | ::Read Book.
156 | You can use Markdown formatting to style your text. Note the asterisks around the words "THE END" in
157 | Escape from Earth:
158 | these make that text appear in bold.
159 |
::StoryTitle Escape from Earth ::Start There are only hours left before the asteroid hits and, if the news is to be believed, all life on Earth is extinguished. The spaceship is fuelled-up and [[ready to go->Ready]], but after all the rush of the last few weeks, you don't feel like you've had a chance to say goodbye to the planet that's been your home your entire life. [[Your father->Father]] glances over to check that you're heading into the vessel as he shepherds [[the family dog->Dog]]'s out of the hangar door. Behind the barriers, [[your sister->Sister]] gives a sad wave, clutching a photo in her hand. ::Ready You've still got a few seconds before you absolutely have to [[get on board->Board]], if you'd like to go and [[help your father->Father]], say goodbye to [[the family dog->Dog]], or check up on [[your sister->Sister]], who you're having to leave behind. ::Board No, you decide, the time for goodbyes has passed. After your weeks of preparation for the journey through space you don't feel the need to tie yourself to Earth any more-strongly than you have to: it's already hard enough to let go. One at a time, you climb the steps into the rocket ship and find your seat. You close the blind that cover your tiny circular window and take a deep breath. Letting go isn't easy, but there's no reason you should make it harder for yourself. **THE END** ::Father You run to help your father with the dog, trying in vain to keep your mind occupied by anything but the evacuation. Wordlessly, you walk together to the door and hand over the dog's lead to the armed guard there. For a moment, you feel bad about leaving him with a stranger, but in six hours it won't matter anyway. Looking out through the hangar door, you feel a momentary pang of jealousy for those left behind: they get to [[watch one final sunrise together->Sunrise]]... meanwhile, you and the other "lucky" ten-thousand survivors will be [[in orbit->Orbit]], weightless but still weighed-down by your grief over the billions of deaths below. ::Sunrise It's an impulsive moment and you might not live to regret it, but right now, it's the right choice: as the guard is distracted by the dog, you duck under the barrier and run out into the cold night. Minutes later, you hear the deafening boom of the rocket lifting off, and you know that you're among those left on Earth. You find your sister and your mother and exchange hugs. Then, in quiet contemplation, you sit and watch your final sunrise as the first meteor fragments graze the sky. **THE END** ::Orbit Who is making the greater sacrifice, you wonder? Those billions who will die here on Earth, today, or the ten thousand evacuees who are to make their way to the Martian colony? But it's about more than sacrifice: it's about duty. Your age, gender, and health made you eligible for the lottery; your father was chosen for his expertise as a scientist. Now you owe it to your species and to those you leave behind to continue humankind's legacy. The rocket blasts off, and you look back through the window to see the lights of the planet below, artificially-lit for the last time. **THE END** ::Dog The old family dog's been your faithful friend for years, and it feels wrong to leave without saying goodbye. You almost envy him that he doesn't know what's coming for him and all of the humans that will be left behind. Suddenly, you're [[overcome with emotion->Emotion]]: everything you'd pushed down inside you since you heard the news that you'd won the evacuation lottery, last month, comes welling to the surface. Your father wraps his arms around your shoulders and gives you [[a squeeze of support->Support]], bringing your focus back to what must be done. ::Emotion It's no use trying to hide it any longer. You can't hold back the tears. Each wave of grief is followed by a wave of guilt: why should it be you that survives when so many others face almost-certain death? And then, once again, grief at the loss of everything you know and love. Your legs buckle, and the dog tries to comfort you, but he doesn't understand. It's your father who eventually helps you to your feet and back towards the rocket ship. You can't bring yourself to look back as you climb the steps, using all of your emotional energy just to make it onto the craft. You'll never recover from this suffering, you're sure of it. **THE END** ::Support "Goodbye, boy," you say, scratching the dog behind the ears. He looks up at you with concern in his eyes, sensing your discomfort, and you try to make your voice as reassuring as possible. What does it say about you, you wonder, that your last words on Earth were to an animal? Later, in the shuttle, you'll lose the last of your emotional reserves and break down: but for now, you need to be strong. You are the face of hope for the future of the human race, and it's time to take your place on Mars. **THE END** ::Sister In violation of the rules you were told as you entered the hangar, you turn and sprint across to your sister at the barriers. Reaching over the fence and with tears in your eyes, you give her one last hug. You try [[not to think->Hold On]] about the fact that this time, when you let go, you'll be letting go forever. She clutches you tight, and you can feel [[the photo->Photo]] in her hand scrape against the back of your neck. ::Hold On You're still locked in an embrace when the armed guard comes and separates you. You know that you shouldn't have, but you couldn't have left without saying that one last goodbye. You're shepherded swiftly onto the spaceship, and you're disappointed to disover that your window doesn't look in the direction of the crowd. You'd had this romantic idea that you'd be able to look back on your sister as you took off, but it wasn't to be. The rockets ingnite, and you take a deep breath. Here begins the first chapter of your new life, and ends the last chapter of your old one. **THE END** ::Photo "I wanted you to take this," your sister says, thrusting the photo into your hands. You recognise the photo: you took it at arms-reach to capture the pair of you, sitting out on the grass under a starry sky while, in the background, your father shows off a telescope to a group of onlookers. You stuff it into your pocket before the security guard arrives to shepherd you back towards the rocket ship. Weeks later, you'll frame it in your new home on Mars, and it will come to represent everything that you left behind in order to be there. But right now, all you want is one final hug before takeoff. **THE END**163 |
169 | You now know enough to start making simple 'choose your own adventure'-type stories with Twee2. 170 | For more-detailed information, see 171 | the full documentation. 172 |
173 |89 | Twee2 is built on top of 90 | Twine 2, 91 | minus the graphical user interface. As a result, virtually all of the 92 | documentation about Twine 2 93 | (and specifically the documentation about the 94 | different story formats) 95 | is relevant to Twee2, too. 96 | Because Twee2 is inspired by Twee, its documentation is also a valuable resource: however note that 97 | you can't use Twee 'macros' in Twee2. 98 |
99 |
101 | Write Twee2 code using your favourite text editor. Syntax highlighting is available via
102 | this Sublime Text plugin
103 | for Twee. By convention, Twee2 source files have the
104 | .tw2
105 | extension.
106 |
108 | Compile Twee2 files using the
109 | twee2
110 | command-line tool. There are two important modes of operation:
111 |
twee2 build input.tw2 output.html
115 | produces output.html based on the code in input.tw2
116 | twee2 watch input.tw2 output.html
119 | does the same thing, but
120 | watches
121 | input.tw2 for changes, automatically recompiling whenever it is updated (note that it's not
122 | smart enough to understand when
123 | 'included'
124 | files have been changed, though).
125 | 128 | Because Twee2 source files are just plain text files, they're well-suited to use with 129 | source control systems: you could, for example, use 130 | Github 131 | to share your code or to collaborate with other authors, even working on the same file. 132 |
133 |135 | Twee2 comes with built-in support for all of the same story formats that Twine 2 does: 136 |
137 |155 | If you've having difficulty choosing between them, there's 156 | a summary of the differences 157 | in the Twine 2 documentation. 158 |
159 |
160 | To specify which format to use during compilation, use the optional
161 | --format
162 | parameter. E.g. you might type
163 | twee2 build input.tw2 output.html --format=Snowman.
164 | You can get a list of the formats that Twee2 natively understands by running
165 | twee2 formats.
166 |
168 | It's possible to use any story format, e.g. if you've downloaded or written your own, by specifying the path
169 | to the story format's directory (the one containing the format.js file) in your
170 | --format
171 | parameter. For example, you might run
172 | twee2 build input.tw2 output.html --format=./MyFormat.
173 |
175 | Rather than setting the format on the command-line, it's possible to specify it within your source code 176 | itself, using 177 | build configuration 178 | options. 179 |
180 |182 | Twee2 uses a syntax that's heavily inspired-by but not 100% compatible with Twee: 183 |
184 |186 | Each block of text in Twee2 exists in a 187 | passage. 188 | Each passage begins with a title, which is prefixed by two colons: 189 |
190 |
191 | ::My Passage Name
192 |
194 | Passage titles may only contain letters, numbers, basic punctuation, and spaces. Some authors prefer to avoid 195 | spaces in their passage titles. Passage titles are not case-sensitive: you don't have to use the same case when 196 | referring to a passage every time. Passages titles 197 | should 198 | be unique within a story: if they're not, only the last passage with a given title will be included in the story. 199 |
200 |201 | Passage titles may optionally be suffixed by one or both of: 202 |
203 |::My Passage Name [tagone tagtwo]
210 | ::My Passage Name <123,456>
219 | 225 | If you include both tags and coordinates after a passage, the tags must come before the coordinates, e.g.: 226 |
227 |
228 | ::My Passage Name [tagone tagtwo] <123,456>
229 |
231 | Some passages and tags 232 | have special meanings, 233 | as described below 234 |
235 |237 | Each passage may contain any amount of content, most of which will be stuff that the player sees. Many 238 | story formats understand 239 | Markdown 240 | formatting in passages, which makes it possible to easily add formatting to your passages. Links to different 241 | passages are supported in any of the following syntaxes (where 'Dungeon' is the name of the passage they'll be 242 | transported if they click the link, and 'click here', where present, is the text that they'll see to click on): 243 |
244 |[Dungeon]
247 | [click here->Dungeon]
250 | [Dungeon<-click here]
253 | [click here|Dungeon]
256 | 260 | Some passage names and tags have special meanings. These are: 261 |
262 |
264 | The
265 | ::Start
266 | passage will, by default, be used as the initial passage that your player sees when they start reading.
267 | You can override this using
268 | build configuration options,
269 | but it's probably easier just to follow this convention.
270 |
273 | These names were used for special passages in Twee 1. They're not used by Twee2, but to maintain compatability 274 | with Twee 1 they're ignored and you should avoid using them unless you're writing a story that needs to be 275 | capable of being compiled by both Twee 1 and Twee2. 276 |
277 |
279 | Any
280 | ::StoryIncludes
281 | passages (you can have as many as you like, but you probably should avoid having more than one in any file in
282 | order to avoid confusion) are treated as lists of secondary Twee2 files to 'include' into your story. This is
283 | described in more detail below, under
284 | splitting your code into multiple files.
285 |
288 | Any passages with the 'stylesheet' tag will not be included in your story, but their contents will be injected 289 | into the story's stylesheet. For example, you could write: 290 |
291 |292 |
::MyCoolStylesheet [stylesheet]
body {
background: #eee;
}
tw-passage tw-link {
color: red;
}
293 |
294 | 295 | It's also possible to use 296 | SASS 297 | to enhance your stylesheet. Simply add the tag 'sass' or 'scss' to specify the dialect of SASS that you want 298 | to use, e.g.: 299 |
::MyCoolStylesheet [scss stylesheet]
body {
background: #eee;
}
tw-passage {
tw-link {
color: red;
}
}
300 |
301 | 303 | Any passages with the 'script' tag will not be included in your story, but their contents will be injected 304 | into the resulting web page as Javascript. For example, you could write: 305 |
306 |307 |
::SomeAwesomeCode [script]
alert('This message will appear when the adventure starts!');
308 |
309 | 310 | It's also possible to use 311 | Coffeescript 312 | to make your Javascript development more-beautiful. Simply add the tag 'coffee' to your script block: 313 |
::SomeAwesomeCode [coffee script] alert 'This message will appear when the adventure starts!'314 | 315 |
317 | Put the 'haml' tag into your regular passages in order to allow you to write 318 | HAML 319 | code into your passages. HAML is a sophisticated templating language for producing HTML output, and 320 | for some it might be preferable to writing plain old Markdown. This includes the ability to inject 321 | Javascript/CoffeeScript into particular passages. For example, you could write: 322 |
323 |324 |
::NicksBar [haml]
%p
Nick's Bar is exactly the kind of nightspot that helps you remember why you quit drinking.
A depressed-looking barman pours another beer for an equally depressed-looking drunk, while
over in the corner a street thug plays with a knife as he eyes you up. The floor is sticky
and the air reeks of stale alcohol.
%p
%strong What would you like to do?
%ul
%li [Nick<-Talk to the bartender]
%li [BarToilet<-Go to the bathroom]
%li [BarSit<-Sit in a booth]
:coffeescript
$ ->
alert "This message will appear when you reach Nick's Bar!"
325 |
326 | 328 | Passages marked with the 'twee2' tag are not included in your story. However, any Ruby code in them 329 | will be executed when the passage is processed by the builder. This can be used to 330 | set build configuration options 331 | as described below. 332 |
333 |335 | A major benefit of Twee2 over Twine 2 is that it's possible to break apart your story into multiple 336 | files, which can be used to structure your work, to facilitate teamworking with or without source 337 | control, and to make 'reusable' components such as stylesheets and scripts which can then be injected 338 | into later stories. There are two ways to do this: 339 |
340 |
342 | Insert a
343 | ::StoryIncludes
344 | passage into your file and list within it the names of the files to include. Each will be appended
345 | to the end of your story before compilation. For example, the following game skeleton includes the
346 | contents of four other files - the main file contains only the
347 | ::Start
348 | passage:
349 |
351 |
::Start **Journey To The Centre Of The Earth** by Dan Q [Play] ::StoryIncludes first_section.tw2 second_section.tw2 stylesheet.tw2 javascripts.tw2352 | 353 |
355 | You can put an
356 | ::@include
357 | directive anywhere in your code to insert the contents of another file at that point.
358 | ::@include
359 | respects your current indentation level (e.g. when using HAML), so it's safe to use at any indentation
360 | 'depth'. For example, the following passages each include a separate file that contains a description
361 | of the house in the distance: that description is shared between the two passages, and updating the
362 | file updates the description in both.
363 |
365 |
::Greenhouse [haml] %p Light shines brightly through the tall glass walls of the ornate wrought-iron greenhouse, and the plants are verdant and lively. The [Garden<-door] stands open and a cool breeze blows in. %p ::@include description-of-house.tw2 ::Garden [haml] %p The garden winds around decorative trees betwen the [greenhouse] and the [Porch<-mansion]. %p ::@include description-of-house.tw2366 | 367 |
368 | Note that neither method of including code works recursively (i.e. you can't include a file that in 369 | turn includes another file), but this may be fixed in a future version. 370 |
371 |373 | Creating a passage with the 'twee2' tag can be used to run arbritrary Ruby code or to pass additional 374 | options to the Twee2 compiler. This expands the potential capability of Twee2 almost-limitlessly, but for now 375 | the only supported options are: 376 |
377 |Twee2::build_config.story_ifid = '[your IFID]'
381 |
382 | - used to set the
383 | IFID of your story, to facilitate catologuing. If you
384 | don't include this directive, the compiler will suggest a random one to you every time you run it and
385 | explain how to add it: if you're going to publish your story publicly, you should add the line it
386 | suggests before you do so.
387 | Twee2::build_config.story_format = '[a story format]'
391 |
392 | - an alternative way of specifying the story format used by your story, rather than using the --format
393 | switch to the compiler. The syntax of format names and means of specifying externally-stored formats is
394 | identical to
395 | using the --format switch.
396 | 399 | For example: 400 |
401 |402 |
::Configuration [twee2] Twee2::build_config.story_ifid = '41AB7776-D198-40F5-BD54-0493D49DA58C' Twee2::build_config.story_format = 'Snowman'403 | 404 |
406 | It's possible to convert existing (compiled) Twee2/Twine 2 story files, in HTML format, back into 407 | Twee2 source files for further editing. This can be used to convert your Twine 2 projects into Twee2 408 | files or to easily examine the contents of somebody else's story. This feature does not work on Microsoft 409 | Windows. To use it, run: 410 |
411 |
412 | twee2 decompile input.html output.tw2
413 |
415 | The input HTML file can optionally be a full web URL. 416 |
417 |