**HTML markers:**
<text_color1>This is one method of styling text in Twine.</text_color1>
This method is pretty easy to set up on the fly - wherever you need a new font style, simply set up an HTML marker on the fly like so:
<codetext>
`<text_color1>` Your text here `</text_color1>`</codetext>
(click: "marker ")[You can call your marker whatever you like! `<haughty_gentleman>` or `<rude_child>` - whatever is memorable enough (and short enough!) for you to recall when you need it.
<hr />
**CSS:**
The second part is just as simple - enter your story's stylesheet and type the following:
<codetext>
`text_color1 {`
`font-family: Verdana;`
`color:deepskyblue;`
`}`</codetext>
//**Note:** Americanized spelling of 'color' is used in CSS.//
<hr />]
(click: "deepskyblue")[**Fonts and colours:**
You don't have to use the colour <text_color1>deepskyblue</text_color1> - there are hundreds of named colours you can use in CSS (or you can use the hexadecimal value if you'd prefer)- here is a full list:
https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords
Similarly, you don't need to use the font Verdana, either. There's a list of web-safe fonts here:
https://www.cssfontstack.com/]
<hr />
(This doesn't suit me, show me [[another way)|more text styling]]To display a persistent header at the top of your story (perhaps it is the title of your game? A logo? A place to display some character stats or statuses?), all you need to do is to create a passage, and **TAG** it as `'header'`.
(click: "TAG")[When you run your story, you'll see that whatever you wrote within this passage tagged 'header' is now displayed at the top of every passage.]
(click: "every passage")[<hr />If you want to style this, you must target it in CSS in the following manner:
<codetext>
`tw-include[type="header"] {
display:block;
margin-bottom: 50px;
}`</codetext>
(You of course don't have to display it as a block, and nor do you have to give it a larger margin at the bottom - these are just some things you can do.)
]{(set: $choiceCounter to 4)}
There is a train coming towards you. You are rooted to the spot in fear and if you don't move it will squish you flat, spraying what's left of you all over the tracks.
What do you do?
|choice1>[[[Try to move->Choice 1]]]
|choice2>[[[Freak out->Choice 2]]]
|choice3>[[[Stand your ground->Choice 3]]]
{(live: 1s)[
(set: $choiceCounter to it - 1)
(if: $choiceCounter is 0)[
(stop:)Time ran out!
(replace:?choice1)[]
(replace:?choice3)[]
<!-- You could also use (goto:) to jump directly to a passage -->
]
(else:)[
([$choiceCounter] seconds left...)
]
]}**Styling the entire story:**
To edit the entirety of your story's text (aside from any special sections or markers you've set up), type the following into your stylesheet:
<codetext>
`tw-story`
`{`
font-family: Lora, serif;
font-size: 18px;
background-color: #f5fff0;
`}`</codetext>
<hr />
(click: "type")[**Enchant:**
To change the appearance of a single, repeated word rather than set up a separate marker for every time it appears, you can retroactively style all words with an `(enchant:)` macro.
<codetext>
`(enchant: "you", (font: "Courier New") + (colour: red))`</codetext>
//**Note:** Twine is stupid, and you must use the English spelling of 'colour' here, despite the inconsistency with the global, Americanised CSS standard.//
<hr />]
{(enchant: "you", (font: "Courier New") + (colour: red)) }
(click: "appearance")[(font: "Indie Flower")[Oh hello. were you wondering how I'd imported this obnoxious font into my text? ]
Head over to https://fonts.google.com/, find a style you like and import it into your CSS at the top of the stylesheet, like this:
<codetext>@import url(https://fonts.googleapis.com/css?family=Indie+Flower);</codetext>
Then you can reference this in your CSS as above.
And, [[lastly...|Under the sea]] ]
Welcome! What do you want to learn?
<hr />
* [[Styling Text|different methods of text styling]]
* [[Common things you need in CSS]]
* [[Click and replace macros]]
* [[Headers|how to display another passage as a header]]
* [[Popups|Popups]]
* [[How to make a "Telltale style" timer! (covers time, text replacement and conditional logic)|telltale timer]]
* [[Adding images and images as links|Adding images]]<hr />
<h3>Twine Tech Demo</h3> [[Back to Menu|Menu]]**You try to move, but you're too slow. You die horribly.**
(live: 1s)[There was actually no happy ending to that one.
To achieve this Telltale Games-style timer, first set a variable at the start of your passage to act as your countdown. Be as mean or as generous as you like, but I opted to:
<codetext>
`(set: $choiceCounter to 4)`]</codetext>
(click: "countdown.")[<hr />
Next, set up your choices in a series of named hooks so that you can refer back to them later, removing options if players dither and take too long to make a choice:
<codetext>
`|choice1>[[[Try to move->Choice 1]]]
|choice2>[[[Freak out->Choice 2]]]
|choice3>[[[Stand your ground->Choice 3]]]`
]</codetext>
(click: "dither ")[<hr />This is the fun bit. We're going to be setting up a live timer that counts down our choice counter every second, and when it reaches zero, it will remove the options. The first part is like so:
<codetext>
`(live: 1s)[
(set: $choiceCounter to it - 1)`</codetext>
This part says simply "every 1 second, subtract 1 from our choiceCounter variable.]
(click: ", subtract ")[<hr />This next part is a conditional logic section which checks every second whether or not our choiceCounter variable has the same value as the stipulated condition:
<codetext>`(if: $choiceCounter is 0)[`</codetext>
]
(click: "every second ")[<hr />When this condition has been met (i.e. our counter has counted down to zero), we want to stop the timer with a `(stop:)` macro, and then replace the named hooks from earlier with empty space to prevent the player from chasing those options:
<codetext>
` (stop:)Time ran out!
(replace:?choice1)[]
(replace:?choice3)[]`]</codetext>
(click: "prevent")[<hr />If you're really mean, you could also use `(goto:)` to jump directly to a passage.
Lastly, you need to put in an else condition. In our case, we want to display how many seconds the player has left to make a decision. This will automatically update every second because it is embedded in the `(live:)` macro:
<codetext>`(else:)[
([$choiceCounter] seconds left...)`</codetext>
]
[[This is long and I don't care. Just show me the full code please|TT Timer code]]**You are squished. The end.**
(live: 1s)[Don't worry about it, most people freak out under pressure.
To achieve this Telltale Games-style timer, first set a variable at the start of your passage to act as your countdown. Be as mean or as generous as you like, but I opted to:
<codetext>
`(set: $choiceCounter to 4)`]</codetext>
(click: "countdown.")[<hr />
Next, set up your choices in a series of named hooks so that you can refer back to them later, removing options if players dither and take too long to make a choice:
<codetext>
`|choice1>[[[Try to move->Choice 1]]]
|choice2>[[[Freak out->Choice 2]]]
|choice3>[[[Stand your ground->Choice 3]]]`
]</codetext>
(click: "dither ")[<hr />This is the fun bit. We're going to be setting up a live timer that counts down our choice counter every second, and when it reaches zero, it will remove the options. The first part is like so:
<codetext>
`(live: 1s)[
(set: $choiceCounter to it - 1)`</codetext>
This part says simply "every 1 second, subtract 1 from our choiceCounter variable.]
(click: ", subtract ")[<hr />This next part is a conditional logic section which checks every second whether or not our choiceCounter variable has the same value as the stipulated condition:
<codetext>`(if: $choiceCounter is 0)[`</codetext>
]
(click: "every second ")[<hr />When this condition has been met (i.e. our counter has counted down to zero), we want to stop the timer with a `(stop:)` macro, and then replace the named hooks from earlier with empty space to prevent the player from chasing those options:
<codetext>
` (stop:)Time ran out!
(replace:?choice1)[]
(replace:?choice3)[]`]</codetext>
(click: "prevent")[<hr />If you're really mean, you could also use `(goto:)` to jump directly to a passage.
Lastly, you need to put in an else condition. In our case, we want to display how many seconds the player has left to make a decision. This will automatically update every second because it is embedded in the `(live:)` macro:
<codetext>`(else:)[
([$choiceCounter] seconds left...)`</codetext>
]
[[This is long and I don't care. Just show me the full code please|TT Timer code]]**The train grinds to a halt and...**
(live: 1s)[**Naw, just kidding. You are dead.**
]
(live: 2s)[To achieve this Telltale Games-style timer, first set a variable at the start of your passage to act as your countdown. Be as mean or as generous as you like, but I opted to:
<codetext>
`(set: $choiceCounter to 4)`]</codetext>
(click: "countdown.")[<hr />
Next, set up your choices in a series of named hooks so that you can refer back to them later, removing options if players dither and take too long to make a choice:
<codetext>
`|choice1>[[[Try to move->Choice 1]]]
|choice2>[[[Freak out->Choice 2]]]
|choice3>[[[Stand your ground->Choice 3]]]`
]</codetext>
(click: "dither ")[<hr />This is the fun bit. We're going to be setting up a live timer that counts down our choice counter every second, and when it reaches zero, it will remove the options. The first part is like so:
<codetext>
`(live: 1s)[
(set: $choiceCounter to it - 1)`</codetext>
This part says simply "every 1 second, subtract 1 from our choiceCounter variable.]
(click: ", subtract ")[<hr />This next part is a conditional logic section which checks every second whether or not our choiceCounter variable has the same value as the stipulated condition:
<codetext>`(if: $choiceCounter is 0)[`</codetext>
]
(click: "every second ")[<hr />When this condition has been met (i.e. our counter has counted down to zero), we want to stop the timer with a `(stop:)` macro, and then replace the named hooks from earlier with empty space to prevent the player from chasing those options:
<codetext>
` (stop:)Time ran out!
(replace:?choice1)[]
(replace:?choice3)[]`]</codetext>
(click: "prevent")[<hr />If you're really mean, you could also use `(goto:)` to jump directly to a passage.
Lastly, you need to put in an else condition. In our case, we want to display how many seconds the player has left to make a decision. This will automatically update every second because it is embedded in the `(live:)` macro:
<codetext>`(else:)[
([$choiceCounter] seconds left...)`</codetext>
]
[[This is long and I don't care. Just show me the full code please|TT Timer code]]<codetext>`{(set: $choiceCounter to 4)}
There is a train coming towards you. You are rooted to the spot in fear and if you don't move it will squish you flat, spraying what's left of you all over the tracks.
What do you do?
|choice1>[[[Try to move->Choice 1]]]
|choice2>[[[Freak out->Choice 2]]]
|choice3>[[[Stand your ground->Choice 3]]]
{(live: 1s)[
(set: $choiceCounter to it - 1)
(if: $choiceCounter is 0)[
(stop:)Time ran out!
(replace:?choice1)[]
(replace:?choice3)[]
<!-- You could also use (goto:) to jump directly to a passage -->
]
(else:)[
([$choiceCounter] seconds left...)
]
]}`</codetext>
Thanks to Murray for helping me out with this one!(alert: "hey! I'm a boring, regular pop-up that tells you a thing")This is probably the easiest thing I'll cover here.
To display a simple pop-up, just wrap the text you want to display within an `(alert:)` macro:
<codetext>
`(alert: "Write some text here!!")`</codetext>
<hr />
As mentioned in the code snippets doc, you can also use pop-up boxes to prompt the player for some written input, and then store that input in a variable to call throughout the text, like so:
<codetext>`(click: "hook here")[(set: $charactername to (prompt: "What is your name?", "Type your name here!"))`</codetext>
(click: "prompt the player")[(set: $charactername to (prompt: "What is your name?", "Type your name here!"))
Then Twine will remember that your player's name is $charactername, and will print it out any time you type `$charactername` within your passage.]
<hr />Quick cheatsheet for some common CSS needs!
**Changing the font and colour:**
{<codetext>(click: "Changing the font and colour:")[`font-family: Arial;
color: blue;
font-size: 16px;`]</codetext>}
**Changing the story background colour:**
{<codetext>(click: "Changing the story background colour:")[`tw-story{
background-color red;
}`]</codetext>}
**Margins:**
{<codetext>(click: "Margins:")[`margin-top: 10px;
margin-bottom: 20px;
margin-left: 5px;
margin-right: 15px;`]</codetext>}
**Borders:**
(click: "Borders:")[
<solidborder>border-style: solid;</solidborder>
<dashedborder>border-style: dashed;</dashedborder>
<dottedborder>border-style: dotted;</dottedborder>
]
**Text alignment:**
{<codetext>(click: "Text alignment:")[`text-align: center;
text-align: right;
text-align: left;
text-align: justify;`]</codetext>}
The CSS bible: https://www.w3schools.com/css/
[[Show all]]Quick cheatsheet for some common CSS needs!
**Changing the font and colour:**<codetext>
font-family: Arial;
color: blue;
font-size: 16px;</codetext>
**Changing the story background colour:**<codetext>
tw-story
background-color red;</codetext>
**Margins:**<codetext>
margin-top: 10px;
margin-bottom: 20px;
margin-left: 5px;
margin-right: 15px;</codetext>
**Borders:**
<solidborder>border-style: solid;</solidborder>
<dashedborder>border-style: dashed;</dashedborder>
<dottedborder>border-style: dotted;</dottedborder>
**Text alignment:**<codetext>
text-align: center;
text-align: right;
text-align: left;
text-align: justify;</codetext>}Adding images is a bit more of a pain than it should be, bceause you need to ensure that you have somewhere to host them if you're going to upload your game online. If hosting online, you must link directly to that image's URL, i.e.
<img src="http://pngimg.com/uploads/chrome_logo/chrome_logo_PNG17.png" width="50" height="50" alt="Chrome logo">
<codetext>`<img src="http://pngimg.com/uploads/chrome_logo/chrome_logo_PNG17.png" width="50" height="50" alt="Chrome logo">`</codetext>
<hr />
If you just have your game locally, you can link directly to a source on your desktop, but make sure that it exports correctly, i.e.
<img src="http://fscomps.fotosearch.com/compc/BCP/BCP112/woman-holding-a-knife-and-a-big-block-stock-images__bcp012-26.jpg" width="400" height="250" alt="Cheese woman">
<codetext>`<img src="C:\..\Documents\Twine\Stories\cheese-woman.gif" width="400" height="250" alt="Cheese woman">`</codetext>
<hr />
If you wish, you may also embed links in images, like so:
<codetext>
`[[<img src="https://vignette.wikia.nocookie.net/austinally/images/d/dc/REALLY-sign.png/revision/latest?cb=20130518131552" width="80" height="80" alt="Yeah!">->Menu]]`</codetext>
(You could use this to build a simple, persistant navigation system using a series of images that each links elsewhere in the story. Maybe you might even nest this in your header...?)
[[<img src="https://vignette.wikia.nocookie.net/austinally/images/d/dc/REALLY-sign.png/revision/latest?cb=20130518131552" width="80" height="80" alt="Yeah!">->Menu]]The styling on this passage is especially marvellous, don't you think? (not)
It is the only passage like it in the entirety of this tech demo, and is achieved by tagging this passage with a tag (I've decided to call it <codetext>"underthesea"</codetext>), and then referencing that single tag in my CSS to style it separately to every other passage, like so:
<codetext>
`tw-story[tags~="underthesea"] {
background: linear-gradient(to bottom, rgba(228,245,252,1) 0%,rgba(159,216,239,1) 25%,rgba(191,232,249,1) 31%,rgba(42,176,237,1) 100%);
font-family: Indie Flower;
color: darkcyan;
}`</codetext>
Also check out this awesome visual tool for creating nice CSS-driven gradients and dumping out code to use generate them: <codetext>http://www.colorzilla.com/gradient-editor/</codetext>Sometimes, you might want to hide some text behind a link so that the player isn't overwhelmed when they first enter a new passage...
(click: "behind a link")[ This is rather easy to do, and will invoke the common `(click:)` macro, like so:
<codetext>`(click: "a word in the passage above")[The rest of your hidden text here.]`</codetext>
<hr />
Other times, you may wish to replace some specific text with an additional detail to [reveal some hidden information.]<reveal|
(click: ?reveal)[ (replace: ?reveal)["add a different, optional perspective to your story, perhaps.
This is achieved by marking the text you want to replace as a "hook":
<codetext>
`[Mark the text like this]<reveal|`</codetext>
And then, beneath it, refering to the hook you set up through first referring to it in `(click:)` macro, and then telling Twine what to do with the text within this hook using a `(replace:)` macro.<codetext>
`(click: ?reveal)[ (replace: ?reveal)["Write your hidden text here!"] ]`</codetext>"] <hr />
You may also not wish to fully replace text, but merely to append it
]
(click-append: "append it")[, as this means you don't need to re-write text again to keep it as-is.
Achieve this with the mighty `(click-append:)` macro like so:
<codetext>`(click-append: "text to append here")[ and the rest of it, to be revealed, here]`</codetext>
]
]