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