Welcome to //Twine//!
Twine is a tool for building interactive fiction, games, and choose-your-own-adventure stories. You can find Twine at [http://twinery.org]<earl|
If you want to learn more about programming in Twine, you'll want to look at the Harlowe documentation at [https://twine2.neocities.org]<harlowe| as well as the [[tutorials here|Tutorials]].
What follows is a brief introduction to Twine and some example games.
The basic building block of Twine is the ability to connect one scene, or //passage//, with another [[like this|FirstLink]] or [[like this!|SecondLink]].
A cool thing about Twine is that ultimately it just creates web pages, which means that once you're done with your stories they can be viewed on any device!
If you want to see some examples of Twine games, we have a few different styles of game below.
First, here's a simple [[adventure|AdventureGame]] game where you have to walk around a set of caves and solve a tiny puzzle.
Next we have a [[puzzle game|PuzzleGame]] inspired by very loosely by escape rooms, where you need to find clues so you can break the code to the door that's trapped you in an odd chicken themed room.
Finally, we have a conversation based game that's centered around texting a friend to get out of a [[dangerous situation|ConvoGame]].
{
(click: ?earl)[(open-url: "http://twinery.org")]
(click: ?harlowe)[(open-url: "https://twine2.neocities.org")]
(set: $notBeenRight to true)
(set: $notTalkedToSamael to true)
(set: $bottleFilled to false)
}Here's a new passage! As you can see, the old text we were looking at is gone.
We got here by a //link//, that looked like `[[like this|FirstLink]]`, which lead to this passage called "FirstLink" while displaying the text "like this". That's actually the majority of everything you need to know to make Twine work! By making links to passages that don't exist yet, Twine will **create** passages for you.
Now, maybe this seems a bit limiting but links and passages can do be used to make almost any kind of game you want. They can be used to make:
* scene transitions
* branching conversations
* explorable rooms
* interactions with items in the game
* menus
* combat engines
* etc.
All that being said, it's time to provide a link back to our previous segment: [[Welcome to Twine!]]We've already explained how links work in the [[FirstLink]], so now we can talk about some other small things here about what Twine **is**!
Twine is a tool for turnings //stories// into //webpages//. The coolest thing about that is that it lets you create games and turn them into something that can run on any computer or phone or tablet or any device that has a web browser.
Beyond that, though, the fact that Twine creates a web page means that all the normal tools you would use to make a web page are relevant here. If the words "HTML", "CSS", and "JavaScript" don't mean anything to you that's absolutely fine! If you //do// know something about how webpages are made then there's even more you can do in Twine. For example, here's a picture of a really fluffy chicken.
<img src="http://i.imgur.com/Y0N8US4.jpg" style="height: 500px;width: 500px"/>
You see, it's actually really easy to include straight up HTML into your Twine program. We included an the image above as `<img src="http://i.imgur.com/Y0N8US4.jpg">` and we even used a little CSS to style it to a particular height and width.
Even this entire story was styled with a bit of CSS. If you want to see more about that, then take a look at the menu option that says **Edit Story Stylesheet** from the menu in the lower-left corner of the screen.
Back to the start! [[Welcome to Twine!]] Well, you're home now. You've been suspended from school after the weirdest day of your life. Your friends are all mad at you and you **still** have to deal with the creepy texts that hijacked your brain:
[[Uriel]] 5 unread messages
[[Unknown Number]] 2 unread messages
[[Gabriel]] 1 unread message
{
<!-- Hi! So the main concepts that this game demonstrates are
* dynamic links
* text changers
* variable usage
Since the idea of the game is that the player character and a few other people are talking over text, we want the actual phone conversations to look differently than the descriptive text.
We can do that with what Harlowe calls "changers". Changers are things like the (font: 'Courier New') or (background: blue). Now we could write something like (font: 'Courier New')[this text will be in a different font] but that's tedious. Instead we can **store** the changer in a variable. So for example $textFont[this text will be in a different font] does exactly the same thing as the command above.
The other trick Harlowe lets us do is combine changers together with the + sign. That's what we do below in defining the $yourText and $theirText variables so that we can just use $yourText and $theirText the entire time.
A thing you might notice in all of these games is that we do a bunch of setup of variables right at the very beginning and then make sure we never re-enter the passage that does the setup for the rest of the game.
-->
(set: $textFont to (font: 'Courier New'))
(set: $yourText to (background: blue) + $textFont)
(set: $theirText to (background: green) + $textFont)
(set: $knowsTheIncantation to false)
(set: $urielDestination to "Uriel")
(set: $sandalphonUnread to true)
(set: $gabrielUnread to true)
(set: $urielUnread to true)
}{(if: not ((history:) contains "AdventureGame"))[You suddenly find yourself standing in a dark, dank, cave. The dripping of water off of distant stalagtites is echoing through the cavern.
"Funny," you think to yourself. "I was just reading a tutorial on making games in Twine and here I am."]
}
There's a split in the path in front of you and a solid cave wall behind you.
The [[righthand fork|RightPath]] appears to have the flickering reddish light of a fire further down the way.
To the [[left|LeftPath]], there's a wet-smelling draft hitting your nose and a quiet gurgling.
{
<!-- So one of the tricks in this game is that we repeatedly change how rooms behave if you've been in them before. There's a couple of ways you could do this. The first is that you could use a variable to keep track of whether you've been in the room before, which is the kind of thing we do in the other games.
Another cool thing you can do, though, is use the (history:) macro which spits out a list of all the passages you've been in during this game. You can then check with the contains operator to see if the passage you're currently on has been visited.
Now there's a slight problem here: the way we've built our multiple games in one system means that the game can "start over" without the history being cleared, but most of the time using your history is a great way to check if a passage has been seen before.
-->
}You walk down the left path as it curls and twists deep underground.
Eventually, the path opens up into a large cavern of bubbling pools lit from beneath by dramatic yet unrealistic mood lighting.
$notTalkedToSamael[It's very pretty, but you're not really sure what to do here. [[Go back?|AdventureGame]]]
(else:)[Well, this must be the spring that Samael wanted you to vist.
[
Fill bottle]<fill|
(click: ?fill)[You fill the bottle and stopper it, rather uneventfully. I guess it's time to [[go back?|AdventureGame]]
(set: $bottleFilled to true)]]$notBeenRight[You slowly walk down the right hand path and the flickering light gets brighter.
You see a person made of living flame, flickering red & orange in a roughly human---though androgynous---shape. They're standing in front of what appears to be an exit out of the caverns.](else:)[Again, you see the figure of flame standing casually in front of the exit to these caves.]
$notTalkedToSamael[It's not clear whether this fire person is dangerous, so you could either [[go back the way you came|AdventureGame]], [[say "hello"|TalkToSamael]], or attempt to [[tackle|Tackle]] them by surprise!](else:)[
"Hey Samael," you say giving a nod of respect.
Samael waves back, lackadaisically (colour: red)[Hey yourself]
$bottleFilled[Since you have a full water bottle, you can [[give|GiveWater]] it to Samael.]
[[Go back the way you came|AdventureGame]]
]
(set: $notBeenRight to false)You shift your weight onto your back heel and prepare to dash forward and tackle the stranger. Then, suddenly, a very important thought occurs to you:
(text-style: "bold")[THEY'RE MADE OF FIRE AND THIS IS A BAD IDEA!!]
You [[reconsider|RightPath]] your choice.You take a slow step forward "H-hello?"
The figure of flame looks up at you with a plainly bored expression. You're not entirely sure //how// you can tell they're bored given that they have no facial features, but it's an incredibly strong impression nonetheless.
(colour: red)["Hey"] they say finally. (colour: red)["I suppose you want to get through here."]
"Yeah, I was looking at some Twine examples and suddenly was here. That looks like the exit sooooo...."
(colour: red)["That sounds like a really trite and hackneyed cliche."]
You shrug to convey that you don't really have a choice in the matter.
(colour: red)["Fine. I need you to grab me a bottle of water from the other path. It's too damp to walk in there, but I can give you a bottle to fill."]
The mysterious flame-person holds out an empty glass bottle with a stopper out to you. You should probably [take the bottle]<take|
(click: ?take)[You take the bottle from the mysterious figure, carefully. You're surprised the glass isn't even vaguely warm to the touch.
You're still wondering, though, [why they needs this.]<why|
(click: ?why)["...why am I doing this?" you ask vaguely annoyed.
(colour: red)["Ah, right, so y'know how humans like hot sauce on their food?"]
You nod, guessing where this is going "You're saying this is spicy for you"
(colour: red)["Exactly! Spice makes everything less boring."]
One last thing you're curious about: what on Earth is [their name]<name|
(click:?name)["Alright, this is a little awkward, but who even **are** you?"
(colour: red)["Samael"] they says impatiently.
Well, that settles that. [[Time to go get an angel some bottled water.|AdventureGame]]]]]
(set: $notTalkedToSamael to false)
{
<!-- So what we're doing in this passage, to make the conversation more dynamic, is use the (click:) macro and hooks. So technically a hook is text wrapped up in single brackets like [this text here]. The feature we're showing off in this section is the ability to **name** hooks [like this]<hookName| and once you've named a hook you can do cool things with it like change it with the (enchant:) macro or set it to respond to clicks with the (click:) macro.
Here we're controlling the flow of the conversation so that it gets revealed piece by piece by clicking the appropriate phrases. -->
}You're in a room, filled to the brim with [[junk and strangely stacked furniture.|TheRoom]]
There's a [[large door|TheDoor]] that appears to be the only way out.
A voice announces: To Leave This Place, Find The Code.
(set: $triesPressed to 0)
(set: $enterMessage to 0)
(set: $gotPaper to false)
{<!-- In this game, you need to find clues in order to type the code 010 into the door's control panel. Now, there are silly little clues hidden in the room but you might just want to try guessing! In order to keep the game from being trivial, we track the number of attempts at entering the code. You'll see in the passage Failure that we check to see how many times they've failed at entering the code and if it's more than 2, then the player is "blown up" and has to start over -->}You carefully hand the bottle to Samael.
(colour: "red")["Lovely! This is exactly what I needed for my burrito-bar."] They excitedly pour a couple of drops in their...mouth? You think? The lack of facial features make this a bit guess-worky, but you presume they eat with a mouth.
You awkwardly wait a moment staring at the still-blocked exit before Samael realizes what's going on.
(colour: "red")["Right! Let me just get out of your way"]
[[Your way back to the tutorial is clear|Welcome to Twine!]]$theirText[Do we have a deal or not?]
$theirText[Make your decision]
Well this isn't going to be good. Maybe you should figure out a plan before you text this creep back.
[[Accept the deal|PossessionEnding]]
[[Refuse the deal|IncinerationEnding]]
$knowsTheIncantation[[[Write down the exact spell you were taught|IncantationEnding]]]
[[Back to contacts|Contacts]]
(set: $sandalphonUnread to false)
{
<!-- The important things happening here are that you're controlling whether or not the option to use the spell to sever your contact with the alien intelligence is visible with the variable $sandalphonUnread -->
}You check your texts from Gabriel, that jerkface:
$theirText[Nice]
$theirText[Getting yourself suspended for a week? Classic]
You want to tell them that it's not your fault. That something strange is happening and you didn't mean to start screaming about the end of the world.
Eh, they probably wouldn't listen anyway.
[[Back to contacts|Contacts]]
(set: $gabrielUnread to false)$theirText[whAT HAPPENED]
$theirText[No seriously you went to the bathroom and then there was screaming]
$theirText[What. Did. You. Do.]
[[Do you explain?|ExplainToUriel]]
[[Do you give up on trying to tell your bestie|DontExplain]]
[[Back to contacts|Contacts]]
(set: $urielUnread to false)There's a lot of strange junk in this room as well as [[piles of school desks|ExamineDesks]] arranged in ways that seem geometrically impossible.
Two things jump out at you from the mess: a bunch of [[pencils laying on the floor in an arrow pattern|FindEtchings]] and a [[fluffy chicken|Chicken]], clucking angrily.
At the far end of the room, there's the only [[way out|TheDoor]]The door, your only escape, is a large rusted monstrosity with a small [[control panel|ControlPanel]] built into it but no handle or keyhole.
[[Go back to looking around the room|TheRoom]]The door unlocks and swings open slowly.
It looks like you can [[leave|Welcome to Twine!]]The control panel has a three-digit display and three buttons labeled "0", "1", and "2" on them.
[[Press 0|OneRight]]
[[Press 1|Failure]]
[[Press 2|Failure]]
[[Give up and go back to looking around|TheRoom]]You stare at the desks, which appear to be piled together so that they form two interlocking rings.
You think it [looks familiar]<infinity|
(click: ?infinity)[<img src="https://upload.wikimedia.org/wikipedia/commons/c/c8/Infinite.svg" style="height: 80px; width 80px;"/>
But what on Earth does that [[mean|TheRoom]]?
]
The panel chirps and a 0 appears in the first slot of the digital display.
[[Press 0|Failure]]
[[Press 1|TwoRight]]
[[Press 2|Failure]]The panel clucks at you, like an angry chicken.
(if: $triesPressed > 2)[
You faintly hear a rooster crow, a flash of light comes from the pile of desks and then
...the room exploded. Whoops.
[[Back to the tutorial|Welcome to Twine!]]]
(else:)[
Maybe don't do that again. Who knows what might happen?
[[Back to entering codes|ControlPanel]]
]
(set: $triesPressed to it + 1)The panel chirps and a numeral 1 appears in the second slot:
[[Press 0|Unlock]]
[[Press 1|Failure]]
[[Press 2|Failure]]You follow in the direction the arrow of pencils is pointing. You step over empty soup cans, torn notebooks, and a shocking number of shoddy drawings of possums to find a clear spot on the ground with an etching on it.
(font: "Skia")[One step forward, one step back]
What does that [[mean|TheRoom]]?A familiar looking chicken is sitting on a very short pedastal of stone, clucking at you.
<img src="http://i.imgur.com/Y0N8US4.jpg" style="height: 500px;width: 500px"/>
(if: not $gotPaper)[
Hung loosely on its neck is a leather cord with a piece of [paper]<paper| on it.
(click: ?paper)[You carefully take the cord off of the chicken and look at the paper. It simply says "one divided by desks".
(set: $gotPaper to true)
"That seems a bit on point for a clue, really." you think to yourself. ]]
[[Time to wave bye to the chicken and look for other ways out|TheRoom]]You decide to agree to the deal and you quickly type out your reply
$yourText[Sure. Fine. Let's do this.]
You feel a pressure in your head and black out for a moment.
When you come to you're watching yourself from an odd angle. It's like you're seeing your own face from the position of your hand. You realize you can't move. Your body isn't your own anymore.
You watch your body look down at you and smirk.
"The transfer is complete," you hear yourself say in a voice not quite your own. "You are no longer necessary."
Your face pulls away quickly. You're falling.
Weightlessness.
A feeling of shattering.
The last thing you see is your heel.
[[Game Over|Welcome to Twine!]]$yourText[Yeah. So.]
$yourText[I'm not agreeing to anything with a creep texting me]
$yourText[Especially not to "give up my body"]
$theirText[Then you're useless]
For just a moment you can feel the pulsing voltage that fries your nervous system.
[[Game Over|Welcome to Twine!]]You know what you have to type and how exactly to do it
$yourText[QRHF RK ZNUPVAN]
Your phone immediately starts sparking and, surprised, you drop it on the floor cracking the case. A liquid like flame oozes out from the edges of the crack and melts the phone entirely.
Well that was weird, but at least you're still alive.
[[You survived!?|Welcome to Twine!]]Your contact list:
(link-goto: "Uriel", $urielDestination) $urielUnread[5 unread messages]
[[Unknown Number]] $sandalphonUnread[2 unread messages]
[[Gabriel]] $gabrielUnread[1 unread message]
{<!-- So in this passage we have probably the most interesting part of the entire thing. Dynamic links!
Now normally something like (link-goto: "Unknown Number") does the exact same thing as [[Unknown Number]] and (link-goto: "Back", "Contacts") does the same thing as [[Back|Contacts]].
Where dynamic links get cool is that you can provide any text as the passage name, **including the value of a variable**. So in this case we want to make sure it looks like your conversation is progressing every time you switch back to talking to Uriel but we want the link, which represents their name in your contacts, to be the same every time.
So if you look in the passages where you're talking to Uriel, you'll see that it keeps updating the variable $urielDestination in order to make sure you go back to the right spot.
-->}$yourText[Okay so this is going to sound wackadoo..]
$yourText[but I think I talked to something not human]
$theirText[...wut? like a chatbot?]
$yourText[just listen!!]
$yourText[really, like I don't think it's human]
$yourText[I got this text on my phone right]
$yourText[it was like gibberish but there was a link and a bunch of emoji]
$yourText[and I don't know I think spam sites are funny]
$yourText[and I clicked on the link]
$yourText[then I was here at home]
$theirText[so you don't remember anything you did at school?]
$yourText[kinda but not super well]
$yourText[it feels like a bad dream]
$yourText[and now there's a contact in my phone I didn't add]
$yourText[and they're texting me]
$theirText[yeah you do sound wack]
$theirText[but what's it saying?]
(if: not $sandalphonUnread)[[[Tell them about the messages|Keep talking]]]
(if: $sandalphonUnread)[[[Do you go check the messages?|Contacts]]]
[[Do you give up trying to explain?|DontExplain]]
[[Back to contacts|Contacts]]
(set: $urielDestination to "ExplainToUriel")You sigh and stare at your phone, knowing that there's probably no point in trying to explain.
$yourText[It doesn't even matter]
Nothing left for you to do here
[[Back to contacts|Contacts]]
(set: $urielDestination to "Hopeless")$yourText[It wants to make a deal]
$yourText[I think it wants my body]
$theirText[sick]
$yourText[No like possession]
$theirText[why though?]
$yourText[I REALLY DON'T WANT TO ASK OKAY]
$theirText[fine]
$theirText[okay so what do we do?]
[[Tell your best friend in the entire world to talk to the terrifying being|BetrayalEnding]]
[[Ask them to check their extensive library on occultic practices|LearnMagic]]
[[Back to contacts|Contacts]]
(set: $urielDestination to "Keep talking")You stare at your phone knowing that there's no point in trying to say anything.
[[Back to contacts|Contacts]]Maybe you're just being silly and taking all of this too seriously. Maybe Uriel can help you feel safer.
$yourText[Look why don't you talk to them? The number is xxx-xxx-xxxx. Maybe this is just a prank after all?]
$theirText[Sure just a sec]
An agonizing amount of times passes before you see their response
$theirText[Behold I am born into this world and am made manifest]
That's when you noticed that reality was melting.
[[Game Over|Welcome to Twine!]]$yourText[Don't you know anything that could help me?]
$theirText[Sure just a sec]
An agonizing amount of times passes before you see their response
$theirText[Okay so you need to type QRHF RK ZNUPVAN in your message]
$yourText[but what's that going to do?]
$theirText[It's a general ward against extra-dimensional entities]
$theirText[how much do you want to save this phone? because this might nuke it]
You better try this fast
[[Back to contacts|Contacts]]
(set: $knowsTheIncantation to true)
(set: $urielDestination to "LearnMagic")Double-click this passage to edit it.So we can't really explain how **all** of programming in Harlowe works in this tutorial, but we'll try to cover a few very basic concepts that will help you get started.
First, there's the concept of the **macro**. Macros in Harlowe might be called "expression" or "statements" in other programming concepts. They're essentially commands that *do* or *calculate* something.
Macros can do all sorts of things like change your text color or create data or choose which parts of your story to display.
I think the two most important first macros to learn are `(set:)` and `(if:)`.
`(set:)` is how you make variables. A variable is basically a named place to store information for later.
So in the puzzle room game we want to store how many times the player has tried to guess the code for the exit door. We set initially create that variable with
`(set: $timesPressed to 0)`
Variable names have to start with a dollar sign.
We can then increment Welcome to the tutorials section! If you want an interactive way to learn more about advanced topics, here's your stop!
[[I want the game to remember I've been to a room/had a conversation/etc.|Variables]]
[[I want music to play when a passage starts|Music]]
[[I want my text to look different|Styling]]
[[I want custom fonts!|Fonts]]
[[Can links do something other than open passages?|Hooks]]
[[I want to have background images and change the way passages work.|CSS]]
[[I want to include images|Images]]
[[I want my passage to react with time| Time]]
[[I want something I write to affect every passage|Heading]]
[[Nah, I'm good|Welcome to Twine!]]So you want to make your game remember that the player has had a conversation before or has been to a room before or basically *anything* where the player leaves some kind of permanent *effect* on the world of the game?
Well, the big concepts you need are **variables** and **conditionals**.
First, we'll talk about variables. These show up in basically every programming language ever! They're like containers for information, keeping track of things your game needs to remember. You can think of them like labeled boxes that you can put things into and take them back out again.
You can make a variable like this:
`(set: $thisIsTheName to 0)` (set: $thisIsTheName to 0)
In other words, you make variables just by putting a value in them. Twine itself will go ahead and make the box for you stick something in it. You can actually name a variable whatever you want, but it **must** start with a $ or else Twine doesn't know it's supposed to be a variable.
You can change what you've put in the variable even after it's been made the same way.
`(set: $thisIsTheName to 1)` (set: $thisIsTheName to 1)
Now how do you *use* a variable? Just call its name! So for example, here's a line of code that adds 1 to the variable `$thisIsTheName`:
`(set: $thisIsTheName to $thisIsTheName + 1)` (set: $thisIsTheName to $thisIsTheName + 1)
You can even call variables right in the middle of a passage so you can do something say something like `$thisIsTheName` and then you would see the number 2 appear in the text. In this passage, I've actually been running the code you've been looking at which means I can call the variable as so $thisIsTheName
Okay, but how do we use them to control how our games play? Well, most of the time you're going to need to make some kind of choice!
Like a lot of programming languages the way you make a choice in Twine is to say "if" and then what you're testing. So for example if I type
`(if: $thisIsTheName > 1)[Here's the text that should show up if $thisIsTheName is bigger than 1](else:)[Here's the text that should show up if it isn't]`
what'll show up in our passage is:
{(if: $thisIsTheName > 1)[Here's the text that should show up if `$thisIsTheName` is bigger than 1](else:)[Here's the text that should show up if it isn't]}
There's a lot more to cover about variables and conditionals, but hopefully that was enough to at least get you started!
[[Back|Tutorials]]So if you play through some of the games included in this tutorial, you might notice that there's a number of times the text looks different than others: different fonts, different colors, etc.
There's actually a bunch of built-in Twine commands to easily change the way the text looks! Not even just the text but everything else about the passages too.
You can directly change the properties of text like so
`(font: 'Courier New')[Here's some text in an old fashioned font.]`
which actually looks like:
(font: 'Courier New')[Here's some text in an old fashioned font.]
You can also change the colors like
`(colour: red)[This text should be pretty red]`
which will look like:
(colour: red)[This text should be pretty red]
Now, typing that much text is a pain if you're going to be styling something like a narrator or different characters in a dialogue. The cool thing is that you can actually store your formatting of choice in a variable to make it easier to use. So here's an excerpt from one of the games in the tutorial:
`
(set: $textFont to (font: 'Courier New'))
(set: $yourText to (background: blue) + $textFont)
(set: $theirText to (background: green) + $textFont)`
{ (set: $textFont to (font: 'Courier New'))
(set: $yourText to (background: blue) + $textFont)
(set: $theirText to (background: green) + $textFont)}
which then can be used like `$yourText[Hey there!]`
which is going to look like: $yourText[Hey there!]
Of course, there's a lot more you can do than just changing fonts and colors. There's a whole mess of effects you can use to modify the way your story looks!
For example, there's transformations like
`(text-style: "mirror")[This text is going to be backwards]`
which will look like
(text-style: "mirror")[This text is going to be backwards]
or
`(text-style: "smear")[This is going to look weird]`
which will look like
(text-style: "smear")[This is going to look weird]
You can mix and match these and even do other cool things like changing the appearance of every single instance of a word with the `enchant` command, like this
`(enchant: "dog", (colour: magenta))` (enchant: "dog", (colour: magenta))
which has the effect of making all the instances of the word dog be magenta without you having to type anything else. Dog is a good word, right? Notice, though, that this only works for the literal word dog and not Dog or DOG or dogs?
[[Back to the list|Tutorials]]One thing you might be wondering is how we can make "links" that do more interesting things when you click on them.
There's a number of commands that can help out with that, but we'll need to talk more about *hooks*. We've been using hooks for awhile now. A hook is technically just `[some text inside of square brackets]`. In the last tutorial we were styling them, but we can do other things with them too.
We can actually give *names* to hooks that we can reference later in the same passage so that that [something can happen up here]<tada|
(click: ?tada)[and then affect things down here]
That effect was done by the following code
`[something can happen up here]<tada|
(click: ?tada)[and then affect things down here]`
So the part `<tada|` is the name we gave the hook `[something can happen up here]`. If you looked at the first tutorial and saw the way we used variables started with a $, similarly the names for **hooks** start with a ? whenever you want to use them.
In this case, we just used the `click` command to make somthing happen when `?tada` was clicked on. In this case, it was just to have text appear but there's a **ton** of things that you can do with named hooks and the documentation we linked to in [[Welcome to Twine!]] explains all the different things you can do with them and the kinds of commands you can run by interacting with text.
There's also several special hooks like `?passage`, `?page`, and `?sidebar` that you can also reference to do something like making a thing happen whenever you click on a location.
[[Back to the list|Tutorials]]Okay so you probably want to mess around with how your background looks and do things like include background images.
You can do that without *too* much trouble by using built in commands. So, for example, we can set a background image like
`(enchant: ?passage, (background: "http://www.publicdomainpictures.net/pictures/30000/velka/water-background-5.jpg"))`
which we can see in [[this page|ImageBackground]]
How did this work? Well there's a few pieces here.
First, there's the `enchant` command that we're using to enchant a *hook* rather than just a particular word. The second part is that we're using a very **special** hook called `?passage` that refers to the entirety of the passage. There's other special hooks that Twine gives us to modify the way the entire page looks, the way the sidebar looks, and the way links look.
So if we type something like
`(enchant: ?page, (background: red))`
we'll make the entire page red which is exactly what we do in [[this example|RedBackground]].
You can use the `enchant` command with a number of other "changers", which is what things like `background` or `text-colour` are called in the Twine documentation.
If you know a little CSS, *Cascading Style Sheets*, then you can do even more neat stuff. CSS is the tool built into every browser to that allows you web designers to customize how their pages look! You can use the `css` command to create custom *changers* with CSS code. You don't have to do this and you're not really missing out if you **don't** know CSS, but if it's something you've already learned there's extra fun things you can change about how your game looks.
[[Back to the list|Tutorials]](enchant: ?passage, (background: "http://www.publicdomainpictures.net/pictures/30000/velka/water-background-5.jpg"))
Here we have some text and other things
just to take up room
but you should be able to see
the background image load
since we're fetching it over the internet, it's taking a moment for it to work
[[Back to styling tutorial|CSS]](enchant: ?page, (background: red))
okay and again
we'll have some filler text
that's going to be able to
make the passage big enough
that you can see what's happening
[[Back to styling|CSS]]In order to break up the text of you game and keep it visually interesting, you might want to include *images* in your story.
The easiest way to do this, I think, is by including actual HTML into your story.
If you don't know what HTML is, it's the underlying language that tells your web browser what exactly goes into a web page.
HTML is its own big topic too large to cover here, but fortunately all you need is the `<img>` tag. The way you use it is something like
`<img src="http://bit.ly/2h9gSHn">`
which will look like
<img src="http://bit.ly/2h9gSHn">
One caveat to note: you need the link to the *image* and not just the search result page. Make sure your URL ends in something like .png or .jpg or some other image format.
Also! Animated gifs do work in Twine
<img src="https://media.giphy.com/media/aWRWTF27ilPzy/giphy.gif">
if you want to make some small animations!
[[Back to tutorials|Tutorials]]Actually using different fonts is enough its own topic that I wanted to separate it out from other text effects.
Now if you want to change the font to something that's pretty standard across the web then all you need to do is type something like
`(font: "Courier")[And the text is going to look different!]`
(font: "Courier")[And the text is going to look different!]
The problem is that, in general, if you want some super cool looking font you're going to have to do some setup work to make sure that the player's browser has the right fonts loaded.
I think the easiest way to do this is to use Google fonts
(click: "Google fonts")[(open-url: "http://fonts.google.com")]
From here you can click on the little plus sign of any font that you think looks cool. Once you have you should see at the bottom of your browser a little note about "# Family Selected". If you click on *that* you should see some text explaining how to use the font. So I selected the `Lobster` font, which means that Google tells me I need to load the font like
`<link href="https://fonts.googleapis.com/css?family=Lobster" rel="stylesheet">`
Now! You need to make a new passage, it's actual name doesn't matter, but you're going to click on the thing that says `tag` and give it a tag of `header`. When a passage has the `header` tag it means that it'll silently load at the beginning of every passage before the "real" passage you're on. Go ahead and copy and paste the link you got from Google into your `header` passage, then in any passage you should be able to use the font like normal.
In our case we type
`(font: "Lobster")[a bunch of stuff and it should look super different]`
and it'll look like
(font: "Lobster")[a bunch of stuff and it should look super different]
[[Back to tutorials|Tutorials]]{<link href="https://fonts.googleapis.com/css?family=Lobster" rel="stylesheet">}So another cool thing you can do in Twine is have your passages run code that continuously updates over time. This allows you to do things like give timed choices or force delays before new details are revealed.
The key is the `live` macro. You can use `live` to write code that will re-run over and over again as long as the player is on the passage.
So, for example, if you typed
`(live: 1s)[
(set: $someVariable to $someVariable + 1)
$someVariable)]`
You'd see a number that keeps changing roughly once a second.
{
(live: 1s)[
(set: $someVariable to $someVariable + 1)
$someVariable]}
You can use this to do all sorts of cute things, like the following code that will display something only after roughly fifteen seconds. Just wait a bit for it!
`(live: 1s)[
(set: $ourTimer to $ourTimer + 1)
(if: $ourTimer > 15)[This message should only appear after fifteen seconds]]`
{(live: 1s)[
(set: $ourTimer to $ourTimer + 1)
(if: $ourTimer > 15)[This message should only appear after fifteen seconds]]}So you have a background or a song or a bit of code that should run in *every* passage.
Twine actually provides a really easy way to take care of that! All you need to do is make a new passage and give it the tag header.
The Twine code you put in there will run before the code in the actual passage you're on. So this is an easy way to set backgrounds or reset variables or even just include introductory text.
[[Back to tutorials|Tutorials]]Once you opened this passage, you should have heard a song start playing.
The way we did this was kinda similiar to including images: using raw HTML5 in order to load up the audio.
You need to type
``<audio autoplay>
<source src="Metalmania(Incompetech).mp3" type="audio/mpeg">
</audio> ``
to load the file if you've downloaded it *or* you can paste in the URL to the song in the ``src`` field if you're just grabbing it without downloading it.
<audio autoplay>
<source src="Metalmania(Incompetech).mp3" type="audio/mpeg">
</audio>
Hecker (click: "Hecker")[<audio autoplay>
<source src="Metalmania(Incompetech).mp3" type="audio/mpeg">
</audio>]