Twine 2: Make Simple Games! - Beginner to Advanced (Harlowe) | Eyevenear | Skillshare

Playback Speed


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

Twine 2: Make Simple Games! - Beginner to Advanced (Harlowe)

teacher avatar Eyevenear, Teacher in Audiovisuals and AI

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

    • 1.

      THIS IS TWINE!

      0:30

    • 2.

      Downlad The Resources

      0:56

    • 3.

      Install

      0:48

    • 4.

      Browser

      1:05

    • 5.

      The Passage

      1:38

    • 6.

      Basic Stylization

      1:22

    • 7.

      The ( )[ ] Principle

      3:07

    • 8.

      Tags And Sizing

      1:32

    • 9.

      Basic Link

      3:00

    • 10.

      The CSS

      2:29

    • 11.

      The Javascript

      0:57

    • 12.

      Advanced Link

      1:55

    • 13.

      Left Right, Top Bottom

      1:11

    • 14.

      Macro Variants

      1:04

    • 15.

      Variables

      3:01

    • 16.

      Global vs Local

      1:38

    • 17.

      Randomization

      1:40

    • 18.

      Set vs Put

      0:40

    • 19.

      Delays + Time Cycles

      2:08

    • 20.

      Conditional Statements

      1:44

    • 21.

      More Conditions

      1:47

    • 22.

      Events

      1:13

    • 23.

      IF Inside SET

      2:06

    • 24.

      Hooks

      1:24

    • 25.

      Show / Hide

      0:46

    • 26.

      Code Containers

      1:00

    • 27.

      Replace Content

      1:09

    • 28.

      Reloading a Hook

      0:47

    • 29.

      Targeting a Hook

      2:00

    • 30.

      Datamaps

      1:40

    • 31.

      Arrays

      2:44

    • 32.

      Live Data

      2:50

    • 33.

      Visits vs History

      2:19

    • 34.

      Spacing Optimization

      2:29

    • 35.

      Color Change

      0:32

    • 36.

      Size + Opacity

      1:14

    • 37.

      Dynamic Styles

      1:25

    • 38.

      React on Mouse Cursor

      0:43

    • 39.

      Verbatim

      0:38

    • 40.

      Transitions

      1:21

    • 41.

      Install Audio!

      0:44

    • 42.

      Definitions (audio)

      1:40

    • 43.

      Play a Sound! (audio)

      1:54

    • 44.

      Stop a Sound (audio)

      1:12

    • 45.

      Retrigger (audio)

      1:15

    • 46.

      Basic Loops (audio)

      0:49

    • 47.

      Advanced Loops (audio)

      2:52

    • 48.

      Fades (audio)

      1:18

    • 49.

      Realtime Volume (audio)

      0:45

    • 50.

      Crossfade (audio)

      3:08

    • 51.

      Playlists (audio)

      1:44

    • 52.

      Shuffled Playlists (audio)

      1:03

    • 53.

      One-Shot Shuffle (audio)

      1:32

    • 54.

      Groups (audio)

      1:19

    • 55.

      Seek (audio)

      1:37

    • 56.

      Realtime Monitoring (audio)

      1:20

    • 57.

      Global Controls (audio)

      1:06

    • 58.

      Format Considerations (audio)

      1:19

    • 59.

      Relative Paths (audio)

      1:37

    • 60.

      Preloading (audio)

      1:32

    • 61.

      Configurator (audio)

    • 62.

      Image Integration

      1:18

    • 63.

      Basic Repositioning

      1:02

    • 64.

      Relative Repositioning

      1:15

    • 65.

      Absolute Respositioning

      0:59

    • 66.

      Video Integration

      1:52

    • 67.

      Video Events

    • 68.

      Basic Realtime Media Switching

      1:50

    • 69.

      Key Commands

      2:37

    • 70.

      Avoid Key Repeats

      2:51

    • 71.

      Tips and Ideas (controls)

      1:37

    • 72.

      Gamepad Input

      1:15

    • 73.

      Button Up / Down

      2:26

    • 74.

      Analogs and Triggers

      1:28

    • 75.

      Vibration Toggle

      1:28

    • 76.

      Vibration Intensity

      2:01

    • 77.

      Maximize Math

      5:43

    • 78.

      Header Footer

    • 79.

      Initial Conditions

      0:52

    • 80.

      Bypass Code & Comments

      0:51

    • 81.

      Spreading

      1:45

    • 82.

      For Loops

      2:02

    • 83.

      Sandboxing

      1:34

    • 84.

      Maximize Conditions

      2:24

    • 85.

      Number to String and Viceversa

      1:08

    • 86.

      Cloning Referencing

      3:21

    • 87.

      Custom Macros

      1:32

    • 88.

      Typewriter

      2:44

    • 89.

      Display (custom macros 2)

      1:03

    • 90.

      Make a Timer!

      3:20

    • 91.

      Save Load Progress

      3:38

    • 92.

      Musical Stingers

      11:10

    • 93.

      Monitor Changes (typing sound system)

      5:12

    • 94.

      Final Export Considerations

      1:57

    • 95.

      Preparing the Game

      2:55

    • 96.

      Exporting Online Versions

      2:57

    • 97.

      Import Fonts

      1:08

    • 98.

      Exporting Offline Versions

      4:31

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

1

Student

--

Projects

About This Class

Ok, You are someone who wants to communicate.

It's no secret that Twine is the king of Choose-Your-Adventure Text Games.


Who said that this type of game has to be basic and boring?

What if i told you that in Twine you can also modernize the genre up to incredible levels, i.e. building intricate audio/video systems allowing you to create highly immersive experiences? Well, now you know.

Can Twine allow you to make a Triple-A Game? NO!

Can Twine allow you to make a short and immersive indie game that can already become viral by itself? YES!

The problem with that is that it takes a lot of time to master all the facets of this software for free, and some people don't wanna wait that long, that's why this gig is my present to you:

You will take the absolute shortcut to proficiency and reach it in a few classes because i will show you exactly what you need and let your knowledge expand to its max.

Twine Harlowe is user friendly but actually very powerful is you find all the ways to squeeze the best out of it, this course will literally guide you from knowing nothing to knowing everything; then you’ll be able yo realize your dreams with the right amount of effort!

Be patient, follow the classes slowly and you'll realize your vision; Let's do it.

Meet Your Teacher

Teacher Profile Image

Eyevenear

Teacher in Audiovisuals and AI

Teacher

I'm an Italian/Canadian Audiovisual Specialist and Twine Game Designer.

I've built a Top-Rated community of students in Fiverr in 3 years.

My Skillshare courses are a thoughtful present to those who normally can't afford my 1:1 classes but still wanna reach a decent level with arts.

I also teach in real life. I'm developing an action-puzzle game.

YES, i do have AI video/audio proficiency.

With tens of thousands of hours spent in music and video making,

I help other creatives push their craft into whole new levels.

Innovation comes from ideas. Show me what you can do.

See full profile

Level: All Levels

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. THIS IS TWINE!: Hey, guys, I'm Sad. If you're looking for a simple way to create video games, Twine is probably the answer. Especially if you want to create a text adventure or a protype that you want to run in browsers. You know, one of the best features about Twine is that it has a very intuitive called syntax. You can always track what you're doing, and you can easily add new features to the game as you progress. If you don't need extremely fancy graphics, I just want you to be able to demonstrate the solid game concept. Well, this software's pretty much for you. So if you're ready to start, let me know. 2. Downlad The Resources: Alright, so before you start doing anything, you need to download the resources. All right? To do that, you need to go to the landing page of the course and then simply scroll all the way down here, go to projects here, and then just read the description and then you will see a special link here called click here. So click this special link, and it will give you a drive folder that we need you to download. So we simply download it. After you download the folder, simply right click on the file and then extract need to type a special password, right? So let me zoom in. So the password is Banquet 947. Underscore, underscore, underscore. Alright. So and then just confirm with a couple seconds. And we have all the files. Alright. Let's go. 3. Install: All right, so for the installation, just means you go to Twinry. So just search Twinery like this. Then go to the first result where we see the icon of the application. Click on download here. Then scroll all the way down. If you have Mac, you need to download MacOS DMG, this guy here. If you have Windows, download this one. And in both cases, you just need to skip through the process, so you just install it regularly, just skip through the things, confirm confirm confirm, and the application will instantly become available locally at any time into your machine. That's it. 4. Browser: The next step is to install either of these four browsers Oprah GX, chrome, edge or brave. Then if you want to really optimize your workspace, you need to install a extension called Love tabs. It works in any of these four. And the way it works is that you copy my settings here. Let me just show you what happens. If I try to open a new tab, it automatically closes the older tabs and always makes one only tab existing. The reason this is important is that normally, if you don't use this extension, let me show you what will happen. When you test a game from Twin, it will start to accumulate tabs over tabs like this, which obviously is going to create some chaos, you know. So to prevent this from happening, which would be an issue for the RAM, also, you just need to install this tab limiter like this. So go all the way back to one like this. And when you work in Twine, it will safely keep only one tab open. 5. The Passage: This is what you'll see the first time you opened the software. Here, the stories are kind of the gain given to the projects. So each project is called story a story, you know. So let's just create a new one. Here, new. Call it detail one. I will immediately go inside that project. So when you open the program, you will see all your projects like this. Double click. Just like this. So this little square here is the main molecule of any project entwined. This is called passage. Fundamentally, is a container that contains either something that will be displayed like text like this or an image or video, Jif or a audio file, wherever, and will always be inside this project. That's fundamentally how it works. You put the content here and to display it to simulate how it will look like in the final project. We just make sure you select the passage. We rename it initial. Click this and then press test from here. When you do this, it will show it will render the test, the final result into the browser, you know, into the default browser of your system. And as you can see, we can literally see it here. So that's how easy it is to go back and forth between the browser and twine. 6. Basic Stylization: So let's just go back to do some customizations. For example, as you can see, when you enter a passage, there are so many buttons available. But for now, let me just explain very simply the first six. One, two, three, four, five, six. These six buttons here are all related to the main customizations regarding the appearance of the text. So when you slice this text a little bit, we can just select like this. And then you click on styles as you can see, we start to see the classic things, bold, italic. But if you want to customize it a little more, we go here more styles. We start to see extra things. For example, we can emboss it or we can blur it or shadow, et cetera. Just make it glow, for example, smear. And also, we have things regarding the movement, so we can make it fade in, fade out, rumble sway, you know, all things that makes it a little more interesting, versatile for any case possible. Just give us some tremors like this. Alright, then we just confirm, add. And now we see something happening. First of all, let me just show you what happens at the final render. We literally see the text with a new style applied. That's how easy it is to customize the text. But let me just show you what happened here in the code. 7. The ( )[ ] Principle: So as you can see, we had our text here now is encapsulated by these square brackets. So fundamentally, when you see Sofi inside square brackets, you can call it a container. And also, before the square brackets, we have these classic brackets like this, these parentheses. Contain something called macro. A macro is something that is going to change the appearance or the positioning or something regarding the logic of the game. It's something that allows you to change how something looks like or modulate the background code of the game, you know, to track something, track a choice for an ending an item will always be achieved by using a macro. But in any case, the macros always follow the same logic, which is just like this. You create he paradess like this, and immediately after you place she square brackets like this. So a macro in 90% of the cases will always look like this. So here, where you put the name of the actual macro, you can see that as a start typing, it will show it will suggest all the possibilities. But for now, let's just type, this is a macro, whereas inside the brackets is going to be the target of that macro. This is the target of that macro. And ly, we can see this happening here. You know, we have this macro here, which changes the text, the style of the text. And to decide the target, we place the text inside the square brackets immediately after the macro. As you can guess, there are cases where you can stack multiple macros one after the other or one inside the other. Let's suppose that we want to align the text as well, so we can just select again, the text like this. And this time, we click on this button here, alignment. We go here, alignment again. And lily, we just select center. Choose a custom alignment. Let's just keep it there. We can expand it, justify, confirm. So we have now the style macro outside everything. And inside that, we have the alignment macro, which ultimately aligns the text here. So, fundamentally, you can stack multiple changers, multiple macros one after the other or inside the other. So let's just test this passage again. As you can see, now the text is not only with the style, but also centered. And this is fundamentally how it works for 90% of the cases. What I invite you to do is just play around with these, modulate the text style in different ways, and you're pretty much familiarized with this. It will probably take ten to 15 minutes, to fully understand all the possibilities that you can do with these first six buttons. They are pretty simple changers. Don't worry about all these remaining buttons. I will show you gradually all of those 8. Tags And Sizing: Another useful button that you would use and I recommend using is the size button. So this will allow you to understand better if some passages are more important than others. So you just select a passage. You click on size, and you can choose different shapes for each passage. This will just allow you to go immediately where there is a beefier passage containing more stuff. Another feature that will be extremely useful is sometimes tagging a passage. So fundamentally, you can label it. You can give it a color. So for passages that serve a specific function or that contain a specific important event, you can color them like this. You go in sign the passage. You go here, tag, and you create a new tag, in this case. So just call it Pv choice, for example. So these are going to be passages that contain a really important choice that will determine a ending. So in that case, let's just give it a color here, confirm, and we can see that passage having that color. So from a distance, we will immediately know that there there's going to be an important choice in the game. Well, you can pretty much use labels for anything you desire, you know, passages that need to be debugged or need to be rechecked twice. But let me just spoil that. Actually, tags are more than this. They can be used to actually talk with twine to unlock specific functions. 9. Basic Link: Now, let me just talk about the really core functionality of Twine, which is going through different passages. Even though, technically, it's possible to build an entire game with just a few passages or even just one where all the action occurs, in most cases, you will need to actually have multiple passages. This will allow you to have more arrangement of the information of the game, right? So you will segment the game in multiple steps instead of having a single BF passages that contains too much stuff. So, that's really important. You just need to double click on this passage. Let's just create something called a link. Create square brackets. And also you close them like this. Inside this, we can type the name of the destination passage. You can say you see that something starts to happen here. Room. Like this. And now, as you can guess, we see already a new passage with that name. If we test Room one, let me show you what happens. We literally see a button named room that lily goes in Room two. So if I click this it goes into room two. So now it's empty, obviously. To verify that we are actually in room two, you see this window here at the bottom right, this is called debug window. It's extremely important because it will allow you to track all the variables that have been tracking during the game, and you can see where you are right now. We are exactly in the passage called Room two. You can also kind of reset the current test by reloading the page. So if you do something like this, it will restart from passage one. And we see again this, and now we are back on room two. This button here allows you to go back. I will show you later how to disable it. If you go inside the link like this and you type hyphen greater than if you type a custom word, for example, continue. Now if we go back to the test, Room one test, you can see that the button now shows as continue. So it's a custom word that we can change. But actually, it will go to room two. So when we click it, you can see here we are in room two. Wow. So that's fundamentally all you need to know about twine. So okay, that was nice. Thank you. Just leave a review. Okay, sorry. I'm just kidding. Obviously, yeah, there are people that create entire games just using the basic link like this. But obviously, if you want to have more custom systems, if you need to have little things that are beyond 10. The CSS: Right. Sometimes you may realize that you are using a specific style consistently for the rest of the story. So for those type of things that are valid on a global scale for the entire game, maybe it's wise you apply that changer only once using the CSS section. So to do it, you just need to go here story then you go to Style Sheet. This section here, you will be able to paste CSS code. Already prepared some basic things that you will be able to do very easily. And just copy this code from one of the documents called CSS in this chapter. So let me just explain what these do. The sidebar here allows you to disable the go back arrow that normally you see when you go in a different passage, if you change it. I can see that now, if I go in room two, I see this arrow here, whereas if I put none, it will show nothing. So in case you're doing a book, it may make sense you leave that there. But in case you're doing a proper game, maybe you want to disable that possibility also because it will allow people to kind of cheat on your game. I can also change the phone in this section, type exactly the name of the phone that I want. It will automatically use that. You can also install it. I can show you later how to import phones from a website. And here is where you decide the default centering of a text. So to left, it's going to go to the left. Let me show. Same if we type right and so on, so on. So for now, it just type Center because I like it. And then you can change the default color of the links. So as you can see here, you just type the specific color. You can also type purple, for example, and it will become purple. Just like this. If you want to type a specific shade of color, you can just give a raw X code, pasted here, the X code of that color. Ultimately, you can also change the color of when the link is going to be hovered by the cursor. So let me show you now it's white here. So it means that if I hover it, it becomes white. So as you can see, these are really simple things, but actually, you can already start to have more power on the stylization of the project. If you want to change the color here, you can still give a custom color, even though on the CSS level, there is already default color decided. And that's all you need to know from now for the CSS. 11. The Javascript: The JavaScript section will be useful later in the course to install some extra features that normally twine is not able to do. So we will use it specifically to have interactive music, interactive sound effects, and also to use the keyboard for input. So we will really be able to use the keyboard keys to control the game. So that is going to be fun. Also, there is also a library to use the joyPad to control. There are so messy things that you can do just by installing libraries in this section. But for now, this all you know. 12. Advanced Link: Alright, so unless you are in a situation where the only thing that you need to do is you just leave the passage completely, kind of just change page and go to a new one, sometimes you just need to avoid using the basic link and instead, the most flexible version of the link. So you need to type just a macro like this. Link then between chew quotes, you give the name to the button. So, for example, leave this place. And then inside square brackets, we can make anything we want happen. So it's not necessarily leaving the passage. It can be anything we want. You know? So this is fundamentally a button, and we can make inside those square brackets happen wherever we want, even just hundreds of things at once. We will just take more space. You know, we'll just take space like this. So let's just start by just making a basic go macro. That will go to the room two. So we just type exactly the name of the destination. So right now, let me show you. It's gonna be literally the same as the basic link. So it literally shows the button. We click, and we go to Room two. And so far so good. But actually, that's where the perk comes in. You see this space here, we can insert wherever we want. So before leaving the passage, we can make tens of things happen here in this space. We can say variables, we can change some variables. We can disable some buttons. We can show some content. Fundamentally, this, as you can guess, is going to be the link that you're going to use 90% of the time, maybe even more often. It's extremely powerful. So it's going to be the main macro that you will use in any game. 13. Left Right, Top Bottom: Fundamentally entwined, the code is read from the left to the right and from the top to the bottom. It means that if you place, for example, let's just create a third passage, call it room three, like this. And then we go back to room one, insert new just a new macro after the room, like this. And then we just call it your room three. So the code is going to be read from the left to the right. Logically, we should just go to room two. But here we also have Room three. So where will we go? Obviously, we can only go to one place. Let's just check. So we go here, test. Okay, press. Alright, so we landed in the room two. Fundamentally, since we completely left this passage at this point, at this exact point, the rest of the code from here on will be completely ignored. If you want to make stuff happen before leaving the passage, it's going to be placed on the left of GT. 14. Macro Variants: For many macros, there are also variants. You know, there is kind of a base version, which in this case, is just the link, but there are variants which are specialized for a specific case. These are kind of things that you can kind of start to ignore because they are secondary. But sometimes to save time, you may start to memorize some of those. For example, one of the most common cases for the link is exactly to go to another passage. And as you can guess, there's a version of the link called Link let me show you ink go to. As you can see, it shows you all the possible variants of this. So as you can see there's one called Link go, o. Check the documentation to check exactly how they work. But I already know that this works by giving cho quotes. So one is gonna be the name receipt and second quote for the destination. As you can see, the variants allow you to save some space in the code. So let's just test. Alright. Proceed. Works. Who. 15. Variables: So at this point, you probably understood that leaving a passage completely ignores all the known persistent data in the game. You're probably wondering if there is a way to actually make some data persistent to make the game. Remember some specific numbers, pieces of information. You need to use variables. You need to kind of define a variable to make it exist. To do it. Let's just create a simple passage. Let's just say that when we are in room one, we will already save a variable. So we're going to use this macro set. Then you need to type the dollar and you give a name to that variable. So we just call it money for now. And then we type two. A variable can be either a number, so we can just type zero. So set money to zero, test. All right, you see now, we start to see the variable being registered with the number zero. So it worked. Second case is going to be a string. So to do it, just type two codes and let's just type low. So in this case, it's going to be a string. Money is the string low. Alright. Finally, third case, true or false. So let's just type false. Alright, so money is the boolean value falls. Okay, in case that has been registered correctly. So it's kind of a switch. You know, it can be either true or false in a very useful way. But it's kind of the same if you just use a zero, one or true or false, also just here using a string. All these three cases are interchangeable. So you just need to develop your own taste for your variables and just stick to those. You know, there are cases where you will need specific types of variables. So it's really important to be able to use all these three, right. And that's all you need to know about the variables. This value will be able to change over time into the story. Let's just say that we want to change the value as soon as we click on this link, leave. So just paste another one here, set money to it. So it means itself money plus one. Let's see if you can guess what is going to happen. So we got to room one. As you can see, you have money zero. And as soon as you click on leave, who, you see what happened? Now it became one. So that's how you can change very easily the values of a variable into the game. That's the first case. Same principle in case you use a string. So if you type low and you want to change a new string as soon as you click, obviously, it's going to change the new string. So let me show you so it's low, if I click. Hi. Alright. That's fundamentally all you need to know for now about the variables. 16. Global vs Local: There are actually two types of variables. It can be either global with the dollar. It's going to persist for the rest of the game, or there are also local variables which can self destroy as soon as you leave that passage. You may wonder why you may want to delete some variables. Well, with the local variables, you can just declutter the dbug window when you leave finally that passage and leave more space to read better the code for more important stuff, to use local variables. Instead of the dollar, you use underscore. Alright. And let's just give a slight different name like status. Alright. Happy. So now, in theory, when we test this passage, we will have also a local arb as you can see, we have status registered with the string, happy. When I leave this passage, take attention on this spot here. As soon as I leave it, three, two, one. You see what happened? The status variable has been completely destroyed. It's not existing anymore. So that's how useful it is to use sometimes the local variables. If you happen to use local variables, you may have some additional issues sometimes. So unless makes sense, don't use them. And also, make sure that you set those at the beginning of the passage. Because if you place those at the very end, sometimes it may create some issues. Let me try here. Maybe it will still work. Yeah, in this case, still works, but it's just wiser to set the local variables as soon as possible. So just place those all the way to the top here. 17. Randomization: Two Now, let me also tell you a couple of things to make the setting of a variable more flexible. So let's suppose that you want you set a random number when you decide the initial value of the money. So set. But this time, instead of giving a fixed value, brackets, then type random column. And here we just define a range. So for example, let's just say that it's going to be 0-1 thousand. Like this, with this trick you can set random numbers within that range. Test. It's been set 50. So if we reload this passage, 676 543. So every time I reload the passage, as you can see, restart the test, and we can see that every single time, we have a random test. The other way that is very similar to random is called either. So if we go here and we change with E either, like this, 500, whatever, you know, like this. The difference between random and either is that, in this case, either, it's going to choose only one out of this list that we create. So let me show you as you can see now it is zero. Again, zero, 100, ten, as you can see, both are similar, but they are slightly different in the way they work. That's already going to be extremely useful if we want to assign, like a random damage or you want to assign a bonus. And obviously, either can also be strings, sad, happy. Make sure that obviously you separate all the values with comas like this, that's. 18. Set vs Put: Okay. Sometimes you may feel the need to set the variable in a slightly different way. To do it, you can just use a variant of set, which is called put. Like this. It's fundamentally the same thing as set, but in reverse. So you just define first the value that you're going to give and inch. As you can see, it's the same as set, but we put the value and then the destination. Put happy inch money. With the string, happy. Who. Sometimes it may make sense to put the actual value at the front of the code, so you can easily see 19. Delays + Time Cycles: All right, so let's just dedicate a couple of seconds to talk about time related macros. Just suppose that we want to delay this macro here by a certain number of seconds, right? The simplest way to do it is to use after like this, 3 seconds. So three a. You can also put milliseconds numbers. We put the put macro inside after. Only after 3 seconds that we enter the passage, we will see the moni variable being set. So we go here. One, two, three? Hurrah. That's how it works. Fundamentally, it kind of delays one event by a certain number of seconds or even minutes, you know, it depends. That's it. Okay, now, in theory, after 3 seconds, we will see money become one. They just say that we want to make it happen only after we click on this button here, like this. So just lily change the name to live, 3 seconds. Then we can finally shift it inside Link. Okay. So let's just go here. As you can see, we don't see any variables for now. So in the, if I just click here, Okay, we wait 3 seconds. We should say, Okay, we start to see number one. And do you notice one thing, it is starting to increase every 3 seconds. So the reason this is happening is that live by default, is kind of a loop. So it repeats that function every 3 seconds in this case. So it's kind of increasing infinitely money by one every 3 seconds. So that's one thing. But let's suppose that we want to make the event happen only once. Do it. Type parenthesis, stop, and now it will make the event only happen once. Let me show you. Click 1 second. As you can see, it's just stopped. To one. So that's the equivalent to after, but way more flexible. 20. Conditional Statements: Two. Let's suppose that you want something to happen only when specific conditions are met. We want to go to a specific passage when the Moni variable has reached a certain minimum value, right? Let's just modify, first of all, this link here, so it's going to increase this number infinitely. After the money has been increased, insert a new macro here called I. You just break line like this. Alright. So the way this macro works is that here we specify the condition. So let's say if moaning is greater. So we can use greater, lower. You probably saw this in school, you know, greater measure is lower or equal than. These are kind of all the possibilities, right? So for now, let's just type greater than three. This is going to be our condition. Just specify what happens. Go to a specific passage inside the square brackets. Go to Room three. Now, in theory, we will see the moni increasing and only when it reaches beyond three, it will immediately go to room three. Go. So just take attention on this. One? Two? Three? Four. Okay, you see what happened? Now, as soon as we reached four, which is greater than three, we left the passage, and at CNC now we are in room three. Whew. So that's how the conditions work. And you have no idea how many times you will use this because they allow you to make your logic of the game more intricate. 21. More Conditions: Two I macro can also monitor for multiple conditions. For example, you can go here at the end of this if, and you just need to type parenthesis and then else if. Fundamentally, is a second if where you just define a new check, a new condition. So first of all, let me just do a change here. Let say that we set money to a random number, like a die. Then we just go here if Moni is one, one. Else if Moni is he, che. And also to make this clearer print physically the text of the moni variable after it gets updated. So we see li if it's true or false. Like this. I just test. Okay, go. So we see the variable one. You see what happened. Only when it reaches one, it prints one like this. And same when it reaches two randomly. You can see that. Alright, two, and then again, when you variable two again, so on, so on, right. Let's also say that we want to see a text for all the other cases. To do it, you just inue se after all the se ifs, s, which means do this in all the other cases that are not the previous ones, you know, so neither this or this Older go. Alright, Odor, odor, order and only it's one or two changes. But in all other cases, it prints Odor. Whoo. So that exponentially increases the power of I. 22. Events: So far, we kind of built a system where we combine the live macro with the I macro. But actually, there is a specific macro that you can use to make a I online, so it kind of triggers as soon the condition is met automatically. So we just put it at the very bottom. Like this. Okay, it's called event. And the way it works is that you type when moaning is one, go to Room three. Fundamentally, this is the same as using a live plus F. It's going to be ready to trigger this as soon as the condition is met. Super fast, you know, the fastest you can do. Let's make it a little more interesting. Maybe we decrease the speed even more, but we increase the numbers. Let's try this. Go. So it goes goes goes until eventually we'll touch one, and it will immediately go automatically to the thing that we set. That's fundamentally the power of the event macro. Only one advice, don't overuse those. You know, don't overuse multiple avant too many times. Only use those if it's necessary. 23. IF Inside SET: What if you wanted to incorporate a if condition directly into the definition of a variable? You can do it with the condition macro. So let's just define, first of all, again, set mon, mooning random $1-100. Maybe 10,000. Alright. We don't know if we will have only $1 or 10,000. Right. To define if we are rich or broke, we can just do it from here. So set status, type cone. Then call the variable, you need to check. So money. Let's say if it's greater than 9,000, we are going to assign the string rich, choose status. And then we need to define which string will be assigned for all the other cases. So it's going to be's coma and give a value for all the other cases. So let's say broke, test. So now we are broke because, as you can see, money got only 1054. So if we reload broke again, 7,000 close, again, again, again, eventually it will be rich. Go, go, go. Okay. Wow, Rich. Because, as you can see, money now is over 9,000. That's the way it works. Condition is extremely powerful, and you can incorporate where we want it. It can be even inside the print, and you can also define multiple conditions in the same cond. Well only just copy this. Let's just define an intermediate case where you are above 2000 and is lower than 9,000. Alright. So, in that case, we can say that it's mat. In all the other cases, it will be actually broke. Okay, M, because, as you can see, we are 7,000. Mat, just take careful on this point. Again, M, Matt. Okay, now we are truly broke because as you can see, we have only $69. 24. Hooks: Let's just suppose that sometimes you may need to have a piece of text that you want to hide and show dynamically, or you want to have a piece of code that you want to re run only when you want. To do stuff like this, you need to use hooks. So the hooks are fundamentally mini paragraphs that are kind of mini containers that can contain either something that will be displayed or code, and they can be replaced. They can be hidden, shown, re run. I'm going to show you how to do all these things. Let's just read a new passage here. First of all, you just type a vertical line like this. And you give the name to this hook to this container. Hook one. Then you need to decide is this hook going to be visible by default or hidden by default? If you want this to be visible, just type greater than this symbol here. Then just type the two square bracket as usual. And as you can see, it completes the function, and now we can type wherever we want here when I preview this passage. It's as if I just written normally that text, but now it's inside a hook. L suppose that we want the hook to be invisible by default. Well, just change this symbol with the closed parentheses like this. We don't see anything. 25. Show / Hide: You will always use one macro called show. Then you type question mark and you name the hook. So hook, one. So now, as you can see, also, there's a match after 1 second. Alright, one and shows. Same for the reverse. So if by default is visible, you can hide it. Change show with height. So after choose seconds, it will hide the hook. One, two. Hide. As you can guess, this can happen also with live, with event. You can go with fantasy and find new ways to show or hide a hook in different ways. You know, there's no limit fundamentally. 26. Code Containers: Oh. Another amazing feature of the hooks is that you can also place code inside it. So you can make it hidden by default. If you place a code inside it, it will only trigger, it will only start only when you open the hook, only when you show it. So if we, for example, place something that goes live like this, every half a second increases the money variable by one and prints it. Since it is inside, the hook is hidden, we won't see anything when we test the passage. Let's just go here. As you can see, we have nothing, and we also don't have the variable. But as soon as I press this, we start to see the variable being printed and going on and on. So it's kind of a box that contains all the info, and it only starts only when you open it. That's the beauty of the hooks. You can use those to trigger entire advance into the logic itself only when you want. 27. Replace Content: You can also change dynamically the content of a hook. To do it, you need to use the replace macros. Replace, we target the hook or the hooks that we need to change. Hook one for now. Inside the squares, you just place the new content that will be placed instead of this of the old one. So it will completely overrite the old code. For now, just select a sequence of zeros like this. We press go to show the standard content, and as soon as we press change, you see what happened? Now we see the new content on that hook. So obviously, you can repeat this step dynamically. It can be extremely useful for dynamic dialogues and games or even from code itself. Just be careful when you use this with live functions. If there is a live function going on, maybe it's wise to try to incorporate the replace into the hook itself or even make sure that you stop the live function otherwise, it may still be running somewhere. 28. Reloading a Hook: So as you can see, right now, we have set money to eight plus ten and print it. So as you can see, it's going to be shown. So if we run this passage, we just see the number ten, and that's it. So let's just suppose that we want you to create a button that tells this hook to re run this code, and in theory, we will see a higher number. So just go here, create Link, try again, and then inside it, let's just place the re run macro. We call the target hook, so just hook one, and then just go here. Test, we have the button. So as soon as I press it, Who. You see what happens. So it kind of told the hook. Okay, rerun yourself. 29. Targeting a Hook: All right. And finally, let me just show you a little more advanced approach where, for example, you have multiple hooks with different content. Let's suppose that you have a system that hides only one of them at a time. To just discern the target dynamically without having to create too many copies of the same code, one approach will be using the so called hooks named macro. Let me just show you how it works. First of all, a button to choose the target. So target one, and we will use a variable called target to hook one. Then we just copy and paste this for target two. Alright. Okay. We just create a third link that will be used to finally hide one of them. So just hide target. And here we just play hide. Instead of naming directly only one hook, we make it dynamic. Use the new macro, which is called Hooks name. This one here, like this. And then we use the variable target like this. So fundamentally, what's going to happen is that first, we press on one of these buttons to choose target one or target two. And then ultimately we press on the second button here, hide the target, which is automatically going to hide the correct hook, according to the one that we pressed earlier here. Let me just show you. Let's say that we target number. Okay? So you can see the variable here being set. Target is hook Q. If I press hide the target, now it's going to hide this one here, the second. We. That's the way it works. Let me just show you also the first one. So obviously, if we press only this without a target being set, it will probably an error, because it doesn't have still a target being set. So you need to set the target. So let's just target one design like this. And now, if we hide, it will automatically hide the right target. 30. Datamaps: Let me show you how to use packet data. Create a first situation where we set a money to ten. We want to set automatically the status to broke or rich. According to this number here, then we set status money, which is the source of the modulation of DM data map. And inside the data Map, we use pairs of values. So for each possible value that can be assigned to money, we will return a certain specific value. That's the way a data maps works. So we just go here, and we know that money will only go either to one or 1,000. So inside the data map, we can just type one comma, assign the string, broke, obviously. Then coma count for the second case, 1,000 rich. And at this point, we can just print status one or 1,000. Alright. Let me show you what happens. So broke, rich, rich, rich, broke. Which carefully this number here. So we are broke only when it's one. And we are rich exactly when it's 1,000. Wow, that's the beauty of the data maps. Always be careful because you need to make sure that that data map takes account of all the possible cases. Otherwise, it will return an error. For example, type a weird number that we didn't register into the data map like this number here. Okay, immediately. So now works, now works, and eventually will break because there is a number that we didn't register. 31. Arrays: In case you're wondering if there is a way to have maximum flexibility, the answer is using arrays. Fundamentally, arrays are the most general way to pack multiple types of data in the same place. To do it, very simple. You just set a variable. So you give a name to that group of data, choose box one, and then choo A, and here we can just type wherever we want. Set the first number to be one, two, three. So as you can see, can be either mixed types of values in the same pack. That makes the arrays extremely flexible and powerful. You use them all the time. At this point, we have an array that contains one, two, three, four values. This whole packet will be called box one. Let me show you what happens. It will register all the contents of box one as individual elements. And you probably wonder what we can do with arrays. Well, if we set Ming, box second, for example, like this, just like that. So fundamentally with this is gonna pull the second value from box and put it into money. Alright. You see what happened? We just assigned the second value of box one to money. So we can use third, here, and so on and so on. As you can guess, there is a way to change the content of an array after you already said it. Let's just do the following. After seconds, we put zero in. Boxes second position. Print. Alright. Let's do it. Alright. Now we just printed box second position, which initially was 1,000, but after 2 seconds, it has been changed with zero. And finally, another thing that you can do with arrays is to convert each value inside one into actual variables. To do it, you need to use the pack macro. So you go here. We type unpack box one, obviously, in parentheses. And here we just type again array. But this time, we just need to type the name of the variables and we need to assign each of these values to. We have one, two, three, four values, so we're going to create four variables. So it's going to be value one, so on and so on, like this. That's the way it works. As you can see, value one, two, three, four have respectively exactly the numbers of the original box array. That's going to be extremely useful, especially for commands into battle games. But actually, it can be pretty used for anything you desire at that's the point. 32. Live Data: Displaying live data. You already know about the print command, which allows you to display actually some variables or wherever. If you encapsulate it inside the live, obviously, we will make a displaying variable, always update to the latest value, right? So we already know this at this point. Well if you want to be able to type something in real time, you just need to use this new macro input like this, and we just need to type to bind like this. Just name a variable that you want you assign this value one. Let me just show you how it looks like. We literally have a text box where we can type wherever we want. And you can see that as soon as we type, the actual variable gets updated with that value that we sign here with the Strick, this value that you type there can trigger something. If there is an event that is monitoring for that value, the second thing that you may need sometimes to display data live is some kind of slider that moves according to a variable changing over time, like a health bar, for example, do something like that. You just need to use the meter macro. So you just type meter, bind, and the variable that is going to pull the values from. So let's just say he comma and then just make sure you define the max number. Let's say 100. Then coma, again, just type X like this. This is kind of where it's going to be aligned, too. It's gonna be to the center, to the left to the right. And X means just to the center automatically. Finally, let's just give a color for the bar. So yellow. Now set a value for that. So obviously this is gonna change in real time if we create an after 1 second, he to 15. And then we create a second after this time, 3 seconds. When we set it down to ten like this, let's try. Okay. 50? Wow. And that's how easy it is to integrate a mirror bar into your passages. They can also be reside as well, aligned wherever you want. And as you can see, there is no border to this bar. So we just type B for R, like this. And then solid. And this is gonna give nice solid borders that makes it look more legit, like an actual health bar. Wow, there are advanced ways to customize these bars. You can kind of have, for example, a gradient where it kind of changes color according to where it is, or change the way it fills. You know, maybe it may be filled from the center to the borders or the other way around. 33. Visits vs History: Two so let's suppose that we want to trigger some special event in room four, but only when we return at least three times into this passage. To do it, we just need to put a nice if condition at the bottom, like this. I sit is equal or greater than three, let's say. Then we just go to a secret passage or we can trigger something into this page itself. So let's just go into a completely secret passage. Start from room three. So regular room three, room four, three, four, three. Now be careful. Alright, as you can see, we returned the third time into room four, but instead, we have been redirected into a different passage. That's secret room one. That's how you can use this special variable. This is really powerful for this. And finally, let me just go just one level deeper. Now suppose that after we went through secret room one, we go back into room three, and we want to make room three aware of the fact that we went into secret room and thus trigger some additional secret in room three itself. We need to us history. So we go here at the bottom of room three. You create a simple if condition history where its name contains. Inside quotes, we type the name of the passage that we need to monitor the visits of. So in this case, secret Room one. And outside of the parentheses, we just type apostrophe S, length and finally, here we can decide what is the minimum number of visits that will trigger the secret. So in this case, just one greater than zero. So what this whole line means is that in case we went through secret room at least once, we will trigger the secret three. They just test this passage. So in Room three, now as you can see, we do not see yet the secret thras if we eventually reach the secret passage. Alright, let's return to room three. And if we do everything. Okay. Who as you can see, that's what happened. Since we just went through the secret, Room three now checked that we indeed went through 34. Spacing Optimization: All right. So now let's just talk about spacing properly the things twine. Fundamentally, the code and the text that will be displayed will always take some space into the page. So in theory, if we render this, it will be exactly one after the other right. But if we type some code, if I render this passage, let me show you what happens. It actually takes space. The trick to automatically collapse all the space. You just need to go at the very top of the passage, type a nice, curly bracket. Just open it like this. And then at the bottom, close it. This is called collapse. And what it does is exactly you automatically use as less space as possible. Let me show you what is happening. As you can see now, it collapsed so much that it also collapsed the line breaks. So it kind of solved one issue, but also created a new one. Maybe we want to preserve the line breaks. You just need to type the standard HTML line break. Copy exactly this. It's just the same. This track allows you to use both. In theory, we should still have Who. Same thing, but also with the I finally completely ignored. If you use the partial collapse, which looks like this, like open the curly bracket and then equals. As you can see, it becomes ready function. When you use this, it will only collapse the space from that point on. In theory, we will see the first three normal because it's completely rendered. The following three with the space collapse. So there will be no line breaks anymore. Let me try. Alright. So that's also another trick. So to use partial collapse space, in some situations, you may need to use this instead of the standard to collapse. And let me show you one more thing. Let's suppose that we have an actual line break like this, but you want to collapse it without using the the actual collapse trick. To do it on only specific lines, just type the reverse lash, and it will automatically collapse the next line. So let me show you what happens just with this. It will automatically collapse only the line break. 35. Color Change: At this point, you already know how to salise the text in the most basic ways. Now, let me just show you a whole extra things to just expand the set of personalizations that you can apply to a text or where you want. To change the color of text, hyphen, and then, as you can see, suggests you things you could do. But one of those is color. Here, just type where we want. Purple, and then just encapsulate the text exactly. Purple. Pooh. 36. Size + Opacity: Let's suppose that you want to make a piece of text, bigger than a different one. Let's change text color with text size. You need to be careful because size goes from one, which means no change. And then, obviously, if we insert 0.5, it will be half the initial size, just like that. And so on and so on. So if you want to make it three times as big, put three should decide the opacity of a piece of text or anything else type opacity just like this. And then same thing. So it goes from one, which is the basic means no change, fully opaque. He down. Let's make it really almost completely transparent. So 0.25 and obviously, it's going to look really light, just like that. As you can guess, you can combine all these things just by adding a noise plus 0.5 opaque and also change the color, type in noise. Plus, and add whatever other changes you want to stack on top of the first one. Now show a text also smaller size, so you can see all the properties stacked on top of each other. So we change the color, the opacity, and the size all at the same time. 37. Dynamic Styles: Let's suppose that you want to make these properties dynamic. The two most common case that you could use, would you place this entire thing into some kind of live event. So you can place it either inside the giant live like this, and then you just change some variables or one way, would you just place the entire thing into a hook, and then you can re run it with the variables they just do it. Instead of using the fixed values here, we just use variables. So literally here O P one, okay, then here we use color, one size, what? Right now, these variables have only the default value, which will be zero. So set the default values. So you can also guess that you can just set multiple variables using a single set. That said, we just start to test this guy, if it works by itself. Alright. Now, to be able to change these things dynamic, way could be to create a event after 2 seconds that we enter the passage, change all these nice properties to new values. So we make the text bigger, like this. We change color. White. Opacity choose 0.5. Alright, re run text like this, and that's it. So let me show you text. One, two, Magic. Who. So now you can imagine how flexible this system can become. 38. React on Mouse Cursor: Let's suppose that we have an invisible text, text, color, transparent. So by default, it's going to be invisible. But then when we hover, that text is going to become visible or it's going to change color. The way to do it just use hover style. Like this. Here you define what is the change that is going to occur, change the text color to white. The sign the text, query Test test test. So right now, it's invisible. But as soon as you move the cursor on the text, Who fundamentally, that's another trick that you can integrate it. You can hide some secrets or wherever you want. 39. Verbatim: Let's suppose now that sometimes you have a word, hello, and we make it bold. If we render this, it will only show the word in bold style, right? But let's suppose that you want to be able to render this including the quotes here. So normally there's no way to do it unless you use verbatim, like this. And then just encapsulate the text. So now, it will render the raw text like this. That's the w you can exclude any possible stylization only the raw text. 40. Transitions: Et's just suppose that we have, again, our word Hello. And we want you give some movements. When this text will appear or disappear, just use transition. The options that you have are the following. Okay, just freeze this frame because all these guys they see here are all options that you can put into this place. Well, let's use shudder, and that will already apply movement to this word here. Let me show you test. Okay, so you get what it does, and it will automatically play when you reload the passage. Let's suppose that we want to have control on the speed of this animation. Add the nie plus, and let's change transition time. And as you can guess, we're gonna just indicate a value in seconds, 0.5 seconds. It's already faster, slower instead. So 3 seconds. As you can see, it will be way lower. Wow, that's it. You can have fun with the transitions and the times. 41. Install Audio!: Two to be able to use audio twine, you just need to install an external library. Go story, Javascript. And here, you just need to copy and paste the content of the text file of this chapter. Paste it here. You will see this long text. Don't change anything, just close this. And then do the same also for the style sheet. So you open the sleseet. In case you have already some stuff, go at the bottom here, and then just paste again. Just like that. Close to kind of double check it test when passage. So you just insert some random stuff like this, and it does it give you any error? It means that it's properly installed. Perfect. 42. Definitions (audio): After we have the library ready to be used, you just create a special passage where we will indicate the exact location of the audio files into your drive. So let's just create a new passage, name it exactly like this. Whole dot tracks. Just copy exactly this name. Then inside, we will just initial define where all the audio files are. So the way it works is this, create define our first track. Give it a name, so click one column. Space here, you just needs to paste the absolute path of the audio file to get that path very easily. One trick is the following. You just open the browser here. Then you go where the audio file is. Here. Okay, so we have this file, for example, one N P three, which is kind of a click. And then you just drag the file into the browser exactly here where normally you have the links. And you see what happens, I automatically converts the file into a absolute path. You can just confirm it by the fact that it always starts with file. If it starts with file, it means that I worked. In case it doesn't work, just retry it until you see file. Then copy the entire thing and paste it into a Twine. So like this, click one equals to this path. Here, this is a track definition. So now Twine knows that the sound called click one is there, and now we are able to use it. 43. Play a Sound! (audio): Two be able to use sounds, go into a passage and just create kind of a Are you ready passage? So we just do this, where we go like, ready like this. And then into the ready passage, we actually insert a message like, welcome. So the macro that you use most of the time is called Track Track column. And don't worry if it doesn't recognize an existing macro, actually, it will work. So then just types space. And first of all, we need to refer to the custom name that we gave to the track. Go here, as you remember, we define this first down as click one. So literally we type inside the quotes, click one. And then coma and we give the command. We just play like this. So we start from here. Okay, ready? Go. Who you here. So that's how easy is to integrated sound. So you're probably wondering why we integrated the sound in the second passage and not in the first. The reason is that if you want to have sound right from the beginning, right from the start of the actual story, you need to use a variant of this macro here type. Play when possible, and now it will also work from the very first passage. So if we go here, we paste the same thing here. It will also be able to play from the beginning. But only as soon as I click anywhere in the passage. You see? So, and the reason is that it's not a limitation of twine, but just a safety things of all the browsers. So the sound will only play after the first click from the user. So you need to kind of make sure that the user clicks the window in any way. And then from here on, you have sound ready to play at any moment. 44. Stop a Sound (audio): Two let me show you one new case. We go here, and we want you, first of all, play the track after we click inside the link. So actually, let's create a custom link. So just call it play Lily. And then inside the link, Lully we place Track. And we call music one, and we make it just play for now. Then let me just also create a second link below here called Stop. So you can guess What we are about to do with this, you are able to stop a track. Use the same exact logic, but just change play with stop. So we're going to click here. Wow. We hear music, revive for a couple seconds. And then we want you to stop it. Stop. Just like this. Pooh So play, stop, are interconnected. And you can also place these functions inside links. 45. Retrigger (audio): If you want you cannot be able to re trigger the sound every time you click on the link repeatedly, you just need to modify, first of all, the link. Just make this link able to be repeated. We're just typing repeat. Link, repeat, just like that. So instead of disappearing, it will stay there. And then before we play the track, we make sure that we stop the track itself in case it was already playing. Copy this, place it above and change with a nice stock. Let me show you. Okay. Now I'm going to repress it multiple times. You see? I'm able to do it all times that I want. So it always restart exactly from the beginning every time I press. So with this always can work wonders where the click sounds. Alright. So it's gonna be kind of a sound button. Alright, go here, right? All the times that I want. 46. Basic Loops (audio): Oh. Okay, now let me show you a little trick to loop the tracks. They will automatically restart as soon as they end. Play this once for now. Suppose that we want this to restart automatically. Well, you tell this track to enable the loop, copy this function. Let's just place it at the bottom like this called Music Tube and we want you modify the loop property. So loop, just enable it by telling True. You know. Infinitely. Until you stop 47. Advanced Loops (audio): Fundamentally, you probably notice that when we loop the sound right now, you hear it? It's gonna insert in a slight gap. So this silent gap that there is between the repetition is not into the sound. It's kind of added by the browser, which is obviously can be annoying if the sound doesn't end with silence. Right, it gets noticeable. The way to have a perfect loop can be to use actually a custom loop intertwine. So we can just do the following. Let me show you. Convert. A link into live. For this to work, you only need to know the actual duration of the file that you want to loop. So that's really important. In this case, we can just check it together. Let's go here. So this is long, about 1 second. Okay, so one as for now. Maybe it's slightly shorter. Then every time this live will play, obviously, it will re trigger the track, stop it to make sure that it doesn't accumulate instances of the same sound. Okay, so stop, play. And fundamentally, that's it. So go here. Actually, you know, just insert into a link. Start. So fundamentally, as soon as we click the link, it will start the live. Which will re trigger the track repeatedly. And thus, it will have more control on the loop. So let me show you. Okay, here it. Less gap. And obviously, you can close it even more. So maybe even faster, 800 milliseconds. Let's try. You know, so this way, it just closes more. If not completely that gap that normally you have, in case you want to override and have more control on the loop, that's the trick to do it. In case you're wondering how to stop this automatic re trigger from playing, stop this live. If check like this, you create a temporary variable. So you give a name, for example, loop one, and when the loop one is falls, it will actually send a stop signal to this live, and it will also a stop signal to the actual track. Alright, so we cannot actually try it. Let's create the initial state, set this true, by default, link. It will stop the entire thing inside the live. Let me just show you play. Eventually we press this. I just stopped the live, and then also the track itself. So that's fundamentally the trick. 48. Fades (audio): You probably notice that when you do this, it goes instantly to zero volume, which can create some kind of cliques, which can be really annoying. Let me show you. You see what happens? There's this kind of click because it goes instantly to zero. To prevent this issue, we need to use something called fade. Fades are fundamentally automations on the volume. So instead of using play, we just use fade in, insert how long it will take to fade in. So this is a value in seconds. Let's also fade this out. So we just change with fade out 0.3 seconds. Try. You see? There is no more instant clicks. There is kind of a ramp into the volume. So let's just try the lower fades, maybe one entire second like this. Let's go. You know, and then it goes out. So it goes in, goes out. 49. Realtime Volume (audio): There is also a way to change the volume of the track without stopping that. Instead of fade out, let's just use fade. And then we just need to specify how long it will take to go to the new value. And then specify which value in volume it will go to. All the volumes go 0-1. Music one will fade to 0.5 in 1 second. Just make it even quieter, maybe 0.25. And also a little faster. Let's right. Okay. Ready? Oh. You seeing? I became choir. So that's the beauty of fade two. 50. Crossfade (audio): Two. Alright, so now I'm going to show you a little more advanced use of the fades. Suppose that we have the character going into trouble, so we want to make the music reflect the fact that the character is about to die or is in heavy damage or goes underwater, something like that. To create that can effect create two versions of the same music track. So I already do it. Here, just make sure that they play exactly the same content, but with a different effect, untouched version. Alright. And then a muffled version. You know, All right. So we're going to create system that alternates these two tracks according to a change of state into the game. I already defined these tracks. One is going to be called normal one, and the other one is called underwater one. Go, Scheer link normal. First of all, prepare the volumes. So we need to make sure the track normal one will have the volume to standard. So just volume one like this. Then at the same time, we make sure that the second track, the second version underwater one has the volume zero. This way, we can just proceed to play both tracks at the same time playing in the same here. But we only hear one, just like this. So that's the first step. Test this. Alright. So we only hear one. Second step is going to be easier because it just create a second link underwater. Inside, we just need to put two fade tube. Track normal one, fade tube, zero in let's say in 0.2 seconds, like this. Then we apply the same command to underwater one. But we obviously bring it to one. So finally, from zero, we bring it back to full volume in 0.2 seconds, like this. And that's why it's important for this technique to work to make both tracks play at the same time from the beginning, even though we hear only one. That way, they will perfectly synchronized. Everything is ready. Let's just go here, test. P here. Normal. Yo. Woof. You hear? Well, let's just also add a click sound so it kind of hide the trick. Click one. Lay. Right, everything's ready. Let's go. Woof. That's the trick. 51. Playlists (audio): As you know, you can already play multiple sounds, but sometimes you may want to organize these sounds in a certain way. Playlist plays the tracks sequentially. So it's kind of like ABCD, EFG. Group plays all the tracks at the same time. So it's pretty useful to layer multiple sounds, make a bigger, fatter sound. Both obviously intertwined, to create a more immersive experience. So let me just show you how to use those. First of all, you need to define playlist or the group anywhere in the passage. So new playlist. You give the name to that container to that playlist. Background music. After you give the name, just list the sounds that you want to include into this playlist. Okay, and then you just need to use the playlist macro. We target the playlist and then just send the command to start playing. You know what? Let's just set a link to be able to re trigger. When it starts playing, it will play all these tracks one after the other, and then it will stop unless we can re trigger it, obviously. So it will always restart from the track one from the beginning like this. Alright, let's go. Okay, just wait that this finishes. You just buy together. You know, I just goes on, goes on for all the tracks, you know, that's the way it works, you know, Until I press this. So every time I press this, the restart the whole playlist. 52. Shuffled Playlists (audio): The shuffle mode rearranges these tracks into a new random order to enable this use playlist, name the playlist, right Lily shuffle. So if you only send this command once, when you play this track, it will start from any of these three randomly and then it will precede to play all the other ones. They will just be rearranged randomly. That's what happens. To make this even more interesting, we just place the shuffle inside the red trigger. So every time we press this, it will play randomly one track. You see? Just like that. So if we leave it playing, obviously, it goes on with a full playlist. But as you can see, in a random order, and it will stop when it plays all the tracks. 53. One-Shot Shuffle (audio): No So, as you can guess, a shuffled, re triggered playlist can be extremely useful for footstep sounds because if you have the character and you have like ten sounds for all the footsteps, you may want to have a behavior where you play every sound randomly, which is exactly something that you can do with this. But actually, in that specific case, maybe we want to avoid something that the playlist does by default, which is the fact that every time it finishes one sound, it continues to play the rest of the playlist, right? To be able to tell the playlist to play only one random sound at a time and then stop. We just need to paste this custom code here. Alright, let me just show you Javascript. Just needs you copy this line here. So make sure that this section here has exactly the name of the playlist. So put background inside this section. So fundamentally, using just a stop followed by this line will make this behavior possible. Okay? Poof. You see? And then just stops, and it will play randomly. Every time we press this button. So that's gonna be extremely useful for step sound. Poof. 54. Groups (audio): Now, let me just show you a way to easily play multiple tracks simultaneously. To do that, we need to use the groups. So just suppose that we have these two tracks here, we have this kind of click, sound, and then we have this second sound. So they just use a group to arrange these two sounds simultaneously. New group, then we give the name Victory. Then we just list all the sounds. So click door just like that. Now this passage is aware of this group, and we can use it. Inside this amazing link. We just place our group Victory. And then use any command ally the same as the track macro. So mute, pause, stop, loop, all the things that normally you can do with a track you can do with a group. Play for now. Poof. You hear both sounds at the same time. Alright. So now you can imagine that this can be extremely useful to create important sounds into the game. 55. Seek (audio): If you want to be able to play a track exactly from a specific position from the beginning of the file, seek command. Just suppose that we want to play from 2 seconds from the beginning. So here we just type 2.5 seconds and then play the track. Like this. Now, it will start from that point and not from the beginning. Let's try. You see? It doesn't start anymore. That's the beauty of the Sk. And to make this even more fun, we just do the following. We make this become a trigger. Instead of using just a fixed value here, we just use a variable, Sk one, and we just set a random value every time we click on the link. So we go here, set seek one, che, random. We use value that goes from zero, let's say, 10,000 milliseconds, which would be 10 seconds, right? And then we just divide the entire thing. By 1,000. So we convert it to seconds. This result will go straight to SQ one and will make this function work, now it should already work. Let's try it. See what is happening? Every time I click, it's randomly going into different spots of the song, which can be really fun to do, especially for musical games. You can create that kind of satisfying glitch into a song. 56. Realtime Monitoring (audio): It is possible to know in real time if a track is playing or not. And consequently, you can trigger some custom events according to that. To do that, you just play this track, first of all, so music one like this. And then into a if we just place another track where we say, I Music one is playing, literally, we can do a custom event. Say is playing elses not playing. You just add another button. Should be able to stop the track. Only like this. Alright. Okay, so right now it's not playing. In fact, we are just silent. But as soon as I play here, of. You see what is happening? Is automatically because it's monitoring the track. And when I stop it, obviously, it returns immediately to is not playing. So now you can guess that according to this, you can make custom events happen only when certain tracks are playing or not. There is also a variant of this, which is called I muted. It's really the same thing, but makes stuff happen only when the track is muted or not. The 57. Global Controls (audio): Sometimes you may want to be absolutely sure that before starting a new track, everything else completely stops. Instead of using just track music one stop, we use Master Audio, and then just use the command top O. I will make sure that completely stops everything before starting new things. Right now, it's just the same as if we use Stop. Or you can use this like a panic button where there are so many tracks going on and once you have a wait, you completely kill all the audio. There's also a variant of this. If you target the group called playing, which is a pregertd group, as you guess, it's going to target only the tracks that are playing at that moment. It will stop only those tracks. So again, same behavior, but fundamentally, these are the two options to stop everything. 58. Format Considerations (audio): Alright, so let's suppose that you finish the game and you are going to publish it. But when you do that, you should do a couple of things regarding the audio. Otherwise, it won't work. So first of all, if the game is going to be downloaded and thus played locally, you are free to use all the formats that you want. So you can use MP three, wave, OGG, probably also Flack unless if the game is going to be played completely online, you need to use only OGG and mp three. To maximize browser compatibility, you need to make sure that you use two versions for every single file. So for example, here for the click file, we have just the mp three version. So actually, that would be an issue in some browsers to make sure that it will completely be compatible, and any system just need to convert a second version of this file into OGG. The full name of this format is g Vorbis, like this. Extension will look like this OGG. Then place the file close to the p three and just here in the definition, add a nice comma, like this. And paste the other path. Obviously, it will finish like this. Ideally, when you are going to publish the game, prepare a double version for every single audio file. 59. Relative Paths (audio): All right. So far, to be able to define the tracks, we have been using the so called absolute paths which indicate where actually the file is into your system. That is good as long as you're just testing the game. When you finally finish the entire game and you're ready to publish it, you need to prepare the files in a slightly different way. Fundamentally, you just need to go into a folder. You just prepare a new folder called Audio, and inside this folder, you need to place all the files that you have been using. After you do this, here you would just play the HTML file that contains the game, and then you pack it, you compress it into a zip file. But before you do this, you need to do one more thing. Back to twine, and then you go outside to the list of all your stories, and you duplicate your story here, duplicate. This way, you can do this change only for the published version of the story. So you go inside the copy of the entire story. You go into the definitions, and you initial to change the paths with relative paths. So the way they look is very simple. You just change all this weird thing with a way simpler path that looks like this, audio then the name of the file. And at the beginning, make sure that you add a dot and a slash like this, these two. And then obviously, it will refer to the audio folder. And fundamentally, what happens is that your files will automatically be referred to the right place, which is exactly into this folder. This way, you'll be able to play audio into the published version of the game. If you don't do this, it will never play. 60. Preloading (audio): When you play the game completely online, you need to give time to the tracks to be downloaded. So if you play too many tracks at once, you may not have enough time to load, and thus the user will just hear no sound. To prevent this issue, you need to use pre loading. By default, all the tracks when you start the game will be pre loaded already, but that will take some time. So actually, when you play the game completely online, at least integrate some kind of loading screen. You cannot force the player to wait, you know, some kind of ten, 15 seconds. So at least 50, 60% of all the tracks have been already pre loaded. And the tracks that get pre loaded by default are all the ones that you define here in this section. So all these ones will be pre loaded by default. Then in case during the game, you cannot define custom groups, custom plates, maybe it's wise to pre load also those into the passage itself. So, in case you define new things, mid game, you need to use this command here. Just type master audio, then preload. That's it. So just putting this into a passage where there is a bunch of new stuff that you are defining like new playlists, new groups, new systems, make sure that you also integrate one of these. This will kind of make sure that the audio will be the most ready as possible. 61. Configurator (audio): If you are wondering if there is a way to hide this weird bar that just appears randomly every time with the volume of the entire master track, the answer is yes. All you need to do to hide it is just create a special passage called al config, and then copy and paste the content that I just prepared in the document with the same name into this section. To hide that bar, it just needs to change. Show control, she falls. Same for this guy here, side bar, start closed, true volume display also on falls like this. So changing these three will automatically be make sure that it will never show again. Wow, just like that. So we don't have that annoying bar ever again. The other controls are pretty simple. Fundamentally, pre load if you place it true, which I recommend, will automatically try to pre load all the predefined tracks when you start the game from here, from this specific passage. Mute blur, as you can guess, it will automatically pause the audio when you go into a different application while there is audio going on into the browser. So just do an example. Right now it's untrue, which means that if we play some music here and we go back in twine. You see what happened? I just automatically. It automatically goes and pause. Whereas, if you want to disable this behavior, just put falls. Then here, you can decide the max possible volume of the entirety of the sounds. As you can see now I said it to choose 0.75, but you can go all the way to one, which means no change. And finally, these numbers define the max amount of time that the game will try to dedicate on the preload of every single track at the beginning of the game, fundamentally. We don't want the game to just get stuck in case the Internet is not fast enough. So we can dedicate a certain amount of time for the pre loading, and in case it fails, it will still go on. So at least the player will still be able to play the game, right? 62. Image Integration: To Alright, so to be able to integrate images and videos into your game, you just need to use some raw HTML code. Spoil alert. You don't need to copy what I'm about to do by hand, but you will find all in my text files of this chapter. So just copy those. There are instructions. Alright, so first of all, let me show you how to integrate an image. So we go into a random passage here. We paste this amazing code here. And the only thing that needs to change the absolute path of your image in your computer with the same check that we saw with the audio files, paste it here between these two codes. That's it. And then just let you test this, right. Poof. That's it. So that's how you display images. With this code, you are able to resize the image automatically by just changing this with percentage. So right now it's 50% of the original size. So if we want this to be bigger, obviously, let's get you 85%. Well, obviously be bigger. That's it. And we'll automatically keep the same ratio and we'll automatically center the image and occupy as much space as possible. So all these behaviors are all integrated into this code. 63. Basic Repositioning: If you are wondering if there is a way to be able to reposition the image with more control, there are two ways. First is just using Harloy methods. So if you break line, obviously, the image will be slightly lower like this, or if you want to have a horizontal disposition of the images, you just make you create two columns like here, comes two or three like this, and then you just past the code here in this space. Number paste. Let's just delete show you how it looks like. Just like this. And then if we preview, obviously, we have the two images close to each other. These are fundamentally the main options that you have within twine itself. All the things that you can do normally for text, you can also do for this code here if you encapsulate it inside one of these macros, same for opacity, et cetera. Most of them work with HTML code like this. 64. Relative Repositioning: If you want to have higher control on the positioning, we can use the CSS. Before doing that, we need to encapsulate our image inside a hook. We create a hook called image one. Alright. Then into the side sheet, you just need to go here, scroll all the way down, paste the code that are prepared the step here. So just copy it and paste it here. Make sure that the name here matches exactly the name of the hook that you want to be with your reposition. Right, so image one, image one. Just by changing these pixel values, it will reposition the layer from its initial position. Vertically or horizontally to make it, for example, go a little lower. Right now, zero, zero obviously does not change. So if we test, it will be just in the default position, right. So is that we want this to go a little on the right and also a little on the bottom like this around here. So if we add 200 pixels on the top and 200 pixels on the left, now if we test, it will indeed be lower end on the right. So that's fundamentally all you know already, should be able to reposition layers even more precisely. 65. Absolute Respositioning: So if you paste the next text file that are prepared for this chapter, you will just notice that there are two differences. This changed with absolute here. Then these two, instead of being a value in pixels, they are a percentage like this. And then there's this final line that makes it all work. So the way the absolute positioning works is that instead of being tweaked from the initial position that you already assigned into the passage, it will actually decide a precise point into the screen. So zero, zero now corresponds to a top left position. So if we play this, see that the image is there. The advantage of the absolute positioning is that it will always be in that position of the screen, no matter which screen, no matter which browser you use. 66. Video Integration: Should be able to play video. You just need to copy the text that I prepared in the document of this chapter again and you paste it here like this. And if we play, as you can see, here we have the absolute path again, so very similar to the images. If we play this passage, we don't see anything. The reason is that video is very similar to audio, so you need to have a previous passage where you at least get a first input and only then we go into the video passage. We finally see our video. Wow. Just like that. To be able to resize the video, I recommend changing these two values width and height. So simply just specify the desired values on how big you want this video container to be. In this way, you have a consistent container where you can seamlessly loop a video or switch the video anytime. Without flickering. It will be really consistent. So let me just test this for now. So now it's going to be 1,000 by 250. And the good thing about this technique is that it's going to automatically avoid stretch. If you make the height 100. In theory, this is not 60 by nine perfectly, but actually it's gonna just compensate it until it will just avoid the stretch. So let's try. Just like that. So that's where you need to know to be sizing the video safely. Obviously, you can reposition it with the same technique with the CSS that I just showed you earlier. And only thing that you can use is to decide whether this video is going to loop automatically like a Jif or play only once. And to do that, you just need to remove this word here. Right now, we have loop here, remove the word. You want only play once, just verify this. Alright we have the guy does a punch and then stops. That's what we want. 67. Video Events: In theory, you could use videos that contain audio, but sometimes they don't play or sometimes they can show some interface that you don't want. To simplify all of this, I recommend using videos that do not contain audio. Instead, manage the audio separately using the library that we just installed in the previous chapter. That way, you have max control on video and audio separately. At that point, the only thing that you should be careful of is to have perfect synchronization. Suppose that you have a video that loops over time, and you want to replay the sound every single time for a lot of times. If you have audio and video separate looping together, there may be some delay that accumulates over time. Maybe the first time is perfectly in sync, but then it progressively gets off. To prevent this from happening, you just need to create some video playing event that we can link to the audio as well. Fundamentally, when the video plays, there is audio and vice versa. So to do that, go here, you integrate the video here, and then inside the same hook, we have also the track macro here, that plays. So right now, let me show you what happens here. If we play from here. We have exactly the punch sound starting exactly when the video starts. So they are extremely tight together, you know? And also, I can reload this See what is happening? Every time I press the again button, it will re run the hook. Let me show you here, just like that. So I stop the audio when I press this link here again, then I just re run the hook. And consequently, it will just replay the audio and video together again, perfectly in sync. 68. Basic Realtime Media Switching: To be able to switch images and videos over time, you just need to build some kind of system that allows you to re target a new image or video and then display that instead of the previous one. The quickest way is to replace the image or the video inside the hook like this. And then now we're going to simulate a target change by just re clicking on this link here. I will change the target string to one and two, and it's going to alternate. At the same time here at the bottom, as you can see, we have a live it is going to monitor very quickly if there is any change at any time into the target variable. And consequently, as you can guess, as soon as the target becomes true, I'm going to replace the content. Image one with the whole code of the new destination. And then when I go back to one, I just replace, again, with the previous image le code. They just test this now here. Alright, so now we see Image one. As soon as a click on Image, like this so I change, you can see the string right now is one for target. When I click on two you see what happens? We just change Image very quickly because this variable here is being monitored over time very quickly. That's the trick. And yeah, as you can guess, it's very reactive. This allows you to switch back and forth between images and videos very quickly. An 69. Key Commands: Alright, so to be able to use keyboard input in Twine, we need to install a new library called mousetrap. Let's just go into the Javascript section here, copy and paste the code of this section document. You just paste all this stuff here, and that's it. Now Twine is able to use keyboard input. The way this works is that fundamentally, we are going to simulate a click. Going into a hook. So it's a two step process. We're going to go into a passage, and we create the first hook jump like this, make sure that it's visible. Inside the hook, we're going to place either a normal link or a repeat link or where we want, actually. As long as something that can be pressed, we're going to use a repeat link for now. We call it just go. Then inside here, we can make where we want happen. So we can change a piece of logic of the game. We can trigger an animation where we want. So in this case, let's just change a variable, set jumps to e plus one. And then let's create a second hook here that's going to display the number inside our shortcut. We're going to replace the content of counters with the new number of jumps that we did. Like this, let me just show you full screen. That's what it looks like. So that's the first part. Then you need to go into the Javascript. We scroll all the way down. For each shortcut that you create, you need to use these lines here. I already prepared to comments so you see exactly where one bind starts and where it ends from here to here. Ends here starts here. So the way it works is that you need to change the name of the hook. It needs to perfectly match the hook that we created. So if you remember, it was called jump. Change this section here. Name equals jump. That's the first thing. Then here we just decide exactly which key is going to be ready to be pressed for that. So we can use the enter. Right. And then here, you can decide if the key is going to trigger the jump hook when you press down or when you release the key, just change key up with key down or vice versa, like this. So for now, keep it like this. Alright. And then go back here, test this passage. So now, in theory, when I press Enter, we should see Wo You see what is happening. Every time I press Enter, right now, we see the number increasing as well, the logic. So that's how you create shortcuts for your keyboard input. It's really the simplest and quicker straight to do that. 70. Avoid Key Repeats: So when you will use this, it will start you notice a certain behavior. When you keep the key down, it will not only trigger the logic every time you press it, but also if you keep the key down, it will keep firing infinitely like this. So in some cases, this may be okay. Machine gun, that may be perfect. But in all the other cases, we may want this to happen only once. So imagine like making literally a character jump, you'd need to make sure that every time you press the key, even if you keep it down, it will only make the jump happen once and then recharge it only when you finally release the key. So let's just see how to implement the ex. First of all, we need to change the link repeat with a link and that's it. So a normal link. And that will already avoid the repeats because obviously, if we keep the key down, doesn't matter. I will only happen once. That's what we want. Then we go back to our Javascript here, and we create a second bind. So we just copy all these guys, create some space, paste. And here, we just change the target of this bind from jump to jump release. And also, we change key down to key up. Just like that. That's all we need to do to fix this. We go back to our passage. We create Lily a new, call it jump, release. And inside this place a nice re run jump. Let's place it into a link, repeat, actually. So we go here, Link, repeat, like this. Fundamentally, what is going to happen now is that every time you press the key? It's going to fire the code only once. So right now I have the key down. And as soon as I release it, it will recharge the jump, finally. So it's just here, which means that then I can finally repeat a new jump. But it will only happen once, even if I keep the key down like now. So that's the key that's the key trick of this. And now it will only happen when I press the key only once. As you can see, just now, a final issue, which is the fact that we have all these weird links that we don't need to see. We can just encapsulate inside a nice opacity, zero. Like this, and they will disappear. And then what I recommend is just to place these key strokes at the very bottom of your code, so they will not interfere in any way with stuff that is happening into the actual game. So that way, we have our counter on the top of the passage and also recommend collapsing the space. Alright. That way we have our counter at the very top completely undisturbed, and that's what we want. Pooh. 71. Tips and Ideas (controls): A little more advanced way to get rid of all these keybns down here is to just shift those using CSS. Encapsulate all the shortcuts inside the giant hook and move that single hook somewhere else completely. That way, even by mistake, the player will not be able to press on those links because right now, those are just invisible. So you need to make sure that those are just completely away. Right. For that, actually, one trick would be to just push them all the way down into the passage like that and then just block the scroll, the do that. You just need to paste a single line of code into the CSS. Talking about this code here. So you scroll all the way down and you paste this guy here. Overflow hidden. This, no matter how long the page is, would prevent the player to scroll down with a wheel. The key minds are extremely powerful. Just with these simple principles, you can build really complex command systems. You can use link repeats, but also something that I recommend is cycling links. If you want to be able to scroll through weapons that player has or items. So you place one cycling link inside a link repeat. And also, this library supports multiple keys at the same time. To do that, Lily just go down here and create one bind for each single key. That way, you will be able to create systems that recognize if you are pressing multiple keys at the same time and thus trigger a specific combo of keys, right? That is really all with this single trick. KeybindHok. 72. Gamepad Input: Alright, so now that you know how to use keyboard input, it's time to show you how to use game pads. I created a mini library called spring. I'm going to give it to you right now. So just copy lily the file that you will see right now and paste it here in the JavaScript. Wow, just like that. So all this text is the gamepad library called spring. The main features of this library are being able to track the state of each single button. So when it goes up and goes down, you can make it become a click and send it to a customer hook, exactly like mantrap. Second feature, you can track the state of the analogs. So the Y axis, and the X become four variables and also the triggers. Finally, you can also trigger the vibration. And not only that, you can also control the intensity of the vibration. So you can already imagine so many things that now you can do, and now let me show you how to use it. 73. Button Up / Down: Before you do anything else, we need to test the game pad if it's working correctly. So make sure that you install the drivers for your system so it will work. And also, remember to turn that on. So just press usually this button here. Ten, now it's actually on. So go into this website here, and if you see the information appearing here, it may be working correctly. So try to move all the buttons, press. Sometimes it will not be calibrated correctly. So as you can see, you may see some slight flickers in these numbers, especially if your controller is old. But for the most part, you see all these numbers reacting correctly. Your controller is pretty much usable for this. Okay, now that we're here, right into the code, scroll down until you read this comment that left button down event. Alright, here works exactly like mousetrap. You just copy the content between these two comments here. And you can recognize that we just need to name a custom hook. This case is going to be called jump. And then the index number. So the index is exactly the number that identifies the button that you need to map. And to extract that number and use it that tool I showed you here. So for example now, for the button A, you can see that B zero reacts means that this is actually the number zero. We can use that as an information for here. Index zero is going to be the button A. He's going to send a click to the hook named jump when we press A down. Let's say that we want to also do this when the A gets released. So well, in that case, let's scroll down here, button up a Bens. And same thing. You can recognize again the same comments here. This is going to be one bind. Index is zero. So A is going to go either to the same hook or jump release. Let's just test this. Jump link. Okay. And then same for the release. So D. Alright, let's just press this. So now when I press, A is going to through click down. When I release it, you should press up. Who. That's how easy it is to map the up and down events through every single button that can be pressed. 74. Analogs and Triggers: Yeah. Before I say anything, let me show you one thing. If we test this passage already, you notice something, there are all these variables already pregenerated. Those are already done by the Javascript. The axis X and Y, these two are the left stick. Axis X two and Y are for the right stick. And finally, the trigger left and right variables are the two triggers when you slowly move them down. So all these six variables usually are already generated by any controller. We always go 0-1. They just print them in real time. Okay. Now these at the top are the two triggers. As you can see, my left trigger is slightly broken, so it just says slight path all the time. But it's fine. Move the right trigger. You see that number moving. That one is the right trigger. That goes 0-1. And it's dynamic. It's not only a switch. Same for the left trigger. Alright, then I'm going to move to the left stick. Okay, so it's X and Y. As you can see, it's extremely reactive. And finally, the right stick. Alright. Just like that. So to recap, these six variables are ready and updated all the time, and you just need to use them if you. 75. Vibration Toggle: To me, were to control vibration, shift the toggle variable, which is pre generated to one or zero. Let me show you. So if you soft lay this where after 1 second, we shift it to one just exactly 200 milliseconds later, we will go back to zero. The result, as you can guess, is you have a short impulse of vibration. So let me show you. You hear it again. So we passes 1 second. The vibration stays for 200 milliseconds and then goes back to zero, all controlled by this single variable, Tuggle. Now, you can just already imagine that. You can create automatic vibrations whenever you are in a dangerous environment. One idea can be to compose some kind of rhythms, combining multiple afters or lives, and then you kind of make them become custom macros. And then you can just use them inside buttons very easily, like this. For example, we create one called short heart beat like this, imagining something like this. And whenever you click the button, it will also trigger that specific rhythm of vibration only like that. 76. Vibration Intensity: Two to be able to control the intensity of the vibration, you need to tweak two variables that are pregenerated, and go 0-1, weak magnitude, and then strong magnitude. These two variables fundamentally needs to stay kind of close to each other according to what you want. So if you want a really precise vibration, as you can see, when I press A down, it's going to go to 0.85 for a week and one too strong, which is the max. Then when I release A, so now we are on jump release, it's going to set weak to 0.45 and strong choose 0.6, which is going to give a lighter vibration. Now let me show you what is happening. We go here, as seen a suppress A. You see what happened? It did a precise vibration, as you can see, A here, 0.80 51, and then I release it. Very light. 0.45 and 06. Now I'm going to land the mic exactly on the controller. Alright. Okay, that was hard. I finally released. As you can see, it's very subtle. I can grant you that even though the weak vibration is weak, let's say, you can still feel it, and that is a new level of expression for your game. That's all you need to do and all you need to know to control the hapti feedback of your game and twine. I know that it's incredible to be able to do this, but now you can. 77. Maximize Math: Alright, so now let me just show you a couple of things that you need to know to maximize your ability to manage numbers. First of all, just create a simple number just this set test 1.75 for now. So let's suppose that you want to have maximum certainty that this number will be rounded to the nearest whole number. All you need to do is just encapsulate this number inside a nice round like this. Now, since we know that the closest number is Q, we should just see Q. Wow. That's the way it works. If we have 1.4, obviously we're closer to one now. Logically, we see only one. And instead, let's suppose that you want to calculate the absolute number, change this with ABS like this. And now it will automatically remove the sin and make it become a absolute number like this. And finally, if you want you know if a number is above or lower than zero, we encapsulate the print into a sine macro like this. So now the test will normally be -2.45. But let me show you. So right now we see minus one. This number, this variable is under zero. If we make this positive, it will become just one. So you can use this to diverge logics in different ways if a number goes above or lower than zero. And another very useful trick is to be able to clamp a range of numbers to a specific floor of your toys. And we want to make sure that we will have only five as max possible. So we have numbers 1-5, and only one will automatically be brought back to five MAX. Test condition. And we say that if test is above five, it will give us obviously five. Whereas, in all the other cases, we will just return itself. So in all the other cases, we know that it would be either five all the way down to one. Just like that. So I can do it all the time I want, but it will always safely be five max. Without this, let me show you what will happen. Be free to go above five. But with this trick, we clamp it down to five max. Now only just go slightly more advanced. Create a crazy number like this. So one to 10,000, divided by one to 10,000. So, in theory, we will start to get numbers with huge decimal points. And we want you to have a system that just displays maybe the first two points after the zero. We encapsulate this entire thing, the entire variable generation inside a nice micro called floor. Alright, so first of all, we insert all this guy inside floor like this. Then we need to multiply it by 100 and then divide it by 100 again, just like that. Let me show you what's happening. Oof. Right now, we have only two positions after the zero max to decide how many decimal points you want. After the zero, you add or remove a zero from these two numbers. So for example, we have 1010, so it's only 10, which means only one position after zero, just like that. You can also simplify this by just changing these two to a temporary variable. So decimals set here decimals to the power of ten. This number here is where we decide how many positions we want to allow the number to have. So right now we will only have one decimal after the zero. Let's check. Just like that. Five positions. Just hit this number to five, like this. Alright. And finally, let me show you how to have battery control on the random net of numbers. So right now, as you can see, you have just a string of random numbers 1-10, appearing into this hook every half a second, just like that. You know, just random numbers, appearing like this. So if you notice every time I test the game, it shows a different string of numbers. So the sequence is always different every time I test. As you can see, the first number is six, then changes again. Always different, right? So in some cases, this may be ideal because it means that all the random numbers of your game will be unique for each single player. Whereas, if you grant a consistent experience to every player, you can generate a so called sed. Just go here and use at the very beginning of your game only once, Seed and then type a string. So let's just call it hello. Now I can grant you that every single time I play this random sequence. As you can see 410, five, six, if I re test again, it will be again the same. In some cases, to make a game that is more fair that doesn't change the difficulty too much over the players, you may use a seed to grant consistency. When idea to grant a unique experience could be to link this seed to the name of the character. 78. Header Footer: The first thing that we need to be able to use to have a cleaner code overall is the header and freer. These two are fundamentally two special passages that will run their content every time you go into a new passage into the game. To do it, you just create two new passages. We don't need to rename those. Just apply a tag header. And then footer to the other one like this. Futer. Inside this shoe, we can just place some code. So, for example, into the header, we place set money, how eight plus one. Inside the footer, we place a print to see the new value like that, place some space, just break line. This shoe will literally be at the very top and at the very bottom of every single passage. So you need to be careful with the spacing. Now just preview test. Alright. So we see number one. Alright, you see what's happening. Every time I go back and forth, the set money code has been re run, and consequently, we see a higher and higher number. So you can re imagine all the ways this can be used. Fundamentally, allows you should automate redundant code, place it in a cleaner way, and that may be one way to incorporate 79. Initial Conditions: There is a way you set the initial conditions of your game. No matter which passage you start from, create a new passage and tag it as startup like this. When you give the stab to multiple passages, even, those codes will be run at the very beginning of your game when you started. So this can be extremely useful for debugging sessions. So you can just set custom conditions directly from a passage like this and test directly from a passage that initial debug. Set energy 0100. And now, if we preview from room one, you can see that we have Energy Set 100 and saying, what happened if we preview from Intro. Let's try it. Again, that's because the startup is being run at the very beginning. 80. Bypass Code & Comments: Instead of deleting that or just placing it in a separate passage that you don't use, one way is to just bypass it using the Ignore macro. So you go here, Ignore, and then inside these square brackets, we place the code that we need to bypass. That way, when you run that passage, it will completely ignore it. So as you can see, no setting here. And that's it. Instead, sometimes when you build really complex systems, you may be able to take notes just to remember what they do, right, because you may lose track. So to do it, go where you want into the passage. Click this button here. And then you can just take notes. This thus X, Y, and Z. So you can type entire paragraphs of what that specific section of code does 81. Spreading: Fundamentally, right now, we have just an array defined as test that contains the first seven letters of the alphabet, just like that. If we want to print a random letter of this array, as you can guess, we can use either. But then, how do we tell the either to consider every single value of this individually? Well, place three dots at the beginning of the variable like this. These three dots are called spreader spread the array into individual values. Consequently, now it will work. Let me show you. We, you know, we see the behavior that we want. So we're printing any of those letters randomly. And now let's just go slightly more complex. Let's just instead use a custom index. Go here, set a second variable called index, choo a random number for now. Just like that. One, two, seven. Alright. Then instead of the either, we change it with a new macro called Nth like this. And at the beginning, we just place the index, and then the spreaded array just like this. What is going to happen now is that we fundamentally have the same exact behavior as just using either. Let me just show you. With the difference that we have now, the ability to use a custom controllable index. So this is going to be extremely useful when you want to control actually with more precision, the index. So here, imagine that you set a variable as an index source. That way, you will fundamentally be able to diverge entire sentences or statistics directly into specific spots very easily with the system. 82. For Loops: Okay, now that you're able to spread values one after the other from an array, I'm going to show you how to process every single value into an array individually. So let's just suppose that we have, again, variable here. Let's call it pocket to array, say that we want to halve all these numbers individually and then bring it back into pocket. Well, to do that, create a temporary array. Set pocket two, two, an empty array for now, just like that. We use the new macro called four. And the way it works is that we need to create a temporary variable that is going to be used as an index for each index. And here we just spread the original array. So just pocket like that. What we just wrote means through each value into pocket inside the square bracket so we can do wherever we want. So we can print each value individually. For example, just say, This is your lucky number, and then we just bring the index like this. Welly print for each single value this sentence with each value of the array, just like that. That's the simplest use of this. But let's suppose that we were to change the value. We lowly set a new array, pocket two, which originally was empty, two itself plus a new array containing index divided by two. So what is going to happen is that now for each single value into the original pocket, we are going to divide each of those by two and bring those back into pocket two. And finally, we can just set pocket one, pocket two. So bring it back the values into pocket one. And finally, we can just print the entire thing. We're going to see these values divided by. Oof. As you can see now, we are seeing the new pocket one after we looped each single value to be divided by two. 83. Sandboxing: Sometimes you may need to have the ability to test new code ideas before implementing those into the actual game. One way to do it locally is just dedicate in passage to that. So you can call the ten box, you test all your things, and finally implement it into the actual passages. But sometimes this will not be possible because it will go into conflict with CSS or the Javascript. So you can just dedicate the entire project to the sandbox, so you can go out here. And vindicate here just a project like this. That way, it will not interfere with your main project. But one thing that may be a little confusion on you, maybe the fact that after you finish your test, you may need to have a way to copy the code that finally working into the game. So, in theory, you will need to copy it from here, then go back to the list, enter again the game, and finally paste the code here, which is not the best process, right? So one way to avoid this process of going back and forth is to just open a completely separate instance of twine. To do it, at least in Windows, you just need to open the Sort menu and literally reopen Twine a second time, like this. And after a few seconds. So now I have to open independently. When you do this, be careful to not open the same project in both versions. Right now, I have tell one, open here, but here I can open any other projects, so I can open the sandbox project here. Now I can just cope and paste We code I have here, into the actual project all the way 84. Maximize Conditions: If you want to make your if conditions more intricate, one thing that you can do is you add more checks before actually delivering the result. So right now we have money being set one, and it will give us the result bingo if it's greater than zero. So let's just add a new condition, which is going to be mandatory. We just type and is lower than 1.5. So now it will just give us bingo only when it's greater than zero, but also lower than 1.5. Now we see bingo because it's one. As soon it's going to be two, we won't see it anymore because it is true that two is greater than zero, but it's not true that's lower than 1.5. That's the way it. Then if you instead have multiple conditions, but only one of them is going to be sufficient change with or. So now, if we satisfy any of these two, we will immediately see this regardless, Bingo because it's satisfying at least one of those. And you can specify as many as you want. You can even check all variables, not necessarily this all in the same then just suppose that money instead is a string, and we want to trigger bingo, only if a specific character or specific word is contained into that string to scan it automatically. We can just use contains. And here we just type whatever will trigger the result. So it can be even a single character or an entire word. If this string contains even just a H, it will trigger the result. Wow. As soon as they change it to a character that doesn't exist into the string, for example, Z, we won't see Bingo anymore because now it's scanning the entire thing for any matches. It contains works very well also with arrays. So let's just suppose that money was actually an array. As soon as it change contains into something that will match fully one of the elements of this array, it will trigger, again Bingo. So let's just try with the number one. So if money contains one into this array, it will trigger Bingo. Let's try. Okay, and one more if it contains Pacman, again, we will see Bingo. 85. Number to String and Viceversa: No sometimes you may need to convert a number variable to a string variable. There are some macros that you can only use if a variable is a string like this, substring, which can be extremely useful to trim a specific string from a specific spot. Or also trim. To be able to do this, set a first variable, Moni to one, to convert it to a string, set again, many it. But then we encapsulate the it inside SDR. So what happens is that we will see Moni be a number first, and after the seconds, it will become a string instead. That's right. Alright, one, two, three. Alright, poof, just like that. Now became a string. And you can also do the other way around. So if this was a string first, we can make it become a number in order to be able to use some math on that, right? Just change STR with Num. So now what happen the opposite. So we just go here. So now is a string and then becomes a number. Poof. 86. Cloning Referencing: Now let me show you something really interesting. If we create a new variable called energy and we set it to 100, then if we create a second variable called target, we can clone the values of energy automatically just by doing set target to energy itself. If we print target, it will show the value of energy. Just like that. So 100. But you need to remember one thing. When you do this, when you clone a variable, there will be two separate things. As you can see now we have target energy, both having 100, which means that if we do any subsequent change to energy after the cloning, for example, 50, if we print target, target will still be with the older value. So right now we still see 100 because target has not been updated, whereas energy did, as you can see, they have now two different values. The secret trick to be able to still make Target aware of the changes that we do to energy, even after the cloning is just this encapsulate full name of the source between two codes, just like this. So target now became the string energy with $1. And consequently, when we do subsequent changes to energy, so it became 50 now and we print target, let me show you what happened. Wow. Now we see 50, which is the updated value of energy. Let me show you here. Target in theory, never became a number. It just became the reference, the direct link to energy. Just with a trick you can do amazing things. For example, you can use it for bank systems where you can do complex arrays that contain multiple values and then reference to all those banks with a single variable they can call target or active target. This will spare thousands of lines of code because you can just compress complex things with this simple solution. And finally, you can use print to do direct changes to energy. We just encapsulate set energy to 50 inside a print like this, and then we change energy to target like this. And then we encapsulate anything that is not a variable inside quotes, just like this. So this, this becomes quotes, also the parenthesis, right? And also, we need to make sure that we have the spaces too. So this will have a space, right. Just like that. And then between all these elements, we need to put a plus, plus plus plus. So now what is going to happen is that we are going to change directly the actual value of energy, just using the placeholder name, which is target because this ideally in a real game is going to be a relative thing. This is going to be one solution to change the actual source values of the important valuable. Let me show you what just happened. Energy now 50, and we did it directly from the print using target. So target now represents energy directly. So it's not just a clone, but a direct link to energy. And you can change source values of a variable just with this technique. 87. Custom Macros: Let's suppose that this is something that we reuse multiple times, maybe too many times into the game. So we want you to compress it into a single word. To do it, we need to use something called custom macros. Set, clamper, two macro. Be careful because now we are going to see a lot of parentheses, create two parentheses. Inside, we type out to data like this. Then inside here, we just place tube square brackets. Then you go outside this first parenthesis and you type two more square brackets. Alright. Guess what? Now, inside here, you can place wherever you want to compress into this single word Lc. Let me show you full screen, and the way is just this. You type two parenss, type the name of the castm macro. Just like this. So, fundamentally, this here represents this for the rest of the game. So to use it, use this instead of that. So imagine using this on very big chunks of code that will be likely like this, right? Very bigger. So set test 1,000. We call our clamper after the test, like this. So now if we print test, it should be 100 because the clamper now is working. So let's just go here. Print test. Woof that's it. 88. Typewriter: So let me show you how to have the typewriter effect twine. Copy the document that it's called typewriter and paste all this code here. As you can see, I left some comments, you fully understand how it works. You can change the style of the entire thing from here. So right now it's going to be none, but you can take with blur or wherever you want. Let's go full screen. Let me show you what is happening here. The content of this typewriter needs to be changed from here. Your custom text goes between these two codes just like that. Let me just preview this. So it's typing this. You can also notice that the speed of typing is not just flat. There is a slight variation on the speed of each single character. That's something that I placed on purpose in this algorithm. If you go all the way down here, there's a comment per character granular speed. Here. These numbers are literally the speed of each single character. Right now, it goes from one millisecond to 60. Well, you can change it. You have a slower effect. For example, 100 to 200 milliseconds, maybe 50, it will get obviously a slower typing. Overall, one final feature of all of this is that if we go all the way down to the bottom of this, you see another comment, insert post typing event here. That's going to be really powerful because if you insert wherever you want into this space, you will be able to make something happen only when this typing is done. So exactly after it's done, let's just say that we show a hook. Outside of all of this, we place a hook. So here, hook one, and then we say finished. So now if we preview this we will see finished only when it's done. You see what had just happened? So that's the beauty of all of this. And obviously, as you can see, this is very big as a code, so you can just compress it into a custom macro now that you know how to do it, you can really copy all of this and compress it into a single word. And if you're wondering how to change then the content dynamically, you can indeed do it just by using a data map or TH. Where we want? Just change it here. So set typewriter text to a second variable so that we will use as an index, right? So it can be, let's say, text, index, for example, of, and then here, you just create your data map with pairs of values. That's one solution to make this dynamic. Or you can use NTH as I said, NTH, that's the solution. So there is literally no limit. 89. Display (custom macros 2): A valid alternative to using custom macros, C just dedicate a passage to the typewriter. We call it lik test. Cut and paste it into the typewriter, and then you can, first of all, free your main passage from old up chunk of code. You can still use the typewriter into this passage, using a fantastic macro called display type display. And then name exactly the passage that you want to host into this passage, and it will automatically trigger its code. Just with this trick, it will really be the same as if the code was here in the first place. Let me show. Just like that. You can become even more powerful by just making this become a variable, so you can ly use the same display, maybe inside a nice hook like this. So then you can re run it with this variable updated with a new name and Lully reuse it as many times as you want, to display different passages. By combining custom macros with display, you can have a cleaner code overall, obviously. 90. Make a Timer!: What happens sometimes that you need to be able to measure absolute time into your game or really display some kind of timer in real time. To do that, we need to have some kind of clock that is going to just accumulate numbers over time. First of all, we're going to call it raw time. Just go here. Raw time, chew eight plus one. And then we place this inside the noise live. In theory, this will ultimately be 1 second. So that's going to be the clock. But just for now, let's just make it very fast so we can experiment very fast with this. So let's just encapsulate all of this inside a live. So the first thing that is going to happen is that time, the raw time is going to increase. Then let's also create variables, one for the seconds and one for the minutes. Set seconds, two, raw time. And then the following is the new operations called modulo just like that. Modulo 60. So when you use the module fundamentally, you're going to constrain that number into that range, which means that even if this number increases above 60, then it's going to automatically restart 0-59. That's the trick. You rescale automatically a accumulating number into a specific range that you want. That's exactly the behavior that we want for the second. So it's going to go 0-59. Then we just create the minutes. The minutes fundamentally, are going to have the same behavior. We call the new variable minutes. Tho. This time we use raw time divided by 60 a every 60 seconds, we're going to create a minute. But then to prevent issues, obviously, we need to round this number. We encapsulate this division inside a nice floor. Just look at this, right. And then we just need to print already minutes plus seconds. We just convert these two strings, and now we will be able to have some space to fully understand what is happening. Alright. So we see the seconds going exactly as they should, and it's counting the minutes. Then if you want to go slightly more than, you can do the following. Let me show you one thing. If you see right now, when we are under ten, we have only one character, and that creates a slight shift back and forth into the whole thing, which can be annoying, right. To use a way to fix this by using a technique called mono spacing. Change, first of all, inside the print the name of these two variables by adding a two. So minutes two and seconds. Then we create some space here, and we insert an additional check set seconds he condition. If seconds is lower than ten, so it has only one character, we convert it to a string. So SDR and here inside the quotes, we just type zero and the variable itself. So seconds, just like that. Whereas, in all your other cases, seconds, then we copy the entire thing and we can apply the same thing to minutes, alright? Now, in theory, we should have the timer perfectly mono spaced. Let's try. Poof. You see? No jump. 91. Save Load Progress: To if you want to be able to save and load previous states of your game, use this new macro called save game. So we just create a new button. Inside, we use save game. And here you just need to specify one or two things. First of all, the name of the slot can be either the player name or just a letter like this or a number where you want. So just call it player one. So you can just use it like that. Or you can specify second string with a contextual indication of where in the game you saved. So for example, we are in the first one, and then we create a second button to load to that spot later in the game. So we just change the macro to load, also the button, and we remove this. So we just want to load that slot. In the other passage, I placed a final macro here, saved games, which will print automatically all the currently used slots with their own names. So you can consult which lots are free, which lots are being used. You can save as many lots as you want. The only limit is the browser memory. Go here, test. Okay, so now we have this number one. We have all these lots being used. Number two, let's just make this increase. So for example, now we save. We save while money is on three, and also we did five turns, which means that we went back and forth five times already. So save. Then we just go on with our game. As you can see, there is already our slot being used player one is being saved with forest one already. Alright, so then we go on, we go on until we want you to restore a previous state of the game. All we need to do is just press load and instantly we go back to three, and the terms went back to five. So the slot will also remember the exact number of times we visited every single passage. So it's really precise. Be careful because if you clean the cookies of your browser, you will lose also all the saves slots that you did. This is not true in case you release the game completely offline. So in that case, you're safe, but be careful in case you play it completely online. And finally, something that I highly recommend is to actually integrate a double check that confirms to the player actually saved successfully because there are specific cases where something might go wrong and the browser may have issues saving the game. So in that case, we want the player to know about this incident. So to do it, just integrate the save into a if like this, place Lully all of this into a if condition. As a result, in case it will correctly save the game, we just display some confirmation message saved. Else, we will bring back error message. So Lully just type, Oh, no. I highly recommend you always integrate the saves into some kind of if like this. So now if we test and we save. Wow, in this case, you just brought back a nice true, which means that correctly saved. So now if we go back here, we have still play one being saved correctly, and that's it. 92. Musical Stingers: Alright, so let's talk about audio stingers. Fundamentally, when you play a first track in twine like this, let's just call it track A. And then you want to transition into a full a next track because maybe something changed into the game and you want to kind of emphasize the fact that you entered into a different state into the game. We want to trigger immediately a different track. Let's just call it track B like this. Normally, as you can see, there is an instant change because you don't have any way to transition smoothly. Yeah, you can use some kind of cross fades to make it slightly smoother, but it will never be exactly as smooth as you want, unless you use something called stingers. Stingers are exactly a piece of audio that you play simultaneously around the end of track A like this in order to have a smoother transition into Track B. So that's exactly where you just incorporate the stinger. As soon as you know that we're going to enter into track B, we start to trigger the stinger that's going to play at the same time. Now, there are two main types of stingers. There are non musical ones and musical ones. The non musical stingers are pretty easy to integrate. You just need to integrate some kind of oh sound around the time you trigger the switch to go to track B, and it can be anything you want. It can be like a shooh sound or a click sound or in some kind of noise that is going to emphasize the fact that we are going to enter into a next state into the game. That's pretty easy to do. It's very different instead if we want to make the stinger actually musically on time with the song. If you learn how to do this, you can do whatever you want to make your experience extremely more interesting. So the first step to make this possible is to prepare the loops. So you need to prepare the main loop and the stinger. These two need to start exactly at the beginning of the bar of the music bar. 90% of the music goes in four beats per bar. So it goes like this. One, two, three, four, one, two, three, four, all the time, like this. Fundamentally, we want the loops to start exactly on the one. So we need the audio to start immediately like this on the one. That's really important. Second thing is that the main loop doesn't need to be extremely long. So, ideally, 30 to 40 seconds is the sweet spot. Try to make it as short as possible so you can just re trigger it. So you don't need to make it 30 minutes long. Otherwise, the system will start to go all over the place. Let's just here, first of all, the main loop that we're going to then integrate the stinger on. Alright, and then restart. So now, let me just listen this stinger. Solo, let's go. Alright, one more time. Let's go. So you have an idea of what we're going to do. We're going to integrate a system that will trigger this piece of audio, not only when we want, but also exactly in time with one of the bars of this main track. So it will not start randomly. It will not interrupt the main track all of a sudden. It will only do the transition on time with the bar. Next step is to calculate exactly the length of one beat of the song of the loop. If you already know some softwares like QBs or Ableton Live FL Studio, you already know how to do this. But in case you don't, you can just use this tool here called tune bat.com Lyser Dragon drop the loop into the space here. Just wait a couple of seconds, and it will instantly tell you the BPM of that loop. So I know that personally, when I created this loop was in 180 BPM, so I'm going to use that. But as long as it gives you an even number like this, which is exactly one half. In this case, 90. It's perfect. So you can just use that or double that in case you want a faster measure. But fundamentally, that's the easiest way to do this. With this knowledge down, we need to calculate the absolute length of one single beat. In this case, I know that I did the loop in 100 BPM, which means that 60 seconds are in 1 minute. We can just divide 60 by BPM that you see, 180, and we obtain the absolute length and seconds of one single beat. This number is extremely important to make this system work. Copy the first ten digits so one, three, nine, ten. There are going to be enough. Okay, first of all, just create a noise button called play. And here we play the main track. So just track. We know this at this point. Main loop, play when possible. Then immediately after we start to make the musical clock start with the main track together. So immediately after we start a nice live. And here, we're going to use the number that we calculated. If you remember, it was 0.10 three, so seconds. Really important. This is the length of one single beat. So it's going to do one, two, three, four, one, two, three, four. We can use a modulo operator. Set beats 28 plus one. Do two more parentheses like this. Here, just outside, we place a nice moduFour. So we're going to have four numbers. That's exactly what we want. And finally, let's just offset it. We create a second variable, set beat two beats plus one. Just to display exactly one, two, three, four, but on efficiency point of view, you can just avoid this step, but to make it more clear for now, let's just offset it. Alright, now just to verify what we have, print, beat two, see what it has so far. Ready? Go. You see what is happening? This number here is exactly on time, song. Why don't you? Why don't you? Why don't you in four? Exactly on time. Keep going. Keep going. So as you can guess, we can use the fact that now Twine is perfectly aware of the time of the song to trigger, to synchronize perfectly another piece of audio to transition away from this music. That's the beauty of the musical singers, and now we are ready for step number two. The best way to integrate the stinger now is to kind of create, first of all, a nice button. So just here, and we make the main track fade out like this in about, let's say, 0.5 seconds, all the way to zero, like this. That's the thing. Immediately after we get a trigger the stinger called stinger one play like that. Right now, is going to interrupt the song randomly. So this is not what we want. To make the stinger enter exactly at the beginning of any bar of the main loop, we just need to trigger it exactly when beat two is on one. That's the way. So to make a system that automatically waits for that number to come, use an event. So we just go here. When Bs is one, so exactly the beginning of a new bar, we trigger this event like this. When we press, we will only tell the event to start being aware and just wait then automatically for the one to come, and only then it will automatically make this event occur. Let me show you what we have so far. Alright, plate. Now I'm gonna press end. Be careful. Alright, right, right. We're starting getting there. But, first of all, to make it more satisfying, we can layer an additional sound at the exact time we press. So exactly when we click, we want some clicks to layer and hide even more the transition. So we just use Click and also door. Try now. Ready? Go. Did you notice that? When I click, it also triggered an additional sound to hide the transition. Let's do it again. No oh Alright. Alright. You probably notice that there's still one issue. If I accidentally press and when it's already on one, it will kind of still interrupt the song. So we want you add an additional check to make sure that it will only trigger when one is not even entered. So to do it, insert fundamentally the first event inside another event that's going to wait for the number four this time. Like this, we just add a new square bracket, so it's two dance inside each other. This way, make sure that it will trigger one when it's fresh and not when already it's started. Now, fundamentally, even if I click and while it displays one, it will wait the entire rest of the bar to trigger the stinger. So let's just add a comment here. This prevents triggering on mid one. That's what it does. Now just test with all these fixes. Now I'm going to press it on one on purpose to show you that it will still not interrupt the song, but it will wait the rest of the bar before entering into the stinger. Let me show you. You see what happened? Alright. You know. And you can make this even better by just layering an additional sound when the actual stinger triggers. Alright. Yeah, this is my present for you. Norbalytwine, would not be possible to do this in the slightest. But now you know how to do it. Who 93. Monitor Changes (typing sound system): Alright, so let me show you something else that is interesting. Suppose that we have this input box here. And we want you to have a way to assign keyboard sounds whenever we click any key in the keyboard. Right. So right now it's completely silent which is boring. So let's just make it more live using sound. The first step is to prepare multiple sounds that are very short. These are 16 variations of the same type of sound. Let me just play them once in sequence. Let's go. Alright, one more time. A. So these are the 16 sounds that we're going to integrate into our game. So, in theory, one way to pull this off is to obviously install both the audio library Hall audio and mousetrap. So that's down already into the Javascript. And create one bind for every single possible key stroke and then link those to a sound into an event, into a hook. But that, as you can hear, can be really time consuming. And also doesn't solve this issue that if we use the Harwey input box, it will kind of bypass temporarily the input read by mousetrap. So even by doing that, it will still not be able to trigger the hooks that are linked with mousetrap. So we need to use a different approach. The way to solve this issue is the fact that when we type anything here, do you notice here what is happening? The variable sentence is changing as soon as we type anything. So it's changing. We can use this to our advantage. Build a system that triggers sounds whenever this variable changes. The first step is past some kind of clock that is going to monitor the sentence variable at any time. Hesen here, spend, as you can see, every 0.15 seconds. We're going to set sentence two to sentence. So we are literally cloning sentence to a copy of itself. This acts as a monitor. This number here changes according to which use you're going to do to this system. For typing sounds very fast, short sounds, 0.15 is the sweet spot that I personally found. But obviously, tweak this to your liking when you're using this for steps, sounds, for example, or similar situations. The consequence is that now with this in place, whenever we type something new. We're going to have a clone of sentence here that just follows along, but only with a slight delay. Sentence is slightly slower. Thanks to this, we can literally know now when sentence changed compared to a slightly previous version of itself. For the second step, in copy exactly the content of this hook here. Type sound. So just freeze this frame, copy exactly what you see here. The way it works is that you will see just an event, first of all, which is monitoring whenever sentence becomes different than sentence. That's really what it means. It's not mat means that whenever sentence you becomes different. So it's not the same anymore, trigger the content of this event, which is, as you can recognize just the one shot trick, you play a random sound from the playlist cded typewriter here, which I just defined already into the preloads. Here, let me show you have here the definition of the playlist when we start typewriter. I just contains already the 16 sounds that I already defined even here in the whole track passage. We already know hold this up at this point. And also, I set the volume for typewriter here, 0.6. Then I said, let's go back to the main passage. Then finally, the final trick is to re run this hook, so it will recharge the event and will immediately come back online to be aware again of any further key presses that we do. You know, some final tip, which you place this rerun inside a slight delay. Cause fundamentally, this final trick allows you to filter away some extra re triggers that may be annoying. And that way, the playback will become very clean and accurate. Now let me just show you the final result. So we play All right. So you can see, it's extremely precise now. That's the beauty of this. Whoo. 94. Final Export Considerations: Alright, so let's suppose that your game is finally ready to be released. When that moment comes, you need to decide in which form you release the game. There are two main paths. You either release the game fully online like this online or fully offline. The main difference between these two is that if you go fully online, your game will fully be represented by a link that people will just access to and then run the game from the browser itself. Whereas, if you go fully offline, will be more like a steam game that people download fully into their own machine. And then run locally into the machine itself. So just look like a file that they execute locally using the actual performance of their machine. Generally, I recommend going offline because it gives you the most reactive experience. So you don't have absolutely no issue with playback of medias, images, videos, audios all at the same time. You can go really crazy with action elements, no issue at all. Whereas, if you go online for that type of game, that's going to take a little longer because you don't know if people are going to have issues with their Internet. If your game has many medias and you are forced to go fully online, well, in that case, stretch you optimize your game as much as possible. So make the files as small as possible so they can be downloaded with less data in all devices you play this from. The reason why I prefer generally offline is that actually, it makes the fact that people download the, the executable file local little more personal experience. That's going to be a consideration that you need to take account for. Whereas, if they just have a link, they still stay in the browser. They may get distracted. So if you want the game to be the most reactive and immersive as possible, go offline. 95. Preparing the Game: Export the game practically. Before we do it, let's just explore these three passages. I just prepare the mini demo that contains text and audio at the same time. Alright. So, you see that this set to be closer to a real project. So regardless of whether you're going to release this as a offline file or as fully online, you need to change all your media references with relative paths. Right. So if you explored the chapter about audio, you already know about this, right? But in case you skip that, let me just show you what I mean. In case you use videos, audio files with absolute path like this, you need to absolutely change all these guys with relative PADs. For example, for this file here, click it changes from this format like this to a way simpler format that start with a dot and reverse slash, and then it becomes like this. Audio slash, and then the name of the actual file. That's what a relative path looks like, and you need to do the step for all your medias that you're using, whether those are videos, audios, images, all of them need to be into a simple folder called audio video Images. So that's the first thing. Use relative paths before you export. And then you just go outside of here to the list of all the stories, and you just export, you publish your game here, build and then publish to file. And here, it will just convert this game into a TML file. That's fundamentally the whole game compressed into a single file. Then you just go into a specific folder that you choose, and you place the STML into that folder. Then create three folders according to any media that you use. And you place all the files that you use into these folders. Be careful on using P threes and OGGs for audio, JPEGs for images, and then MP fours for videos. That's all you need to use. 96. Exporting Online Versions: To. In case you want the game to be available fully online, you need to rename the HTML to just index like this. When you're done with this, so you have all the medias here, the format, you change the paths, your relatives. You need to just compress index and all the folders medias into a zip file. So just right click, use any program that creates zips. Make sure that it's going to be a zip file. Like this, and then compress it. This is the file that we're going to upload into a specific site called HIO. So let me just show you. Completely free website, create an account, here HIO, go into your dashboard and create a new product. Create. We give a name, for example, Adventure one. The most important things are the following. You go here kind of project. You choose what is going to be in this case, it's going to be HTML file. So we do this, and then you select if you want to be paid or it's going to be a free game, whatever you want. For now, just go all the way here, upload files. Double click on the zip file like this. Then you choose all the other things. It's going to be playable from the browser. Then we go all the way down here. We want the game to be fully in full screen. We can check mobile friendly, even though it will probably break, at least it will make it slightly visible from mobile. You go all the way down. You can fill all the details, skip all these parts for now. And finally, just the privacy sections. If you want this game to be just unlisted or fully public, all the things that you want. So if you want to just test it, go here, save. Okay. And then we are ready to test it. So we go here, run. That's it. As you probably noticed, in the first couple of seconds when we started the game, it was still using the default phone and the audio didn't start immediately. That's because the pre loading was occurring. That's why if you release the game online, incorporate some kind of loading screen. So you can force the player to wait some seconds with a loading bar. And that way, in the background, the game will load all the medias and all the phones as well. That would be the way to avoid that mini bug at the beginning. Try to optimize the sizes of all the medias as much as possible. Where you will have a very fast pre loading and will be compatible with 99% of all the devices. 97. Import Fonts: If you wonder if there is a way to automatically use the font that you want in the fully online version, the answer is yes. To do it, add this line here into our CSS. Copy and paste this code here. That's it. Fundamentally, what this does is just calling the API of Google phones and just allows you to use any phones from that website, change this section with exactly the name of the font. So you go into Google phone. You search any phone that I want to use. So in this case, I chose this one pixel $0.05, copy the name from here and you paste it into this section here and serve the same exact name second time here into font family like that. When you start the game online, it will also download and display the actual custom font. That's why in the very first second, it was still using the default, then it downloaded and immediately refreshed the whole story text with the appropriate phone. You can also use multiple phones as well. That's your choice. 98. Exporting Offline Versions: If you want your game to be available offline, well, the easiest way would be to lily leave your index file like this, where you can just rename it at that point, deliver this as a zip file that contains the raw folders. But actually, the disadvantage of this is that people will be you can see all the contents directly from these source folders. But in theory, you could just deliver this where people just start this file and it will run from the browser like this. So as you can see it's there working correctly. So that will be the first super quick option. Then if you want to kind of make these folders in a different format that people would not be able to access that easily, you can just use a so called wrapper. This is an application for Windows, but there are also some other ones for Mac that do the same thing. It's called HTML wrapper. This is called WebTEecutable. Don't load it, and then go into a nice sandbox here and install it. Like this, skip all the steps. You will start it from here. So the way it works, click here, Bros. Select the folder that contains the whole game. Not compressed. Select folder. Alright, then let's go full screen. Leave most of these things by default, but this will allow you to customize in detail how the final executable five will look like. So you can assign your custom images for the icon, as you can see here. But if you want you to stay simple, go here window settings, classic things. Like, you want the game to be recizable window or go in full screen automatically. Maybe, yeah, we want the game to be recizable. We go here and to export settings you choose how many operative systems this single build will be compatible to. So maybe you want a single file for any system. So you just check all these boxes. Obviously, the more checks you enable, the bigger will be the file. So maybe you want to do a separate expert per operative system. So in this case, you just want Windows 64, and that's it. Then here you can double check all the medias, as you can see they're correctly being detected. Then you can choose Yput folder. So let's just say that I will go into the desktop. Final, just like that. Select folder. Alright. You can attempt to reduce the size by increasing the slider, but for now, let's just keep it on zero, so we have a really fast export. And finally, you can just confirm all of this. So you go all the way here and export. The first time you will do this, it will take a slightly longer because it will kind of download some additional features to be able to do this in the first place. But then, from the second export on, it will be instant. As you can see, I already download it, so it's already done. So then we just check what we have. Alright, we go here. Final, we have, again, the same folder that contains the build for Windows 64. Poof. Alright. And the file itself is this guy here, game that you can also rename Adventure one. And again, you can customize the behavior of this file when people double click and customize the icon, et cetera. So let's just start this. Poof. Alright. So, as you can see, we can move our game full screen. It is all there reactive, super reactive, ready? Just like that. Yeah. Alright. And in case people go like this, as you can see the audio poses, so it goes automatically in pose, as we know, we can change that behavior as well. And that's it. There are also different wrappers that do this process in a slightly different way. But this is kind of an easy to access solution. Here, there is no way to access the actual medias. So your actual files are actually slightly more protected. Who