this is a [[link->LP2]] (visited: "LP5")[[[back to where we just were->LP5]]]a link is formed by writing two square brackets and then another pair of square brackets like this: `[[link]]` [[next->LP3]]when you click a link, you are taken from passage to passage. a passage is represented by the editable nodes in twine, and appears as an entirely new page during the story. [[next->LP4]]the only things needed to make a twine story ever at all links and passages. if you can make a link, you can technically make as many passages you need for whatever amount of variable options you want to have. [[next->LP7]](visited: "RL5")[thanks for playing! [[back to start->LP1]].] (else:)[everything after this point is optional, but using more options at our disposal will let twine become reactive. ] [[macros and hooks->MH1]] [[images and links ->IL1]] [[menus, story formats and sheets->MSS1]] (visited: "MH10")[ [[decorative and functional macros->DFM7]] ][ [[resources and libraries->RL1]] ]the first thing to learn about macros is the syntax. just like a link is written like `[[this]]`, a macro is written like (text-colour:magenta)[`(this:)`]. [[next->MH2]]to use images and links in twine, one must first know very basic HTML and CSS. to sum up quickly, twine publishes straight to an HTML file and can be uploaded to the web very easily, but it doesn't have a built in function for web links or image embedding. [[next->IL2]]so what is a story format? twine features harlowe 3.3.8 as the language to use in twine. macros and hooks are entirely a feature of harlowe, which is designed around minimal to none experience with HTML, CSS and Javascript. [[next->MSS2]]a macro is a string of code that will do anything from (text-colour:yellow)[changing the text colours] to (link-rerun: "dice rolls ")[(random: 1,6)] to remembering complex data structures. [[next->MH3]]the two most important macros are (text-colour:magenta)[`(set:)`] and (text-colour:magenta)[`(if:)`]. set lets us make variables and set them to a string, if lets us read the variable and react to whether it fulfills a condition. [[next->MH4]]to use set, you can write the following: (text-colour:magenta)[`(set: $key to "true")`]. using the passage editor, click the button "Test From Here". the debug menu that appears in the bottom right corner should say (text-colour:blue)[`$key`] and (text-colour:cyan)[the string "true"](set: $key to "true") [[next->MH5]]some macros like (text-colour:magenta)[`(set:)`] don't require a hook, but many macros do. in a confusing twist of fate, twine's syntax for a macro's hook is text surrounded by only one set of square brackets like [this]. the syntax for most macros is going to be this: (text-colour:magenta)[`(macro:)`](text-color:yellow)[`[hook]`]. [[next->MH6]] <!-- so something about putting links in hooks is that when you want to, make sure there is a space around the link. ie: (macro:)[ hook hook hook [[link!!!]] ] this was explained in person during the lesson so i figured i'd drop a comment here instead.-->to use our (text-colour:blue)[`$key`] properly, we need to use the (text-colour:magenta)[`(if:)`] macro to set up a condition to meet. lets say if our variable is true, we want to unlock a chest, but if it's not, we can't. [[next->MH7]]the (text-colour:magenta)[`(if:)`] macro needs us to have a hook after it. inside, after the colon we can place our condition using boolean values. booleans are "true" and "false" and "string of text" and use the logic expressions "is" or "contains" or others... to make a chest we can unlock, copy the following: (align:"<==")+(box:"===XXXXXXXXXX=======")[(text-colour:magenta)[`(set: $key to "true")(if: $key is "true")`](text-colour:yellow)[`[the chest can be unlocked.]`]] when you run this passage with the Test From Here button, the following should appear: (align:"<==")+(box:"===XXXXXXXXXX=======")[(set: $key to "true")(if: $key is "true")[the chest can be unlocked.] ] [[next->MH8]]what if we didn't have a key? the macros (text-colour:magenta)[`(else-if:)`] and (text-colour:magenta)[`(else:)`] allow us to create (text-colour:magenta)[`(if:)`]'s that don't need us to list confusing and long strings of (text-colour:magenta)[`(if:)`] statements. (text-colour:magenta)[`(else-if:)`] is (text-colour:magenta)[`(if:)`] if it checked whether the macro behind it just ran, and if not, will begin it's if statement. (text-colour:magenta)[`(else:)`] is almost the same, but requires no boolean at all. so: (align:"<==")+(box:"===XXXXXXXXXX=======")[ (text-colour:magenta)[`(set: $key to "false")(if: $key is "true")`](text-colour:yellow)[`[the chest can be unlocked.]`](text-colour:magenta)[`(else-if: $key is "false")`](text-colour:yellow)[`[the chest remains locked.]`] ] will output as this (align:"<==")+(box:"===XXXXXXXXXX=======")[(set: $key to "false")(if: $key is "true")[the chest can be unlocked.](else-if: $key is "false")[the chest remains locked.]] [[next->MH9]]if we happened to have more strings that (text-colour:cyan)[`$key`] could be listed as, say we were storing an inventory of keys instead and we list every key by its colour and we can only have one key at a time (who knows why), then we can say something like: (align:"<==")+(box:"===XXXXXXXXXX=======")[ (text-colour:magenta)[`(if: $key is "bronze")`](text-colour:yellow)[`[you unlock the first door.]`](text-colour:magenta)[`(else-if:$key is "silver")`](text-colour:yellow)[`[you unlock the second door.]`](text-colour:magenta)[`(else-if: $key is "gold")`](text-colour:yellow)[`[you unlock the third door]`](text-colour:magenta)[`(else:)`](text-colour:yellow)[`[you don't have the right keys to any door!]`] ] which means we have three keys which work, and any other colour of key won't no matter what colour it is. [[next->MH10]]there is a long long list of macros that twine uses. to learn about story formats and twine's language, we have to go back and learn about [[menus, story formats and sheets->MSS1]]. otherwise, we can continue with macros and hooks and learn about a couple more macros that can be used to make twine reactive. [[decorative and functional macros->DFM1]] [[back to the hub->LP7]](link: "this is a link")[or is it...? lots of macros appear as links, but don't do link like things. this macro is called (text-colour:magenta)[`(link:)`] and lets you replace a link with text held inside the hook. something about macros similar to this is that the hook can be asssssssssss looonngggggg as you want it to be and as many lines as necessary, as long as it has a bracket at the end of it. you can faintly see what's covered by the end of the square bracket as if there's a starting one, it will highlight the text inside a little yellow. the more hooks inside a hook, the yellower it gets. [[next->DFM2]] ] to embed an image, we have to learn a teensy weensy bit of HTML. an open tag will look like this (text-colour:green)[`<tag>`] and to close it, (text-colour:green)[`</tag>`] [[next->IL3]]the HTML tags for embedding an image is this: (text-colour:green)[<`img src="URL"`>]. so we can use web images pretty easily, but we can run into a few problems with that fast. [[next->IL4]]1. a website doesn't allow hot-linking: websites will protect their images or their bandwidth by not allowing hot-linking, which is to say an image you try to link from their url's will break instead of displaying. 2. an image you used gets taken down or some other similar thing: all the time, images can be deleted, moved to a different URL or privated. this means it may work when you publish the game, but in six months to a year, every image you used is broken now. 3. a file hosting service you use goes down, takes your stuff down or you run out of free images: don't use imgur. so what do we do now? [[next->IL5]] because twine publishes to HTML and integrates CSS and Javascript, we know that it supports the file structures of HTML and friends. we can test with images on our computer (to later be packaged and uploaded for play) in a couple of different ways, with their own advantages and disadvantages. [[next->IL6]] publishing to file: in the menu bar across the screen, find the build button and click it. you'll see test, play, proof, publish to file and export as twee. for this, we use the publish to file option. create a folder on the desktop (or wherever you want) and name it something. then, use publish to file and export the story into your folder. now lets make a second folder inside your story folder and call it assets. [[next->IL7]]inside the assets folder, grab an image and drop it in. name it something short and snappy if it's long since you'll need to copy the whole name of the image file. inside your twine passage, let's make that HTML image tag again. (align:"<==")+(box:"===XXXXXXXXXX=======")[ (text-colour:green)[<`img src="assets/FILENAME.PNG"`>]. ]look closely at the (text-colour:green)[src=] here, we're going to make it so the tag reads into the folder assets. before the filename.png, write (text-colour:green)[assets/] so it matches the above. finally, publish to file back in the main folder, then click your game and find the passage with your image in it. here's some images that show how your folder structure should look. <img src="assets/filestructure.png"> [[next->IL8]]wow that looks terrible. time for a tiny CSS lesson. CSS looks like this in a stylesheet, (text-colour:red)[`img {`] (text-colour:red)[(align:"<==")+(box:"=XXXXX====")[`width:100%;`]](text-colour:red)[}] but when it's inside an img tag, we can write it like this (text-colour:green)[<`img src="filename.png" style="width:100%;">`] <img src="assets/filestructure.png" style="width:100%";> now the image will size to the element above it, in this case the text passage width and will look a lot better. now you know how to add an image into twine. [[next->IL9]]similarly, (text-colour:magenta)[`(link-reveal:)`] lets you append text to the (link-reveal: "link.")[ which is great for adding just that little bit of interactivity to a long passage another macro which can be great for various things is (text-colour:magenta)[`(input:)`] which can also be made to bind the inputed single string of text as a variable by adding (text-colour:magenta)[`"bind $string"`] after the colon.. (input: bind $string)[[next->DFM3]] ] if you want to control what the player says in an input box, we can do something creepy (or maybe silly depending how you play it) and use (text-colour:magenta)[`(force-input:) `]. i want the input box to say "YOU HAVE NO POWER HERE." so i'll write out the macro like this: (text-colour:magenta)[`(force-input: "YOU HAVE NO POWER HERE")`] (force-input: "YOU HAVE NO POWER HERE") [[next->DFM4]] <!--with force-input, you can't bind to a $variable. you'll actually need to learn to use temporary varibles, which can be written like this (force-input: bind _power, "YOU HAVE NO POWER HERE"). when you try it, the string will read "YOU HAVE NO POWER HERE".-->now how have i been colouring text this entire time? (text-colour:magenta)[`(text-colour:magenta)[like this!]`] [[next->DFM5]] <!-- you can also colour text with html/css, if the macros start getting too confusing. <p style="color:red;"> red text </p> is perfectly valid. another good thing to learn is (enchant:), which can enchant whole strings of text in a passage all at once, everywhere it's mentioned. -->unfortunately we don't have all day to spend playing with macros and i can't teach you all of them (i don't even know how most of them work) but i can direct you to the library of macros, <a href="https://twine2.neocities.org/#macro_live"> the harlowe 3.3.8 manual </a> which is the default language for twine. [[what is harlowe?->MSS1]] [[back to the hub->LP7]]if you want every link to say next but realize not every passage can be named next, you can write a link out like this: `[[next->passagename]]` [[next->LP5]] (forget-visits: 1)what's great about twine is that you can let a person interact with any passage anywhere, as long as you link it. [[this takes us back to the first passage.->LP1]] (visited: "LP1")[if you choose, you can design a story where all passages are always accessible and can be experienced entirely non-linearly. [[next->LP6]] ]very quickly, to add a link into twine, you can use (text-colour:green)[`<a href="URLHERE">`] words for the highlighted link (text-colour:green)[`</a> `] to make an image a web link, instead of words for a highlight link, include an image tag. (text-colour:green)[`<a href="URLHERE"> <img src="assets.png"> </a>`] <a href="https://www.youtube.com/watch?v=utTUFnsWEYA"> <img src="assets/road.png"> </a> [[next->IL14]] other elements can be styled in twine to make not just single passages or images using HTML and CSS, and twine's passage editor has ways to change text colour, text alignment, borders and other things, but editing your entire story can be done with things like stylesheets. [[menus, story formats and sheets->MSS1]] [[back to the hub->LP7]]in the event that you decide you HATE!!!!!!! harlowe and the way it works and you HATTTTEEEEEEE!!!!!!! macros and hooks, you can learn some of the other twine story formats which also maintain regular support: sugarcube, chapbook and snowman. all story formats have complicated pros and cons, different systems for representing links and code and their own unique syntax. [[next->MSS3]]the story format can be changed in the menu above under Twine. under the Story menu, you can see at the end the options for Javascript and Stylesheet. Here is where anyone with the knowledge or the will to learn can flex their skillsets. [[next->MSS4]]Javascript and Stylesheet menus allow you to import/write your own Java and CSS to be able to create edits across the entire story, not just single passages or elements of a passage. if you wanted to edit whole parts of a passage for the entire story, you can edit the CSS element called "tw-passage". similarly, there is "tw-sidebar" and even hiding the undo and redo buttons with "tw-icon" and more. i'm unsure about other browsers, but firefox has an inspect element function that will allow you to hover and discover the names of elements to edit in twine to put in a stylesheet. [[next->MSS5]]for the knowledgable, the same should be possible with javascript and it's own sheet. as far as i know, harlowe is built with/integrated with javascript and should be able to be affected/rewritten to a degree. [[next->MSS6]]some other things about harlowe: there is no way to integrate music files. to include music in your story, you must use the [[harlowe audio library->RL3]] (HAL) which is two files to be copied into the javascript and css sheets in twine to be used. it also requires using tagged passages with special tags, which is not within the bounds of this intro but are close to the bottom of the harlowe manual and can be used to great affect for custom menus and startup actions. [[next->MSS7]]thats publishing from file. if we want to be sneaky, lets use the twine file structure to make it so it always sees our files. this trick is one i only know how to use on macOS but i'm sure it can be recreated on windows OS or linux OS if one can locate twine's folder. [[next->IL10]]go to the folder called Documents on your macbook. it almost always located in the sidebar of the finder app, it's called Twine and inside there's three folders. Backups stores old versions of stories, Stories is what twine edits and where your current version is stored but the folder titled Scratch is where the story is tested and played from. you can move the folder you called assets earlier into the Scratch folder (drag and drop or you can duplicate it, move it, and rename back to assets) and now when you test your game inside twine, you can see the images without having to build and export! [[next->IL11]]the only reason not to do this (that i know of) is just that it's kind of strange having to update your files inside of twine's repository instead of your own, and you'll have to upload your assets folder separately from the finished story. but thats it, you can have images in your story now. [[next->IL12]] if you ever want to make a passage link into an image, just put square brackets around the image. if you wanted a link to an entirely different webpage, well... [[next->IL13]]finally, how do we publish our twine stories? we know how to publish to file and include images with it, which is exactly what we need. you only need your html, and the folder containing your assets. lets learn where we can upload a story, [[next->RL2]] <a href="https://neocities.org/">neocities</a>: an indie webhosting site, free for 5GB of data. great for portfolios, file gardens, geocities nostalgia. <a href="https://itch.io/">itch.io</a>: an indie games site, you can play your game embedded in the site very easily. great for interactive fiction games, indie fame, web-play support. <a href="https://github.com/">github</a>: a code projects website, you upload your files and publish them to github pages. great for informational projects, nerds, frustrating interfaces. [[next->RL3]]now some resource links for twine, <a href="https://twine2.neocities.org/"> harlowe 3.3.8 manual </a> which you should be consulting for endless lists of macros, issues with harlowe and learning about data storage and logic. <a href="https://twinelab.net/twine-resources/#/"> a whole library for twine resources </a> which contains pretty much just links for all sorts of twine related things. </a> <a href="https://twinelab.net/harlowe-audio/#/"> the harlowe audio library </a> which is your one stop guide and addition to twine for adding music to your stories. <a href="https://ifdb.org/"> the interactive fiction database </a> for looking at more twine stories (and non-twine creations i believe) which can give you a great sense of what can be done with twine. [[next->RL4]] the only last thing to cover is whether you should be using the web app or downloading the application: both are fine! however, the web app comes with a caveat, if you ever clear your cookies or browser cache, you'll lose everything you worked on which means you need to be saving and publishing to file constantly to make sure your work is preserved, just in case. [[next->RL5]]lets use this stylesheet knowledge to quickly remove the undo and redo buttons in the side bar. open the stylesheets through the story menu at the top and type the following: (align:"<==")+(box:"===XXXXXXXXXX=======")[ (text-colour:red)[`tw-sidebar tw-icon {` `display:none;` `}`] ] now when you play your game from any point, the buttons to undo and redo turns at no longer there. this is helpful because the undo and redo completely erase the turns taken, where including your own passage links to go to the previous passage (while time consuming) make sure that passage history is preserved for macros like (text-colour:magenta)[`(visited:)`] [[next->MSS8]]some things to think about learning next are named and hidden hooks, HAL and music, passage tags, data systems for complex storage and varibles, temp variables, twine styling and of course, javascript which i have no experience with. here are some places you can learn about twine, [[resources and libraries->RL1]] [[back to the hub->LP7]]this twine intro will be posted and shared to the discord, where you can play it online or you can download the .twee and import into your own twine app to play. thanks for tagging along! [[back to the hub->LP7]]here's how you can make a dice roll: (text-colour:magenta)[`(link-rerun: "dice rolls ")`](text-colour:yellow)[ `[`](text-colour:magenta)[`(random: 1,6)`](text-colour:yellow)[`]`] (link-rerun: "dice rolls ")[(random: 1,6)] [[next->DFM6]]if you want to (after: 2.5s)[delay text from appearing... you can use (text-colour:magenta)[`(after: 2.5s)`] to delay things. 2.5s is equivelent to two and a half seconds, you can also specify miliseconds with ms. [[next->DFM7]] ]<!-- this is comment text. this passage is here to let you know that the passage the arrow is pointing at is the hub for the story. -->you've downloaded the intro to twine, you can see all my mistakes and successes here. one thing to know is that this file is designed to be viewed in the debug testing on your browser and is //exceptionally// ugly to look at in terms of styling. all over the place there are going to be (color:) macros and `verbatim` texts to make sure things are visible in the debug menu, but look terrible and confusing in the editor. you will likely need to break things down and rebuild macros on your own without my styling edits to recreate things. i will also leave comments in some passages for more information.