Transcripts
1. Course Introduction: Hello, and welcome to
the Got to boot camp. I'm Mike Maguire, and I'll be your instructor
throughout this course. In our first video here, we're going to go
over everything that we're going to cover
throughout this course, which is mainly
going to be around game development within
the GoTo game engine. However, we are also
going to tackle a bit of software development where you'll be creating your
own desktop applications, as well as branching
into things like APIs and websites and have everything communicate across
with each other. And all of these things
can always be loop back and used within games itself, so we can still
consider everything part of game development
at the end of the day. Let's take a look
at the overview of the Goto game engine. Well, Goto is a powerful and versatile
game engine that offers a wide range of features and tools that are very useful
for game development. Now, one example of this is something like cloth
physics, for example. Let's say you wanted to
make a cape on a character. In Goto, you could have that
set up in about a minute, whereas in other engines, it would take a lot longer just to get the cloth
physics and that working. So that's one benefit that
we would have if we were to be creating a three D game that involves
things like cloaks, capes and anything else
that needs cloth physics. It is an open source engine, which means it is
great to use and has a large community of developers contributing
to its growth. Now, I emphasize
the free portion because some people say
that unity is free, and at least at the current
time, it's not free. There is a personal version that you're allowed
to use up until a certain point once you have a certain amount
of revenue or if you want certain features, you would then have to pay. So I wouldn't consider
Unity free completely, and other engines that people
consider, such as unreal. They do take a portion
of your royalty, so though you're
not paying upfront, you are paying in the long run. And then we have
other engines like GameMaker that are I believe they're on a
subscription basis now. So GOTO is completely free
from beginning to end. You never have to
pay for anything. GOTO also supports both two D and three D game development. Which, of course,
makes it suitable for a wide range of projects. It's not going to limit you in what you can do or make
things extremely difficult, for example, again, with
GameMaker, it's a TD engine. And if you want to do three
D, it would be a huge pain in the butt to force it to do that because
that's not what it's for. GoTo is meant for
both TD and three D, so you're not going to have any pain when it comes
to doing that. You just have to worry about how to create
your games, I suppose. Alright. Now let's look at
the benefits of using Gato. Well, let's explore some of the key advantages of using Goto for your game
development projects. GoTo has a user friendly
interface that makes it easy to both navigate and
work with even for beginners. I offers a visual editor that allows you to
create game scenes and manipulate objects and set up your game logic without having to write a
whole lot of code. And that's where GD Script
will come in where it is very beginner friendly and
fairly easy to pick up. Goto's node based system simplifies the creation and the organization of all
of your game objects, making it highly
intuitive and efficient. Let's look at the Gatto
communities and resources. Gatos community is vibrant and supportive with developers
from all over the world, sharing their knowledge
and experiences. There are various online forums, websites and social media groups where you can connect
with other Gato users, ask questions, and
find inspiration. One of these main ones is
on the Gato website itself. There's a forum specifically
for people to ask questions and get help with anything that they're stuck on, whether it's a beginner question or something more advanced. Additionally, Gato has
extensive documentation and tutorials that are available pretty much anywhere
at this point, making it easy to
find answers to questions that you're looking for and to help you with
learning new techniques. Now, what are you going to
learn in this course, exactly? In this course we'll cover a wide range of
topics to help you become proficient in using the Goto engine to
create applications. You'll learn the GD Script
programming language, which is essential for building gameplay mechanics
and interactions, and will be our main
scripting language. Now, the reason
we're going to go with GD Script over
something like C Sharp is GD Script has a better
support at the current time, although C Sharp
is getting pretty good in their support as well. But GDScript also has a tighter grasp, I
guess you could say, to the engines API itself, as well as being much easier for beginners to pick up
and get running with. We'll explore both two D and three D game development,
including sprite manipulation. Of course, we'll
go over novations, collision detection, working with particles
and a lot more. You also gain
experience in creating a Goey or graphical user interface based desktop
software using Goto and learn to utilize APIs and incorporate using web sockets
for real time networking. Alright. Congratulations
on completing the introduction to the Goto game engine
in the next video, we'll delve into GD script, the scripting language
that we'll be using in Goto and get hands on
with a bit of code. Now, remember, the
Gatto community is always there to support you, and I'm here to guide you
every step of the way. Let's dive into
the exciting world of game development together.
2. Download and Setup: Welcome future developers. If we're going to be developing things using the Goto engine, either video games
or desktop software, first thing we're
going to need is, well, the Goto engine. So let's take a look at how we can go ahead and get
this downloaded. Now, the first thing or
the first way I should say that we can get
this is to download Gato from the official
website here. Simply go to Goto engine.org, like we see here, right
here on the screen. And once here, you'll see the download section up
at the top of our screen. As well as two download buttons in the center, we have the LTS, which is three point X and
the latest, which is 4.1. We will be using the latest
version, which is 4.1. There's nothing wrong with
the three point X version. It's still being developed on, and it is the long term support. However, if you were to use it, that version while
following along, there may be some functions or some things that we
write that might have different names or potentially not even exist in
the old version. So just keep that in mind,
and because of that, I would recommend
that you do use the 4.1 version as we go through. Alright, so this is the stable
version 4.1 just came out. So you can either hit the
Download latest button or the download tab at the top. Both of them will bring
you to this screen here. All right, so to go ahead
and to download this, all we're going to need,
since we're going to use the GD script
programming language. All we need is the
standard version here with the blue button. And the difference between
this one and the.net version is the.net version
also supports C Sharp. And if you were to use that, then you'd have to scroll
down and also pick up the.net that is required
in order to use it, as well as preferably external programs to
write your code in. And it's just a whole lot of
extra things that we don't need when going
through this course. So if you want to get
it from the website, you can go ahead and just
hit that Goto engine button there for 4.1 on the
standard version. Now, there is a second way
that you could get this, and that would be from Steam. You can come over to
Steam and go ahead and download it from there
if you would like. And that is going to give us the standard version by default. Steam version does not have
the.net version available. But you don't have to worry
about any confusion with that if you go ahead
and get it from Steam. Alright, so if you
get it from Steam, you can go ahead and just
hit the Play button. Or if you get it
from the website, you're going to get a zip file, and all you have to
do is just extract it and you can just go ahead and start
running the application. Alright. When you go
ahead and run it, you'll be met with a
screen like you see here. And all we're going
to do, of course, you're not going to
have all these projects and things in your side. But all we're going
to do is we're just going to hit the new
project button here. And that should give you a new window that pops
up just like you see here. And all you have to do is decide where by going into Browse, decide where you want
to place the project here as we go throughout the course and go ahead
and give it a name. For this, I'm just
going to go ahead and call this boots bootcamp. For this purpose, I'm
going to go back, and then I'll call
it Goto boot camp, and I'm just going
to hit Create folder because it has to be in
an empty folder here. And there you go. We see we got a nice little green check here indicating
everything is fine. We then have three render modes, forward plus, mobile
and compatibility. Compatibility is used as OpenGL. As you can see, from
the points here, each version has their
own pros and cons. But for the most part, you're going to be working
with Board plus. Unless, of course,
you're doing something you're going to be creating a mobile version or something, then of course, you should
use the mobile option here. And if you're working on a
version to be deployed on the web of your tool
or old hardware, then you would use
compatibility. So I'm just going to go ahead and leave foward
plus here selected, and we can just hit
Create and Edit, and that'll go ahead and create the project
and open it up. So that will just take
one moment there. All right. You'll then be greeted with
the following screen here, and we are now inside
the engine and ready to get ourselves to work here. Now, to give you
a brief rundown, down on the bottom left, we have the bile system, which is where all of our biles, scripts, game assets, et cetera, are all
going to be stored. Continuing on the
left hand side here, we have the scene tab. This is where we would
visually build out, well, the visuals
of our projects. Here's an import tab. So if you need to
reimport an object for whatever reason, you
can do it from there. Going over to the
right hand side, we have the inspector, which
will be very important. We'll be in there quite a
bit throughout this course. We have the node section, which will allow us to connect
some built in signals, and we have a history that
we can go back through. All right above that, we have a couple buttons. We have a play button here, and that is to run the project. That is going to run
through the default the default scene as
if it was being opened through running the executable after the game was exported. The majority of the time,
you're going to see me hitting this one here, as run current scene, and that's going to run
the current scene that I have selected rather than
running the entire project. So, for example, in the middle, you have this tab
that says empty. If I built if I built
something here, hitting that run current scene, it's going to run
what is running in this tab regardless of what
my other settings are set to. In the middle, you're
going to see this where we have our two D or three D, or scripts, and
the Asset library, where you'll be able to
come in and you might find tools or new additions
to the engine, things like that that might
help you in the future, or make your life
a little easier. Depending on what it
is that you're doing, so keep that in mind, the Asset library could be
very helpful, very useful. And, of course, you could
always use it to just look at code and try and learn
from it. Alright? We have the engine downloaded. We have it running. I'd
say we have it installed, but it's not really
installed, right? We just kind of unzipped
it and opened it up. And we have a new
project created, and we're ready to jump into learning about this
language of GD Script.
3. 03 Printing to Output added images: All right. So now that
we have our project created to give you a quick
look at the interface here. On the left hand side, by default, we have
the scene hierarchy. So this is our scenes and how
the current scene or level, as you might look at it, if you're doing game
development looks, and below that, we
have our file system, and this is our
folder structure and all the files that we
have in our project. So this is where we're
going to see our saved scenes, our scripts, any textures or other resources that we have in our project is all going to be
shown up down here. On the far right, we
have the inspector, and this is where we're
going to see the properties of each item within our scene. Along the bottom, we
have our shader editor. We have our animation timeline, our audio bus to do some mixing. We have our debugger to fix
any errors that we need to, and we have our output console that we can take a look at, and we'll be quite useful
throughout this course. And of course, right
smack dab in the center, we have our big view port. And by default,
you can see we're putting the three D area. And at the top, we're
just going to move over to two D because that's
all we need for this. If we just zoom out, you'll
notice this blue box. That is essentially the
size of our window. Now, if you want to go
ahead and change this, you can just head on up
into project settings. And that does not get
picked up, it looks like. Let's see if I can
toggle in that. There we go. So all we're going to do
in here if you want to change the size of
your window there, we're just going to come on
down and see display and window and viewport
width and height. There's what you
can change there. And you see this doesn't have a whole lot of settings here, but if we too advanced, we'll get a lot more options
that you can take a look at, such as a high refresh rate, and it looks like the
high DPI is on here. I know there is high
DPI, energy saving mode. So there's quite a
few options here that you can take a look at. But for now, we don't really
need the advanced settings. I just wanted to
point that out for you the width and height here. I'm going to go ahead and
I'll just change mine to 12 80 by 720 just to get a nice round and
standard number, and being windowed
perfectly fine. We don't need to start minimize, we don't need to start maximize. And by the beginning here, it's not even going to be worth really paying attention to. For the first good part
of this. But there we go. I'm going to set a 12 80 by 720. And if you set at
that, you might notice the blue rectangle
change. You might not. And that's only
because it's just a really small,
minute change there. But yes, anything within that blue rectangle is going
to show up on your screen. So to get us started, I'm
just going to go ahead and in the scene on the left, I'm going to select
user interface, and that's just
going to give us a control node by default. If we wanted to, we
could click other node, and we can see all
the different things that we can add and just
selecting control here. We can see all user interface nodes
inherent from control. It controls anchors, offset, adapt, position, size
relative to its parent. But in general, we
can see control is used for a user interface. And that's what
we'll notice here, anything related
to user interface is going to be colored green. All right, so we'll go
ahead and select that and hit Create or hit the
user interface button there. Either way, you'll come to this same screen or
the same result. And with that, we
have a scene that we can add our script to
so we can actually start on the code a scene that we can play so we
can see our code run, and a scene that we need
to save.Quite frankly, so I'm going to go
ahead and save it. Control dot C TSCM that's fine. Just go ahead and save it there. And I'll add my first script. Now I'm going to
call this printing because that's what
we're going to go over here to begin with. Print. Language is on GD script, enhanced control,
templates on no default. We could just go with empty because we're just going to delete everything in it anyway, so let's go ahead and
go with that object empty and create. Alright, so all we see here at the top is extends control. And that's just saying
that this is coming from our control class, and whatever is extending is the type of node that the
script has to be attached to. So since it's attached
to a control node, it has to extend control. So just moving on down
a little bit there. We're going to create a
we're going to go ahead and type in Bunk Underscore. Ready? I put a cool in at
the end of that. Hit Enter, and just
type in the word pass. Now we can remove the error
that's appearing there. But this, what we just typed in here is
just a piece of code that was removed because
we did an empty script. And I can go ahead and show
you that here as well. So if you do it the
other way, I'll go ahead and delete that script, take it off of the control. And if I add a
script to it, again, you can just hit
the slide Control and hit the script
button here up top, or right click on Control, and you should be
able to add it. And I'm noticing that this
is not appearing there. That's fine. You can you know what's good
because you're able to well, you're seeing it on your side. But if we were to select
a node colon default, the template when
attached in our script, hopefully, I remember and
I'll put a picture up here on screen in case of you guys
are a little confused. You hit Create, you'll be presented with this screen here, and all we essentially did when we created an empty
one is we deleted all this, and we just typed in
this section again. That's all we did. Now, the reason why
we're going to use this underscore ready here is because anything inside of this block here,
which at the moment, is just the word pass, is going to run as soon as the control
here enters the scene, which is already part of
the scene to begin with. So it's going to run as soon
as we hit our play button. And what you're going to
learn here is we're going to learn about the
different ways that we can actually
print out to AR Console. And why might you
want to do this? Well, you can use this to give
yourself some information. You can use this to
help you try and debug some small errors. And importantly, things that you
print out here can actually go to your logs. So your logs, of course, if you've ever had
problems with a game or a piece of software in the
past and post on a form, you might notice that people
ask you to post your log. Well, this is what
they're asking for. So let's go ahead
and jump into this. And the most default way or plain ways we type
in the word print, open and close a
pair of parentheses, and in between
those parentheses, we can use a pair of double
quotes or single quotes. Does not matter, but whatever it starts with, it has to end with. So if we have
single quotes here, you cannot type the word
don't as you see there, because we're having an issue where the T is not included, and basically, it's stopping here at this
apostrophe, the single quote, and then it's continuing
after the So in this case, if we're going to have
something like that in there, we would need to do
double quotes for the start and the beginning,
notype that properly. So you can use either one, but depending on what you're
writing, it might limit you. So the first thing
we're going to type in here is Hello world. Now, this is a
staple when learning any programming language that we print out to the
console Hello World. So it's kind of like
a rite of passage. It's something
everyone does when experiencing a language
for the first time. All right. So you can come
up here and you can either hit this play button
here at the top. With the little clapper, and that's going to play
the current scene. Or you can hit this play
button here at the top. I says Run Project. And if you hit the one
that says Run Project, it'll be prompted with a screen to select your main scene, which in this case, we going to use the one
that we already have, so you can just go ahead and hit the select current
option, and it'll run. You'll notice a window pop up. Hopefully without any issues. And you'll see down
in the console down here that we have
printed out Hello world. So we've already learned how
to print out to the console. So at a bare minimum, you now have your
first application. It's not a very
exciting application, but it's something that
you created that works. Now, throughout this
course, if we do print, this is more than likely the
method I'm going to go with, but there are a few other things that is worth noting here. And one of those is
print with two Ts. And what that's basically
going to do is that's going to put a tab between objects. So if we like this and separate our objects with a comma and
we go ahead and play this, you'll see in the output, this is now space by tab
in between our words. If we have two different
objects like this, we can do prints that at
the end, one T and an S, and that's just
going to put a space in between each object, just like we had
initially, where we had hello world as one piece. Now, we also have printer with twoRs and this is actually, I call it printer, but it's
more of a print error. And you'll notice when we run this that this
actually pops up in our console as red with
a little red dot there. So this is something that we
can use if we want to show an error in the console. There's something
that we can see. And since it's red and the
rest of our text is white, it's something we can
jump to immediately. And that just leaves us
with one last option here, and that is print raw. Now, if we do this, you're
not going to see anything here in the console output. But what this does is
this is actually going to print out to the console window
that's running behind the scenes and should
still go out to our logs. That should cover
it for printing, being able to do all these
printing methods here. So again, we got print
like we see here. We've got print two Ts. Boom. S there. And to note, you don't have to have a
space after the comma, but just looks nicer. It's kind of something standard
that people end up doing. But I'm going we got
prints with an S. And there we go. Go ahead and type bed in.
What else do we have? We have printer, which is
printing your own errors. And we had print raw. So there's all the different
ways that we can print out to the console, of course, minus print raw, which
would only be useful for us if we're
going to our log. But there we go. There's all the different
ways that we can print, and that'll do it for
this lesson here. And the next one, we're going
to go ahead and we'll jump into some variables
and or mathematics.
4. 04 Variables: Alright. And this lesson, we're going to go ahead and start talking about variables. And if we have time, we'll
jump into mathematics. So variables. What are they? Well, they're
something that we can use to represent any piece of data. So like we had before where
we had a piece of data that was set and sign
a pair of quotes, we can set that to a variable, which would be very
useful, for example, if we had a really long sentence and we could just type in
one word or one letter, and that could mean
the exact same thing. So a variable is a label that you can use to
store a piece of data such as what we've printed
before with Hello world. So let's go ahead and
add that into a script. So let's create a
little control. I'm going to add a script here. And I'm going to go ahead
and just call this. Let's go ahead and we'll
call it variables. And hit Create. And the only one we're
gonna need here is gonna be our ready
function, of course. And Yeah. Alright, so we'll go ahead and let's just put type
pass back in there. And our variables are going
to go right here at the top. So to create a variable, all we have to do is type
VAR VAR for variable. Put a space in there, and we can type
whenever we want here. And this is going to be
the name of our variable. So what we're going
to put in there is let's let's call it
a greeting, right? And at the minimum,
that's all we have to do. We can assign it later
if we wanted to. Well, we're actually going to assign it right
here at the top. So we're just going
to say equals. So we'll say greeting equals, and we can put our
pair of quotes, and you can say hello new W now, we have ourselves a
little sentence here, but we can put that in wherever
we put the word greeting. So if we go ahead and we print
out our variable greeting, and if we go ahead and run this, You'll see down here in
our outbook we're going to get the greeting that we
typed up there at the top. Now, you can type in
whenever you want here. You can make it as
long as you want. And all of this will be represented by this
singular word. And if we wanted
to go further, we could just make it a singular letter like G and do this again. And as you can see
that one letter represents all of that. Now, for the purposes
of a variable, especially ones
that are top here, using one letter like this is terrible naming because
someone comes in, they look at this You can see there's a
variable called G, but it doesn't tell
you what it is. And a variable should tell
you exactly what it is, and as little
context as possible. So we'll leave it as greeting because that's what's
going on here. We have a greeting that
is happening, right? I just Controls to save. So now we have our
first program running, and now we're using variables. Now, piece every
variable is going to have some type of data
that is connected to it. This is normally
called the value. Now, it doesn't matter
what type of data this is. I can always be
labeled as a value. So in our case, greeting
is the variable name, and Hello New World
is our value. Now, one of the benefits
that we have for this is it's a little more work. But let's say we come in
here and we wanted to use that sentence or
that greeting over and over and over and over
again, throughout our code. Can you imagine having
to come in here and edit all of these
things if you want to make one change
to your greeting, then come in here and edit
all of these one by one. Well, with the variable, we can just do that
right here at the top. So instead of hello, new world, we'll say hello and welcome
to the World program. And because we're
using a variable here, we just changed that phrase in all of these lines
of code at one time. Now, like I say, if we were to go through
that one by one, that would extremely suck. As I was mentioning earlier, we could set this earlier
or we can set this later, and we can actually
overwrite this as well. So we say greeting, which
is our variable name, and we'll say equals, I'll
say this is my new value. So we'll see that the
top grating is going to be what is set here at the top. But then after that,
we're going to change what that variable means. We're changing the value of it, and then we're going to
print out our new value. If we go ahead and
play that, there you go. You can see that there. So we can change it at the top, which ideally you
should when you can, or you can change it lower down inside of your
script at a later point. You can change it or sign it to something
completely different. All right. So that gives us our quick overview
here on variables. So what I'm going to
leave you on here is that there are a few names, a few rules that you should try and follow when it comes
to naming your variables. Now, these rules typically
is a variable name. Variable can be named using letters and numbers
and underscores, which cannot use any spaces
in the variable name. The language will just not allow you to either
that to do that, and you cannot start your
variables name with a number. That's something to
keep in mind there. Avoid you should
also avoid using any keywords or function names that already exist
within the language, or you will receive an error. And you'll learn as you go through what's a
keyword, what's not. And a keyword would be something like VAR there or variable. Now, you might wonder
when something like that might come into a situation. But what if you had the wanted a variable called
pass to represent password, what you saw when
creating the script that pass is actually already a thing, so
we can't do that. And last, a variable
name should be short but descriptive at the same time of the piece of data
that it contains. So as an example, having a variable
called name length would be a lot more
appropriate and acceptable versus something
such as length of my name. Now, they both convey
that same information, but one of them
is a lot shorter, it's more concise and overall will be seen as
a better variable name. Okay now, something worth
noting as well when it comes to our variable errors is notice
how this is all lowercase. If we had any of
this at any point as a capital, as you see, we're going to get an
error from up there, and we just see at the bottom
identifier grading with a capital G is not declared
in the current scope. So what that means is this, it looks like we're
trying to use a variable, but this variable
does not exist. So capitalization is hugely going to be something worth paying attention
to, especially encoding. Alright, so that'll finish up here for taking a quick
look at variables. And in the next one,
we'll start looking at some of these
different types of datas. Namely, we'll start
looking at strings.
5. 05 Strings: Alright. Today, we're going to take
a look at at strings. Strings is a type of data. So let's go ahead and jump in. All I've done here
is I've created a new script, of course, for strings to pertain
specifically to this lesson. Now, as programmers, we're both defined and gather
some data to store, as you saw previously
with our variables, and it helps if we can classify the different types of data. Now, the type that we've been using has been called a string. And a string is
anything that falls in between a pair of
quotation marks, be that the double quotes or the single quotes that
we mentioned earlier. So our hello or rather our greeting variable
that we were using was holding
a piece of data, and that data can be classified
as a string for its type. All right. So when
assigning a variable, it is best practice to also assign the type of
variable that it is. And if we go ahead
and take a look, so if we come back and
we have our ba greeting, we set that equal to hello
new world like we had before. We can actually set this
in two different ways. So we can put a colon after
our variable name and type in the type of data we're looking for,
which can be a string. And you can see this
is one way that we can classify it as a string. Now, alternatively, we can
use the Walrus operator, which is a colon right
beside the equal sign. We have colon equals. And what's that's going to do is
that's going to take our grading and we're
going to assign it equal to this piece of data. And then whatever
type of data this is is also what we're
going to classify it as. So we're going to both
classify it to this piece of data to the type of this data and set
it equal to this data. So there are two different
ways that you can do and it is highly
recommended that you do so. Of course, in this language,
you don't have to, but especially on
much larger projects, this is going to help
a bit in performance, being able to classify
all the stuff beforehand. Alright, so what we can
do here is every class, in this case, string there as you saw when
I typed that out, and it changed to this
more of a green color. Everything here has
a different case. So I'm going to go ahead
and create a new variable, and I'm going to call
it name with a capital N because all lower
case is already taken. So I'm going to say name equals, I want to just go ahead
and put my name in there. And remember, we still
want to classify it. So I'm going to use the
Walrus operator here. So I'm going to
say colon equals. Now, everything has a
set of methods on it. So if I go ahead and type in
my name here or variable, and I do a period, you can see all these
different things pop up, these are all things that
are related to a string. And the one that we're going to look at specifically right now is called capitalize. If we come in and we just
do name dot capitalize, we can see that completed. Now it's blue. We have an open and closed
parentheses in there, and our error here has gone away from where
we waited there. Now, if we wrap that
a print statement and play that we'll notice
inside of our output, everything has capitals
after every space. So even if I make this
as all lowercase, as you see here
and we rerun that, you can see it still
comes in with. Now, capitalize is something
that you should do for things like names and
titles, as you would expect. Now, with the name capitalize, you might be a little swayed
to think that it's going to make everything a
capital, but it does not. And this is where Python kind of does that better because
they call it title, which I feel is
more appropriate. In this case. But either way, you notice
that's how capitalize works. And likewise, we can make it all capitals and we can
make it all lower case. So all we have to do here is instead of
calling capitalize, you can say we can do
two underscore upper. And if we run that, we're
going to have all capitals. We're missing one
parentheses there, which is what our error was telling us down
there at the bottom. Now if we take a look so we see everything is now in caps. And if we did this
the other way, so if we have all caps, and we did to underscore lower with our open and
closed parentheses, now everything is going
to be in lowercase. So we can make
things capitalize. For things like
titles and names. We could make things
into all upper case, and we can make things
into all lower case. Now, with strings, we can
also add these together, and we can use something called we can use what's seen
as a placeholder. So for example, we
come back in here. It's going to hit
Control Z or Control Z back that up till we have
all lowercases here. And let's say, for example, we want to print out a greeting. We want to say Hello. Welcome to programming, and we want to put
in the name here. But we also want to put in. We want the name to be dynamic. So we might not
know what the name is by the time we get or we should know what it is by the time
we get to this point. But we might not know
what it is at the start. Now, this could be
because our user hasn't input hasn't
told us what it is. Or it's just something that we haven't that we may
change later on. But all we're going to
do is we're going to do percent sign and
lowercase S. Now, this is a placeholder
for a string, and all we have to do is
outside of the quotes, but inside of our
parentheses still, we do a percent and we could type in
our variable name here, which is just name with
N. And if we run that, we can see that's
going to insert where that percent S is with whatever the value of our variable name or the
value of our variable. Now, this changes up slightly. If you want to use
multiple variables, so we'll go ahead and
say create another one. And we'll say let's call it job and we'll set
that to feature, and we'll say, Hello, welcome to programming percent
S. You are a percents. Now, you might think
that we could just do another one like that, or you may think we just do
another percent job in there. But really, what we do is we
have our percent sign here, and we use square brackets. Now inside of here,
this is where we can put all of our
variable names here, separated by a comma in the order that we
want them to appear. So if we run that, we can see
everything gets filled in, and you want to make sure that you fill that
incorrectly because again, the order that you
fill it in here is the order that is going to be filled in in the sentence. And obviously, this
doesn't make sense. Welcome to program teacher. It doesn't sound right. So just kind of
keep that in mind. Also noting, if you have
multiple things here, such as if we go
like this, right? If we have too many variables listed, it's perfectly fine. We're not going to
run into any issues. The only time we're
going to run into an issue is if you
don't have enough. That's when our
error is going to, I suppose they don't have
any errors in here anymore. What you see? I know, there it is just not
showing up as an error. Which I expected. But here
in the console, rather, it says not enough arguments to format string or
for format string. So it's telling us
that we don't have enough arguments here that really should have
appeared more as an error. But you can see it does pop up. Just put those back
in the right order. So if you are filling
in information, just make sure you have
enough information and you're filling it
in in the right order. Now, I'll say alternatively, you could fill this
in in another way. However, it takes up more room, looks more cluttered,
tartar to read. And by that, we're talking about doing basically this addition. All right, so like this, boom, again, so we can
do something like that. And you see, you
can do it this way, but it looked a little more problematic or not
as nice looking, but you can certainly
do it this way. And I'm missing a space
between there and here. And you'll see if
we print that out, that's going to give
us the same result. So that is two
different ways that you can use your variables
inside of your strings. All right. So that'll
do it for strings. We're going to go
ahead and move on to looking at some other
variable types next.
6. 06 Integers and Floats: Alright. Today, we're going to
take a look at numbers, as you can probably
see by my script name. There? Now, numbers in programming can be broken down into two different categories. Now, numbers in programming or rather they're used
in programming for all different kinds of things
such as keeping score, different kinds of
game mechanics, algorithms, visualizing
different data, some of the things that you
looked at that are art or shaders that may have
all come from just math. Now, these numbers are
either going to be called an integer or a float. Now, a float may also be
called a real number. So if you ever hear someone
talk about real numbers, they're probably
talking about floats. Let's go ahead and
start with integers. Integers are a whole number. Now, their class, if you
wanted to create a variable, let's say binuM if you wanted to create
a variable for this, an integer, it's just
shortened down to INT. That's it. And a float is going to be classified just as that as
float in all lowercase. All right. So if you want to
create a variable, those are the two
ways that we do that, and I'm just going to
create another one here just to have
them here at the top. So you can always
take a look at it. Now, when we're
printing things out, we can print out numbers. So if we type in five here, go and print that out, we can see five comes up
in our console. Now, what may be a little different is we can
actually perform math in here. So if we say five, that's ten, and maybe we want
to put a space in there, make it a little more readable. Take a look. That's going to print out our total here of 15. So we can actually perform a
subset of math within thes. And we can do that
with addition. We can do it with
multiplication. We can do it with subtraction. And of course, we can do it with division, as you can see there. And you see division
in this case, has given us a debugger, and that's because
integer division goes into a decimal part. The decimal heart
will be discarded. So this doesn't go unevenly. This actually returns
to us a float. And since we're
dividing two integers, we actually did not
get that out to us. So we got zero, but we did
not get anything after it. And that's what that error is telling us there
in the debugger. And we'll get to that when we touch on floats
here in a moment. But what we can also do is we actually support exponents
and square roots. So example here, we can do P, which gives us a
number to the power, something else or an exponent. So if we say two, we put a Tama. As you see there, we have our base number
followed by our exponent. If we say two to the
power let's go with five. All right? We're going to going by
the rules of exponents, we're going to have
two times two times two times two times two. So that would give
us two times two, which is four times
two, which is eight, times two, which is 16, times two is 32. So if we run this, we
should get 32 as a result. There we go. So we see
that we do exponents out. Likewise, we can also get the square root of
something with SQRT, and the same situation here. Similar situation. We
pass in one number. In this case, we'll do with
32. And we pass it in. We'll see what times itself
will give us 30 or yeah, what times itself
would give us 32. What is the square root of it? And we see that gives
us a float here. 5.6 5685, 42, 4942,
three, eight. That is a long number, but if you multiply that number
by itself or with itself, you will get 32. As you see, we gave it an
integer and we got back a flow. And with square root, that
is certainly possible with exponents that's not
going to happen unless, of course, we use a
float to begin with. And as you can see, square root is expecting a float
for the first argument. So that is why this is essentially being
converted into a float, which would be the
same as doing 32.0. In this case. Now, you can use any combination of math that you want in here, so you can use any combination of using all those together. Let's say, for example, we have five plus in parentheses three
to the power of 7/3, and then subtract nine. Now whether we're
using bed Miss, bod Miss PEMDS, however uber taught the
order of operation, we're going to be looking at
our brackets or parentheses. They are parentheses.
I don't know why some places call the
brackets, but parentheses. So in that case,
we're going to be looking inside of here first. Then we're going to
look at the exponents. So the first thing we're
going to do is our math here. So three to the power of seven. And then we have to do what's
inside the parentheses. So then we need to divide
it by three, right? Because next up is our
multiplication and division. In this case, we
just have division, so we're going to
divide that by three. That leaves us now with
five plus our result here, and then subtract
nine and addition the subtraction could be done same time, just
going left to right. And if you do all of that math, you'll get an output of 725. All right. So it doesn't matter. The order that we
do this in well, the order that we type it in. The order is going to be
done in the correct way, and we can mix and match
all different Basically, you can do any mathematical
formulas in here. All right, so now when
we look at floats, I said that we had
five minus ten. So if we come back here
to this situation, we had five minus ten, and we do that and we
got a little debugger, sorry, not minus divide. And we got a little
debugger saying, Hey, this is the float and everything app to zero
is being left off. Well, what if we
want that? Well, we have to convert one of
these into a float. So we either have to do we
have a solid number like this. We can do 0.0 on one of them. And you see now we can actually
get our decimal number. Or what we can do
is we can do dot, and they still have this? No, they do not. Does not appears. So what we can do is we can just type in the word lot and surround one of our numbers inside
a parentheses. That's going to convert
our ten into a float. So we can do it
that way as well. If we don't necessarily
know what the number is that's being input into
it, if that makes sense. So if you have a user
typing numbers in, you don't necessarily know
if that's going to be an integer or float
that the user types in. So we can just convert
it at the time, right? So that's how we would
fix that issue there. We simply just convert
one of them into a flow. Now, in code, any number that has a decimal
point is called a flow. And we use this term
in most if not all, the programming languages
like I mentioned earlier, they can be called
a real number. And all languages must be carefully designed to properly manage these decimal numbers. As a user, of course,
just using the language, you don't have to
worry about how the language is handling it. Just know that it
is being handled. And as long as the language
is handling it well, that's all you need
to worry about. Now, any of the mathematical expressions that we
looked at already, we can also do that with floats. They're not exclusive
to integers. And as you saw right
there with our 5/10, and we converted
one into a float, you can use integers and floats together
at the same time.
7. 07 Constants and Comments: Alright. Now, before
we move on further, I do want to talk about a special variable
called constants, and I want to talk
about comments. Now, these are small topics, so I'm just going to do them
both here in the one video, and should only take
a couple of minutes. A constant differs
from a variable. Now, you remember when I said that we could change
what a variable is or we can change its
value at any point. Well, a constant is
a special variable, and this special
variable cannot change its value once it is set. So once that value is set, it can never be changed,
and it just is what it is. So if you do try and
change it later, we should run into an error
that appears in our code. And we can go ahead and
take a look at that. And all we have to do to create something called
a constant instead of a typical variable is we
do CONST instead of VAR. And as you see, we
got some pop ups showing up down
there at the bottom. Don't worry about it. But
constant we can call. And again, if we call it MOM, and see, we still
have an error here because it's expecting me to set the constant
to something. So if I set that to say five, pool in equals five, see, now the error goes away,
the constant has been set. Now, the issue here are
not really an issue, but if we come down
here, we try to set my num to a
different number, let's see if the
error is, it is. There it is. So
you see you cannot assign a new value
to a constant. Is what's showing up down there. And we see this at line
seven character five. One, two, three, four, five, so at the end of our variable name because we're trying to
set it at the end of the name, which makes sense. That's how you set things here. So we're going to come
up with this error. So you only want to use
things with consent that are not meant to be changed. Such as if you're creating a
game or an application that has an online connection
between users, you're probably going to
set this to a max amount of users or a max amount of players for each
of your servers. So you only want to use constants for things
that'll never be changed. Pipe pass back in there again, clean those issues
up. Now, a comment. A comment can be
both good and bad. So they're not exclusively
one way or the other. It just depends on when you should and
shouldn't use them. Now, comments are like minor notes that
you can leave to yourself to explain what is going on within
the piece of code, why you did something
in a specific way or whatever else you need. Now, a comment is actually
on the screen right now, and you've been seeing
it this entire time. Comments can be useful
for any future developers that have to look at piece of code that
somebody else has done, or maybe you worked
on it at one point, then someone else is
coming to look at. And a comment, as I said,
it is already on screen, and has this you may know
it as a hashtag symbol, or if you're a little
older, you may know it as a pound symbol. And we set up right above where we have our
underscore ready. We have this hashtag
and it says called when the node enters the scene
tree for the first time. Now, that, since it is prefixed
with that hashtag symbol, this is a comment
in this language. Now, in some languages, you may have to do
the double slash, like so to create a comment. But in GD script, we just have our little
hashtag symbol there. Now, you can also use this to
comment out a line of code. And the reason we can do this is because anything
with a comment it's been commented will be
skipped when the code runs. So if we have print
and we print out, mind num here, if we
go ahead and try this, it's going to get
printed out as expected. But we can also put this
little hash tag here, and it is commented out. Now it's just complaining
because we don't have anything after our
ready function here, so I'll just go ahead and
put the pass back in there. And you see now it does
not get printed because it gets skipped Now, what if we have a lot of code? Maybe we're trying things.
It's not working out. I want to try a couple
of different methods, but we don't necessarily
want to get rid of the attempt that
we already tried. Well, we can actually
comment large sections of code with a shortcut key. And to do this,
all we have to do is we're going to highlight
all the chunks you want. Say we want that,
we want to keep the ending in the beginning. All we have to do is
highlight these pieces and press Control K. Now, if you want to back,
this might be Command K, I know they like to use
command instead of control, I believe, for a lot
of their shortcuts. In general, Control
K doesn't work. Try Command K. But that's
all we have to do, and that's commenting
out that entire section. Now, likewise, if we highlight all those and
we hit Control K again, we can uncomment all
those at one time. And Alright, so there's
comments and how they work. Later on, we'll talk
about a clean code more towards or closer towards
the end of this course, where we'll go over a
little more about when you should use comments,
when you shouldn't. What are good comments,
what are bad comments. But for now, that's
what comments are, and those are what
constants are. I just wanted to let
you know about those. And we'll move on. We'll
see you in the next one.
8. 08 Lists: All right. Let's go ahead
and take a look at a list. Another name for these
are also array ARRAY, but most commonly referred to, at least from my
experiences as a list. So what is a list? A list is a collected group of items that get put in a
particular order, and you can make a
list that contains any type or any combination
of different datas. So we can have integers
and floats and strings all combined together into one list. Now, your list does not
need to be related. The elements don't need to
be related to each other. However, it would make
sense if they were. Think about if we had different
kinds of pizzas, right? And each one of those
different pizza types had a list of toppings. And then they had a some other
random element on there. They had who made it or who
makes that specific type. It's not really related, so you probably there's probably a better way to
handle that kind of situation. But lists are indicated
by their square brackets, just like when we were using our variables inside of our strings with
those placeholders, a list is surrounded
by square brackets. And those square brackets, each item is
separated by a comma. So let's go ahead and take a
look at a list of groceries. Let's go groceries. We
have our square brackets, and let's go tomatoes. Or, you know what,
let's just go singular. We'll go tomato, pickles. Drop and buns. Alright, so if we were
to print this out, If we were to print
out these groceries, you'll see that we're
going to have square brackets down there
in our output. You probably don't want
the square brackets. You probably don't want,
that kind of an output. You might be looking
for an individual item. Well, let's take
a look at how we can access individual
items from this list. To access an element or
an item within the list, we just need to tell GD Script the index position of the
item that we're looking for. So if we go ahead
and print this out, so if we do groceries, we put a pair of square
brackets after that, and we can now put in a number. And these numbers will
actually start at zero. So even though we count one, two, three, four, a computer
is going to start at zero. So tomato is going to be zero, pickles one, ketchup
two, and buns three. So if we do groceries zero, and print that out, we see we're going to
get tomato in there. If we do row shoots one,
we're going to get pickles. Now, if we go out of
order, for example, if we go four because
we count one, two, three, four
items, we're like, Okay, we want item number four, we're going to have
an error because four would actually
be the fifth item. So what we really want is three to get that
last item there, or buns if you're
getting the wrong item, just make sure you're going for the index value and
not the item number. I've seen quite a few
people get confused by that or get confused
on that mix up. Now, since in this case, these are strings, we can use things that we've
learned before. So we can use like two upper, for example, and
get an upper case. Oops. Here we go. As you can see there.
We can also to lower, capitalize and all that. Let's see once we
put this.in here, we are getting a
good list fantastic. But you can see all
the normal stuff that we have in there
with all strings. So we can do our upper
or lower capitalize. Now, what if you want to keep
everything to a set type? So setting this to
a list like this would be the equivalent
of going like this and setting it to an
array, which is fine. An array can all
different kinds of items. But if you want to narrow
it down even further or maybe just want to squeeze out that
slight more performance, what we can do when we're
declaring it as an array, we actually type
it out like this. We give it the square brackets, and on the inside, we declare
what type can be in here. So in this case, all
of mine are strings. So I'm going to use
string for the inside. And what this means here, the square brackets
element tight, and then square brackets again, theta tight right beside
our declaration of an array tells our script or code that only a
string can be in here. So if we put a number, an integer, we're
going to get error. So this is how we can
narrow down our list to a specific type and squeeze out just that very slight more performance, that little extra. But again, unless you
work on something that's more of a big project,
probably won't notice. And thus, just calling it a normal array or using
the Walrus will be fine. Now, something that
I didn't mention before is when we're
looking at strings, we can actually get the length. So if we get light, like so, we'll actually get the length of that character or that item. So in this case, we go for
index three, which is buns. We want the length, and
that's going to give us four because we have
four characters, B, U, and S. Now, what's
different is a string. You can access the index
of a string as well. So if we were to come in
here and ask for Index one, of that string, we're
going to get the letter U because each character has its own index
within the string. So B is zero, U is one, N is two, and the S is three. So we're accessing
the third element. We're going into our groceries, getting the third index value, and we're getting the third
index value of that item. Hopefully, that makes sense, and it's not too confusing. But if you want
just the front or the back of a list
automatically, we can actually get the
index of negative one, and that will always give us
the last item in the list, which in this case, buns. But alternatively, we can also
on our list of groceries, you can just kind of dot front. You get the first item,
which would be tomato. Ooh. We need one more
parentheses there. We can call dot
front for tomato, and we can call dot Bat. We get the last
item in the list. So if you don't want
to use an index, you could just call
dot front or Dot Back if you want to get the
first item or last item. Now, since in this case, they're all strings
in that, remember, we can still use them
inside of a sentence. So we'll be like, honey, we still need to get some, and we'll use our percents, and therefore our playder and now we can just go ahead and insert
what we need here. So we can go ahead and we can replace the first
placeholder with groceries, and we'll call that index. Let's go with index two, and then we can call
Let's go with capitalize. Now if we print that out, I'm missing one parentheses
on the end there. Go. So now we can see
our statement here. We have our item being inserted in and it's
being capitalized. So we have a capital
K to start out, which would work nice if we had a list of
brands, for example. And of course, you can
do this and fill in multiple items as well. All right, so that'll do it for introduction into lists here. We'll continue on with some more features
in the next video.
9. 09 Adding and Removing: Alright, we're going to continue using our same
script for this one, since we're still
talking about lists, and we're just going
to go ahead and talk about how we can add we're going to go ahead and talk about how
we can add items to our list. So to do that, we're
looking at it, and most lists can be
most lists that we create are dynamic, right? Which means they
can be modified. We're using variable. We're not make it at a constant. Obviously, a constant
cannot be modified. And the majority of the ones that we're going to
create are going to be to zivar which
will be dynamic, which means we can add and remove items to and
from that list. Now, you might use a
list to keep track of what quests a player has
in a game, for example. Thus, you need to be
able to add new ones, remove ones once
they've been completed. In terms of data, we may use
a list for registered users. Now the simplest way for us
to add to a list would be to call the method append. So if we go to groceries, we can call a pen so dot append, and then whatever
we type inside of here will be added to our list. So if we go ahead and add in, let's go let's go with
some Pringles, right? We type that in. Let's go ahead and print our groceries
before and after. And we can see the
difference before and after it's been
added to the list. And you see a pen is going
to add an item to the list, and it's going to add it
onto the end of the list. So it's going to end or add
it to the back of the list. Now, using a pen allows
us to easily and quickly add items to a dynamic
list, which is fantastic. And that means we can also
start with an empty list. So if we come in here, I'm just going to
comment that one out, so we can go with
the same thing here. And we're just going to
make this an empty list. Now, if we start with
this Z we can start with something empty and we can add into it. That'll also work. It's just as easy. And creating a list
like this is common, so we don't always
know the data we need to add until the
program is running. Sometimes we have a
set list of options, and other times
maybe we're going to add to a list in the future. So it's always good to know
how we can add into it. Now, what if we want
to insert into a list? We don't want to add
it to the end, but we want to insert into it. Well, instead of adding
an item into a list, we may need to insert
an item into a list. And to insert an
item into a list, it takes two parameters. And that just means two
things that we pass in. So when we did a pen and
we put one item in here, this would be a parameter. And when we insert an item, it's going to take two
of these parameters. So going back to
our old list here again, Just back that up. There we go. And the position of the first is first position and
second the value. So we're going to go ahead and call insert on
here, and we can see. The first thing we put
in is the position. So let's say we
want to put it in position two, in index two. So right now, index
two is ketchup. So we want to put something in between pickles and ketchup. So we're going to have pickles, our new item, and then ketchup. So after we put our
index, put a coma, and we put in our new
variable or sorry, our new item, which I'm
going to go Pringles again. And if we print that, we can see pringles was put in between
pickles and ketchup. I was inserted as
index number two. So not only can we
add to the end, but we can insert an item at a specific point
inside of our list. Now, when a new item
gets inserted into a list in our case position, one of our items gets
put in between, well, in our case, two and three, and we have a brand new item. Fantastic. Now, the fact that we can add to list and
insert into a list is great. But what if we need to remove
an item out of your list? Well, we can easily do that. All we have to do is call
dot remove And in this case, with the new system here, it pertains to remove at. And we just go ahead and
pass in the index, right? So if we pass in two
now, we pass in two. This is going to remove ketchup, so we're just going to have
tomato, pickles, and buns. That's what we should have
when we run this now. So there you go. We've remove
the item at index two. So removing items is fairly
simple, as you can see there. Now, there are going
to be cases where you want to you may want to get an item and remove
the item at the same time. And we could do this in
multiple lines of code, but we don't have to because we can
actually pop this out. And I say pop because that is the name of these two methods
we're going to learn here, and that is pop
front and pop back. So if we do Pop, underscore, front, and you see when we
print groceries here again, the first item is
going to be missing. But this actually
not only removes it, similar to the remove, remove that that we just did. But this also returns
that front item. So if we were to store
this in a variable and call this item, this is actually
going to return that, and that first item in our list, which will be our tomato
that gets removed, it's going to be
assigned to item. So if we print item afterwards, we're going to get that tomato. And it's the same concept. If we pop from the back, we're going to get the last
item, which will be buns. So items will be equal to buns. All right, so it's going to go ahead and
yell at us there. So what you would want us to do is because it can't
imply what the type is, we would have to declare
it manually like this. So there are some situations where you won't be
able to get with that automatic
inferred declaration. And you'll have to
do it yourself. This is one of those few
cases where you would need to if you choose
to go that route, which you probably should. Again, just something
to get used to. That way, you can always get the maximum performance
that you can. That way, if you reduce the amount of optimizing
that you'd have to later. And the last thing we're
going to take a look at in this video is we're going to take a look at
how we can erase an item, even though we don't know or where that item is in our list. If I just we're going to go back to printing out our
groceries again, and we don't need that
variable anymore. What we're going to do
is we can call dot eras. And for this, we can actually
just type in the value. So we can come in
and we can say Keto. Now, remember this is case sensitive when
it comes to springs. So a lowercase K is not going to be the
same as an uppercase. Though to us, it looks the same, or we would consider
it the same. In code, there are two
completely different things. So if we call erase and just
pass in the actual value, we can go in and we can see
that is going to be erase no matter where it is in our line. Now, you may think, what if we have multiple values that are the same, and we call erase? Well, it's only
going to delete or erase the first instance
that it comes across, so it's going to through
it's going to say, is this matching what
we're looking for? No. Is this, no. Is this Yep and delete. And it's going to
stop there. So if you wanted to erase multiple, you would have to keep going through at this current time. We will learn a better way
if you wanted to erase all instances of
a specific value. But for now, it's only
going to remove one item. All right, that'll
do it for today's lesson or this lesson. We have just a little
bit more to learn about lists before we can move on. So one more lesson coming in.
10. 10 Pushing and Sorting: Right now on our final
lesson on lists, we're going to be looking
at the push methods and how we can organize our list and getting
the length of our list. The push method, there
are two of them. They allow us to alter
the contents of the list. There's push front
and push back. Both take one argument
and that is a value. Now, when using push front, our value gets added to
the beginning of the list, just as if you were to
use insert at index zero. Likewise, when we use push back, our value gets added to
the end of the list, much like when we use append. So if we were to
take a look at this, we can then take our groceries
and we can use push front, and we'll add in our Pringles. And if we take a
look at that now, we'll have pringles pushed
to the front of our list. And likewise, we could use push back to get it sent
to the back of our list. Now, personally, I
usually just end up using a pend when I want
at the back of the list. But we do have the alternative pushback
to put it in the back end, of course, push front instead
of insert in deck zero. The push methods
are that simple. It's not a new concept. It's just two more
methods that you can think of as an
alternative way to do this. Now, when it comes to
organizing our list, you can see that in most cases, our lists are created in
an unpredictable order as our program runs and
as we add things to it. And you can't always
control that order, especially if you're having the user input a bunch of items. And because of this, the
problem becomes unavoidable, really. But we are in luck. Inside of GD Script, we are allowed to sort our list using a simple
method just called SRT. Now, SRT will begin sorting out our list in an
alphabetic order, and this counts for
numbers as well. It's going to go in
order for our numbers. Now, it's worth knowing
that numbers get included here in other languages, having numbers such as a list
that contains one, three, and 025 or 025 would get sorted in the order
of 1025 and three, whereas in GD script here 025 and 25 are read as
the exact same number, allowing our sort to be
a little more accurate than there may be
in other languages. All right, so let's take
a look if we run sort, and then we print it again. Afterwards, we can
take a look at it and we can see
the normal look, and then we have a sorted look
that comes into play here. Now, this also runs
in with our numbers. So what happens if we have numbers like this
running, and we try to sort. Well, you see, we're going
to run into the error here. Because it's not really compatible for the
sorting we resolved. So what we would
need in this case is we could have two separate
two separate lists here. We'll call this one numbs. We'll do our one,
95, three, 287. And if we were to sort this one, we can see all of our
numbers will get sorted out just as we would
expect in order. So one, two, three, 87, 95. So we can sort a list of numbers and we can sort
a list of strings, but we cannot sort a list
that has numbers and strings. So we need a list that's
one or the other. If we have a list that contains both then we kind of
got a problem going on. We just have to accept the fact that we're
not able to sort it, and maybe we should go
back and rethink how we're organizing our
lists that we need. Now, what we have as well here is we can take a look
at the length of a list. Now, length when
we get the length, this is actually going to give
us return a number to us. And when it comes to a list, it's actually called size. So if we print out
the size here, we see we're going
to get a number. In this case is telling us five. Now remember, we
have index zero, one, two, three, four, but the amount of
items we have are one, two, three, four, five. And since this gets
returned back to us, we can actually store
this into a variable, and we'll call it List. We should probably
call it list size. But here we go. And then, of course, it's just like any
other variable, and we can go ahead
and just call it in. If you need to get the size of a list for any
reason whatsoever, and there are quite a few
reasons that you'll come across to your
journey that you'll need to know the size of the list while your list
can dynamically change, Alright, so that covers everything that we're
going over here with list. So we're now done with list, and we're going to move on. We're still going
to use our lists, but we're going to cover a
completely different topic now or in the next lesson. Alright. Take care. And if you need to go
back, review this. The list section here had a
lot of things to go over.
11. 11 for Loop: Now that we know how to
create our list, edit them, add to them, remove from them, and get specific items
out of our list. Now we can take a look
at another feature set, another basic coding term, we're going to be talking about what's called a four loop. Now, there are oftentimes
where you may need to perform the same action on
every item within your list. For example, if we wanted to
list out all of our items, we would need to come in and print all of these things out,
right? So let's go ahead. Come in, groceries, and we're
going to need index zero, and we'll just copy this down. One, two, three, and we
can remove that editor. They'll say index one,
index two, and index three. So normally we would
have to go through and do something like that if we
wanted to list them all out. Now, this is tiring. It's needless or needlessly
takes up a lot of space. By the time we've gone
through them all, and honestly,
looking at the code, it's not a very attractive code, looking at the same thing happening over and over
and over and over. But when you want to
perform the same action on every item inside of a list, we use what is
called a for loop. So looking at our
groceries list up there, we can see that
it's full of items, and if we add anything to it, we're going to have to add
another print statement, another one, another one. Anytime we remove it,
we're going to have to pull or delete
lines out of there. It's a hassle, it's
annoying to maintain. But we're able to automate this process within
this four loop. So if we want to print things out just like we're
looking at here, all we have to do I just
comment that out real quick. As we say, or, and you notice that's
going to change color. We have a keyword here. And the next item
here is you can use pretty well any variable
that you want to use here. This is a completely new one. If you want to do something to help you keep things clear, you can use item, but a popular popular shorthand is just using I and
I stands for item. Now, we talked about
variables and how your name should it should
speak to the person, you should know exactly what it is just while looking at it. And it's become common
practice to use I to stand for item that
once you get into coding, you're going to
recognize what that is. And also, if a variable
is only going to be used in one spot, such as in this one loop, it's okay to have your variable
be shortened like this. But going on, so we have four, we have a variable to represent our items to four
I or four item, we say N, groceries. And what this is saying
is every time we go through and do whatever block
of code we write down here, I is going to be
equal to tomato, and then I is going to
be equal to pickles, then I will be ketchup, and then I will be buns. So at the end of our for loop, we can put a colon, head enter,
go down to the next line. Now, you notice how we are
now indented two levels now. This is our first time having
to indent a new level, so make sure that your
indentation is correct. When coding in some languages, they use the curly braces, but in languages like
Python and GD script, we use the indentation method. And I've seen quite
a few people come up with errors or tell
me something isn't working when their
problem ends up being that they're not indented enough or they're still indented and then come
backwards then come out. So do keep an eye on that. And let's go. So for
item in groceries. All we want to do is we want to print our groceries, right? We just want to print that item. And that's it. That's
all we have to do print, pass in I for item. That's all we have to do,
and we're going to get the same result as you see here, now, the difference
is is we can go ahead and we can add as many items
as we want to this list. So we can come in
and go like this. Again, you see how many items we have starts
getting ridiculous. And this happens when we start adding or appending more
items into our list. And you see, I don't have
to change my code at all, and they all get printed out. No problem. Same as if we
were to delete them all. And go down to two
all of a sudden. We only have those
two print out, we don't have any issues. Was back with this print setup, we're going to have issues
because at this point, when we had all of
these items in there, we would have had to
come in and create a bunch more print statements or whatever it is that we
want to do to each entry. And now that we're
down to two, we would have to come in and modify our code and remove the
bottom two lines here. So whenever you want to run the same code on multiple
items inside of a list, we're going to use a
four loop for that. All right. So hopefully
that's clear. Inside of our four loop, our first item here
is a variable, commonly referred to as I, but you can make it whatever
you want. Stands for items. So for each item in groceries, we're going to print that item. So I is going to be
equal to tomato. And then once we print it
out, I is going to move on and become pickles, and
then we'll print it out, and then it moves on to
the next item and so on. Just back this up here. There we go. Now, what if we want to do something after this four loop has completed? Well, we're going to hit Enter to go down
to the next line. And you see how we're
still indented two lines. Well, what we can do is we can
hold Shift and hit tab to, I guess, outdent, right? We go back one level, or you could just
hit the back to base key once and that we'll
also take you back one. And now you can
see that the carat here is lined up
with the four loop. That means we're outside of it. So we can go ahead and
print now and say, four loop completed, and we'll see that's
only going to happen after everything
else has been printed. So if you want to do something
outside of the four loop, just make sure you pull your
indentation back a level. Now, to help you avoid errors, make sure that everything
as I was saying, as I said earlier, make sure your spelling is
correct for things. Capital G for groceries and
a lowercase G for groceries. Though to us, they're
the same thing. They's both groceries. They are, as far as
code is considered, two very different items or two different
variables in this case, and same with our I there. So we say four I to lowercase I, we can't print to capital I. It's not going to
know what that is. And we're going to have
errors from there. And then, of course, our
indentation levels that we just went over. All right? So that completes that on as far as a basic four loop
goes and principles of it. Now, you can do the
same thing if we had set of numbers here. If we were to come in
here, you can come in. Just put a bunch of
numbers. Oh, this minum. So now, when we do
for I and minum, I is going to represent
the numbers three and then 675 and then 23 67. So since we now have numbers, we can also do math with that, so we can say I plus 100. Keep things simple.
And there we go. We can now see printed out 103, 775, 123, and 167. And then our print
statement afterwards telling us the four loop
has been completed. So if you don't have a string and you have
something like that, you could perform some
math. You have numbers. Of course, with strings,
if you really want, you could insert them
into a placeholder, if that's what you
wanted to do repeatedly. All right. So that gives a quick look over what a four loop is
and how we can use it.
12. 12 Range: Something that we can
use a four loop with. Typically, when we want to do something maybe a
set amount of times, but we don't need a list. We don't want to go through
a set number of lists or a set list of items
we just want to do something a set amount of times. Well, this is where things
like range come into play. Now we can use range to get all numbers between a set
of values if we wanted to. And this would require a couple
of arguments pressed in. If we take a look at range, we can see this, well, in this case, just has
three dots at the moment. But the first argument is
going to be the lower number. So if I say ten, then that takes a
second argument, which would be the higher
number, so let's say 20. So this would give us a range 10-20 so let's go ahead and print this out in
the form of a let's say 44, let's say, N for number
four N in range. And let's print N
and see what we get. Well, if we look at it, we
see we got ten, 11, 12, 13, 14, 15, 16, 17, 18 and 19. So you don't get the last number that's printed out here
because once we get there, if you can imagine it,
if N would be equal to 20 and 20 is not 10-20. It is 20. So it does not get printed, and
the four loop ends. Now, likewise, we can come
in here and we could put a range of what if we put a range of just 20?
We print that out? What do we get? Well,
we got the same thing. We only go up to 19, but
we're starting from zero. So if I wanted to do
something 20 times, I could put in the number
20, and it would happen. It's just since
we're starting off with our index at zero, starting counting from zero
and not counting from one. So using this, we're able to
go through a set range of numbers either from zero up to a number or all
numbers between a set range. Now, you can do this for if you want to repeat
a specific action. You could do this if you
want to do or loop through it based off how big
your list is, right? Because we know how
to get the length of that now by calling size. Anything that can give you back a number, we can
plug it in here. That's really all range
is for is to give us all the numbers within a set ring and then the four loop has
us going through. So one thing that we can do
with this is, for example, let's take a look, and we
could print out or rather, let's go ahead and
create a variable. We can create a
whole new list here. So we'll call this square, and set this equal
to an empty list. And what we could do
is we could then do square pen so we can
add to our list. And what we're
going to add would be an exponential value. So we want to add all
the squared numbers. So numbers 0-20 all squared up. So we would put that in
a Posh do exponents. So I'll say N for whatever
number we have here. With the power of two. And
we want to print the inside? No, we'll print on the outside. We'll go ahead and print square. All right. So we have an
empty list to start off. We're going to go through
every number 0-20, and we're going to square. So we're going to
say zero squared. Whatever that equals
is what we're going to add into this list. Is going to say one squared,
that equals will go in, two squared will go in,
three squared, and so on. So if we take a look
at our list now, you can see we got
zero, one, four, nine, 16, 25, et cetera, all the way up to 361. So range is a way that we
could add some numbers into a list or create a list based off of something
that already exists. So preexisting value. All right. So that's about all we
can really do with that. So there's four loops and how we can use
them list with a list. And there's four loops and
how we use them with range to repeat a set of instructions or a piece of code for
a set amount of times.
13. 13 equality: Oh the core of every check. So very important part here to coding is going to
be the if statement. And these are the kind of things that we would run through in everyday life where we check if this happens,
then we do this. Otherwise, we do this, right? So for example, just using
your computer there. If you're in editor, if you press K, we put K on the screen. Right? If we hit backspace, we delete the
previous character. That's the general idea of
how an if statement works. Now, an if statement is always checking to see if
something is true, right? So if we press K, which we did, we pressed it, which
means that is now true. Then it's response was
to put K on the screen. So in order to get these checks, we have to use if statements with what is called
an equality check. Now, an equality
check is basically check if two items are the same. And we can check if two
items are the same, easy. We come in, and we do a print. We can say five
equals five, right? We can do that, and
if we print it out, we're going to get
the word true. Now keep in mind when we
do an equality check, this is going to
be a two equals, double equals sign here. So if five is equal to five, so if five and five are the same, we're going
to get through. Now, if we check for
five equal to six, we're going to get
false because five and six are not the same. They're
two different things. And this counts with
printing as well. This comes back to our
statements earlier. So if we have tomato with a capital and we check if that's equivalent to tomato with a lowercase and we
print that out, you see we're going to get false because even though to us, it's the same word
because one has a capital T and one is a lowercase code sees it as two separate things. So they would both have to
be capitalized to be true. So that's all the
equality check is. It's checking if this is true or if these two things are the same, then
we can do something. So let's go ahead
and jump in, right? We can say if, and
then you can type in. So if we do our tomatoes again, tomato. Double equals tomato. And then we end
this with a colon and we enter to go
on to the next line. So now we're indented one block. So whatever we put in
here is going to happen if these two are true, right? If this condition is
true, we do this. What we're going to do
is we're just going to print a string. These two are true. So if we were to print that, we go ahead and start it and we notice it doesn't print
because as we went over, T and lowercase T make a difference, so
they are not true. But if we add apt T in there, then this indented
block is going to run. As you see, these two are
true are now printed out. Now, aside from the
equality check, we can also do an
inequality check. And in the case of this year, where we have an uppercase
and a lowercase, remember, we can use two lower. So in this case, if we want to see if these
two are the same, we can say if capital tomato is equal to lowercase tomato
dot capitalize or true, which they would be because it capitalizes the first letter, then these two will
come back as true. Now, alternatively, what this alternative though we can do is we can
use the inequality. And with that, we do we can
do exclamation point equals. And that means not equal. So the exclamation
point means not. So if tomato, not equal tomato, which means we're checking
if these two things are different, then it's true, and we go in and we go into our piece of code
here, or indented block. Now, alternatively,
what we could do is we can actually type at the
beginning the word, not. So, if not, tomato equal tomato. And that would give us
the same thing as saying, I tomato not equals tomato. So you can either
write the word or use the exclamation point before the equals, if
you want to check that. There are plenty of times
where we're going to check if two things are not equal to each other in order
to achieve different things. Now, we looked at this a
little bit with numbers. But what we can do is
we can actually advance to if you remember back in math, where we had greater
than and less than that we had
to check and use. We can use that here
in code as well. So we can say, for example, if we went back to
our five equal to six and we'll print out equal? Does five equal to six?
No, of course not. But we can ask if five is
less than or equal to six. And then we can get
our block pill, which obviously says equal, which is true, which
chans out there to make it a little more
accurate, right? So if five is less than
six, less than or equal to. Notice that. So it could
be six compared to six, and it would still
come back true. Whereas if we just had
the less than sign, it would come back
false because six isn't less than six, six is six. So we can use less than,
less than or equal to, greater than, reader
than or equal to, equal to, and not equal to. I know that's a lot of equality signs and symbols
for you to remember, but hopefully you can keep those kind of checks
in the back of your head. And we can use the s
for if we were to say, say someone goes to the store and they want
to purchase alcohol. Let's say it's 19 for the age
there to purchase alcohol. And obviously, you're going
to have to show your ID, prove your age, right? And if we were to
code this scenario, the cashier is going
to look at the ID, and they're going to
perform an equality check. They're going to see if
the person in front of them if they are 19 or older, greater than or equal to 19, then we come back as true, and we would perform the sale. If they came back
as under, right? So if that check
came back as false, then obviously, you
wouldn't sell it to them. And that's the kind of route that I know some
of these players have gone with video
games as well. So if a game is
rated M for mature, that's, I believe, a 17 rating. And then we're going to check to see if the person
is 17 or older, greater than or equal to 17, sell the game, if
not, refuse sale. So those are two examples of how this kind of if check and equality checks
kind of translate to, like, real life in these
real world situations. So now that we've covered one, we can also cover two
conditions at the same time. So we can say I six
is less than six, and something else to say, and five is greater than two, so we know one of
these is true, right? We know six is not
less than six, but we know five is
definitely greater than two. So if we were to print this out, we'll see, it doesn't come
back true, nothing happens. We don't get to this block. And the reason for that
is because both of these statements need to be
true because we're using and. So this piece needs to be true, and this piece needs to be true. So if we were to change
this down to five, should we say if five is less than six and five is greater than two, it comes back true. So you can have
multiple conditions, and it doesn't have to
stop at two, right? You can come in and you
can add a third condition, a fourth condition,
a fifth condition. You probably shouldn't once we have that many
conditions going on, but the point is
is that you could. You can have as many
conditions as you wanted. Now, what we can also do
is we don't have to check if one of these how
change Baca six, less than six, we don't have to check if both of these are true. We can use the or operator. And this will check
basically if this is true or this is true. Condition one is true or
condition two is true, then we advance inside
of our code block. So we only need one instance
to be true when we use O. We need all the instances
to be true when we use and. Now, what's important
is if you don't want to write out the words
and as well as or, we can actually use
two vertical pipes to represent or or we can use two ampersands to
represent the word and So whichever route
you go with that, again, it's going to be
personal preference, whether you use the
ampersands or the pipes or the aprisands and pipes or
just writing out the word. It's not going to
change anything. And as far as I'm aware, it does not affect
performance in any way. It's just two options of
doing the same thing. So ultimately these come back
as either true or false. So ultimately, this is what
we are dealing with right? So we're basically
checking if true. So if this is true, then of course, we
print it out, right? That's ultimately
what we're doing. But when we're doing
the inequality checks, we're checking if
something is false, right? So we're saying if these are
not if they're not equal, then that is true, and
we move into our blog. All right. Hopefully, that
made sense there. There was a lot of things to kind of juggle
around in there. If you're a little confused,
go back, watch it again. But that'll do it for
our equality checks, inequality checks. A Boolean is just
the result here, either being true or false. And let's see, that
covers we also went over multiple conditions
either through and or through using or. And we've compared
numbers. We got greater than less than equal
to not equal to. We went over a lot here. So I'll do it for this section
and we'll move on to well, continuing our I
statements here.
14. 14 if elif else: All right. So we touched on the if statements briefly because we needed to in
order to use the qualities, equality checks and inequality
checks and all of that. So let's dive in a little
more on the I statement. Now, with I statements, you'll notice in the
conditional section that we were going through, we start our code with I, of course, because we want to
check if something is true. So the if statement says, I this is true, continue and
go into my block of code. So now, this is a
conditional that tells you if something is true
or false, essentially, and pretty well always
follows or is always followed by the I keyword. I think I worded that
a little weirdly. Our check always comes
after the I keyword. So just like when checking for multiple
conditions to be true, we can use that in
our if statements, like we checked with
strings earlier. But one of the key differences
is It's a block of if statements can get a little complicated when we have a
bunch of checks that get used, as you saw when
we could put and, and we could just keep adding more and more conditionals and we could use
Os to keep going. Pretty much we have
an unlimited amount of conditions that
we could check. And we can use condition, any conditional
with I statement. So if we look at the simple if statement like we
did before, we said, If tomato equals tomato, then we would say
it's true, right? As long as they
were both spelled exactly the same with
capitalizations and all that. But what if we want to
have a catch all, right? So what if we want let's see. Let's create a
variable called NUM. We'll set it equal to six. We'll say inside if I ready, we'll say if num is greater
than or equal to six. Right. Colon and we'll say,
go ahead and print in there. Ha, it's greater. And if we go ahead
and print that out, we'll see, Okay,
that's he comes back. It is greater than
or equal to six. However, if we say if
it's greater or equal than to seven,
nothing is going to. But in some cases, you may want something to
happen as a result. And this is where the else block comes in. I'm just
going to lower that. So else, followed by a colon, that's all
we have to put there. We're saying if all those
checks above are false, none of those are true, then the else block will
take care of it. So we can come in
here and we could go ahead and print this, I have a space in there, say, this is not greater. And we can go ahead
and have our checks. So now we're really
going to get this is not greater or we'll
get the response. This is greater. So regardless of whether
it's true or false, we're going to have
some sort of response, some kind of action and you might go ahead
and think, Okay, well, you can just
go ahead, von down, do another if, another if, and another if, and you can keep making all these
different checks. But the problem is, is if
all of these are true, for example, if
we change this to four, this one to three, this one, two, Actually, if we change these, we
want to go the other way. If we say if these are seven, eight and nine, so if these
are greater than six, since these are if checks, all of these are going
to run as you see here, they ran for num,
seven, eight, nine. They all came back true, so
they were all triggered. However, what if we
only need one of these? What if we just want
the first one to be true to trigger it. And then if that triggers, none of the other
conditions are checked. Well, this is where another
keyword comes into play here, and this is the else if. So it's kind of a combination of the I and the
else put together, and we just call it LF. So if we come in here
and we say if for these. I'm saying, if this is
true, then we do this. If not, then we check se, if this is true, do this, else, if this is true, else,
if this is true, and if all of those fail, we'll be left with just
the else statement. So if we were to run this now, you can see the first one
becomes true up here, and then we never get to these. And we can tell that if we
come in here and we just put a bunch of
exclamation points in so we can differentiate it. We can see the first one
gets detected as true, and then we skip
all the other ones because we don't
need to check them. So we're not checking if all of these things are
true individually. So there may be
certain situations where you want to use multiples, multiple if checks on their own. But a lot of times you're
probably going to have more of an I else if or an if else. Kind of chain going
on like we see here. Now, this can really
get things to be a little complicated at
times when we go into this. So if we take a look at an
example here, there we go. Alright, so we have all of
our checks in place here. So I just select a random
number for age to 15. So we're going to check
if age is less than 13. All right, we're going to
take on the assumption of maybe movie theater
prices, right? So come in there, we'll say, I age 13, it's going
to be this price, if it's 13-64, so it's greater
than 13, less than 64, it's this price, and if it's over than 64, we do this price. And then we have an here
saying that he is not valid, which is just in case catch all. We should never have a
situation like this. Let's go. So we have 15. We can go through ourselves. We'll say, it's
not less than 13. So skip that. We go
to our second check. Age is greater than
13 and less than 64. Yep, 15 is. So we should get
back the price is 14 50. If you play that, we can see
that's exactly what we get. So there is an example
of doing an if, else if and else kind of
chain going on there. So again, the example
there would be something like maybe
a movie theater with different ticket
prices based off of the age of the person
who needs a ticket. Now, we can use these
if statements as well, and merges kind of with our
four statements or 44 loops, and we can chat things such as we'll let's say we
have our groceries. Right? Cereal. Ketchup. Milk. However, we may have a check
for out of stock items. Which maybe you're developing
an application that keeps track of what items are
out of stock and in stock. When an item is out of
stock, they'll appear here. So we'll say, this store is
out of stock of milk, right? So we'll say we have no
milk, but we want to check. So we want to go through
our grocery list. So we want to say for I, right? For item in groceries, just like we did previously
in the four Luke section. And we want to see if that
item is in our out of stock. So putting this
whole thing together so that we have for
item in groceries. We want to check if
I in out of stock. So using in here is going to check if the
item is in there. So if cereal is in this list, we're going to do this
next block of code. And if it's not, we're
going to continue on. So we're going to
say we're going to print and we're bringing
everything together here. We'll say percent
S is out of stock. And then we'll just pass in the percent I to pass our
item into our string. Putting this whole
thing together, we see the only thing
that triggers it is milk because milk is indeed inside
of our out of stock list. So you can see how quickly we're starting to
string things together. We're printing out
to our console, we're inserting variables
into our strings. We're using I checks to
see if something is true, and we're running a four loop to go through everything
inside of our groceries. Go through everything
inside of our list. Alright, so that should cover everything here to go with
the if checks and if, else, if, else, as well as
hopefully some examples to make things a little clearer and to see how all
of this comes together.
15. 15 Dictionaries: A all right. Everyone, today
we're going to take a look at dictionaries. Now, we're obviously not talking about the kind you pick up, this kind of word and a
definition associated to it, but you could use a dictionary
to make a dictionary. And a dictionary is pretty good relations to what
a dictionary is encoding. The reason for this
is because they work in the function of
having a key value pair. So in relation to a
normal dictionary, we would have the
word as the key, and then the definition
would be the value. So dictionaries are a set
of data that can hold data types of any kind that we have discussed
up until this point, including other
dictionaries in of itself. A dictionary can keep a set of related information
all at one place, such as game or program settings or information
on enemy characters. A dictionary can easily be
identified since all the data, all of their data will be
encased within a set of curly braces versus a list which uses the square brackets. So let's go ahead
and take a look at how these dictionaries
get formatted. All right. So going here
up here at the top, we're going to make
a new variable. I'm going to call
it M dictionary. And of course, we're
going to set this and equal to a pair of curly braces. Now, the way this works is we can go ahead and enter to
make it nicer to look at. And we do a key value pair. So for example,
we'll say key one, and then we do a colon
and then the value. So we'll go this my value and if you want
to insert another one, we put a comma, and we can enter drop down to the next line,
and we can do key two. There we go. This
is my new value. And, so on all the
way down the list. Now, the name of
our dictionary can be anything you'd like, just like a normal variable. But once we get inside
our curly braces, you can see we have a string, and this first string
here is our key. You can obviously name
this whatever you wish, but similar to variables, it should be clear on what
the data it's related to. So it should have some
kind of indicator of what the value is relating. Example, this could be inside of maybe a weather dictionary. A key might be temp
or temperature, and then the value would
be the actual number. All right. So an example of this if
you're doing settings, could be having an
audio dictionary and a graphics dictionary. Now, your key, as you can see there is followed up with a
colon and then your data. Your data here is what we're
referring to as the value, and it gets treated similar to a list with an index of zero, if that makes sense,
being your first value. Now, we could go
ahead and call this with different situations or a couple of different ways
that we can actually call it. You can even, I guess, we can have different
data types in there. We could have a list in
there as one of our values. So if we want index zero here, we'll give it will
give us our name, returning with Jim
and Index one, returning yes. We're
turning as our health. So if we had it in sorry, a dictionary inside
of a dictionary, which we can go ahead
and do here, right? So we'll say this is name, and this would be report back as him and the next one
we'll have health, and we'll say 100. So in a situation like this, This where indexes
that are coming from. Now, of course, we don't
have to use indexes. We could just fully write out names when it comes to dictionaries,
which is always nice. Just remember each key must be separated with its own comma, so let's go ahead and
come on down here to our reading take a look at how we can access
a dictionary. All right? So when we
access our dictionary, we'll go ahead and
print it, of course. And what we're going to be
looking at is we're going to be printing out my dictionary, of course, and we could
just print out like that. But of course, if we
want to narrow it down, let's take a look. So it gets printed out is we get Key one and then
we get key two, and then those go inside of another curly brace
for the other set. So we can either get Key
one or key two here. Now, if we want to get key one, we can just do curly brackets right next to it,
similar to an array. Only we can go ahead
and type in Key one. And as you see here,
we're going to get the result, Key one down there. And the same thing.
If we do k two, we're going to get the new dictionary
that Kit is holding. Now, what happens if
we go ahead and use zero for our dictionary
here? Try to access that. We're going to run into into this situation because we are out of bounds of
this dictionary. So there are different situations
for something like this. For example, what we could do
is go my dictionary, right? Again, and we can do dot keys and
something like this. This is just going to get all of our keys and return
it as an array, so this is going to be
a list of all our keys. And then we can do our square brackets and
put a zero in there. So we could do something like
this, and this would work, although it's a long certainly much longer
than it needs to be. And I know with three, occasionally, this
would work as well. You could just dot Key
one. Yeah, there you go. So you can just do dot and
put in the key value here. So we can do two, and the K two goes into
another list of its own, sorry, another
dictionary of its own. So we could then go
and do another dot. So we can do my dictionary.k2
dot, I'll say Health. And as you see,
our result is 100. So there's a couple of different ways that
we can actually access the contents
of our dictionary, be it going to log method by getting a list of our keys
and putting in an index, just passing in the
key that we want as a string or using a
dot method like this, similar to a function
call or a method call. Now, when we have dictionaries
inside of dictionaries, you've seen essentially what we'll be doing here
with dotqt dot HeL. Only you can access that
through our square brackets. So we can do key two. And then right beside
it, we will just do another set of
square brackets. That's also we can just
write it out like that, which has a pair or two pairs of square brackets
each key going down. So that's how we can access our dictionaries and
side of dictionaries. It can be a little confusing, so hopefully that
was clear enough, at least if not the
explanation with the actual demonstration
with seeing it in use here. Now, dictionaries can hold, all other types of data. So they could have list in them. They could have numbers,
you know, integers, floats, strings, dictionaries
and side of dictionaries. So we have this whole wild set, and of course, accessing
those is really going to come down to the methods
that we've shown you there, and based upon what
type of data it is, obviously if the value
is going to be an array, then you're going to access the values in there like an array. Now, what if we want to add
into our dictionary, right? So we have my dictionary there. Let's go ahead and
create a new one. We'll call this Colors, have the sequel to an
empty dictionary. Give me errors for down there because we
didn't fill that in. Now, what do we
do for passing in some piece of data here if we want to add a new
entry into our dictionary? Well, we can just go to our
colors and we'll go ahead and pass in a key as if we
were trying to access it. So we'll call this let's go with cool or cold colors, and then we just set that equal to the value that we want. So we'll go with a blue. If
we print our colors now, we should see blue
being the value, being a string value
here of the key cool. So we should see that here inside of our colors dictionary. And there we go. We can
see that right there. So it's as simple as that, you add onto it, and
this should work for an array as well. So if we just have a list here and print that
out, as you see, it works just as you would
imagine it works the same, even if we're doing different
type of data set here. So there you go. Easy
enough for us to do. We simply call it and then set and this works the same way if you want to
reset or change this as well. So if you want to change
the key inside of it, if you come down here
and change this books. So first, it's going
to be these numbers, and then we're going to change it to red and print
it out again. As you see, you can
add keys to it and overwrite keys using
the same format. Now, what gets a little
complicated is when you want to add a dictionary
into the dictionary. Do we just pull that out? And let's see if this now
works, typing this in. So we'll say e one. All right, we'll say value here. And let's see if this works. Alright, cool. So we can do dictionaries this
way just as easily. Awesome. So I don't have to go over any type of work
arounds for that. Perfect. All right,
so there you go. There's how we can add to our dictionary and
overwrite the keys. Now, we can take a look at looping through
our dictionaries. So obviously,
dictionaries are going to be a little different here. So we're going to use
My dictionary again, and we're actually going to run a four loop so we
can go through it. So what we want to
do is we want to do four and typically, we're going to use four
key in my dictionary. So at this point, we're going
to get key one and key two. This is what we're
going to loop through. And if we just print
that out, print P. You can see we're
going to get key one and two printed out to us. Now, if we want to go even
further in inside of this, we can go for value, let's say, in Key, we can print out value and we can see what we get there
going two layers deeper. Oh, here we go. My mistake. My dictionary and surround the same curly
braces. There we go. That's what we want to do, and we'll print the value that way. And there we go.
So we see Key one, name, health and key two. Now in this situation, since we do have a string here, it did print out all the
characters individually, which is what you're seeing
here with it being vertical. And characters do include spaces. That's all
we have that there. As you see we went through for key and dictionary
so we got key one. And then what we do
in here, we then loop through the value, and we're printing off all
these letters individually, and then we print the key name. So that's why we have
this and then key one. And then we move into key two, and we print out the next one. So name and health, and then we print on key two. So you can see how we loop
through these dictionaries and you could go
further in or you can loop through a specific
set of dictionaries. So you can see how we go looping through these dictionaries. All right. So that's about everything you
need to know in order to use and access elements of your dictionary. So
that'll do it for here. Next, we'll take a look at
getting input from the user, and we'll be jumping
into some more looping.
16. Getting Inputs: Alright, so it's been
brought to my attention that apparently inputs is missing
from the language portion. So we're going to go ahead and I'll show to do
that real quick. I'm just going to do
a user interface. I'm just going to click
Control for my new scene. I'm going to go ahead
and rename this. I'm going to call it. Let's go input test. I'll go ahead and save
it with Controls, input test dot TSN. That's fine. And I'll add a script to it. Great. And I'll just close all these other sections that we do not need
for this, right? So, in my case, I'm extending a control,
but in your case, might be extending
a character body two D when it comes to creating players for games
or really anything, it doesn't matter too much what it's extending because you can add in or take input from
pretty well any node type. Right. Now, what I'm going to Yeah, we'll just use print
for acknowledging it. So there's a few ways
that we can get input. And one of the main ways that you'll see a
lot of people do is going to be inside of a
funk underscore process, or it's going to be under
funk Physics process. These are two different
points in the frame. The physics process
is where you should put anything that
is physics related. So something like
moving your player. Since you're probably going
to have to deal with things like collisions and other
physics based things, you should probably do it in physics process at the frame. And process up here is probably where a
lot of other things within your projects
are going to go, but you usually want to try and keep this as clear as possible. Now, another situation
that you might see used is going to be another
function called input. And unhandled input, and our last one is
unhandled key input. Now, there are some
small changes as to how these are
handled and see if I just hold my mouse over here, depending on the
version of Gudo you have, you may or
may not see this. If you don't see the pop
ups and your version, you should be able to
just hold control and click on the function and you'll get the same information. You read about some of these differences here
with unhandled key input, unhandled input, and so on. But these bottom three here
are specifically for input. And then up here is where you're going to have more
continuous things like holding down forward
to move, for example. All right? So I'm going to get rid
of the unhandled ones. We're not going to
need it for this. I just wanted to point
those out to you show those are an
option to use here. I'm going to get rid of the
Do I want to get rid of that? No. I'll keep that
from my example. And I'll get rid of physics process just
because I'm not going to be moving any characters or
doing anything physics based. And I'll show you here. The easiest way for us to do some input is going
to be if input, and this input class holds
all the inputs that are available either built in or ones that you add
to the input map. So we're going to
say I input dot. We can say I and
you can see here, I anything pressed is
similar to how you would get to a main menu and
would say press any button. So if you press any button,
this is going to trigger. Other than a main menu, I'm not sure where you
might incorporate this, but if you do need it,
is anything pressed is there for you? And we'll
go ahead and test it. So we say, I input is anything pressed and tabbed into that, we'll say print something
if we can spell, spelling is hard sometimes, something pressed, and I'm going to go ahead
and hit Run current scene. You see, as we sit here,
just take a second to run. There it goes. If I hit any button on my
keyboard, I'm going to hit J, something press and it
actually triggers five times with it being just where it is
right in the process. If I hit L, there we go. We can see that
numbers increasing. If I get rid of the stack, you can see Every time
I press buttons here, you can see our number
down here in the corner. Filling out, right? So even just clicking into it, because that's input,
that's something. Left click, right click, any of these buttons on
the keyboard, right? Always work. All these
things trigger because anything can trigger.
It's anything pressed. Now, what other
options do we have? We have is, and we have
action just pressed, action just released,
action pressed. And then we have some joy. So these joy buttons, of course, is going to be your
controllers, right? So it's going to ask
you for a device, and then it's going to
ask you for a joy button. Now, I don't have a
controller plug in, but this is you can do something specific
for controllers, which is not what we're
going to be doing here, but it is something
to point out for us, just like we have key label, keypress, the physical
key, mouse button. So you can see, you
have a whole slew of things that you can here. So let's go with the easy
one, the simple one. Let's say, sorry, just
take a drink. Okay. So if input is
action just pressed. Now, you're obviously not going to have a
whole lot of these. You're probably
going to see a lot of these UI buttons down here. Some of these UI except, I believe that is the
enter key by default. And you see we're passing
in a string of an action. Yeah, so we'll go
ahead and put that in. And now you'll see when I run it now keep in mind this
is action pressed. So if I press the button down, I'm holding it, it's only
being pressed one time, right? It's only
showing up one time. No problem. And I let
go, nothing happens. Now we can have
another system set up, so we can say I
input dot is action, we can say release. We'll go with the
same button here. I accept, and we'll go ahead and print and we'll say
something release. We have pressed
and just released, and we're using the enter
key for both of those. So if I press this button down, it says something pressed. If I keep it held
down, nothing happens. And as soon as I lift up off of the key, something released. So depending on
what you're doing, you may want something
to happen on press, or you may want something
to happen on release. Now, alternatively, there is another option
that you saw on there. It's going to be if
input is action press, so not just press, but press. And I'll say I accept. Great. So we can see
the difference here. Print. This is what's going to trigger when something
is held down. So something held. So you're going to see,
I'm going to press it. We're going to see our
something pressed. I'm going to keep it
held down for a moment, so we're going to see a spam in this output console of something held down,
something held. And then when I release,
we'll see something released. Right? I did that just for a moment there.
I pulled this up. We can see something pressed, and then something held
for all this time. And then something released when I lifted off of the button. They see you got a three
different situations that you can use here. And depending on the kind of
system that you're doing, what kind of inputs
you're doing, you can use any of
these for your purpose. Now, I I did mention
that we also had key say is key Press. And then this is going
to take a key code. So in our case, with what
we were doing now will be key Enter, right. And we'll just go ahead
and print Enter, press. And we run that, we hold it down and we can see we get that. So we don't get just pressed and just released
when it comes to keys. So do keep that in mind. Now, if you want to set
up your own actions here, I'll just back this up. More. There we go. Like I
accept like we have here. We're going to be doing
this in the gaming portion. But you just go on up
to project settings, go to Input Map, and then you can
add a new action, make sure you're in
the right box here. I'll say new we'll go ahead
and call this test action. Hit the add button. Now if I scroll down to it down
here at the bottom, I can hit this plus icon, and I can put whatever
button I want. So let's say I put
the K button, right? I hit Okay. And I can come
in here and I can say, I action just pressed, test action. Now I run that. Now, if I hit the K button, we got that something
pressed being triggered. So adding new inputs to your project is as
simple as that. And there are a few other
things that you could get into. So are going to have or they're going to
have more specifics such as action word things
like action strength. So action strength is where we're going to get
actual numbers. So input, get action strength. And if we were to
take a look at it, we see if we're going
to get a blows. We're going to get
a number back 0-1. And this is how much or how hard a button
is being held down. So on a keyboard, it's
basically zero or one, right? It's either press or it isn't. However, if you deal
with controllers, this is where you can create things such as holding a button halfway down to aim and pressing it all
the way down to shoot. For example, there were
quite a few old games that have that kind
of system with that. Metal gear solid
had where you would press I think it was the square
button in the old games. You would press to aim, and you would press
it all the way or release to do the shot. And get action strength is how we would actually get that. Alright, so there's a lot of options you can do in
order for getting input, but I've shown you all the main ones for dealing with that. And I still have
input here set up, and that's because event
input event is anything. So that could be a mouse click,
could be a keyboard one. It could be just moving
the mouse on the screen because mouse motion is
an input event, right? So if I just went
ahead and print event, here. And you take a look. See, as I just move this, you can see mouse motion
comes with a lot of things. The position relative, you got pen and pressure and tilts, or if you want to
do tablet support. You got that. You
got the velocity, which is how fast
the mouse is moving. Alright. Let me see
the button index. So left click is going
to be Index one, right click is Index two. So if you're going to be
using something like input, you're going to have
to narrow it down. So for example, we would
do something like VR let's say I event
is input event. So we can say key if
you wanted it to be a keyboard, JoyPad buttons. If you wanted it to be a button, event action, mouse,
mouse button, mouse motion, screen
drag, screen touch. These are things that
you would use to create a touch screen
button, for example. Input event, shortcut. So you got all these
things in here, but let's just say input event. Let's go. Input event key. And then we can say ar EV equals event as input event key. And let's go ahead and print EV, see what we get from here. We see nothing is
happening here. And as soon as I hit a
button on the keyboard, we can see now we're
getting buttons, right? We're getting key coodes. We're getting the mods, whether it's physical,
the location, whether it's pressed,
and of course, echo, which of course, echo is going to be true if
the button is held down. So we have these
input event keys now. All right. So now we
can go ahead and we can say I EV press, right? So if the button
is being pressed, and we can use the
word here or you can use two ampersands
and just enhanced. So we're checking to make sure both conditions
trouve and EVP code equals P ED, in my case. And I can go ahead and
print out something like D, E, press. Now if I had any other
button on the keyboard, nothing is going to happen,
but as soon as I press the Dkey, we get
that acknowledged. Now, if you really want it, you could just come in here
and inside of your input, just say I input
action press, Film. You can do all that
in here. But when we're getting event,
you may as well use it, and these are the kind of
situations that you can do now, if you want to use
the event as well, as well as the action here. All right. We can say if event is input event key, if we want, and event is action press, and now we can go ahead and pick something we had test action. I don't really remember
what test action was. I'm not going to
idea about that. But I'll say action Press. I don't remember what that was. I think it was the
KK. I hope I'm right. And I hit it, and we
see Action Press. Alright. So there we go. So we have that working for us. All right, so I
hope that gives you a pretty good idea of how we can get input
from the player. There are some other small ways. For example, if we had
a text box on screen, we could grab the text
property out of that. And I believe if
I remember right, we're going to be seeing
that in our first project. All right, hopefully that clears up any confusion
that there may be, and hopefully you can understand some of the ways that we can
get input from the player.
17. 17 while loops: All right let's take a
look at while loops. Now, we've used a four
loop before in the past, and now we have a
second type of loop. And a four loop,
as you remember, we'll loop through a set of items that is within
something else, whether that's within a range of numbers or within a list. A Wile loop is something
that's going to loop forever as long as a
certain condition is true. So Let's go ahead and take a look at how
we can use a Wile loop. In this case, we're going
to use it to count up. All right, so let's
go ahead and create I'm going to save myNum, set that equal to
zero by default. And we're going
to say Wile binuM is less than or equal to five. We're just going to
print out myNum. And at this point, if we
go ahead and try this, our loop is going to get stuck, and the whole program
is going to crash. We're going to be stuck
on the splash screen. And as you can see in the
output console down there, it's just going to spam zero because that's all
it knows how to do. And in fact, this isn't
even going to close, so I have to hit the
stop button in the top. So with a wile loop, it is dangerous to get
yourself stuck in it. You have to have a way
to exit at all times. If there is no exit coded
in, you will crash. Now, there are many ways to
do an exit, and in this case, we're checking if M NUM is
less than or equal to five, so the easiest way
to fix that would be to create that statement
to become false. Now, we can do that by simply just setting M
NUM is now equal to six, which will break it. We're not going to count
up, but it will break. It will break out of the loop. But what we would rather want since we're using a wild loop, we can assume we want to count up so we're just
going to call myNum, say plus equals one. Now, that is the exact
same thing as saying M NUM is equal to myNum plus one. It's just a shorter way of writing it by doing
plus equals one. So now if we run it, we're going to see it
count out of zero, one, two, three, four, five, and then once
we get to six, that is no longer going to
fall within our condition. So that's going to
make our condition return back as false, and we will break
out of that loop. So that is one way and fairly solid way to
break through it. However, it's not the only
way to break through. As you saw, when we had just a print num, we
caused the crash. But what we can do is we can actually use a
keyword here called brake. And that will break the
loop, no matter what, no matter if the condition
is true or false, it's just going to
break out of that loop, as you see there. Even though zero is
definitely less than a five, because we use this keyword, we are able to break
out of that loop, regardless of if the
condition was true or false. Now, we can use while loops with things like dictionaries
and list and a list. So we'll go ahead
and take a look. So we'll say Wile new users. And all that means
is while as long as there are users inside of
this list and it's not empty, it'll be returned as true. And once the list is empty, it'll return as false. So what we're going
to do inside of this loop as we can say our current user is equal to our new users dot POP
and we can pop front. And we'll just go ahead
and print out there. Verifying user, and we can do our percent S and just
pass in our current user. All right. So now if we
go ahead and run that, we can see we're
going to go through. And once everything is exited or once you've popped
all of the names out, this is now false and we
break out of that loop. And you can see
down in the output, we print out this statement for every user that
we popped out. Now, if you want to remove
things out of a loop, we can certainly do that in
a very easy way as well. And, of course, this doesn't just count for removing things, but we'll take a look
at our animals there, and we can see we have
lizard in there three times. So what we can do for another statement check
here is we can say, if lizard, There we go. Or wild lizard in animals. So as long as lizard is one of the keys
inside of animals there, this is going to
continue to run. If you remember what I
said earlier or previously when we were looking
at lists, I said, If you had multiple items
in your list that you wanted to get rid of that
were say duplicates, you would have to
call remove or erase on them constantly over and over and over until
they were all gone. Well, now that we
know about Woloops, we can simply just do a check to see if lizard is
inside of animals. And while there is a
lizard in animals, we're going to go
ahead and remove it. So simple, we're just
gonna call Animals Dot. Remove it, not remove it. What you call erase Lezard. You see here, we're
going to go ahead and print animals afterwards. Every time we remove
it and we take a look. And we see we have
two lizards now. We started with three.
Then we add one lizard, and then we have no lizards. So you can see this
is an easy way you want to run through a loop and say, remove all of the
duplicates out. All right, so that'll cover
it for what wile loops are and how we can use them in
a few different scenarios.
18. 18 Functions and Arguments: Let's go ahead and
jump into functions. Now, functions, we've already
seen and used two of them. We've used process and ready throughout the
course thus far. But you can completely
create your own functions. And as an example, we can have one that it would be something like the
following that you see here. So we could have one called
greeting that welcomes you to whatever it is
that we're doing, right? Books if we can spell
that correctly. Now, you'll notice something
in common with all of these. Now, just looking out all these, you'll see some similarities, and you'll see that these have been the
basic structure that we've been using
this entire time, and these make up the
basic structure of any function you'll ever write. On the first line, we start
with the keyword Bunk FNC, which tells GDScript that we want to define or
create a function. And this is followed up by another word or series of words, but we cannot have
any spaces in it. Which then is preceded by
a pair of parentheses, and this creates a function. Of course, we have
to end it with a colon and then go into the
next line and tab in one. Now, starting on this
second line is the piece of code that we want to write or
run inside of our function, and of course, we'll only
run inside of our function. So if we were to run this right now, nothing would happen. But what we can do is
we can go up into our ready so that when this
script is loaded in, we can actually call greeting the function that
we just created. And that means that
function is going to trigger whenever
ready gets triggered. So though we don't have to write everything inside
of the ready function, we can organize everything into separate individual
functions and call them. This will help keep our code
cleaner and nicer to look. And your function name should
follow the same patterns, I suppose you should
say as your variables. So for example, I went over how your variables
should be preferably shorter, well defined and tell you exactly what piece of
data it's holding. Well, a function should
do exactly that, as well. A function should hold or tell you exactly what's going on inside the function just
by reading the name. And not only that, but a function should only do one
thing and one thing only. That function shouldn't be doing four different
things within it. Now, we've gone
over or use some of these functions that have
taken arguments or parameters. Some of these such as
remove that and erase where we have to add in
another piece of information. Well, we can do that with
our functions as well. So let's say we want to create a program that
welcomes someone. We've done this
before. We've done our percents. We put in that. But instead of creating
a variable at the top, we're going to create one right inside of our
functions parentheses. Now, we could just leave it like this and it'll
take any data type, but we can also go ahead and declare what type of
data that has to be. We can even go a step further and we could tell
it or declare it, as well as give it a
default parameter. Now, when something has
a default parameter, that means it is optional. We don't have to put in an argument in when we call the function
up here and ready. We don't have to type
anything in here, and if we type nothing in, the default parameter is
what will be assigned to it. However, if we type
anything in here, it's going to overwrite it. So let's go ahead and
give it a default of Bob. And we can go ahead and
add percent user in. By, we know what to fill in. And you'll see if we
just call greeting and don't put anything in,
we get Welcome Bob. But if we go ahead and we
type something in here like, let's go with Jim. And we type that in. You see, we get welcome Jim
Jim then comes in and overwrites the predefined
default of Bob. Now, what happens if we try
to put something in that is an irrelevant type?
So let's put it zero. What we take a look at, EC, we immediately get an error, and it tells us that should
be a string, not an int. And that's the benefit
that you're going to get from declaring what type
of variable it should be. If we did not have
that and we just, Hey, user is equal to Bob,
now we could overwrite it. And we say, welcome zero, which doesn't make sense, when you're needing
specific pieces of data into your function, you're probably going to need it to be a specific
type as well. So just like variables, it's going to be a good
idea for you to fill in exactly what type of info or
declare your arguments type. Even if you don't want
to set a default, now, it's also worth noting that we can have multiple
arguments in here, and this is where
positions start to matter. So we've done this
before where we had inducer or name and job. So if we do a comma
here to separate it, and we could put job in there, and we just put a string. And again, we can go ahead and We can call these in any order when
it comes to filling them in in our print just as if
they were normal variables, and you're probably
noticing this error here. Now, functionally, there's nothing wrong
with the code here. But what it's telling you is something that you
got to keep in mind, and that's anything with
a default parameter has to be placed at the end, because all optional
parameters must be at the end of your
list of arguments. It's just the way
it is in GD script. So you have to put all the
mandatory ones upfront, and then the optional
ones at the end. So you see all we did was just switch job and user around, and now we don't
have any errors, even though functionally,
it's the same. All right, so that'll do it for our quick introduction here
into functions and arguments, also known as parameters here for us to fill
in as well as showing you our defaults
or how to assign defaults and the order all
these things have to be in.
19. 19 Function Alias: Alright, so let's put everything together that we're
up to at this point. So let's go ahead and
I'm going to open up the input that we did before just by double clicking on the script out
of my file system. And I'm going to go ahead and grab everything
I had here in ready. And we could stick it in ready. But what we're going to do
instead is we're going to set this all into a brand new function that
we're going to create. And I'm going to call
mine Process text. Process text. On in down there,
and there we go. And we can just now say
pass inside of our ready. All right, so now we
have our function inside of process text. And what I'm going to do
actually my apologies. We're not going
to do that there. That is going to be
inside of our ready. Text process is actually going to be done at
a separate stage, and that's going to
take an argument that we can call new text, and we'll assign it with a
default parameter of nothing. All right. Now, I'm just
going to highlight these, hold Alt and use the up
arrow key to move it up. Alright, so in process text, what we're going
to do is we want to take this text
like it's put in, and we can check it, similar to what we did
here in the process here. So I'm just going to go ahead and copy what we
had in the input, move it here into
our process text. Grab these and pull it back by holding Shift and hitting tab. Now, what we're
going to do is we can keep this as quick, but
I'm going to change it to Q. So if my text equals Q, and we don't need to get
the text field at all, because we're going to use
our new text property. So now we're going to pass in a piece of text into our
process text function. And we're going to
check if new text is Q, then we're going to
call the Quit just like we did in our input, and we're going to
create a variable called My Name if there isn't. And we're going to
assign that to whatever the new text is that we pass into this argument or pass into this function
as an argument. And then we can
fill it in again, just like we did with our input. Not doing anything fancy here. Let's go to we need
to get our input. So let's go into our process, and we'll do our if statement, so we'll say I input is actin and we're going
to go with just release. And we'll go with the Enter. Now, if you put now, if you don't have
any action here, you could use UI
except, I believe, is a default one for it's either space or
Enter or the enter key. But if you didn't create one
before in the input section, just head on up to project
and project settings, go into the input
map tab at the top, add in a new action
called Mind Enter. And then beside that
action after you add it, you'll see a plus button. You can hit that and
you're able to select whatever key or button
you want it to be. So all we're going to
do here when we release the entropy is just going
to call our process text, and we can actually pass in
this text field that we had. So let's go ahead and grab that text field and grab
the text property of. Now you'll see once
we come up here, we can go ahead and type
in whatever we want. And it fills in just as we did previously inside
of the input section. So all this works the same and fundamentally,
it is the same. But as you can see, when we're writing this out,
this is all we need now. We have I key is pressed,
run this function. It's a lot shorter, it's a lot cleaner and
nicer to look at. And most of all, we're able to use this function
anywhere that we need it, so we don't have to
write the same piece of code over and over and over. Now, if you have a
long piece of code, or sorry, not a
long piece of code, a long function name that you just can't think
of a better name for, what we can actually
do is you can actually create an alias for that name. Now, an alias is kind of
like a stand in, right? So we can take this short name, and it's going to
represent this function. So it's going to
represent this long name, kind of like a variable does. We have one short name and it represents this
large piece of data. So this is going to
be one variable name that's going to represent
an entire function. Alright, so let's go ahead and up here at the
top of our script, we can go ahead and
create a variable. I'm going to call this alias. And what you're going to
set this equal to is we can just set this to the
name of our function. All right, process just
like that, and it'll work. So if we come down
here and hit Enter, we can go ahead
and do alias dot, Paul, and then inside of these parentheses is
what we want to pass in. So this would be our text field and our text property of it. You'll see if we go
ahead and run that. Boom, everything works just
exactly like it was before. It's just a little bit shorter
and we're using an alias. Now, alternatively,
if you have maybe you want to create an alias
for a function that lives inside of a
different script on a different note completely, the alternative to it's
going to be similar to that. So I'm going to
create an alias too, and these are called callable. And a callable is
psycho function, right? So the only difference is when we create it as a callable, we actually have to add
two arguments in there. So the first one being
where the function is. So in this case, it is on the
same script as the sales. So we can say self. However,
if this was on, say, our text field, then we would do our dollar text field,cel. But since this is
on the same script, we can type in self, and then it takes a second
argument, which, as you see, is a method or function name
in the form of a string. So we would go ahead and
type it in like that. And now you can see that we can do the exact same
thing we did for alias to.com and
pass in our art. There you go. So those are just two
ways that we can create an alias for a function.
20. 20 Classes: What is the class and
how can we create one? So we've already used
classes already. We just haven't referred
to them as classes. We've called them object. And the line edit here, this is a class, and all the classes that exist are in the form of nodes here. So you can browse
through, and you can take a look at all the
different classes. And there are even some classes that are not in that list, such as JSON, which we'll
get to when it comes to when we go over how to save and load
different file types. But this is what we do, right? You call a class and
you call new to create a new instance of
whatever that class is. Now, in the case of a line edit, we have something graphical, but in the case of
something like JSON, where we don't have
anything graphical, but we do have things
that we can use. And we'll see this
in our next section, we will go over regular
expressions as well. So let's go ahead and give ourselves an idea of
how this stuff works. Let's go ahead and we're going
to create our own class. I'm just going to right
click in my file system this time and select New Script. We're going to inherit
from in this case, yeah, we can inherit
from node. That's fine. And I'm going to call it
my PET class and hit free. And now I'm going to find it and double click it so
we can open it up. And I'm going to
delete everything in it except for our
extends at the top. Now, to create a new class, we actually don't need any of that stuff that
we had before. What we're going
to do is type in class underscore
name with a space, and we can put whatever we want the name of
this class to be. So keeping with the
name of the script, I'm going to call it PET and this is going to
be our PET class. Now, you're going to add a second argument here
in the form of a string, and this would be a path to an image inside
of your project. An icon, and that icon will
actually show up here, similar to how control has a little circle
here, green circle. Your function will
replace that icon. All right. So inside of Pet, what we're going to do
is we're going to we can create some
variables here, right? So savar name, right. And that'll be equal
to an empty string. We'll have our age of our PET. And then it'll just be
set to zero by default, and we can have the type, which will be set to a string. Now, since this is going
to be its own class, it would be nice if we had ways of changing some of this stuff. So we can go ahead
and we can create a function called name. Go. And I'll set this to new names so
we can avoid conflict. That and we'll make this function called
change name. We go. So now we have that
and we can do the same for our age and everything else. So we can come in and we can
create our funk just like a normal script or just like we normally do on a
script with a change age. We'll pass in a new
age and we'll simply just set We got
these two Blackbird. Yeah. So we want to set
age equal to new age. And we can do the
same thing with PET, with t that would you change type which
wouldn't really make sense unless you
have some kind of really weird animal that can change what kind
of creature it is, I guess something like
a ditto in Pokemon. So let's go ahead and with a
type equal to the new type. And we can determine
what these are. I'll say string, and
string that way, we have no issues and
passing things in. And now that we have this, I'm going to go ahead in
close out function class. We want to add a new script
onto a control here. Class test. All right. Now, what we're going to do is inside of our
pretty function. We can now go ahead and create a new variable called PET and we can set this to PET dot new. And now we've got access
to all of our functions, so we can say PET, do a dot. And now you can see,
we've got the age name, type change age, change
name, change type, and then all the standard things that we would have on a typical node that
we're extending. So if we wanted to,
we can now print out this is my pet percent S. He is a percent S and is percent S O. And now we can easily
just fill this in. What we have here. So PET
first stuff is names. I'll say Etname fed by pet dot Type and pet dot H. Now, this is getting
a little long. You notice these light
lines here in the editor, and then a much
harder line here. Try not to go past those
lines when possible. And what we can do is just hit Enter it's not going
to see it there. Is it on the oro? So what we can do is
something like this and keep everything
organized in a one line. We can keep everything
clear like this, and when we written or
when we boot this up, we'll create a new pet, but we're not going
to add it into the tree because
we don't need to, in this case, because we just want to access the
properties of it, right? And we can create.
This is my PET. We have this sentence and fill in based off of the information
that we have there, which the information
that we have there, the defaults are all empty
except for the zero. So the sentence still
looks a little weird. But what we can do is before
doing that print is we can call Pet dot change
Let's use Name, for example, and we
can pass in a name. So we'll say Billy. And now you can see that fills in here
inside of our output console. And we can do the same thing
with age and the type. However, if we're going to make something
like that mandatory, then that's going to be
a little annoying to require other user
to do consistently. So what we actually do there is we can call an int function, and this is something that's
built into all classes. So funk underscore INIT, open and close our parentheses. And this is where we can have a set list of parameters
that we have to put in. And these are all things
that will be set out of a default as soon as our
class has been created. So we'll go ahead and pass
in I'll say new name. And then we'll do new
age and new, right? And then all we're going to
do is we're going to say name is equal to new name. We're going to say age is equal, equal to new age, and type is equal to new type. Now, when we go back
to our testing script, you'll see that
we have an error. At least we should have an error that pops up. Here we go. And that's because now we
have to have arguments. So inside of new inside
of the new call here, this is all the parameters that we must fill out
for our int function. So we need a name,
an age, and a type. And again, we can call these
by types your string and and string you see when
we come in here now, we're going to have we
need to fill this out, so let's go ahead so we
can put a name in there. Let's say bats. Our second argument is our
age that we can put in two. And then we needed a type. Let's say dog All right. Let's go ahead. We can run that. And now we
see all that gets built in. This is my pet bax. He has
a dog and is 2-years-old. Now, all that gets filled in. We condense that down because we don't need to do we
don't need to write out three different
functions to change this from our pet. And instead, we just put it all inside of
our in it or our initialized function that comes
rebuild into all classes. Right. I hope that
gives you an idea of what classes are and how we can create them and how we can really use them
inside of our code. A class can be accessed for any script or rather you can create a new instance of
that class from any script. And you might create
a class just to have some utilities so
you can save time. I just bring it in a
utility and calling some specific functions
that you may need all over, or you might use it to
create an object, like, in this case, a pet class or
if you're creating a game, maybe an enemy class, and then that enemy would
have its own health and its own attack and its
own set of information.
21. What we will make(filled space): Alright, this week, we're going to kick things up a
notch and instead of going off of just some text,
like we did last week. This week, we're going
to be creating or recreating an old two D game
from the 80s called Frogger. Now this is going to
give us a chance to work with a two D
player controller. Collisions. Maybe we'll
get into some particles. We can work with some spawners. And as you see, if you've never played Frogger before
or you've never heard of it, you see here, we're
going to be working with UI for heads up display. We have points that we're going
to need to keep track of. Find my mouse there
for a second. But not only that, but we're also going to have see is it going
to show it here? Okay, so we have a certain
amount of frogs per player. Obviously, we don't
have to put coins in. But this is essentially
the game here. So we have two little safe zones in this little purple area. We have a road in
the middle that has five lanes of traffic
alternating back and forth. And if the frog gets hit
by one of these cars, they die and the player loses a life. They make
it up to the top. They can hop on the
turtles and logs to make it across
into the safe zone. If they land in the water,
that's a fail as well. Which I guess now that
you think about it, kind of doesn't make too much in the way of sense,
since it's a frog. But there you go. That's the idea of what
we're going to be creating, and that's what
Frogger is if you've never played it or heard of it.
22. Creating the Story Book: Alright, welcome,
everyone. And today, we're going to start creating
our very first game. What we're going to
create today is actually the storybook for our MadisGame. And this storybook is going
to hold all of our stories as well as the prompts that we're going to
ask the player for. Now, if you want, you
can go ahead and create this in a totally new project. I'm just going to
go ahead and delete our little examples here
that we were using. When you were learning
the language here, just going to select
them and delete them. That way, I can start
with a clean slate. And since I'm just going to
keep all of our projects in inside of this
one project here, I'm just going to
go ahead and create a new folder and call it MDLIbs. Again, I would
recommend that you create a new project altogether. That way you are able to export
everything individually. Alright, so we went
ahead and we have this. We have our MadipsFolder,
for your project. And I'm just going to go
ahead and click on my folder. If you're starting
a new project, you can just right click
in an empty space. And I'm going to
create a new script. I'm to go ahead and
create a script here, and I'm just going to
call this storybook class and hit Preate. All right. So now I can go ahead and mine did not fall on my folder because
I clicked on the outside, so I'm just going to right click and move it to
where I would like. And I've got it inside of
my folder here, right? I'm going to open that up. We
can extend No, that's fine. We're not going to need any of these because this class is just going to hold
some information for us. So I'm going to go
ahead and put in a class name storybook, and we're going to
need extends for this? No, I don't think we are. So I'll go ahead and move all of that so we have a complete
fresh start here. Alright, so this where we're
going to create our stories, and our stories are
going to be held inside a variable that is
up type dictionary. All right, so I'm going
to create a variable called Stories. And that's going to
be a dictionary. And because it's a dictionary, I'm going to go ahead
Enter to open this up. Remember dictionary
is denoted by the curly braces that surround
our information here. And for these, I
can just say story one and a colon,
that'll be our key. And now we need a
value for that. And that value will also be a dictionary because
we're going to need two pieces of information
here inside of the story. We're going to need
the actual story. A and that is going to be
just an empty string for now. And then it's also going
to have one for our props. And that's just going
to be an array. So we're going to have
square brackets here. And this is the
template that we're going to use for
all of our stories. So we're going to
have story one, story two, story three, story four, et cetera. And all we're going
to do is we're going to go ahead and build this in. So for example, for the story, we will say, let's see what
do we want to put here? Alright, so I went ahead and created my
little story here. So one day the percent S. Now, percent S is just a
placeholder for any string. And we can replace this later on with whatever
the user puts in. So this percent S, in this case, is going to act like
our blank in our story. So one day the blank went to the blank to receive a Quest. This quest was to go to Blank
to retrieve blank, right? So we have this
little story here, and and there we go. If you want to split the
story into multiple lines, we can easily just do this. So by doing this by having
our slash here at the end, and then on the next
line, we have a plus. It is going to add this
string to this string, and now we can have it all
together in one place. But not only that, it's
a lot easier to see when it's all inline or
in site like this. Now, I went ahead and printed this out with an int just for testing purpose
just to make sure we're no issues going
on, no weird bugs. There we go. We're all set. Now, for our prompts, these are going to
be strings inside of this array inside of this list. And as we go through,
one day, the blank. So this blank makes
sense if it's a noun, so we can go ahead and
just type in noun. And what's next?
Went to the blank, so this is going to be a place. Our next one to receive a quest. This quest was to go
to the was to go to, and this will be another
place to retrieve something. That would just be another noun. All right? So that's
essentially how we're going to work with our prompts. So we go through. We
have noun then a place, then another place,
and then a noun, and that fills up all
of our options here. That will give us enough
things to fill in our blanks. And all we have to do now for more stories is just put
a comma here at the end, drop to a new line, paste in a duplicate of
what we just had, change story one to story two. And now we can go
ahead and create another story with
some more prompts, and we can just go ahead
and repeatedly do this. In order to have ourselves a
nice full storybook to use. Alright, so we have a
second little story here. One morning, D Baker went to
I went to Blank U in shop. To his surprise, however, there was a blank
stopping blank. Now, I went ahead with verb noun and Pronow, but now
thinking about it, Pronoun probably
doesn't make sense, because we already said
this was a he, right? His shop, his surprise. So I'm just going to change this back to just being a noun, so stop being Blaine. And you can just go ahead and continuously
do this and create as many fun little stories as you can and really
fill up your storybook. And once you have your storybook completely created and ready, then we can move on to
the next section of this and start creating the interface for our
user to interact with. And then we'll actually get into creating the code and
making it all function.
23. Create the Interface: Alright, so let's go ahead and start creating the
interface that we're going to need in order for our player to actually
play the game. So right now, we have
just an empty scene here, and we're going to
need a new one. So let's see what do we want? Well, we're going to need
the player to be able to type in some text, right for the prompts
that are provided. We're obviously going to
need to display text on the screen for the user in order to know what
prompts they need, as well as reading
the story at the end. And we can go ahead and put
a button in there as well. That way, if the user
doesn't want to hit Enter, they can click on the button
and still submit their text. So those are three things
that we're going to need as a minimum here. So let's go ahead. We can create I'm going
to go ahead and click on User Interface here on the create root node
section on the left hand side, and that's going to give us
a control node to start us. All right. And I'm going to go
ahead and rename this to Maine as this is going to be the main
source here for our game. I'm going to hit this
little plus button right above it with
Main selected, and this is going to prompt
me to create a new node. Now here you're
just doing all of the different objects
that we could create. And remember, we can do
this in code as well. We're just doing, for example, we're going
to go into Control. And you know I'm just
going to go ahead and search. I'm looking for this. So the equivalent to
selecting that and it being added in here would
be the same as if we had a script
on our main here, and we just said
line edit dot new, and then we added
it to the scene. That's the exact same thing
as what we just did here, only we're doing
things visually, only because this is going to be quicker at
the end of the day. And if we have the tools
to speed up production, we may as well take
advantage of them. I'm going to go
ahead and just grab the little oranges little
orange handle here, I stretch it out. And I'm going to go ahead
and while that is selected, I'm going to go to
the top of my screen. Click. There we go. This little icon
beside the anchor, and you'll get a pop
up for anchor presets. And I'm just going
to select the one that's in the center
of my screen. There we go. That
way, I know that my text field will always
be right in the middle. Alright. So now this object
has a bunch of properties or you can also
call they're variables, right, that are on these
that we can access. And one of these is
placeholder text. And we can see that if we take a look on the right hand
side of the inspector. We can see the
placeholder text here. Now, we can go ahead
and type in here, and this will give our user an idea of what they're
supposed to type in. Just like how you go to a
website and it might say email in the email field
and password in that field. So we're going to say submit
prompt, dot, dot, dot. That way our user
knows that this is where they submit
their prompt. And I'm going to go ahead
and rename my line edit to user you want to
call it User prompt? No, let's call it prompt
you want to go prompt text, prompt field. Prompt submission. There we go, because we submit our font here or not
fonti prompt, sorry. So I'm going to go with that and just call prompt submission. Now, I did mention
I wanted a button, so I'll select Main again. I want that to be the owner. I'm going to type in
button at the top. And now I have a button, and I'll set the text of this
button to just say, Okay. And I'm going to do the same
thing with button selected, I'm going to select the button
at the very top next to the anchor and select center. That way, it can be centered. And I'm just going to grab
ahold of it with left click, and then I'm going to
hold Shift afterwards and slide it to the right if
I can get ahold of it here. Here we go. Just like
that. There we go. Now, I think some stories
might get a little long. So I'm going to go ahead
and grab both of these, both my prompt and my o button. And for that, I just
went ahead and you can shift click
or Control Click. Either way, we'll work for here. I'm going to grab it on my UI and then hold Shift so we can keep
it in a straight line, and I'm just going to move it
down a bit just so we have a little more space at the top in case our
stories get a little long. Okay. So these anchors show
where our object is going to be in relation
to this point on the screen? So this anchor is in the
dead center of our screen. So regardless of how
big the window is, this text field, this line edit, and this Okay button is
going to be down that far, approximately from the
center at all times. So that's almost going
to automatically update its position based on the
anchors and window size. Which is great for us, it's because we never know
how big a screen is going to be Let's see. Going from here, what
else do we need? Well, we're going to need
to display some text. Let's see. We could use a label to prompt or to show
our information. We could also use a Rich Text, which I think we're
going to use a thad. So we're going to go ahead and add another one into our scene, and this is going to
be a rich text label. And I'm just going to pull this orange box
out, this handle. And I think I'm going
to set the anchors to the center that way everything
will be relative here. Click hold Shift
and bring it up. And I think that'll do for a lot of our information,
how big is this text? Yeah, I think that'll be fine. All right, let's see. Rich Text label, I'm going
to go ahead and rename that to my display text. Alright. So I think that's all
we're going to need. I'm going to go ahead and hit
Controls and save my scene. Here it is inside of my folder. And now if we were to run
that, we would have no issues. We can see everything's worked
out perfectly fine here. Everything looks good. We can
type inside of our books. And I'm going to go ahead and look for the window, so I
can show you that here. Now it's going to be
important for you to see the window. There you go. You can see we can type in it, and delete things out of it. Awesome. We can
hit the OK button. Fantastic. Now, this background is a little bland.
It's a little boring. So what I'm going to do is
I'm going to head on over to Google and just go ahead
and search for Blackboard. There you go. Search
for blackboard, chalkboard, whatever you
want to look for so. And I'm going to
go ahead and just pick an image at
random and save it. So now I just got to find
where my folders are. Here. Save, come
back over to Gato. And there you go. We can
see it saved right here. Inside of my folder.
So I'm going to add one more object to my
main here in my scene. And this is going to be a texture rect that I'll
just rename background. And I'm just going to
drag the Blackboard image here that I created or sorry, didn't create that
I found on Google. And with background
selected, the texture rect, I'm going to drag it over to the texture slot on
the right hand side, inside the inspector
and drop it in. And if you need to, you're going to change
the expand size here and the stretch if you need to in order to change
the size and tweak this. For example, if we set this to keep aspect, it's
not going to move, but if we change our expand
mode to ignore size, for example, here we go. We can see we can go with that. And if we just change keep aspect to scale, here we go. Now we can stretch it
out to fit our needs. Now, what's important is you
see this blue outline here. Everything inside of that box is what we are going to be able
to see inside of our window. So I'm just going to
make it just a little bigger than our window just to make sure it's
completely covered. And our anchors in
the top left corner. Now, for a background, that is not going to work. So I'm going to go ahead
and adjust my anchors, and I'm going to select the
one that is full wrecked. And that's going to put
one pin in each corner. That's going to
ensure that no matter what size our window is, this background is always
going to fill it up. All right. So now we have one issue. Our background is on
top of everything. We can't see our button or
anything that we did before. Well, this is just because
of layers, essentially. If you've worked in
something like Photoshop, you'll be familiar
with layers here. All we have to do is just
grab our background, and we actually have
to brak it out. Because what's at
the top is going to be behind everything
else at the bottom. I know it's kind of the other
way around in Photoshop. At the bottom is usually
what's behind everything. Go in here, just kind of flip, something you have to
remember. But there we go. With that, we have our visuals all set up here and
we're ready to start jumping into some of
the code in order to make our buttons
and everything else work and get our game started.
24. Select Story and Prompting the Player: Alright, we're going
to go ahead and jump into doing some of our code now. We're going to put our script
on our main node here. So I'm just going
to add a script. I'm just going to leave mine
called Min and hit Create. Alright, so let's see.
What do we need to do? Well, we need to keep track
of what our current story is. So let's go ahead and
create a variable for that. Current story. That's going to be it. Is it going to be an
array in our case? We're going to select a story, and that's going to give us No, that's going to give
us a dictionary back. But we can actually hold this back and make it a
dictionary. There we go. We're going to need
to keep track of our players words, right? The words that they
have submitted. So we're going to
say players words, and that one will be an
array that we can add to. Now, we're going to use a
keyword here called on ready. And in 4.1 here, we actually have to use this at symbol in order to
use these keywords. Put this at symbol and
then use on ready. Then we can go ahead and create
our variable like normal. And this is going to
be our player text. Which is going to be equal to our prompt submission that
we want to get ahold of. So in order to get this node, there's actually a
couple ways to do it. The easiest one is to just
use this dollar sign, which just simply
means get node. And from here, we have an easy access to our
prompt submission. As you see, we only have
to go down one level here. And if we begin to start typing, we'll see the auto complete pop up for us and we hit
that, there we go. Whenever we want to
access this object, we can just type in player text. Now, we're going to
do this as well for our display text and our button. So I'm going to say display text is equal to what I just
called it display text. Awesome. And we'll have
one more for our button. Do we need the button?
No, we don't actually. We're not going to
need one for that. No worth using this
default button here. Okay. So let's go ahead and remove
process out of there. So what we're going
to need, let's see. We need to select
a story, right? So we have to assign
our current story, and to keep things organized, we're going to create a function to hold our set current story. It's a funk set current
story. It's like so. And since this is a
separate function, I'm going to go two
lines in between. And how do we set how are we going to set
this current story here? Well, we're going to return nothing at the end of this because
we're just going to assign it directly
to our variable. So in order to get this, we're going to need to
get a random number or select a random story. So I'm going to create a
variable called Stories, and this is going
to be an array, which is just going
to be equal to our storybook class dot STRESOh. And look, we cannot access that. So let's head back to
our storybook class, and to avoid having to create
a new object for this, since all we need is to access the stories
that are in it, we're going to use
that static keyword that we mentioned in Week one. Right now we come back
to our main script, and we can do storybook dot STRS I cannot assign a value of
type dictionary to variable, so we want to get our stories. And on this dictionary, we're going to use we're
going to call dot keys, open and closed parentheses. And what this is
going to do this keys call here that we can
call on a dictionary, it's going to return an array
or a list of story one, story two, story three, story four, et cetera. So that's going to have all of our little story names here. All right. Now, from here, we have to select a random one. So the question is,
which one do we want? Well, we're going to
create a variable called selected story here. And, of course, this
is just going to be a string because all of
our stories are strings. So it makes sense. And let's
access our stories here, right, stories of Ray. And in 4.1, we can just
select pick random. That's all we have to do,
and it's going to randomly select a story to
give back to us. And that's all we
have to do for that. Now all we have to do is just go ahead and set our current story. So we can say current
story. Let's see. We just set it to
that. Then that should give us a
dictionary full. Both of those, that
should be fine. So we'll just say current
story equals selected story. Strength cannot be assigned
to a variable type. Oh, that's right. Got to
write that differently. Storybook dot Storys and then I'm going to use
these square brackets here because we want to access the
story that's inside of it. And the one we want to access
is selected story, right? So again, we're going
to go over this. We're creating a
variable called stories, and that is an array or a list. And that is being assigned to all of the different stories, right, the keys of
our dictionary. Of all of our stories
inside of our storybook. So now stories holds all of
our little story titles. And then selected story is
a string that is being set to a random story out of
there, out of our list. And then we're setting
the current story that we already created up top,
which is the dictionary. We're setting that equal to the story that is inside
of our storybook, the story that we
selected. All right. And we can see this work easily if we just go up
to our ready block here, and we need to actually call, set current story because obviously you're
going to do that at the beginning of the game. And then I'm just
going to go ahead and print out our current story. This way, we can
just see if it's working because it's
already empty by default. So if I print it out before,
we set our current story, we should be able to see that, and I'm just going
to play this scene. Here we go, so we can see
it's empty at the top. And then after we set our serve, we have the one morning
the Baker went to blank to open up his shop
to his surprise, however. So it looks like we
got the first story. Let's run that again.
And here we go. We have a completely
different story here now. The blank sky was
beautiful shade of blank as the blank
blank threw the blank. And we can see we have our
prompts all here as well. This is fantastic. We're all showing up here.
Everything is working great. We now have a story
to work with. We have them randomly selected. Now we got to worry about how
do we prompt player, right? Well, we don't need
these print statements anymore because we know
it's working fine. So our story has been set. How can we prompt our player? Well, simple. We're
going to come on down, create a new function. We're going to call
it prompt player. And what we're going
to do is let's see. Let's go right into
our display text. And we want to access
the text property of that so we can set that. And to remove any
potential confusion, we're going to say, let's
use plus equals here, and see how this looks
for our situation. And I'm going to say, May, I have the thing we're
going to add to it, it's going to be our
current story proms. And the prompt that we're going to ask for how
we know which one we want is going to be based off
of our player words that we created up
top here, right? Our players words. And we're going to
base that off of the size because remember, when we're working with a list, we start counting at zero, one, two, three, right? So if our player size is zero, that means we have
no submissions yet. So we're going to get the
first item in this list. If we have one item in
player submitted one word, then we're going to get the
second item, and so on. All right, so we can prompt
the player this way. And I know that's
getting a little long on that side, but let's see. At the moment, that's all we need in order to
prompt the player. All right. So what
we're going to do from here after we selected
the current story, back up in already,
we can go ahead and call prompt
player from there. And that should be all we need. So let's go ahead
and try it out. Oh, seems I have run into an issue here,
and what is that? Let's take a look. Oh,
yes, I see the error here. Tell me prompts is not
a thing because I used a capital P inside
of my storybook. So if I just make
that a capital P, that should solve my issue. And there we go. So it's
asking us, may I have a verb? And then I can go ahead
and type in here. You can hit Okay, hit Enter. Nothing's going to change
here at the moment. But you notice how
I had to click in that box when we started. So if I just restart that, and now I have to come down here, I have to click in it myself. Well, why don't we
just automate that? Let's go ahead and
get the player text. And we're going to call
something called Grab focus. So now when we run
this, there we go, it's already there,
and we can just start typing immediately. So we don't have to waste
any time. All right. So in order to continue
prompting the player, we have to take a look at our words being
submitted, right? We actually have to
submit these words. So for this, we're going
to have to connect some signals for us to know
when things are happening. So I'm going to go
ahead and click on my prompt submission
in my scene. Then I'm going to move over to the right and click on
the tab that says node. And here we can see all
the default signals that have been in here. And the one we're
looking for is text submitted under the
line edit section. And basically, whenever
we hit the enter key, it's going to submit
whatever piece of text the user has typed in. So I'm just going to go ahead
and double click on that. All right, so you should
see a screen like this, and all of this is
great out because we do not have any
scripts on those, and this one is blue because that's what we're trying to connect
the signal from. So we're just going to select our main because that
has our script on it, and we're going to hit Connect. If you want to rename
the function here, you can, I'm not going to. I'm just going to leave it
with the default name here, and I'm just going to
hit the Connect button. And you'll see it added right here at the
bottom up our script. I'm just going to
hold Alt and use the up arrow key to shift
it up a few spaces. There we go, get
that out of the way. Go. That's out of the way. But there we go. So we see
on this function name, which is going to trigger
from that signal, it's going to execute
this block of code. Now we can see we got new text, which is a string that
gets passed into us. So that new text is
whatever has been typed inside of this line. All right. So when a piece of
text is submitted, what we need to do is we can add this to
our player words. And since we're going to need to do this potentially multiple times throughout or at least
in multiple locations, let's just go ahead and
create a function for it. Funk, add let's see
what did I call it? Add to player words so we
can keep things clean. Here we go. And all we're
going to do inside of this function is we're going
to append our words, right? Players words. Append. Now, append. This call here just allows us to add things into our array, add items to our list. So whatever we type
in here will be added into and all we're going to be adding is
playertext dot text. Now, we could make this
possible do cleaner, but it might cause some
potential issues later. Who knows? So we're just going
to do it this way for now. And what'll be nice is
if that display text, if we clear that out
off of our screen, so we make it an empty an empty string, I
guess you could say. We're going to say
display text dot. And we're going to call clear, and that's just going
to empty it out. And what that's going to
do is that's going to remove the prompt that
is on our screen, asking us for a verb
or a noun or whatever. And to visually show our player that our text
has been submitted, we can go ahead and do that
to our player text as well. Let's take a look at
how that's looking now. We got to call back to
here before we forget. So on our text submitted, we're going to call add to
player words. All right. So if we go ahead and run this
and take a look at it now, you say, May I have a verb
and we'll say running. And I hit Enter. And
you see our text down here was emptied and our board at the top
here was also emptied. So that's great. It looks like our text was submitted and we're ready to update
with a new prompt. Fantastic. All right. So in order to continue
our prompting, we're going to partially set
up what we're going to need for setting up the ending
and restarting the game. So we're just going to leave that portion of that out and come back to this
function in the future. So right now, we're just
going to use this to check the or call it check
player words Lang. So I don't want you to get
confused with that name. It'll make more
sense when we add in when we're checking
if the game is over. So I'm going to go funk, check player words Lang. Alright. So what we're
going to do is the way we can word this Let's see. We can say if we're going to
use an if statement here. So I'm going to say if
player words got size. And remember, that's just
going to get us the amount of items that are inside
our player words here. So the amount of words that
we've submitted already. And we're going to
say that is equal to our current story, the prompts, prom pots No. There we go, dot prompts. Dot size because remember
our prompts is a list. And of course, we have
an error here until we put our colon in there
at the end of our line. So we're going to say
if the player has submitted the same amount of
words as we have prompts, then we can do something. But we don't want
to do that, right? Because we want to say,
if not, like that. Because we want to say, Oh, if the player hasn't
submitted enough words yet, then we need to prompt
the player again, and that's exactly what
we're going to do. We're going to call
prompt player. All right. And when it
comes to the next video, we'll come back and we'll
rewrite this function. But for now, this should work for us. Let's go
ahead and take a look. So, may I have an adjective? Sure. Let's go with pretty. You hit Enter and
thing is updated. But we're not actually checking our player length anywhere, so you see why that's a problem. So let's see where
do we do that? We do that when we add
to our player's words. So after we add the word and actually submit
this word for us, then we'll check the link and see if we can keep
playing and if so, prompt the user
for the next one. Let's see. May I have a verb? Yes, let's go with RN or Run. There we go. May I
have a noun, dog. May I have adjective? Pretty. May I have adverb. Yes, swiftly. May I have a noun? Hope we got a lot
of things here. Red. May I have a
verb ending in ING? Robbing. And there we go, our thing has ended.
We're out of prompts. We don't have our story yet, but we do have all of our
prompts happening there. Now, we can see that
our display text actually did not clear
out, which is interesting. So instead of calling clear inside of our add
to player words, let's just get the text property and set it to an empty string. And let's see how
that works here. I have a verb, run. There we go. So now we
have it updating this way. I'm not sure why
clear isn't working. Maybe there's a bug in there
right now. I don't know. But we can just
clear it manually by setting it to
an empty screen. And if you want to keep that
going as one on each line, if you want to keep that
going, one on each line, all we have to do
is just add a plus equals and do this back end. Or is it a forward? I think
it's the forward here, and this is going
to be a new line. So if we take a look
at it this way, so it can have a b run, and that's actually not
going to go in that way. I always mix these two up as to which direction
it's supposed to go in. Adjective. Pretty. There we go. Now we can have a new ent
on each line to ask you. So if you'd rather
have it like that, that's how you can make that
little tweak. Have a noun. Yes, dog ending with ED I'm drawing a
blank here right now. I don't know why, but
you get the idea. So we can have a new line that way where you can
completely clear it out completely up to you on
how you want your presented. Alright. And I think that's enough for today because I
think all we need now is to basically
end our game, whether that's completely
ending it, telling our story, seeing if the player
wants to play again, and all of that fun stuff. So one quick note here
before we take off. Instead of prompting the
player here at the top, what we can do now is
we can actually just do check player words
length inside of our ready, and that should set us
up the same visually. Yeah, there we go. Alright.
So there you have it. We have a lot of our
game setup here. It's simple in terms
of video games, and it's giving you a chance to really use the things that
we've gone over in week one, regardless of which version
if you did both of them. So we're working with variables, different data types, certainly working with functions to keep everything
nice and clean. We're using object oriented
programming here with our storybook we're
prompting up our players. You're learning some new things. If you didn't go through
the alternate version, you've learned about append. You've learned about Grab focus, regardless of which one
you've gone through there, you've learned about
pick random and keys. So you've learned quite
a bit of things in addition to whatever we've
learned in the first week, whichever version
you've gone through, maybe you went through both. But I'm going to stop
rambling on here, and I'll see you in the
next one where we will wrap this game up so that we can
have a full playable thing.
25. Ending and Play Again: All right, everyone, let's
go ahead and wrap this up. We're going to end our game. We need to check if
our story is done. We need to actually
tell our story, and we're going to use our Okay button to
have two uses here. So it's going to work to both play again
with a new story, as well as submit our text. So let's start out with
that with our button here. So I'm just going to go
ahead and select my button, and I'm going to connect
the signal press and again, I'm going to go ahead and just connect that up to my main, and I'm going to leave it
with the default name here. And just to keep
things a little clear, I think I want to
move this up just a little bit and put my two
spaces in between there. That way you can just have my two signals here
next to each other. Alright, so right now, when our button gets pressed, we can go ahead and just
use add to player words, and that'll function
the same as if we hit Enter on our keyboard. That should work perfectly
fine, exactly the same. So verb, Ron, we hit Okay, we go now, Dog, okay. All right, so everything's being submitted, everything's
working fine. Excellent. So we have to
know when our story is done. That way that way we know whether it's time to tell our story and end our game, or do you keep playing
and keep asking the player for another prompt. Well, in order to do
this, we're going to go ahead and create a new function, and we'll call it I story done. And the whole purpose
of this function is to just tell us whether or not we have any more
prompts left to guess. So we're going to
return a value here. And what we're going to return is whether it's true or false. That's going to be player words, size equals our current
story prompts, right? Remember, we want to
use double equals here because we're
doing a comparison. And that's all
we're going to do. We're just going to return that, and that's either going
to be true or false. Alright, so now in our check
players words length here, instead of writing it like this, we can actually reformat this. And we can say, if I story done. And for now, we're
just typing the word pass because that's when
we're going to end the game, and we'll add an
else block in here. Here we go. So we'll say
if the story is done, then we'll end our game when we write that
part of our code. Otherwise, prompt
the user again. So let's see what happens
if we do this now. We come in adjective, ready, we hit the pay button. Fantastic. Our text
still grabs the prompt. Everything's still
working. Awesome. We have not broken anything
yet. That's great. Alright, so how do
we end our game? Well, if the story is done, we have to end the game. So we're going to create a
new function called end game, and notice how we're
creating a function for everything here so that we can keep
everything organized. And we say, Okay, well, we're having an issue
when the game ends, we know to come down here and look at the end game function. Or maybe our story is not
being shown at the end, and we're going to have to go to the function that we'll create here in a second
called Tell Story. So this will help us with narrow down any bugs that we
may get in our project. In the future by being
organized and prepared now. All right, so how
do we end our game? Well, what I'm
going to do is I'm going to take our display. You want to go with
our display text? No. We want to grab my
prompt submissions, right? So we want to get
the player text. And what we're going to do here is we're actually
going to use quarter. And what that should do is go back to our scene
here on two D, is that should grab this line and just completely delete
it off of the screen. So that way it no longer exists. That's basically what it
does. Completely deletes it, removes it out of memory. So it frees up that memory, and that's important to do, not necessarily in this game, but in other games. Say you keep creating
these new objects, but they never get deleted. You're essentially
going to start getting to a point where you
create memory leaks. So you got to remember to cue free anything that
you no longer need. And at this point, we no
longer need our player text. All right. So what we're
going to do here next is I'm actually going to
change the text on our button. So I'm going to grab our button, that dollar sign, remember
that short get node, right? So we want to get
node in the node we want to get is our button. And the reason why we're just
writing the word button is because that's what it's called
here inside of our scene. So if I renamed that
to something else, I would need to make
sure this matches. So on this button,
we want to get the text property of it, and I'm going to set
that to say play again. And while we're at it, we should make sure that it says Okay when it comes to prompting our player. All right. So I'm just going to
put that inside of our prompt player function and just set the
text to say, Okay. Alright now, the last thing
we have to do inside of our endgame is call tell story. And that's going to give us an error until we create that, so let's go ahead and at
least create that name, tell story, and that
is now a new function. In order to tell our
story to the screen, all we have to do is
completely empty out the text. So display text dot text
equals an empty string. And I'm just going to
put this in here in Side of Tell story
just in case you're going with the new line approach when prompting your player here. So just in case
you're doing that, I'm going to clear out
the text here as well. And all we do now is we set our display text and the text property of
that that we can see. And we set that equal
to our current story. And we want the story property. I'm going to make
sure I spell that right inside of my storybook, story with a capitals. And we have to fill in all
of those placeholders. So the way we do that
is just do a sent sign, and we add whatever we want. So, for example, we
can go with banana, and that's going to fill in
our first blank with banana. Now, we have multiple items. So because of that, we would
have to do it in the form of a list like this and do a
coma and do our next one, right, tomato and do
the next one and so on. But we've already done that. We already have our list or
array of all of our strings. This is our player
words that we created, and that we've been adding all of our text submissions to. So we can just come up here
and say players words. Alright. So now we go to
check player words Link, and we say I story done, and we're going to call Endgame. All right. Now, do we need
to call this anywhere else? No, but we are
going to need to do our restart button
here in a moment, let's go ahead and just make
sure this works. All right. So can have an adjective. Yes, pretty a noun, rock, a verb ending
in ED, educated. An adverb, swiftly, a plural noun flowers.
And there we go. We can see our line at
it has been deleted. Our button now says play
again instead of Okay. And we have our
prompt at the top. The pretty sky was a
beautiful shade of rock as the educated swiftly
through the flowers. Now, I have two Ss there. Was that my mistake, possibly. Was that something that I had in my story? It's
possible, as well. And no, it does not look
like that was in the story, so that was completely on me. I must have hit S twice. But there you go.
There's our story, and our play again button
doesn't work here. And the reason for that is we're trying to add our player words. It brought us to this
function for our error. And if we were to look
at it, parameter, new text is never used,
that's perfectly fine. But the issue that it's giving us is telling us that player
text doesn't exist, right? We can't go to our player words. Can't do any of this stuff. Well, that's fine. Our issue is actually here with
our button press. Because based on whether
our game is done or not, we'll determine whether
or not you want to restart the game or prompt
the user again, correct? So I'm just filling these in. Just don't mind me here. If you are following along with using the arrows
because you want to, I story done, is going to return a pool because we are
returning something, and this will give
us a true or false. Everything else, we're
just returning a void on. So I'm just quickly going through there
and filling those in. And I think that's all of
them. Got them all, right? Alright, so when our
button gets pressed, all we have to do is check
if our story is done. So if I story done, and we want to restart the game. Else, now tap that in. We're going to call
add to player words. So how do we restart the game? Well, to completely
restart it, in this case, all we have to do is get tree, and that's going to get
this entire tree of ours. And all we have to do is
call reload current scene, and it'll be the same
thing as if we had just hit Run current
scene here at the top. If we had just hit that
button for the first time. So when reload current
scene goes off, we should be in this
situation again. So adjective, so I'm just going to run
through this so we can see that we have something
completely new educated adverb Make sure that I only put one in there
this time, plural flowers. There we go. Okay. That's cool. And we play again. May I
have a verb. Ran noun. Cookie. Another noun, Brownie. One morning the Baker went
to ran up should said Run. Up his shot to his
surprise, however, there was a cookie stopping, oh, I said Brownie
instead of Brownie. I put an R in the end. My fingers have betrayed
me in spelling today. But now we can play again, and we can have another
story starting. So we can now just keep playing this for as long as we want. And this game fully
works for us. And if you ever want
to add a story, we can just go into our
storybook and you can just continue adding more
stories and prompts, and it'll just keep working. We don't have to adjust our
code at all for any reason. We just add another entry, story five, story six, story seven, and we can just keep on going with as many
stories as we want to put in. Now, if you're curious
about this error here that's in yellow that
you saw earlier, it's just telling us that
new text is not being used for M signal,
and that's fine. We don't have to
worry about this. It's only a yellow error, which is just letting us know. And we could turn this off. There's a few things
that we could do, but the easiest
thing is to just put an underscore here at the
beginning. That's all. Now if we go ahead and run this, that error is no longer
going to show up. So this underscore at the beginning of your
parameter just says, ignore if not used, basically. But there we go, we are
now telling our story, and we have an end to our game. We're either telling
the story or prompting the user
to keep playing, and we have or prompting the user for more
blanks to fill in. And we have a play again button in case
we want to keep going. Alright, so that'll
do it for mad libs. This is a fairly short game
that we've gone through. This is probably maybe about an hour that we
spent to go through this, and you've started putting together functions,
these returns. If Else statements we've used a few times,
we're using booleans. We're using dictionaries,
arrays, classes. We're using a lot of
things here even though it's such a simple
game, I would say. Well, with that,
you've completed it. Congratulations. Give
yourself a pat on the back. And I'm excited to see things that you
create in the future, and I'm excited for us to
move on to the next project.
26. What we will make(filled space): Alright, this week, we're going to kick things up a
notch and instead of going off of just some text,
like we did last week. This week, we're going
to be creating or recreating an old two D game
from the 80s called Frogger. Now this is going to
give us a chance to work with a two D
player controller. Collisions. Maybe we'll
get into some particles. We can work with some spawners. And as you see, if you've never played Frogger before
or you've never heard of it, you see here, we're
going to be working with UI for heads up display. We have points that we're going
to need to keep track of. Find my mouse there
for a second. But not only that, but we're also going to have see is it going
to show it here? Okay, so we have a certain
amount of frogs per player. Obviously, we don't
have to put coins in. But this is essentially
the game here. So we have two little safe zones in this little purple area. We have a road in
the middle that has five lanes of traffic
alternating back and forth. And if the frog gets hit
by one of these cars, they die and the player loses a life. They make
it up to the top. They can hop on the
turtles and logs to make it across
into the safe zone. If they land in the water,
that's a fail as well. Which I guess now that
you think about it, kind of doesn't make too much in the way of sense,
since it's a frog. But there you go. That's the idea of what
we're going to be creating, and that's what
Frogger is if you've never played it or heard of it.
27. Tilemap vs New TilemapLayer: Alright. It's me again here. And I just wanted to interject here before we
jump into Frogger, you'll notice that if
you're using a new version, Tao Map has this
yellow triangle here, and that's giving
us a notification here that this node is
going to be deprecated, which means it is going to
be removed from the engine. So depending on when
you're watching this, and the tile map node
may no longer exist. And if I have to take a guess, it'll be removed at 5.0 of Gato. That's just my guess.
I have no idea when it'll actually be removed. But I'm going to show you the
alternative that was added in just in case you want to
start using the alternative. Now, instead of the Tilemap, well, if you're
watching in the future, you know what to use instead
to clear up any confusion. Now, with the tile map, we have our tile set
all set up here, right? And we have all of our
nodes, sorry, not nodes, our textures, our road, water, the median, and our home. And you see we go ahead
and paint on here, right? We can come in and just
paint onto the screen. And we have multiple
layers here in a drop down on the right hand side, which is still here
at the bottom. Now, this is what's different. These layers are going
to be their own nodes now instead of having everything
inside of one tile map. So all we would do instead
of this tile map is we would then add in a tile
map layer right? Go to our inspector, tile set, open that tile set
up, make sure we it tile set down
here at the bottom. And we can go ahead
and add in our median. We can add our road, and
we can add our water. Then anything else would
be exactly the same, which I don't think we touched anything as far as
collision or anything here. So you shouldn't have to
do anything else there. And then just like the tile map, you can come in and you
can paint with so you can go ahead and just
make sure you come in, select your node, select
the tile you want to use. And of course, you can come
in and just start painting, just like you do with
the tile map, right? So we can come in.
We can go, boom, boom, put it in,
grab our purple. Change my tile,
grab our purples, come across, fill
in the road pieces. Right. So you can come and
snow pint in like normal. Now, what we have
in a separate layer is this home section. So what we would do is
we would go to we would actually come up and add a
second tile map layer now. Grab another tile set, select the tile set
down at the bottom, and we would bring in that
home tile. And there it is. Now, I left mine is kind of a default
here, default in size, so I probably want to come in and change the tile size here
specifically for this one. But that being said, right? I can just come in, paint, tile map, select all of these, and I can come in and I can
just paint it in, right? I just stamp it in just
like it did before. So using a tile map layer and a Tilemap isn't
too different. You just got to remember
each layer is going to be its own node down instead of just selecting it
from a drop down. And when it comes
to the actual code, if I come in and we take a
look, we take a look here. Normally, we get our tile map. We call Get Cell source ID. We pass in the layer number and then the map position
in this case, so we can get the idea of
what we're standing on. Now, this function exists in both the tilemap
and tilemap layer. I'll select Tilemap
here and you can see right here, Gell source ID. I'll go ahead and use the
magnifier for you here. Let me see it. Get
cell source ID. The first one is the layer,
and then the coordinates, and then we have an optional
flag there. Do we have that. But if you want to use
the Tilemap layer, tile map layer has
the exact same thing, the exact same functions here. The only difference is we
don't pass in a layer. We just pass in the coordinates. So if my tile map here my
tile was a tile map layer, in this case, it would be
layer zero that we're using. So I would get this one that has my median row water on it, and all I would pass in is just the map
position, and that's it. So you just got to remember
to all layers are going to be individual tile map layer
nodes in the future. And any function that asks
you for a tile map layer, you just don't put anything
in. Just skip that argument. Alright, so hopefully that clarifies up any confusion that you may have depending
on when you're watching this. And that's the main difference here that we're working with. Alright, take care. Have
yourself is a good one, and I hope you enjoy Frog.
28. Creating the Background: All right, so let's
go ahead and get a jump start on
creating Frogger. And the first thing
you're going to do is make sure you download the assets and just go ahead and move that sprites folder
into your project. Again, I just created
an empty folder, specifically for Frogger, but I would recommend that you
create a new project for this. That way you can export it
without having any issues in the future. Alright. So the first thing we're
going to need to do is, especially since our
spreads are so small, is we're going to need to
shrink them or not shrink them, but shrink our screen down to more of the
arcade cabinet size. And to do that, we're
just going to head on up to project and go into
our project settings. All right. And so I should start just like this with the advanced
settings turned off. And you'll see on
the left hand side, we're just going to go
down to the display section and go into window. And we're going to
set the width to 336 and the height to 240. All right? This is an arcade
cabinet screen size, the screen resolution for this, and it's going to be perfect
for our small sprites. Alright. Once you go
ahead and set that, you can go ahead and just close, and you'll see our little
blue box has gotten much smaller than
what it used to be. Alright, so the first
thing we're going to do here is we're going to
create the background. So we're going to create
all the road, the water, the purple median,
that they call it, and the scoring area that
we have to get our frog to. So we're going to get all
of that stuff set up. That way we can jump right into getting our game play and
all that set up and running. And the next following videos. Alright, so we're going to
need a two D scene here. So let's click on two D, and this will give us a node
two D for our root node. And if you want to go ahead
and rename that, you can. You can name it
Main if you want. Game manager. Doesn't
really matter. If you really want,
you can just leave it as the default name. I go to leave mine
as default for now. And in order to create this
in our little background, I'm going to create
a new Tilemap. So I'm going to hit
the Plus button. And we're going to go ahead and select tile map
from the drop down. S in our create node. Is like Tilemap. Just go ahead and double
click that and select that. Now, I have mine set up here. I'm going to go ahead and just delete all of these. 1 second. All right, so you should look like this when you
have Tilemap selected. If you don't have it selected,
go ahead and select it. And what we're going
to do is head on over to the right hand side. And we're going to go
to the tile set here. It stays empty at the moment. What we're going to do
is click on it and go to new tile set and then click on that tile set,
and that'll bring us here. Now, what we need here is we're going to need the
little goal area, the water, the road,
and the median. So if we go into our
sprites and scroll down, we will see home,
median, road, and water. If you just hold control,
you can select all of these at one time
like this and just go ahead and drag them into
our tiles box All right. So before we can
actually use them here, as you can see, we can't click on anything what we want to do. I'm just going to
scroll in there with my scroll wheel or
you can plus a minus. The first thing
that we need to do is make sure we're on
the setup tab here, select our water, and
we can click on it, and now we have this
orange box around it. That means we have a tile
that we can now use. And I'm going to do the
same thing for road, median, and my home
bro straight across. Now, home is a little bigger. So I'm thinking it might be
one ty, No bigger than that. Let's see. What do we got? Oh, 26 too big. How's that? I think
that'll do perfectly fine. All right. Did they ever go? I've got a 16 by 24
here for this tile. Alright. So now if we click
on Tile Map at the bottom of our
screen down here, we should now be able to click on and start drawing
our sprites. So click on my median, click on my purple tile here, and just drag one row
across the bottom, go to my road, and we got
five layers of traffic. So we need five rows
of our black here, three, four, and five. And if we refer
back to our image, we then have another
layer of purple, five layers of water. One, two, three, four, five, and then we have a layer of water that goes
underneath of our home. So let's do one
more layer there. Let's grab our home
and just go ahead and click on one sprite and drag your mouse across
so you can select all three. And let's place it. Oh, look at that. We seem to have this issue. Well, what's going on? Well, we are replacing our water tiles here. We don't want to do that. So we need to actually draw
this on another layer, and I'm just going to go ahead
and been filling that up with our water all the way up to the top
in the last two lines. So I'm going to click on
our home section here, and we don't want to replace these. We want
to build it on top. So you'll notice here on the right hand side
of our tile maps, we have something
that says layer zero, and if we have a drop down,
there's nothing else there. So what we want to do is go into our inspector of our tile map, open the layer section, hit Add new element, and now we actually
have a second layer. So back in the tile maps
with our home row selected, we can go to the drop down
layer and hit layer one. And now we can actually draw directly on
top of it without affecting our final
There you go. We got seven across with this. And just to make sure
solve our rows one, two, three, five, right? Looks good to me. If we click back on our no TD, so nothing is great out. There's what we're working with. And if you remember when we're looking at
the Alfoger setup, what it looks like? We actually have our score, and that information is
set up right at the top here in this empty blue area, this empty water space. We have our logs, turtles that jump across that
help us jump across here. Inside of these
little blank areas in home is where we can score
points by getting our frogs. Purple is safe, and our black road is where our
cars are going to spawn. But right, we now have our
background all set up. And just like that,
pretty easy to get going. The new tile map is real nice to quickly get
up and going with this. We didn't used to have
layers, and now that we do, that makes setting things
up like this much easier. Alright. That's our background.
Let's go ahead and jump into the next portion.
29. Creating the Player: Alright, let's go ahead
and create our player, but before we do, I'm going
to go ahead and save this. I'm just gonna hit
Control as go into my froger folder and save
my scene real quick. Alright. So for our player, our player is actually
going to have its own scene that we bring in. So we're going to click on
the plus tab right up top here or add new SEM.
We're going to go to O. And since this is a player that we need
to have control over, this is going to be a
character body two D. This used to be called
a kinematic body, and in other engines, you may hear people
refer to it as such. But here, it is now called
a character body two D. Alright. Now, this
character body, we have this yellow triangle here that gives us
a little warning, and it just tells us that our node doesn't
have any shapes. I can't collide with anything. It's got no collision.
And for now, that's fine. Can to floating there. And what we're gonna do
is we're actually going to go and add another
node in here. And what we want
to add is a sprite two D. We want to add
an animated sprite. Well, we want our
sprike to be animated. We do have two frames for this. So let's go ahead and do
an animated sprite two D. And on the right hand
side in the inspector, let's open up the
animation section where it says Sprite frames. Let's click on it and
do new sprite frames. And then let's open those sprite frames up just by
clicking on it. Alright. So we have our
default animation, which I'm going to
go ahead and rename that to just be idle. Then we're going to add a new animation with this
little plus icon down here. And I'm going to
rename that to jump. All right. So with Idol selected, I'm going to bring
in Boger Idol PNG. And with jump, we can bring in Boger Idol and then our
jumping icon, Boger Leak. And now we should be able
to go between the two. Whenever we want to play
these enemies, All right. Areo, see you see if we
play there. We're jumping. We're doing our
little bouncy bounce. And you might notice
that the sprite is a little blurry up
here in our renderer, but down here, we can see it's supposed to be nice and crisp. Well, to fix that, we can go ahead and we can
just select all of our sprites here at one
time from our file system, go to the left hand
side to the import. Actually, this isn't going to be an import. You've moved this. So let me just go ahead and let you know
where that part is. All right. So if
you head on into your project settings, Whoo. Where did I go? Head on into your project
settings and locate the rendering and
texture section here for advanced settings on. Or do we need it on this? No, we don't need
it on for that. We want a default
texture filter here. Change it from linear to nearest and go
ahead and close that, and you'll see your
sprites go much sharp. So if you're going to
do pixel art like this, this is the default you want to do in your project settings. And now we have a nice
sharp broki Alright. And for now, that's
all we really need. We don't need to worry
about the collision or detection or anything
like that for now. We'll worry about that when
we get to that portion, so I'm just going to
go ahead and hand Control S to save this, and I'm just going
to call this player. Now if I go into my main scene with my node two D selected, I can click on No This
plus for a new node, but the chain beside it. And that'll let us instance in a scene that already exists. And for us, that's going
to be our player scene. And now we can go ahead and
grab it and we can bring this little guy in.
And we can place. And we can do whatever we want to do with this
little guy. Let's see. Let's transform. So we know
this is in values of 16. So 172 wouldn't do. It would be 176 if
we're on values of 16. I'm just going to move my
little froggy up here. Here we go. Be a little
more centered with that. And now I have my little frog in my main scene with my background, and
he's ready to go. All right, that'll
do it for this one. We have our player set up as much as we
need at the moment. And with that we'll
jump into the next one where we will address doing some player movements.
30. Player Movement: All right, let's
go ahead and we're going to create the movement for our little froggy
to be able to move up down left end, right? So to start off, we're
going to need some inputs. Now, if you want to
use the arrow keys, then I up, UI down, UI left, and UI
right already exist. But I want to use WASD. I'm going to go up
into my project and go to my project settings. And I'm going to go into the
input Mapper at the top. Add a new action, and I'm
just going to type in up, add down left and right. Now, for each of
these actions here, I'm just going to go
to the right hand side and hit the plus button. And for up, I'm going
to hit the plus. I'm just going to press
W on my keyboard. And I'll show you
what that looks like. What you'll be seeing
from there, let's see. Is this window here? And I'll just bring that
up above. There you go. So I just hit the W key, and
we have that we hit Okay. We go to down, hit the
plus, press the key. And again, A for left, and D for right. Alright, so now we have up down, left and right for our controls, and we can close out of there. Our player is going
to need a script, and I'll take a note here on
my animated sprite on Jump. I didn't get rid of
the first sprite, so I'll just have this
one with his legs spread. And I put a script on side of our character body t2d
on our players scene. And we just have an
empty one, like so. Now, what I'm going
to do is I'm going to create a function
called movement. Like so. And this is just so we can
keep everything clean and organized and keep all of our
movement in one location. All we're going to
do to take input here is we're going to
use the if statement. The same if statement
we've been using a lot. So we go if, and then
we want to access the input object or the
input class. So input. And then dot because we
want to check is action. And we want to go with
released this game. Or just released
or just pressed. Either one will work for
this game specifically. If we go with pressed, is action pressed, then that is while the
button is held down. Just pressed and release means will just press as soon as
the button gets activated, when you press it
down and released means the block of code is going to execute when you
lift your finger up. I'm going to go with J
press. Let's try that. And I'm going to use the button, and this is a string that should have popped up
you automatically. And this with a
colon, so we can go inside to it and
create the code block. And all we're going
to do is we're going to do two things. We need to move
our little froggy. We need to move
it up the screen, and we're going to
go up by one block, and everything is split into
16 16 block or 16 tile size. So we're going to
move our froggy up 16 blocks in this case. So we're going to
get our position. And if it makes a little
more sense to you, you can say self dot
position because you're moving yourself that
this script is attached to. And right now that's
going to give us an X and a Y coordinates. That has two numbers
associated to it. So if we click on our
character body and look inside the inspector
under transform, you see we have an X and a Y. And these correspond to the location that they
are on the screen. So if we click onto
our main scene and go to our character body, you'll see, its position is
169 and 233, in my case. So this is where
we're starting from, and we're going to be
adding or subtracting from this from either the X or
the Y to get our movements. So since we want to go
up when we press up, we're going to be
affecting the Y number. So we're going to
say position dot Y. All right, we're on ourself, we want to get the
position property, and then we want to get
the Y number of it. And to go up the screen, we actually have to subtract. So we're going to
say minus equals. That we can say this is equal to position Y number is equal to position Y minus sum number, which are sum number, in this
case, it's going to be 16. So if we were to just
leave it like that and run our racein Well, how unfortunate Our little
froggy doesn't move. Why doesn't it move? Hopefully you cue on or grasp that before I
hit the play button. We're never calling
our movement anywhere, so we're never actually
checking for any of this stuff. And for that, we're going
to just stick it inside of the process function here. Movement. And now
it's being called. Whoops, at least it would if
we could spell it correctly. There we go. And if we
try running that now, hit the up button,
which for me is W. You can see we're going
ahead and we're moving our 16 blocks at a time. A dada we win. We got one
little froggy up there. Now, of course, the problem
is we're still moving, but we can't go backwards. We have no animation
or anything. So let's get our
animation working. So how do we play our animation? Well, if we look at
our player scene, we can see from our script, we can go down we can follow
this one line easily, just one level to
the animated Sprite two D. So let's get that node. And the way I've shown that before was using
this dollar sign, it would be the easiest way. And as soon as you start typing animated Sprite, it's
going to pop up. And remember, that's only
animated Sprite two D because that is the name of it. So if I were to name this banana and very poor
spelling of banana, then that's what I
would have to type in here in order to access. I'm just going to reset
that name back to default. And all we're going to do
is we're going to call on it play. So dot play. And you'll see the animations
that we created pop up. So we're going to use jump. And if we try that now just with that one addition
of our line whips, you have to actually play this
scene and not our player. There you go. You can see we go into our jump, but we're kind of
stuck in our jump now. So that's a little
disappointing. So how can we fix it? How
can we go back to normal? Well, we can set it so that
when our animation completes, then we return back
to our idle form. So in order to do that,
we're going to have to access the animated
sprite of our player, go to the right hand
side to the node tab, and we're going to
connect a signal that says animation finished. So if we just double click that, we'll get a pop up to
connect a signal here, and we're just going to
select the character body TD that our script is on
and hit the Connect button. It's going to hold all
to use my arrow keys to bring it up. Yep. So whenever our animation
finishes playing, this block of code is
going to execute now. And what we want to happen
here is we want to return back to our idle state where our
frog is just sitting there. So the same thing,
we're gonna get our animated Sprite two D. We're gonna call play,
and that's gonna be idle. If we try that now, what do we Again, if play
the right scene, how we attempt that now
we see we now have this, like little jump that's appearing as we ping
across the water. That's awesome. Now, the thing is our idol is going to be playing
constantly at this point, our idol plays, and
then it finishes, and because it finishes,
it's going to play. So though that's not really going to be an
issue with this game, that could be something to
keep in mind going forward. So to solve this issue, we can actually fix
this with an IT pick. And as you can see, my
little output there, I was checking things and
I'll show you how to do that. I'll clean that. All we have to do
is we can check if Animated Sprite whoops. You want the dollar sign there. If animated Sprite two d dot. Yet Animation. No, it's not what was it called? Well, if we go into our Animated
Sprite, and by the way, you can access it and we
just hold Control and you click on the Animated Sprite
two D here in our code. Then I'll open up the
documentation page for. And here's what we're looking
for here. Get animation. So we want to get animation. As you see that
wasn't popping up. So sometimes it's
useful to check out the documentation anyway. We want to do I animated
sprite tod dot get animation. And if we were to take a look at that,
the current animation, the Sprite frames resource,
the value is changed, frame counter, frame
progress or reset. But what we want to do is to get we want to get what
this animation is. So that's going to
basically return to us what animation is playing
or currently selected. So we're going to use the double equals
because we want to compare whatever
gets returned to us. And we want to write jump. And then when we play our idol, we're just going to
tab that in one so it could be inside
of our I lock. And now we're basically
going to check our current when our
animation finishes, if the current one is jump, then we're going to play idle. If we run that, there we go. We have our little Bing and
it looks exactly the same, but we're not going
to be constantly playing the idle animation
over and over and over. It's when the idle
animation plays, remember, it plays once,
and then it's done. It's not looping. And if yours, for example, is looping for whatever reason, then go ahead, select
your animated sprite, and if it's looping, you
can see our mouse here. That's because
this is turned on, so you just go ahead and
click it to turn off. So it's white like
that. If it's blue, then it's on, if it's
white, it's off. So now when our animation
finishes, after we jump, we're going to check if our
current animation is jump, and if so, then we'll play idle. And when idle finishes, this if statement will not be true because when
we get animation, it's going to be idle, not jump. So since that is no longer true, we're not going
to do anything else, we're not going to keep replaying idle over
and over this time. So it's a small difference,
one of those things that are on the back end that the player
is never going to notice. And like I said, in a
small game like this, it's not going to make
that big of a difference, if any, that is noticeable. But it's something worth
knowing going forward, but when you do want to make
bigger and bigger games. All right, so let's go
ahead and we can now get our down button. So if we just copy
and paste this, we can get if instead of an I. We want our down
pressed instead of up, and we want to plus
16 instead of -16. Because if minus is going up, then plus is going
to take us down, so now we can go up
and we can go down. Now, our little froggy
doesn't turn around at all, which is a little disappointing. But we can easily fix that by adding one
more line in here, and we can do that by
talking about its rotation. So before we jump, we can
get self dot rotation. And if we take a
look at our players, so we go back to our
player scene like on a character body
inside the inspector. If we come down, we see
we have rotation here. And rotation is in radians
rather than degrees. So what we can do is we
can say rotation equals, and we can use this
function that's built in called Dg two RAD, and that might
have changed here. And it looks like it has. Looks like it's
been renamed here, so deg two RD. It's got the
underscores in it now. And then we'll take one argument
in the form of degrees. So if we say 180, that's going to be a
full turnaround, right? Because if we turn right, that's going to be 90 degrees. If we turn left, we're
going to be -90. So either way, we have to get to positive 180 or negative 180. So I'm just going to go
with 180 degrees here. And this function
is going to convert this 180 degrees into radiance so that it can be
assigned to our rotation here. Now, one full rotation
in radians is 3.14, and this is where i is from. So this would be the same here, 180 as if we were to just copy this rotation equals
Pi divided by four. Then that'll give
us one rotation. So if we want to do
Pi divided by two, that'll give us half our
rotation here in radians. So if I were to show you
that with Pi divided by two, Oh, we split down
the other ways. So maybe it is a
little more than two. Now, I don't normally
use radians myself. We, we can see divided by four, we kind of get this
little awkward angle. So you see, it can be a little awkward when dealing
with radians at times. So what I which is
one reason why I prefer to use degrees to radian, just because it's something I can work through
a little quicker. And as you see, there we go. We flip the face down. Only now we're not
facing back up, so now we have to fix
that inside of our code. And we'll just do the same
thing when we press up. We set our rotation to zero. And if we were to play it now. There we go. Now we can jump
up and we can jump down. And now, what if we want
to jump left and right? Well, we can get those
with two more LCFs here. And I'm just going to
space these out to be a little more legible here. There we go. So starting on our
second SIF here, we're going to say
I action is left. And instead of
modifying the Y value, we're actually going to modify the X of our position
because X is left and right. And if we're going left, we have to -16 here. And degrees to rad. Well, we could set this to 270, just to stay on the
positive side here, which means our last
Elsev here when we press right we're going to modify the position
instead of the Y, we're going to plus 16. And if we're moving right, we're going to be rotating
at 90 degrees. So if we go ahead
and try that now, should see now we can jump
around in all four directions. And we can get around. And if your frog is placed in
the correct location, you should be able
to land in all of these little home goals here. No problem without going over. There you go. And now we kind of got to
keep our position. And well, on the
screen would be nice. But we can worry about all
that stuff later on for now. We just have our
movement going around, and this video is
getting a little long, so I just wanted
to keep movement in its own little section here. There we go. We can run around as our own little froggy going,
boing, boing, booing. But right, and
there you have it. We can now go ahead and move on to the next section of our code. And I think next we're going to I think we're going to create our vehicles and have them start going
across the road here.
31. Creating the Vehicles: Alright. Today, we're going
to go ahead and create the vehicles
to go across. Now we have a couple
of different ones. Let's see how many we have
here inside of our sprites. We have five different
cars. There we go. And some of them go left,
some of them go right, and they're already facing in the direction that they want. So, that's great. All we have to do is create them and have them move
across our screen. Alright, so let's
go ahead and create a new scene with our plus button here at
the top for our tabs. We're going to go to other node, and just like our player, we're going to use the
character body two D here. And we're going to
give it a sprite, in this case, since we
have no animations for it, we're just going to use
a regular Sprite two D, and we can go ahead and assign
one of our sprites to it. Now, in this case,
I went ahead and selected the little truck. But of course, you can pick
whichever one you want. Specifically, I'm using
one that's moving left at the moment, so
that's worth noting. And I'm going to
change this name from character body to D to be Truck and I'll save
that as my truck scene. And I'm going to
need a little more. Now, we're not going to
use a collision shape, although we are going
to have some type of collision be able to happen
here because obviously, our frog has to get squished
in some way if it gets it. So to prepare for that, I'm going to create
an area two D. And that's just going to
pretty much allow me to have a redefined area
that I can check. And to get that area with
area two D selected, that's now where I can bring
in the collision shape. Now, the collision shape has this little triangle on
it, giving us a warning. So collision shape selected. We move to the right
to our shape section, and we create a new one. And this is just going to
be a new rectangle shape. Now, we don't use
complicated shapes such as using the polygon hooks. And instead use
polygon or sorry, will you use shape with some
of these basic shapes here? Because the templer
your shape is, the better it's going to be
in terms of performance. However, the more
complicated a collision is, the more accurate
it's going to be. So it's kind of a balance that you yourself would
have to work out. But in this case,
luckily for us, we can just use these
rectangles and that will find, especially since
we're recreating an older game like this. All right. So now that we have our collision shape
like this, again, if you didn't catch
that, just make sure your rectangle is
covering everything, every part of the truck here. And now our truck is actually going to need a script on it. I'm going to add one
to it. And instead of calling it the truck script, I'm going to call it
the vehicle script. Now the reason why
we're going to call it the vehicle script is because
we're going to be able to use this script on
all of our vehicles. Now, to do this, Bruni
export a variable for us. And what this is going to
do is this export keyword is going to allow us to change this inside
of the inspector. So let's go with
the at sign export, and we'll create a variable, and we'll call this direction. It's going to be an integer, and by default, we
can just set it to zero or sorry, we
can set it to one. Doesn't really
matter in this case. And if you save that and
select your truck again, you should see direction inside of your inspector on
the right hand side. Now, in our case, we're
going to need it to be negative one because
we're going to move left, which means we're going in
the negative direction. So I just went ahead and
set that to negative one. And now in the process function, we're going to need to have
our character or well, character is correct,
but our truck move. And then order to move, we need to have something called move and slide
or move and collide. Either one will work in
order to have movement here. In my case, I'm just going
to use move and slide. Moving collide is
just fine as well. It pretty much just
defines what happens when two physics bodies collide
with each other, right? They either smack up
against each other and stay there or they can
slide along each other. In our case, it
doesn't really matter since we're just
going to be using the area to determine if our frog has been
hit by the truck. So now we have moving slide. We can't just play it now because we still have to
control this movement. So I'm going to have another
variable here called speed, which will also be an integer. And I think I'm
going to set this. We'll try eight for now, and we'll see how
quick that moves. That might be a little too
quick. So you know what? I'll actually try it with two
now that I think about it. And all we're going
to do is we're going to change the velocity, and we want to
change the X number. So just like position, we have both an X and a Y
when it comes to velocity, and velocity is going to control our object moving consistently. So let's go to velocity, and as of four, Interesting. Maybe it's a capital V because I know there
is a built in one. Pretty sure here. Oh, no, it's low right there. I must have just put
a typo in there. But there we go, so we can
just do velocity dot X. And this time we're
going to say equals. We're not going to
say minus or plus because this is going to be
dependent on our direction. So we'll say speed
times direction. So we're going to move
along the X axis, so we're going to
be moving left and right at the rate of speed, which is two right
now, times direction. So right now we're at minus one, so it's going to be
two times minus one, and that's going to
give us a negative two and should
have us move left. But if we went in
the inspector and we changed it to a positive one, then that should
be two times one, bring in a positive two and have us move in
the right direction. So I'm just gonna set
mine back to minus one. And I'll go back to
my main scene and just bring a truck in
to take a look at it. I'll just set it right here, play this scene and
see if it moves. We can see it's moving, but
it's moving way too slow. So we're going to have
to tweak that speed. So let's go back to eight.
Maybe eight was good. Let's try that. Eight is not good, but
it is much better. So let's see. Do we want
to be moving at 16 pixels? 16 looks good, although that looks like it
might be pretty easy, so maybe we want
to increase that. And keep in mind, we can
always come back to this. And since we're using the
speed on all of our vehicles, we could easily adjust this and tweak it once
we actually have all five lanes being
used up for vehicles. So let's see with 32, 32
is looking nicer here. I think 32 is where
I'm going to leave it and tweak it later on. Maybe you want to
go to, like, 48, or I don't think we're going to be able to
get to something like 64, but you never know, I suppose. So I'm just going to
use 32 as my base. Alright, so we have a truck
moving in one direction. And now we can create our
other vehicles as well. Let's see. We have
two more that move left and two that
move to the right. Let's see what do we at here and we're going to go to the left. So we're just going to pretty
much repeat this process and use the vehicle
script on all of them. All right, so I've gone
ahead and as you can see, I've made my other
four car scenes here. All I did was come in, adjust the collesson
shape if I needed to, replace the sprite with
another one of our cars. And then, if necessary, age the direction from
minus one to positive. And that controls
all of our cars. And I went ahead
and I placed them approximately to
where they would be here just so I can
test and take a look. And as you can
see, as we run it, our cars go ahead and drive, and they go across the screen in the appropriate direction, and they never collide
with each other. Awesome. Now, all we need
is more cars that spawn, and we don't want to place these consists because if we have
to place them manually, then we have to just have this huge list of cars and we
have no idea how long it's going to be for them to
spawn or how long it's going to take the player to either run out of lives
or complete the level. So what we're going
to do is create spawners for these
cars. All right. And these spawners are
basically just going to on a set time, spawn the vehicle. And we could have five
different spawners if we want to, one
for each lane. And let's see. I think that's
what I want to do. I think I'm going to have that five different spanors that way, they can all have
their own times. And if you wanted, you
could just have set as one spawn limit or one time
limit for all vehicles. That's perfectly fine, as well. I'm going to go ahead
and create one, and this is just going
to be a basic n2d. I'm just going to call this
spotter Do we want to call it SponterO? Here, yes. Let's go that sponsor one, and this is going to control
my top spawns up here. And, you know, I think I'm going to use this as its
base location as well. I'm just going to
get a good spot, and since this is the truck, I'll bring it back to
there, and that'll show me if the truck spawns on this position,
it'll be right there. Okay. So on my spawner, I'm going to create
a new script. This is just going to be
a spawner dotGD script. And once again, we're going
to use this on pretty well every all of our
Swannas that we create here. So what do we need
to do? Well, we need to wait a set amount of time. Just going to delete this
comment out of there, as well as the one down
here on line nine. Whoops. Yo. Alright, so we need to
wait a set amount of time. That time should be random. And then based on
that, spawn a view. So in our case, we're going
to be loading the truck. So I'm going to go ahead and do bar a variable
here for my truck, and that's going to
be a pre load here. Which means we're just going to load the scene beforehand. That way we can use it. We can instance it
in at any point. So I'm just going
to grab my truck from my file system
and drag it in. That way we have the correct
location here to the scene. And with this, I'm
just going to show you the one vehicle here
because then we just have to come in and
we can tweak this. I'll show you how we can
export this as well. That way we could actually
use this script on everything instead of
making multiple scripts, just because of one
variable difference. I'll show you that. But first, let's get
this up and running. And what we're going to
do, we're not going to use this process at all. We're actually going to
create a function called spawn vehicle. And in here, we're going to This is where we need
a random number. So let's go ahead and
call time wait time. Just call it wait
time. And we'll set this afloat and we'll set
this equal to let's see, and random integer
and not mistaken, we could just do something
like this and that would work. I don't think we have
to use rand range, although I could be incorrect on that.
Alright, there we go. And since I want to
double check that just to be safe, I'm
going to hold control, click on Randi, and that's going to open
me up to this page. And yes, I did this correctly. So by using percent 20, in this case, as you
see, is going to give us an integer 0-19. Percent 100 would give us 0-99, and if we do percent
100 plus one, that would give us
a number 1-100. So in my case, if I do three, then we're going to have
a wait time of zero, one, two, I'm going
to add one to that. Now we have to wait
at least 1 second in between truck spawns. So this is going to be
between one, two, and three. And we can see how this looks. We could always
adjust this later. Now, our wait time,
we have that. Now we have to actually
wait this amount of time. So we'll say await and we have to get the tree
in order to do this. And the await keyword
here means we're just going to wait for this. In our case, it's
going to be a timer, but this could also
be waiting for a signal to be sent out. But right now, we're
going to say await, get tree dot create timer, and this is going to
be our wait time here. Our random wait
time that we have. We got timeouts. We're going to wait for that timeout signal
that gets sent out when our timer ends, which will be based
off a random number, a random amount of seconds. All right. So once that's done, we can create an
instance of our truck of our say VT for vehicle or VI
for vehicle instance equals, in this case, we're
going to say truck, but we should change
it to vehicle. So truck dot instantiate And then we'll add
it to our spatter. So we'll say self dot, add child to add it
into the scene and VI. All right. Let's see
how this works now. And it's not going to
because we didn't call it. Let's go into our
REDI function here and call our spawn vehicle
function that we created. Let's try it now. There we go. So we had another
truck spawn in, and we're not going
to have anymore because we're only
spawning it once. So what we can do
from there is after we add child, right? After we add the
truck into our scene, we'll just have it
recursively call itself. So it's going to cause
an infinite loop. It's going to spawn a
vehicle and do nothing, and then spawn a vehicle. And when it's done
with that, spawn another vehicle. It's
done, spawn a vehicle. And it's always going to
be a random number every time that we have to wait
or in between spawns. So if we just take
a look at it now, we can see they're fairly
consistent in its spacing, and then that was a
much larger spacing. And we went, Oh, we got a really close
spacing on that one. So it looks like
percent three plus one might be the shortest
that we want to go. But there you go. So it's up to you if you want to that's a lot of
close ones together. So it's up to you if you
want to tweet that a bit, play with it at all, and up to you how you want to
have them spaced out there. Now, the reason we
don't have to set its position is because we're adding it as a
child to my spotter, and the spotter is right here. So since the truck here is
at 00 in its position, Oops. This the truck here is at
00 in its position here. And we can see that if
we go to transform 00. It's going to be exactly
the same as its parent, which in this case, is
going to be sponorO. So where my sponorO here is, it's going to spawn
in that location just off screen enough. Now, how can we script to run to be able to use it
for any of our vehicles? Well, what we need to do
to make this work for all of our spawners that we can have as little
work as possible here. Well, first off,
I'm going to change my variable name from
truck to vehicle, now we're going to use it
for more than one vehicle, not just the truck. And that means I'm going
to have to change it down here in our spawn from truck dot instantiate to
vehicle dot instantiate. And we want to have this
variable exposed inside of our inspector so we can tweak it on a per node basis here, so we're going to do the
at sign with export. And now, what are we
going to export here? Well, we could just
leave it as such, and this will just
work if we look at the inside the inspector. But if you want to get specific, this is called a packed scene. That's how you
would export this. And then we could even just
delete the preload here. So we just have at sign export our vehicle and declare
it as a pack scene. Now, if we click on our
spawner and our scene here, we can just open the vehicle and say new pack
them or we can load. Obviously, we would
want to load, but to save some time, we can just go into our filesystem, grab our truck, drag it in, and drop it in there. And if we run this,
we'll see our trucks spawn just like they should,
just like they did before. All right? Perfect. And if we were to grab, say, let's see, car one is
also going to the left. So let's grab car, replace that scene in there,
and take a look at it. And there we have it. We got it working here with a
different vehicle. So all we have to do is
just change this one out. And that's a lot of
cars in a row there. So again, that can come down
to you tweaking things. But there you have it. I'm just going to go ahead
and replace this one with truck again and
stop that from running. And now I can go ahead and
I can make more spawners. Oops. Und we do
history mismatch. That's interesting. I'm not
doing anything with history. I'll just use Control D there. And this one is sponsored two. So just come on down, make
sure that lines up. That does. And this is going
to be car three. So I'm going to look for my
car three scene, drag it in. Go ahead and take a look
at that. There we go. We have our trucks
and our car spawning in at our different intervals. Fantastic. And we can do the same thing for
our bottom here. So I'll duplicate
that one more time. I'm just duplicating that with Control D with spanor selected. And I'm just going to pull that down here for this vehicle. And this one is just car. So I'll pull car in here.
And we take a look. And we see all of
our cars going to the left are all
spawning in correctly. Fantastic. And now we just got to get the
two over on the right. And the same thing, I'm just
going to duplicate my span here and just drag it over
to the left hand side. And then I adjust it here for position,
that should be good. And that is car four,
my car four scene, and we duplicate it one more
time and mass it up here for my car two sne. All right. So now I should be able
to come in here and delete all of these
temporary cars and trucks. And if we run it, it should
be working perfectly fine, spawning all of our vehicles
in there we have it. Now we can run around
with our little I say little froggy
here. There we have it. And now we just need a way to hop across this water
so we can get in there. And, of course, a way for our little froggy
to get squished. I think we'll handle the
squishing next time, so we'll get player
death in here.
32. Player Death and Respawn: Alright, so how are
we going to get little our little froggy to get Gist if he
gets hit by a car? Well, the first thing
I did is I added a collision shape two D to
cover the size of my froggy. And we're going to use that in order to determine if he got hit by a car in combination with the Area two D that
is on our vehicles. And inside my animated sprite, I created a new
animation called death, and I brought in the
Frogger dead sprite. And now that we have that, we also need on our vehicle, we're going to have to add
in a signal connection here, and the one that we're going
to want is body entered. And we could come
through here and connect them one
by one on all of our vehicles or we could save a little time and connect it through script,
through the code. And I think that's
what I'm going to do here that way we saved
a little bit of time. Now let's take a look
at how we would connect this signal through the code
instead of the interface. The easiest way for
us to set this up is, as you see in the following
inside the ready block here, and that error is just because we haven't created
that function yet. So we see we grab our area two D because that's
what's sending the signal. Dot the signal name, which is body entered. You can see that
on the right, and we're going to connect that signal with the
connect function. And then we create
what's called a callable and pass in a name, and this name is going to be the name of our function
that we want to call. So on player hit, froggy hit, you
can go with that. Player Hit is what I'm
going to call mine. And now all we have to do is
just come on down and create a new function for
it, Bunk player hit. Now, this function also
passes in a piece of data. If we take a look
at the body entered signal here on the
right hand side, you can see it
passes in the body, and that is a node two D type. So it's going to be a
two D node of some type. So we have to pass
that argument in, so body, node two D. And just like that,
that should now connect the signal for all of our
vehicles, and to test the cell, we can go ahead and print
body, and we'll see this. And something I've
also done is I changed my player I've renamed my player from character
Body TD to be layer. And then I've had to go
into my main scene here and replace it so that
the name was updated. Now, if we go ahead
and run this, we should have a
body get printed out every time we get hit by a
vehicle slash test lane one. Yep. Lane two. Yep. Lane three, correct? Lane four and our last lane, the truck. Here we go. So all of our vehicles are
detecting when we get hit, and we can see we have a lot of vehicles there with this time. So that might be a good amount, or maybe you want to increase the minimum span between them. Again, completely up to you and how you want
to go about it. What about yours. But with that, all of our vehicles
have now been connected and set up to
squish our little frog. So the reason why I
told you I renamed my character body TD for
the player to player, and I'm using a Capital P is
because we're going to use this name on our vehicle screen. So we're going to
say if and then pass in a string here, a player. So if player N. So we want to see if this string is inside of another string, and the string we want to
check is body dot name. Now remember, body is whatever object we
just collided with, whatever body just entered
our vehicles area, and the name property
of it is going to give us whatever
this name is here, which in our case is layer. So basically if our
name is player, and instead of in body dot name, we could just do a double equals if we want it to
be an exact name. It's completely up to you. In this case, it shouldn't
affect anything. Wind our if statement
with our colon, drop down to the next line, and now we can execute
our PC of code. So what do we want to do
when our player gets it? Well, we're going to call the
DF function on our player. Now, this function
doesn't exist yet, so we're going to have
to go create that, but body dot death. And if you want to have an
extra case of security here, you can say if body dot has method and pass in
the string of death, and then we can tap body
dot death in one more. We can go like this. And this will avoid an error if we were to go
ahead and run this. You see, we're not going
to have any errors here because we're
basically saying, Okay, we're saying if we collided
with the player here, then if that player, if that body has this
function, then call it. And right now, it does
not have that function. So if you wanted to put
that extra layer of security in there by
using HAS method, you can certainly do that. And I'm going to go
into my player now and create this function funk Dak And this doesn't. We're not passing any
arguments in with it. So what's going to happen
when our player dies? Well, we need to play
our death animation so we can get our
sprite corrected. So let's go ahead and do
that. Animated sprite two d dot, la death. And let's take a
look at that now. What happens when we
get hit by a vehicle? La Di Da, poor little frog
crossing the street, at. Okay. So we see you die, and then we one or
sprite is the wrong way. It's not facing up
the way it should. So let's correct that. After that, we're just
going to set its rotation. And we've already done
this when we press up. So let's add that into
our death function here. And we take a look that
should now be acting right, flat or in position. Awesome. Now, what you can't see is we're constantly being
collided with because our collision shape keeps
hitting these cars. And not only that, we
can also keep moving. So we going to being,
and we're alive again. So we have an
unkillable frog. Yeah. Alright, so one
prop matter time, let's stop our collision
from happening. And we can see this. And I'll show you that if we
come into our player hit, and I'm just going
to go ahead and print out squished frog. And you can see that even though we're dead, we're still
getting squished. Squished frog, and
we're going to keep getting squished even
though we're already dead. We don't want this to
happen because this might just keep
subtracting lives from us, depending on how far
apart the spawns are. So let's go ahead and
fix that on our player. And to do that,
we're just going to we're going to get ahold of our collision shape
that we created, the collision shape two D, and we added onto our player. And we're going to
use something called called deferred on it. And what this essentially
going to do if we take a look is calls the method on the object
during idle time. Always returns Nou, not the method's result.
So there you go. Our keyword here is calls
it during idle time. So it's going to call
this, whatever we pass in. When it gets the next
chance that it gets, basically, instead
of trying to call it now when it might
not be able to. And Sum functions is going
to tell you to do that. So before we call that, you don't have to delete them. I'm just going to show
you here the error. So if we come in here and I go, disabled equals true, we're going to see
if we're going to run into an error here. And it doesn't prevent
our game from running, you see, we got squished twice, so our disable isn't
working for one. And two, if we go into our
debugger and look at errors, it's going to tell
us that we cannot we can't change the
state while flushing queries, use call deferred. Tu it's specifically
telling us to use that. That's why we're using
call deferred here. Call deferred. And in
here is going to be a string of what we want to do. And in this case, it's
going to be set disable. I that disabled, and it
takes a second argument, and this is going to
be what we set it to. In our case, it's going
to be set to true. And now, if we look at this, that error is going to be gone, and we're only going to
get squished one time. And there you go. It's not going to pop up
anymore inside of our code. And if you're worried about
call deferred when we get hit by a close
range of vehicles, so when it's like
three back to back, we can take a look here, and it's already been disabled before the next vehicle
even touches us. Now we can actually die here. Now what we have to look at is, how do we get ourselves back, now we're just non killable frog because we can't
collide with anything, so we have to fix
that with our death, we have to have a
respawn of some sort, we need to make sure
that we can only move if we are alive. Oops. I delete a little
more than intended there. Alright, so we need to keep
track of whether or not our frog has been
alive or is alive. And we can do this
with a simple function that just checks if
alive or if dead. And based on that variable, we can either move or we can't. And for this, we're going
to use a set of states, which is going to be an ENOM as you can see here
from the example here, we can use these Enums to hold specific pieces of data,
I suppose you could say. And it's basically like a list of options that
we can select from. And it makes it easier when
it comes to checking things. And you can see this when it comes to basic form
of a state machine, which is used for characters. For example, if you've
played Grand Theft Ato five, for example, you have different controls
when you're on foot compared to when
you're in a vehicle. And that's because you on foot controls would
be one state. Swimming would be another state, and a car would be one state and an aircraft would be
another state, et cetera. And we're going to
use this to know when we are alive and when
our froggy has been squished. So in order to create this, instead of using
the var keyword, we use Enum, the
name of the Enum, which since is going to work like a state machine, I'm
just going to call it state. And then instead of
using equals or colon, we just jump straight
into the curly braces. And traditionally, from
what I've always seen, these are always going
to be in capitals, so I'm going to have live, and then coma drop to
the next line dead. So these are our two
states alive and dead. Alive will be the
default state here. And we're going to create
a new variable called current state and we're just going to declare
this as being a state. So it's going to be one
of our states here. Alright, so now
with our movement, all we have to do is
check if current state is equal to two
equals state live, and then tab our movement in. So now we can only
move when we're alive. So now when we die, we
have to tell it that our current state is now
being set to state equal deb. So if we run this
now, we should not be able to move once we
die and get squished. And there you go. We got all squished in
and we can't move. So now all that's
left is for us to go ahead and create the respawn. Let's create a respawn
function, respawn. And once we have lives in here, this is where
we're going to check. If the player has lives left, we're going to call
this. All right. So let's go with,
how do we respond? Well, we're going to need to set our collision back to working. So we're going to need to call deferred in our collision shape. And instead of setting
it to disabled, we need to set it to false so that it is
no longer disabled. We need to change
our position, right? Self taught position, and we need to reset this to where our starting
position is going to be. And at the moment,
that is 169 and 233. I'm just going to copy
this value real quick. And inside of my main scene, I'm going to add a let's see. What did they rename it
here? Ah, here we go. It was renamed to Marker two
D. And give me 1 second. I'll get that up for
you. There you go. So we're going to
use a marker two D. And I'm going to set it
to transform for now. Just going to paste
the value in. Going to set it to the same position that
our frog is starting at. And I'm going to call this
player spawn location. And now when we respond, we can do self dot position
equals our player Okay. That's not going to
fill out for us, so I'll just have to
type it in player, spawn, location, dot position. And this should happen
pretty instantly. So let's go ahead and go
up to our process here. And we're going to
form another check LI current state is
equal to state dot dead. You can call Respawn, and this should
spawn us right back in the beginning where we
started, if you get killed. And we seem to have a cue. What is myth? Oh, that's fair. Players spawn location,
we can't get access to that because we actually
have to go up the tree, remember we're a player
and the player does not have direct access to this
playersp location here. So we need to follow
this line and go up one, and then that takes
us to this no two D, and then that no two D then has access to
our players spawn. So we have to go up one. And the way we can do
this is a few ways. We can go ahead and do
get parent, get node. And this G node is just a long form of
writing that dollar sign. And then inside
would be a string for the path directly to
player span location. Alternatively, to keep
this a little short, we can just get node, and we can pass in a few things. We can use one dot, which is equal to writing
self or we can do two dots, which is equal to that get
parent we just deleted. And you can see that
as much shorter. So we can do this with G
parents player spawn location. Alright, and that
should fix that. Now when we get squished, let me see we get set right
back to the beginning. Only we can't move yet
still because we do have to set our current stake,
remember, we can't move. Current state equals State Live. And not only that, we have
to set our animation back to being our idol Wops. So we'll get our animated
sprite dot twoB and play our Idol Sprite,
set it back to normal. And when we run it now,
splat only now we can't really we can't really tell
when we get respond to. So what I'm going to
do, first of all, I'm going to use
Caldeford and set that down after everything else because I notice we're
getting squished twice, so we'll see if just moving
that line we'll fix. It does not, okay.
Not a problem. We just have to
have a small timer, for example, afterwards,
which is fine. All right, so let's
see what do we need? We need to Our dead symbol isn't working all too well because we dine and
we're instantly respawn. We can't tell anything
that's going on. So what we're gonna do is inside of this respawn would
just create await. And we'll do what
we did before using Get Tree and create that timer. And we'll set it to 1 second. That feels like a long time
and the timeout signal. So 1 second may feel like a long time here in an
old game like this, splat and then we respawn. Awesome. Now we're getting
squished multiple times there, which is a little unfortunate. So I'm just going to come
down here and create another small timer for 0.5, and I'm going to see
what I can get away with or how small I can
shrink this through testing. Okay, 0.5, we can
get away with it. I'm going to try 0.2. And I can get away with 0.2, so we may even be able
to get away with 0.1. Having that really
short delay here. Yeah, there we go. So now we have
that 1 second that our death image
is going to be on the screen of our poor
little squished Bronte. And then the respond
happens. Awesome. Now if you wanted, you
could set this number into a variable up here to respond
timer or respond time, and that'll be your time
in between your responds. Now for me, I think I'm just
going to leave it at one. That's not a problem.
I don't think I'm ever going to want to tweak. Now, if you notice
here when I was going, if I sit right here, I might get squished by the
car underneath. No, I'm fine. Oh, but I did get squished there
when I turned to the side. So I might want to tweak my
Y position a little more. I might want to tweak my Y
position a little more there, but that's going to
come down to just playing around with the position and that just a little more. But no problems. But that'll do it for this. We now have our player death and respawn system happening. We don't have any lives
going on right now, but we'll get to those
lives when we get to our UI section. But with that, take care. That was a lot of information
that we went over. And I hope you're ready.
We're moving on to the next section of
the game that is.
33. Water Death: Alright, so let's make it so that when we jump
into the water, we die and have to respawn. Well, to do this, we could do this a
few different ways. But the easiest way that I'm going to say for us
to go about this since we are using a tile map is
to take advantage of that and use the tile map to tell us what tile
we are standing on. If we are standing on the
water, then we'll die. If not, we'll be fine. I do this. Let's head on
into our players script. Close on the other tabs. So we'll go into
our players script. And what we're going to need is a new variable to
hold our tile map here. Now, we don't have to
set this at the top, but we don't have to
constantly set it in our function we're
going to make either. Alright, so let's just get this and we're going to use
the keyword on ready, and all that means is the
variable that we're going to make would be the same as if
we set it here in the ready. So if we said, for example, number in equals ten, it would be the same thing as if we crated number and then set it to ten down here
inside of the ready block. That's all on ready means. And this is useful for when
we want to get ahold of specific nodes that are
inside of our scene. And in our example,
we want to get ahold of that tile map here. So we're going to
do var Tilemap. And we're going to set the
equal to yet part node, and of course, it is currently
just called Tilemap. Now, remember what I said, I think it was in
the last video. Instead of using getParent here, we could shorten this
down and in our get no, just do dot dot slash and have the same
equivalent of G parent. I think I'm going
to do that just to keep things again
a little shorter. All right. So now we
have our tile map. Now, what we want
to do is we want to check what tile
we are standing on. So I'm going to go ahead and
create a new function here. I'm going to call
this check, cell ID. Whoops. That's going to
give us some void turn. And what this is going
to do for us is we will basically use it to first get the position of the cell that
we're standing on. So we're going to say bar pause, which will be set to our
tilemap local to MAP. And then this will
take a position, and that position is going to be the position of our player. Now, local to Map is just going to give us back a position, which will be the position of the cell that we
are standing on. And the cells would be each
of these orange squares. So since we're standing on here, immediately when
the game starts, it would tell us this cell here, the location of this cell. And then the next variable
we're going to create is going to basically
go in there and say, Okay, that's made
with this tile. Now, what is that ID, and it's
going to give us back one. And to get that ID, we'll
create a variable here. And this is just
going to be Tilemap. Looks. Tile map. Not yet. Sell source ID. And that's just going to
take the two arguments. The first one is going
to be the layer it's on, which is layer zero. And the second one is
going to be the position, which we already got from
our map pause variable here. So now this ID should now be
whatever we are standing on. So if we come in and
we print this ID, and we just run check cell
ID inside of our process, we see one immediately get
printed out for the median, two get printed
out for the road, and three for the water. Those who run this, we can take a look down in the output. We see one get printed out for our median, two for our road. And if I can make it
to the water here, we can have one for
the median again, and then three when
we hit the water. There we go. So now we know that this is working perfectly, even if we come all the way up here because we'll
check for layer zero. So we're going to have
three is going to be our water since well,
we know that now. So what we're going
to do is we can now check I ID is equal to three, and this is where we
would kill our player. All right, so we then come in, call our death function up here. Now when we touch the
water, we should die. There we go. So now we can die when our player touches the water and wait
for the respawn. Now, this is a little could be a little taxing when we're checking it constantly
like this, no matter what. So the next best
location would be to call in here only
when we're alive, but even better, is we can call it whenever
we actually move. So I'm just going to add this to the bottom of all of
my movements here. Now, when I'm moving any direction is the
only time we're gonna check instead of spamming it. So far, good. Jump up, Dad, wait for the respawn. Now move again. Alright. So now we're able to drown
our frog in the water, and we're able to let our
froggy get squished by a car. Alright. So we have all of our
deaths in check now. All that's left for
us to do is to get our platforms
working and then get our little win points at
the end by jumping into the right locations and then set up our heads up display
with our score. And then I think
we'll be about done. I don't think we're missing
anything after that. Could be wrong, but
there you have. We can now drown our
froggy with the water, and you now know
how to get the ID of whatever tile your
player is standing on. Alright, to do it for this one. A. I'll see you guys
in the next video.
34. Water Platforms: All right, let's
go ahead and get ourselves our platform setup. Once we have our
platform set up, the only thing we can do or
the only thing we'll have left for these platforms
is basically just swap out the sprites and to make these longer and
shorter through. So for my platform here, I'm just going with
a three sprite setup here so that we have using
the log for this example, the end, middle,
and the other end, right, middle, and start. So that means I'm
using three sprites here with my main scene, the root of my scene here being a character body that
I've renamed platform. I could rename it to
a log if I wanted. And that has an area two D with a collision ship that
covers up my log here. And I have connected
both the body entered and body exited signal. Okay. So once you have both
of those signals connected, the script on your platform
should look like this, and we are ready to add information or add
everything onto it. So with the way that
we're going to do this, we're also going to
be adding things into our player script as well. And the majority of this work will actually
be on our player script. So for the time being, let's
go to our player script and add a couple variables
that we're going to use. First one, it's going
to be platform, and that's going
to be a boolean, and that's basic going to
tell or let our water know whether or not we're
safe because we're on a platform or if we're
not on a platform, so called the death
notification. We're going to get our current
platform var platform, and that's a character body
two D that we pass in. Then we'll eventually set to it for now I'll
just sent it to N and we're going to need
a platform direction, which is an integer default. We're going to set to zero, even though it shouldn't matter. All right. So again,
we're going to use platform, current platform, and platform direction as our three new variables
on our player script. We're going to go
ahead and move down to our check cell ID, and we're going to add
to our if statement. So we're going to say
if ID equals three, and platform is equal to false. That way, we'll say if we're in the water and we're
not on a platform, then we'll kill the player. So we have our
conditions set there. Let's see. For a player, we're also going to check while we are alive. If our current platform
is not equal to null, which it won't be it's
only equal to it for now. It'll be have an object assigned to it once our
player stands on our log. So say current platform
is not equal to null, then we can just
go ahead and call our position dot plus equals, we're going
to do a little math. We need to open and close
our parentheses here because we're going to use the order of operations when it
comes to our math. We're going to say
platform direction. Times 16. So we're going to use this as either plus one
or negative one, just like we did
with our vehicles, and multiplied by 16. So we're either
going to be moving 16 to the left or
16 to the right, and we're going to be
doing this over time. So we're going to
multiply that by Delta. This way we're not frame based, we're more time based. All right. So the only thing left
for us to do is to set our platform direction, and we can do that
via a function. Fun. We want to go with, let's go with set direction. And that'll take a argument of an integer, returns nothing. And all this is going to
do is he's going to set our platform direction
equal to ter. All right. So now we can head over
to our platform script, and we don't need this ready
block. We can delete that. And inside of our process, we want our log in my
case to keep moving. So I'm going to go ahead and do position dot X plus
equals 16 times Delta. That's going to constantly
move it to the right. I when we enter when our
player enters the area. So we're going to set
platform here to true, and we're going to set
our current platform to our log here,
my platform here. So I'm going to take
body dot platform and set that to true because now we're on the platform and body I believe it
was curb platform. Yes, curb platform equals so. And when body exited, we're going to do the opposite,
so we're going to set. Instead of true, we'll
set it to false. Instead of cell, set it to know. All right? So what
we're doing so far is when our jumps on the log, which is currently moving
to the right at all times. While it's doing that, Okay. Restart that. Our log is currently
moving to the right by 16 over time and not
based on brains. Now, when our player enters the area of our platform here that
they can stand on, we're going to set
the platform variable on our player to true. That way, when we check the cell ID to see if
we're standing on water, platform will be true and our
player will not be killed. And then we're setting the
curve platform variable of our player for the current
platform equal to self. So the character
body here that's moving representing
our platform. And based on that, we'll be able to move our character here. So current platform
is not equal to null. So if we're on a
current platform, then we're going
to move our froggi in the same direction
at the same speed. So the last thing that we
have left is to actually call this function that
we created set direction. So body dot or set direction, and that takes an integer, which means we'll
move into the right. We'll use positive one. And now, if we go ahead and add the platform to our
scene and run it, as you see, there's our log, and if we jump onto it,
we ended up dying there. Might need to update this. One moment there. Bring
a new one back in. Move on down there,
give Dad another shot. Okay, I'm dying, so my signals might need to be reconnected. I'll disconnect that
and reconnect it. And I'll do the
same with my exit, disconnect and
reconnect my body exit. And we'll see if
that was the issue. Okay. I believe I see
what I missed here, and we're getting this
information a little too quick. So before we have our if statement inside of
our check cell ID, I'm going to use a weight and do what we did
before with Get tree, create timer, and we're just going to have
a small pause there of 0.1 and get that
timeout signal. And that should fix that for us. Here we go. Now we can jump onto our little
log, and we're good. We can jump back and forth on it and be okay,
and we're moving. And as soon as we jump off, we're fine to run back to the
other side if we want it. And still, if we
jump in the water, whoop we went ahead and died. Alright, so how can we
make this script a little more I guess we could
say modular in a way, in a way that's going to be more friendly so that we can constantly change whether we have two sprites,
three sprites, one sprite, how big our
collision shape is, and have all that regardless,
as well as, I guess, set our direction so we
can have some moving right and some moving
right or some moving left. Well, we're going
to go ahead and export a direction
of an integer. That to zero by default. Oh, got the word bar
in there. There we go. Now I want to go to my platform. I can change this to
one instead of zero. We can take direction and pass it in here when
we call set direction. And plus equals, and we could do the same
thing here where we have direction Whoops times 16. And we can go ahead and
check and make sure that everything's still working. We haven't broken anything. Okay? Archeologs still moving. We can jump on it and good. Okay? So we haven't broken
anything yet. That's great. And let's see, what
else do we need? Well, I suppose
that would be it. And we can just go
ahead and set or create all of our
different platforms now using the same script. And then we just create
a sponder for it, just like we did
with our trucks. I'll be right back while I
create a couple of these. All right, so I've gone
ahead and I've made some three long turtles as well, and just do a few
here in the scene. And as you see, go ahead
and play this log, jump to the next turtles. Next one, jump to the right. Hop on my turtle,
wait, jump on the log, and I'm ready to jump into
what would be our wind space. All right. So our platforms are certainly working just fine now. I is great. I do
want to note I did add an await for 0.1 on body Entered before changing the platform on our
platform script. So I do want to
take note of that. And now all we need
now is our spawners. Alright, so let's go
ahead and create those. And we're going to
effectively make those just like our
truck ones here. Then we're going to go
ahead and get ourselves or add on a no two D, we'll call it platform spawner. And we'll go ahead and
start lining these up. Then we'll have one
there. Ha one there. Ha one what looks like there. Okay. That look even does that. Actually, a bit of a weird
spot. Yes, go there. And then we need a couple for the other side for our hurdles. A Thank it over and one for our hurdle. All right. So those look
like some good spawn points. These ones a little close. Help back those ones up a bit. And we're going to
have something similar to our truck spawn, so I'm going to go ahead and
just copy our truck spawner. And let's see. Are those
going to be At the same, different name the vehicle. Yeah, pretty much. So
we could probably get away with just using our
truck script on here. Our platforms would
be named vehicle. But I think I want
to do different one because I don't
like the wait time. I don't think that would
be good for the platforms. I'm just going to
use that as my base. I'm going to click on
my platform spawner, add a new script. And in here, I'll go ahead and just paste in the
vehicle scripts. I'll call these platform. Whoops. That's not what we wanted.
We'll change this to platform dot Instantiate PI for
platform Instance, self at Child PI. Wait time. See, this is where the
issue is going to come in. So I think Let's see. We'll go 1-2, and we'll
add three to that. So we'll see how that works. Then we'll change this
from span vehicle to spawn platform. So this one here is going
to be our log scene. Platform scene. The next one, again, it's going
to be the same. I'll go ahead and just
drag my script up and attach them to all of
my platforms poners. And two is my log scene. Three is the log platform, and then four and five
will be my turf All right. So if we now get rid
of these platforms, move my player to be
underneath the colum so the frog can sit on top. Let's see if the working. Yeah, yeah, I get
all the way across. Yeah, there's my turtles. Well, it looks like we need
to change those wait times. That's going to make
it extremely easy for our player to
just make it across. And this is why we wanted to
use a different script from our truck because we're going to need
completely different wait times for the platforms. All right? So let's
try plus ten. So this will give us a
variation of 11 and 12 seconds. Oh, what did I get
between these cars? A So 11 and 12 seconds might be too small of
a gap in this case. So at this point, we're just kind of tweaking to kind of see what fits best here. But maybe we'll
try five and six. And I'll jump all
the way across, and we'll see what this
kind of spread is like. But at this point,
you're just pretty much tweaking your
numbers to see what looks good for your
platforms and what looks good for your trucks. I just want to make sure
these aren't going to be completely consistent
the entire time, and it does not look like
they are, which is great. Alternatively, if you
wanted to hard code these a little more or make
them different specifically, you come up here and
do your wait time up here and we'll make it
a float, not a flat. Alternatively, you can do it up here and delete this
line completely. If you wanted to have
a specific amount. You wanted to have control over the exact amount
of time that you waited per responder,
you can do it that way. I'm going to continue with
this bit of randomizing here. And you know what? I'm
going to go with Ted there. And I think that'll do it for us because now
we've got our sponsors. We have our platforms. So everything seems
to be up and running. We could make it across. And I guess next, we
can do our victory, our little victory up there when we jump into
the correct zone. Let's see. Do I
like these numbers? And we jumped into the
water, we died. Awesome. I think I like these
numbers for now at least. Alright. So, that's it. We're done with our platform
spawning and riding them. Next, we'll cover the
area where we jump into our wind zone and spawn in
our little home frog there. Alright. I'll see you
guys in the next one.
35. The Win Space: Alright. For the wind zone, you can see that I've
got a new scene here, and that's just an
area two D with a collision shape and a sprite two D that just
has my home frog here. As a texture, and it is turned off or visible
is disabled by default. You can do that by clicking
the little eyeball here. And windSpace has a script, as well as a body entered
signal connected to it. And for the script, simply, what we're going
to do is we have body dot Win Zone set to true. Win zone is a new variable that has been added to the play. Body dot current state is
set to body dot sta dot win. So we have a new
state added here, so we now have
Alive, Dad and Win. Then all we do is we
get our sprite two D, get the visible property,
set it to true. And on our player to avoid any issues and
to fix a little bug, I pulled right here. LF current state is
equal to stat dot dead. I put our 1 second awight here and pulled it out
of the respawn function. It used to be here at the top. I just pulled it out and
moved it up there into our state and that should
be all we have to do. Now we can go back to our main scene and
import our wind zone, our wind space, and just kind of fit it on in there into
each of our little slots. And you may have to do
some testing to make sure that your frog is not prematurely touching it in order to trigger
the wind here. You? So I have mine
covering all my areas. And if you want to check your collision zones
and all these, these debug areas, we just head up to the debug menu at the top, and you'll have the option to show visible
collision shapes. And if you do that,
when you run it, you'll see we can see all of our little
collision boxes here. For everything. There we go. So if you're accidentally
triggering it or you might be, go ahead and enable that. Take a look yourself. And you'll see once
we make our way up. We should have another log. There it is. And we can
trigger our win. Yo. And notice we did not get dead printed out to our
console down there. And when our state is our
current state at dot win, we respawn and then set
win zone back to false. Now, we're also using win zone
down in our check cell ID. So we added another
condition here. So if ID is equal to three
and platform is false. So if we're on the
water, we're not on a platform and our
win zone is not true, or you could say win
zone is equal to false. That would be another
way of writing. Then we can call death. So if we're not
in the wind zone, we're not in the platform, and we're on the water,
then we kill our froggy. Otherwise, our wind stake
should be triggered, and we can just do a respond
without killing our player. All right. The wind
space is very simple, very easy to do there. Now, whether you leave the frog here enabled the
entire time is up to you. If you wanted, you could come
in and add a timer node. You could come in
here and add a timer. And then set this
to, I don't know, we'll say 5 seconds. Then we can come in or
rather we can connect their timeout signal to our
wind space and on timeout. We'll set our sprite
two D visible to Voss, and right after we turn it to
Tro, we can start the time. So we can get the
timer, col start. If we were to do this way, which is up to you. This is where a bit of
design is going to come in. How authentic do you
want and how custom do you want to make your
game, et cetera. So my locks and that
start spawning. Come on. Yo, so I can pop on here and
we wait to go across. So if we use the timer here, our frog our little home frog is going to show up for the win, and then after a few seconds, then it's going to disappear
so you can see it up there and there it goes,
it disappeared. So if you want it
to disappear like that, that's how
you would do it. We can just just add that
timer into your wind space, set it in the inspector to
how long you want it to be. Start the timer after you set the sprite
to being visible. And when the timer times out, set it to false. Alright. So that'll do it
for our wind space, and we just have to take a look at our heads up display or HUD or Qu Wee and look at
creating a score system. Alright. So that's it, and I'll see you
in the next one. We're almost done with creating ourselves
a frog or clone.
36. Memory Leak Fix: Alright, everyone, today we're not going to add any features. We're actually going to fix
what would be a crucial prop, especially in a bigger game. Now, what we have is a
memory leak in our game. And we have this
from two points. I mean, technically
more around ten, but let's take a look. If we go ahead and play this, play this game, and I'm just
going to pull this out here. Its I'm going to have to
slide this over for you guys. So you can see
everything spawning off screen, and they come, they come, and just look at those cars go the platforms up top,
will do the same. They're going to keep going and they're going to go forever. They are never going to stop. And this is what is
called a memory leak. All right. So I'm just going to I'll leave it right there just
so we can see that easier. But if I pause this and click on the remote tab here right at
the top of our scene tree, which is only available when
the program is running. And if we hit remote, take a
look at all these cars just in one spawner
that still exists, even though we probably don't
need the majority of them. And the same with all
the other spawners. And our platform spawners
our platform spawners aren't too bad because they have a much slower span rate than the cars, but they're going
to go on forever, and they're never
going to disappear. They're never going to get
freed up from the memory. So eventually you will have this tiny game
that could take up 128 gigs of am just
to keep playing it. It would take a long time, but eventually it would all add up. So let's fix this very
crucial, I guess, we call it a bug, and it is
very simple for us to do. We just got to put one if statement inside both
of these scripts. Now, the numbers that
you pick here will, of course, depend
on your project. But from what I've tested out and based off our window view, I have a set of numbers
that I'm going to use here. And what we're going
to do is right now I'm inside of my platform script and inside of the process here. I'm just going to check
if global position got X, now the difference here
between position and global position is if we go
into our platforms here, for example, this is going to be our local position, right? So just the position property. But when we're in our main
scene above everything else, this is going to be in charge of our global position
that we see on screen, regardless of who the parent is. For example, if we take a
look at our win space here, we can see that its position in our main screen here
is at 24 and 45. And this is going to be more
of a more of a global space, whereas if we go in here, we can see our wind space, our local position
here is at 00. So these are two
different numbers. So hopefully, that makes sense to you as to why we're
using global position here. And, of course, we
want the X property because that's going to
control our left and right. So if our X is greater than 436, that's about 100 pixels
off screen to the right. And based off where
our sponsors are, this still gives enough
room to go past that. So if our global
position dot X is greater than 436 or
global position dot X is less than negative 100. So we're going about 100 pixels off screen and
left and right direction. So if either of those are true, all we're going to do
is self dot Qu free. Alright. So now we should see character platforms
disabling each other or deleting each
other out of our memory. And this is only one
potential solution. For something like
this, another solution, which if you're
depending on your game, for example, if you're doing something
like a bullet hell, you're going to want
to go with something called object pooling, and we can talk about object
pooling in feature video if you right so I'm going to go down to my sponsor dot
GD here, My Vehicles. And let's see. Which one are we
looking for here? On our vehicle script. There we go. So not on our
span on a vehicle script, and same thing aside
to the process. I go to paste in the same code. If global underscore
position dot X greater than 436 or global
underscore position X is less than negative
100, self dot q free. And now, if I go ahead
and run this and Oops we're in the right
scene, our main scene here. I'm going to go
ahead and pause this real quick, go to
our remote tree. And we can take a look at our
regular spaers here where the cars are going to be here's my game window
to pull that out. And if I go ahead and
let this play, right? So we have some cars
net spotting in here, and we can see this here. And I'm just going to extend
the window off to the right. My mistake there. I seem to
have grabbed Goto instead. Go. And there you go. You
can see they're in the remote as well
as visually there. Once you go far enough, they're actually completely
deleting themselves. So, now our objects
are all being managed, and we can only
potentially have so many on or so many in our
scene at any given time. And you can see the platforms
at the top doing the same. And the same things happening
off to the left hand side, off screen what we
can't see right now. So there we go with
that simple one, technically two lines of code, we have fixed our memory, our memory oh, that's just
leaving my mind right now. Memory leak. It's funny
since we're talking about memory. But there you go. With that, we have fixed
our memory leak issue. And I'm going to show
you an issue here. Not really an issue,
but just to show you one more example here.
We go to the platform. If we use position instead
of the global position, you're going to see
an example here. If we take a look,
you're going to see, especially with the turtles, you're going to see the turtles despawn right about
this area here. All right. Watch them,
they're coming in. So when we're using that
local position, there you go. You see they're
disappearing way too soon. They barely get on screen, and they just barely get
about here, and they're gone. This is why we have to
use the global position. All right. So I just wanted to demonstrate that a little
more visually for you there. No redraw. Free. And are just, like
I said, complete, destroys the object and
takes it out of memory. All right, so there you go. There's how we can
fix that memory late. Alright. Next, we can we'll be moving on to the score and HUD, adding player lives
and all that in there.
37. Scoring System: A Alright. So in today's video, we're going to go ahead
and add the point system, as you can see here. These are the rules
that we go by ten points for each step, 50 points for every
frog that gets in and 1,000 points for every
time we get five frogs in. So that's what we need to
keep in mind when we do this. And I'm going to start
with creating a global, also known as a Singleton
or an auto load script. And for that, I'm
just going to right click in my file system. And create new script, and I'm going to call this my I'm just going to keep
it simple and go global. And to activate this, we go
up into our project settings. Let's see. Do we have that
captured right now? We do not. Here we go. It might
be a little big, but here we go. And we go into the Auto oad tab. Hit our browse button and just flops and select
our global script. I'll get the name
global by default. You could change it, but
I don't see why we need to add, and there we go. Now we can use this script
anywhere in our code. And right now, I think that's where we're going
to hold our score. That's where we're going
to hold our score. So if we close that, we can now open our global script
by double clicking it, and to give you an example here. We can come down here. We
create another function here called Print SCORE. I have a variable up
here called SCORE. It's an integer, say you got 50. And the whole point of this function is just
to print the school. So with it being a global, I could go into my
player script here, and I could just write that name that we had for that I left, which was called Global
for the capital G dot, and then we could use the function we just
created, print SCR. And then when we run this, we will see that score printed
out here in our output. So a global script contains variables and
functions that we can alter and use within our game
in any script at any point. So let's go ahead and
we can remove all of that stuff and set score
to zero by default. And we're going to
go ahead and have a function called update score. All we're going to do
here is we're going to where we're going to be
printing out our score. And do we need to display should we display it on
screen in this video? Now, we'll save
the displaying on screen when we start
covering the HUD. So here, we're just
going to go ahead and print the score. When this happens, update score will take the new amount to add. Can be an int to do score
plus equals new amount. And we can do Well, let's first make sure
this stuff works. So every time we hop, we get ten points, right? So we're going to
have to add this into our movement in
all of our pieces. So we'll go global dot
Updates it Update score? Because we didn't save it yet. Yo. Update score and
pass in ten points. And we'll go ahead and
copy this down into all of our movements and go
ahead and jump in game. And as we move, we
should see ten points constantly get
added. There we go. Ten, 30, 40, 50, 60, 70, 80, 90, 100, one, ten, et cetera,
so this is working. We all of our
buttons, fantastic. We can just get our
points up like that. So the points here are awesome. I just went ahead and got rid of the other printing there falls just to kind
of clear that up, make it a little easier for you. So as we go ahead and run
in there and run around, you can see in our output, our number goes up
every time we move. So there we go. It's working. Fantastic. Now, we also have to keep track of how
many frogs we get in total should we be total frogs doesn't sound like the amount that we want. Blah, blah, blah.
We call it a combo. Frogs in Um, I don't know. Let's call it the Multi frog. Multi frog. Starts at zero. Every time you add to
the multi frog, right? We do multi frog
plus equals one. I remember with
every combo of five, we get 1,000 points. So here's where we
go I multi frog, less than five, then I'll
just tap this line in here. Then we'll just do score
plus equals new amount. Else we do score
plus equals 1,000. We'll get 100 if we get five fog in that's only going to be if we get into
a scoring area, so we can't actually
increase our pi frog there. So for that we
actually have to go to our windSpace and go into
our on body entered, and this is where we are going
to increase that number. So we're going to do Global
MultifrogPlus equals one. I'm just going to stick it
right on in there inside of our windSpace And then we're also going
to call our update so global dot update score, and we're going to pass in
50 because we got a frog in. And since we're increasing
our Multi frog before, updating our score, right? So we're updating our multi frog by one, then we'll check. Basically, if that
is our fifth frog or if that is not
our fifth frog, then we'll do this. We'll just add in that 50. Otherwise, we'll add 1,000, and then we actually
need to set multi frog back down to zero because
it has to be reset. So let's see if this works. All right. We're all
the way up here. Let's go ahead and
get in the zone. Fun. Hey, we're up on the log. Now we wait for these
turtles to come by. Good on, little turtle. The turtle. The frog
and the turtle. So we're gonna have 290. So we should we jump on here. Now, when we go into Zone, we should jump up to 340. And oh, went up to 350
on that one because we also moved at the same
time. Got to remember that. Um, we got our ten points. Does this frog work that way? It's actually been a long
time since I played, so I'm not 100% sure on that. If that's the case, then to
solve this issue, of course, we just we can just add 40, and then it'll count that plus ten from our jump in there. So if we were to go ahead
and jump in that now, it would look like
a plus 50 torque. Like I said, I'm not
sure if it counts that actual jump or not in the actual game. Maybe it's something
we can take a look at. Maybe you can just leave that to personal choice on
whether or not you want to allow that to
effectively count. Oh, my froggy died. Sad. Oh, I seem to
have, rod froggy. Here we go. Seem to have gotten into a little bug by
jumping at a weird spot. There we go. And now my
little Fracki is fine. And this puts us at 5:50, so this next jump
will put us at 600. So there you go. It's up to you if you
want to do 40 or 50 here, which basically comes down to whether or not
you want to count that as your main or count
that ten as your main thing. And I just remember we
should probably get five frogs in there to
actually test this. So I might go ahead and
just fast forward on. It's video here for this part
just so we can get five in. I All right. I've gone through it. I did my loop multiple times
five frogs and went ahead, we got 4,800 points. Awesome. Seems to be
working perfectly fine. A score system works. We got our plus 40 or plus 50 depending on
how you set yours up with whether or not
you're going to count the extra step as part of your 50 or if you want to do a 50 additional
on top of that. We have our ten
points per step here, and we have our plus 1,000 every time we get
five multi frogs. Every time we rescue
five of these frog gas. All right. So we got
our score set up. And I guess next, we can just take a look at how to display this
and start getting our heads up display or
Hud or Gooey all set up.
38. Game HUD Score: Alright. Let's go ahead
and start creating the game Hud for our Well, game. Today, we're going to
go ahead and just get the score up here on our screen. And for this, I just went to MNTD and I added
in a Canvas layer. If I could come in
here, Canvas layer is what we're looking
for, not Canvas grow. And Canvas layer is
basically going to be everything that's
on top of our game, no matter where it
is in our scene. So this is, as you
would imagine, where all of your
hot elements go. So if you're playing
like say Dark Souls, this is where your four quadrants
are in the bottom left, for example, if you're
playing sky Rim, you three health stamina and matabar Wallaby across
the bottom, and so on. And for us, just to
do the score here, on my Canvas layer, which I renamed to Gooey GY. Stands for graphical
user interface. I went ahead and I
added on two labels, two just regular labels here. And I named it score label, which just has the
word score in it, and Score text, which
just has five zeros. Now, the texts of both of them were too big
for this project. So on both of them, I went into the inspector down to
Themovides Mont size, and my score tat is on size ten, and the score label
is on size 12. Now, you might notice
that I do have an extra black bar
down at the bottom. I went up into project settings
and in display window. I went ahead and updated my
viewport height 240-256. There you go. You
can see it there. So I added an extra 16 pixels, so I could add the black across
the bottom because that's where our health bar is going to end up being
down at or our lives bar. In the next video. All right. So once we have our two labels here on our
Canvas layer for the score, and you can't find out where
to change the text for that, it's just select your label and inside the
inspector at the top. You'll see the section
there for text. Just type in score
for one and put in five zeros. For the other one. This will give us a good idea on the amount of space
we're going to need. All right, so now
to make this work, all we have to do
is add one line to our global script here. And outside of our
I and our block. So outside of both of these, regardless of how
much points we add, we need to get our
score text label and set the text on to
actually display our school. So since we are coming
from our global script, if I go ahead and run this for a moment and
then just pause it, switch over to remote, you can see Global is here. It doesn't have
access to anything. So we have to actually go
up the tree once to get to root and then come down to our no two D and then
down to our Dewey. And then from there, we
can grab our Score text. So since we have to
go up and then down, we can go ahead and
just use get node. And remember this takes
a string as an argument. And as you can see, we could
just write the whole path, shrootGlobal, slash root,
slash node two D in this case. But even then since we
only go up to one level, it's still faster if we just do two dots just to go up one, and then we come down to our
node two D. And from there, we access our GY. From there, we get
our score text. And if you're wondering, we're just following
that white line down. So from our global here, where we're writing this code, we have our two dots, which is the same as
writing, get parent, so we go up one to the root. And then we're just
pats following down on every stop
like this white line. We see this white line comes
down and then it goes in, points to no two D. That's
what we've written there. Then we follow the
line down again, stops and points in at the GY. We write that for the next stop, then we come down
and finally points into our square text
and we end it there. So whenever you're in doubts, go ahead and click on the
Node you're looking for, and just follow
that white line to get your path. All right. So on this Score Text, right, this label type object, we're going to access
the text property of it, and let me just get the
game off your screen there. I just looked over and
saw that it was covered. Again, we use two dots, same as get parent
that takes us up to up to the not the sorry
up to the root node, and we just follow this
white line comes down, points at node two
D, comes down, points Guy, then comes down
and points at square text, and we're just following that
path here all the way down. And we want the text property of it, and we're
going to set that. We're going to set
it to our score. However, if we just do this, all those zeros are
going to disappear. And as you see, we can't really do much to the score
in this aspect. So what we're going to do is we're going to actually turn it into a string with STR, and then two parentheses, and we can write our
score inside of that. And that score is
now going to be treated like a string
instead of an integer. So now we can do dot, pad, and we can
pad it with zeros. And we pass in the number five, we're going to have five digits, like we see here, one,
two, three, four, five. So we're going to
have these 50 slots. And our score is
going to change, but even though if
it just says ten, we're still going
to have all five of these slots available to us. So visually, it's going to
look just like it would on an arcade and in a
typical scoring system. So if we go ahead
and play this now, we can see our score
there at the top. And if we hop around, we should see our score
increasing as it should. That's a lot of cars up there. Ooh. There we go. Let's follow this long. Here we go. Let's go get
ourselves some points. Ride the log, ride the
turtles, ride the log. And we can ride the turtles, ride the log, and
jump home free. But uh, All right, so our score system seems to
be working perfectly fine. It's displaying accurately. It's fantastic. All right. So the last thing for us to do at this moment is, in this video, nothing,
but in the next video, we're going to go
ahead and set up our lives that when we
die, we lose a life, and it's going to be
reflected visually on screen by showing how many
lives we actually have left.
39. Game HUD Lives: All right, let's go ahead
and add in our lives. Now, our lives are going to have six lives at the most here. And we're going to go into
our Goey canvas layer. We're going to add a new node. And I know that's not visible, just 2 seconds there you go. And we're going to
search the word texture. We're looking for the
texture progress bar. Alright I'm going to rename
mine to the Lives bar. I'm going to move over to the textures section
in the inspector. And for the progress, I'm going to move
over the Healthbr dot PNG into that slot. Set the max value, again, in the inspector to six. I'm going to set my
current value to six, and now you should see them. I'm going to grab this
little orange handle and pull it up just so it
only takes up space we need, and I'm going to bring
it straight down to the bottom into that
empty black space. Yo. And those are going
to work as our lives. So you'll see as we
tweak the values 6-5, it's evenly split up, so we can easily determine
how many lives we have left. The six, of course, is
going to be our default, and we're going to
need to tweak that every time we actually die. So in my global here, again, maybe game manager would
make more sense for a name, but for now, we're just
going to leave with that. We're going to go to
Livest by default six. I'm going to create
another function, update Lives for nothing. And we're going to
follow Sad path. Only instead of a Scortex, we're going to get Live's bar, and we're going to access the value property here that
we can see in the inspector. And we're going to say
plus equals amount. An amount is going to be a
parameter that we pass in, which is going to
be an end, right? So when we lose a
life, we're going to add negative one to it, which will make it
go down to five. And also gives us the
ability to add lives in future by just putting in a positive
one to gain a life. But also updating that, we actually have to
update our lives as well, the same thing plus
equals amount. And now we can go to our player. We can look for our
death. There it is. On death. We also need to
access our global script, update Lives and pass
in negative one, and that should do it. Very simple, small thing to do. And now when we die on screen, we should lose a life, and we should see our
life war down there, drop down to five. And I need to pull
this up because you guys can't see the
bottom there. There you go. And let's see if we
drop down to five. There we go. We splat. I ran into the back of that car. Also, I was looking
at it and you only gain points when you
move forward on Frogger, and we lose life when we
go in the water as well. So we can go ahead and update
that if you wish as well. If you want it to be a
little more accurate. We're only going to update
score when we press up. Down left and right will
not get us any pins. The only pressing forward, which makes sense
because that is a lot of points you can
rack off real quick. Dom, d d, d m. By where's
my logs. Where are they? There they are. Going. Now, we ride them with the turtles. Doi, doomy, doom. Jump on the turtle. I was
going to go for the log, but I felt like I was
going to miss it, so I stayed, jump
on the log here. Then won't jump on
those turtles and we'll make it home
free on this log. We are good. Go Alright. Awesome. There we go. And
again, we can lose live heat. Cool. So our live system works. It updates visually on screen, and we have the ability to add in our lives in the future. All right. So I guess that'll do
it for this section, unless you want to add
live when we get school. Do you want to do
that? All right. So if you want to be able to
gain extra lives when you reach a set amount of points, here's what we're going to do. We're going to create a
variable called multiplier. And inside of our update score, we're going to perform
a new I check here. So we're going to say I score divided by score divided by, we can say 10,000, do you want? Times our multiplier is
greater than or equal to one. Then this is where we're
going to add onto our lives. So we would need to do lives. And normally we would
say plus equals one, but since we want
to tap it at six, what we're actually going
to do is say lives equal, and we're going to use a
function called Clamp. Now, clamp allows you to I
have three arguments here. The first argument is
what you would add. So instead of plus equals one, our first argument here
is going to be one. And then the next argument, it's going to be the minimum and maximum that this value can be. So the minimum, it
could be a zero, so our lives will never
go below zero here. And the maximum number
that we can have is six, so it'll never be a
higher number than six. And that's how clamping works. Here we can call Update
Lives with one, right? So we're gonna have a plus
one to add on to that. Um you know what? We can actually just move our clamp right
down here inside of our update lives and
replace one with amount. And then we can probably get away with not having
anything in there, not setting it up there, but
just clamping it down there. So update lives one. And then we're going to
want to increase our multiplier, plus equals one. And the reason why we want to do this because if we don't, we're going to constantly
gain a life because our score is always going to be divisible Once we gain one life, every time we move, we're
going to keep gaining it. So we want to change this so if we get a life at
every 10,000 points, then we'll get a 10,000 10,000 times one is still
going to be 10,000. And then the next time, it's going to be 10,000 times two. So we'll need 20,000 points
in order to get a new life, and then it'll be
30,000, 40, et cetera. So if we were to go run
this now with just that, we can see if we
run in, we go and lose a life, maybe
even lose two. And now we just got
to make our way up, pass through all this traffic. Go, go to make our
way to this log. Then we can ride the turtles, turtle log, again,
transfer to the turtles. Wait for this log
to get up here, and then if our score
was high enough, we should get 10,000, W I didn't change it. Now,
did I think about it? So that's a little
disappointing. But we can check that real quick just by going
to our wind space, and we'll say, Hey,
we gain 20,000. Now, if we were to check
it to gain points on every 10,000 this 20
shouldn't do anything. I should just give us the
one life. Which is fine? 'cause you should never
get like 20,001 do anyway. The most you should get at
one time will be 10,000. What do you see as we go? Boom,
boom. We're almost there. We should see our lives at
the bottom increase plus one. And there we go. So our
lives have increased. Alright, so our lives
is now working. So I'm going to go
ahead and reset this back down to 40 points. And we want to make
sure we can game over. But that's going to be in I guess inside of our global
here, Update Lives. And we're going to
go ahead and see, will this let us
go negative one, a chance? No, it will not. That's perfect. We don't
have to worry about that. And we can say I lives
less than actually, we wouldn't have to already
we're setting it up here. So we check beforehand. So we say I lives
is less than zero, actually already be zero. Let's say we have zero
lives left and then we die. We're passing another
negative one. We're saying if our
lives are already zero, then we're going to
have we'd say game, but we're just going
to reload the scene into a brand new game. If our lives aren't
already zero, then we're going to
come down here and we're going to
subtract our life. And for this, we just use Get
three reload current scene, and that'll be the same as if we had just started
the scene like this. So if we write in Our lives are not getting reset. Probably because they
don't reset on Global. Let's find out. Let's
go into our ready, and let's take a
look at how we debug this, I'll say print. Lives. And we'll
see if that resets. We're getting squished broad. We're never actually
getting our ready back. It's constantly
reset itself, right? So instead of in the ready, let's print it down here. Try and figure out why
we're constantly done? A. It resets after two.
How are we going 6-0? Alright. I'm not sure why, but the clamp seems to be
what was causing that break, which is interesting
because there's no real reason from what
I could tell that it should have been
jumping from six lives to break down to zero. But that's fine.
I just changed it back to Lives plus
equals amount. And now, if we run the game, see if we can run through or back to losing
lives one at a time. And once we get down, we're down to three
lives, two, one. Oop, O. Here we go.
And into the water. Well, we're out of live. So when we get hit next, it's going to be
a game over, and our game is going to reset. And here we go. We got a reset of our game
we quickly run across, and we can back to
losing lives again. But there you go.
We have that reset. We now lose lives and
display on the screen appropriately when our
lives are too low, we completely reset the
game and start over again, as well as gain lives every
time we get 10,000 coins.
40. Timer and Bonus: All right, let's get
our timer going now. So onto our Gui, I just added another
label down here with the word time with a override
font size set to 12. I then have a texture prods bar, just like we did
with our lives here. I changed the film mode to be right to left instead
of left to right. I'm also going to rename
it here timer bar. My max value is 30, my current value is 30. Everything else
is left the same. I turned nine patch
stretch on so I can stretch this bar out
to be whatever shape, length that I want. I'm just using the timer
dot PNG that I have here. I just drag it in as the progress bar or
the progress texture. And there you go. I
just stretch it out, place it down there for
something that looks good. I also have a timer that
I added down here with a script on my Guy and the time out signal
here connected to it. So this is what we're
looking at here. And what we need to
do every time this timer times out by default, the timer is set to 1
second, which is fine. That's what we want. What we want to do
if we want to get our timer bar and we need to
subtract one from the value. So we can just go ahead and grab it with our dollar
sign here. You get it? Since this is coming
from Mark Bouie, value minus equals one. And now if we were
to go ahead and take a look at that and run that, we should now see
our timer ticking down, which is beautiful. That's exactly what we want. And now we've got to check. We need to check if our
timer our timer bar value, it has hit zero, and if so, unfortunately, our little froggy has to die. That's just how it is
when our timer runs out. So let's go ahead and get
our little froggy get node. And remember, we're
on our ie here, so we're going to
have to go up one for our no two D and
then come back down. So dot dot slash layer, and we're just going to
call our death function on. Oops, and that should be two equals because
it's a comparison. Yeah. So if we were to run it now, when our timer runs out, our little froggy
so just go splat, and we lose a life on our hut. You know, give it a minute
there for the timer to run. Now, having this time
you're here on 30 seconds. I see that my platforms
up top need to be a little faster or at least
a bit of a smaller delay. But I think speed might be the better option rather than changing the delay.
But there we go. My little froggy has died, and it keeps dying.
That's not great. We need to actually
reset that now. So once it hits zero
and our froggy dies, let's reset our timer bar. So let's get the timer
bar and set its value back to 30 so we can have a
brand new bar filled out. Now, this isn't the only time
when it needs to be reset. It needs to be reset when
we reach the goal as well. So we're going to go
ahead and get node, go up one, get our Guy, and then get our timer bar and set the value back
to 30. All right. Now, before I test this, I'm going to go into my platform here and I'm going to change this to 32 and
double that speed. And that means I have to go
to my player and adjust that. Well, up there. This is when we are
right here, 32. Go. So now these should
at least move quicker, and hopefully I can get
on without missing. Okay, there's the turtles.
We need some logs. Thank you. Log. I don't
know if I'm going to make. I'm not going to make it. I'm gonna lose my froggy. Goodbye frog. I hardly knew you. I see this is gonna be
a little difficult. Oh, does our time or not reset when we splatter? It does not. So we need to set that, as well. So on our player? Where
is it that we die? There's our death right
there, and we respawn. Yeah. Okay. And, yeah, let's stick
it in depth here. So, again, we're going
to go up and then come back down to our timer bar and set
the value back to 30. That way when we
die, that resets. And I guess I am going to change or queak the respawn
the sponor value, platform spanner and I'll
remove the plus six, see how that looks now since we have completely new numbers. Okay. That's licking fine. We might be able to
actually make this now. There we go. We made
it in our timer reset, and when we die, our
timers in reset, as well. Fantastic. And I can see I still need a bit of a boost
in there, my minimum. So I'll do 3 seconds just because I saw quite a bit of overlap when I
ran through there. But we saw the timer is
working perfectly fine now. I now you do, or at least you're
supposed to get a bonus as far as the points go based off of how much time
is left when you do score. So we'll go ahead
and implement that. As well, I just got
to go reactivate myself with what
the multiplier is. I know it's something times the amount of time that's left. So just give me 1 second
there. All right. It's ten times the
remaining time that's left. So let's see. When we get to our wind space before we reset that we need to update the score here again because we're going to add 40, but then we're also going to
add whatever is left here. We're going to say,
actually, you know what? Let's put this in its
own variable here. We call it bonus, not ten bonus, in bonus.
Of course an int. I want to set it to this value
times ten before we reset. Now on our second
update score here, we do time yes. All right. So now we should
have our time bonus in there. So the faster we
can get over there, the bigger bonus we're
going to get up to a maximum plus 300 points, hypothetically, I mean,
you're not going to get there at 300 or 30 seconds
left because it starts at 30. Oh, I might not
get there at all. I might be close. Ah, got it. But you can see I got
190 points on that one. All right. So there we go. We got the timer in there, as well as the deaths when
the timer runs out and the score bonus when we still have timer left,
and we make it to the end. Alright, so that's it. I think that might
be it or Frogger. I don't think I'm
forgetting anything here. And if that's the
end of Frogger, congratulations. You
made it to the end. That's amazing. I hope
you guys learned a lot. We went over a lot of things
throughout this project. Variables, the globals, working with lots of different scripts. But we've completely recreated this old game from the 80s. And what's great
about these old games they're fairly
simple in concept. But especially if you're
new to programming, there's a lot that you can
learn from these games. Alright. Take care. Have yourselves a good
one, and I'll see you in the next week. What
are we going into? Is it Week four now? Oh, boy, Week four
is going to be fun. We got a lot of a lot of
things to talk about in.
41. Frogger Audio: Alright, we're going
to go ahead and add in the audio for us. So this is going to count
our hopping when we move, the background music,
and arc death sounds. Alright. So for our background music, we can just go into
our main scene here, select our root node, which is our no two D. Go ahead and hit the
plus or add a new node. And what we're going
to add is this audio screen player here. And then we're going to go
into our sounds folder, grab the music.p3, and
just drag it in there. Make sure you turn Autoplay on. That way we don't have to waste a script and waste
writing any code to play And it'll just
start all by itself. Now, warning, this might be
a little loud when starting. So if you want to adjust the audio for just the music here, you can go ahead and
change the volume DB here. The lower you put it, the
quieter it's going to be. Zero is the default
for all of them. However, if you want
to lower the music for all of your audio at once, you can click the
little audio tab at the bottom down there, and here is all of
your audio bus. Now we have the master here, which if you've changed audio
settings and games before, you notice you have
the master slider. That's what this is
here, and we can change the volume of this to
whatever we would like. If you do want to add
a different audio bus, so you can customize your sound effects
from music separately, we can just hit the add bus here and we'll just
rename this to music. And now with our audio
stream player selected, you'll notice in the bus
section here on your inspector, we now have a music piece
here from the drop down, and now this music will come through this piece
of audio first, and then it'll get outputted to the master, as you would expect. Alright, so it's up to
you what you want to do. I'm going to go ahead and
lower my music to maybe 0.6. Not sure. I'm going to make
sure that you guys are actually able to hear this. Hopefully, this doesn't
hurt anybody's ears. I'm going to hit
play and find out. Alright, so that seems like
it's quieter than I am. So I'm going to assume
that that is okay. But if you want, you can
always lower it a little more. I think I'm going to go
with minus ten here. And now the rest of our sound
is actually going to be on our player our player
has the death. Our player has the jumping. Our player has the other sound
effect other death, right? The plunk, the
squish, and the hot. So we're going to go over
to our player scene. We're going to add an audio stream player for them as well. And we're not going to
touch anything else in the inspector
unless you want to add an audio bus for
sound effects and then change the bus
there specifically. That's up to you. And again,
a personal preference. But once you have
an audio stream player added to
your player scene, we can go into your
players script. And what we're going
to need to do is set the audio stream by loading in the audio file
and then actually play. So what I'm going to
do is I'm going to go to our Deth function first, and it's going to have
an ID passed into it. ID is obviously going
to be an integer because we're going to
get a two or three. So I'm going to call an IT, and then I'm going to set
it equal to two by default. And the reason why I'm
using two is if we go back to our tile map
and take a look at it, our road is ID two. So by default, it should be our road, so it
should be a squish. So what I'm going to
do here is if we're going to get our
audio stream player. So audioStream player dot stream we want that stream property. You're on our player,
right? That stream here. And we're going to
set it equal to, and we're going to call load, open and closed
parentheses and inside of here is going to be
the path to our file. So two is going to
be our default, so that's going
to be our squish, so I'm going to get
squash dot Wav, squash dot wave out of our sounds folder
and drag it in there. That way I don't
have to write it. And now what we'll do
is on the next line, we'll say I ID is
equal to three. So three, remember
being our water. So if we're dying and
it's on the water, then we're going to do
the same thing we did on the previous line and set our stream and load
in a new file. This time we set of squash, we're going to load in plunk And then outside
of that if statement, all we're going to do
is play our stream. So we're going to say audio
stream player dot play. Just like that. Now, if we go ahead and get ourselves squished on the road, we should have one sound effect, and if we go jump in the
water, we should have another. Okay. For now, I'm going
to go ahead and just turn the autoplay off on the
music so we can listen. Okay? If we jump in the water. Okay. And if we get hit by car? Okay, we have the same audio
playing on both of them. Well, that's a little
interesting. Why is that? Well, apparently,
we're not passing in any ID for three, so it's
never going to be three. And the reason for
that, remember, we got to go down and
and check cell ID, we are actually checking
if our frog is drowning. So that's what we have to
pass three in to our death. Now, it did not air
out because we told it that if we don't
pass anything into it, use two by default, but since we want
specifically an ID of three whenever
we're in the water, we have to make certain
to pass it in down here on our check
Cell ID function. So now if we were to
do it, we should have our plunk in the water,
right, right, right. And squished on the road. Here we go. So we know that's
working perfectly fine. And the only thing left for
us is to do our hopping. And for that, that's
just going to be up in our movement where we can check our audio
stream and set that. So audio stream player
dot stream equals load, and we're just going
to grab our pop sound effect and drag it in. Go. And on the next line, we can just play our audio. It's audio stream player. Go play. And we can copy that into
every button press here. So if it's down, we can do that. Boom, it's left
and if it's right. Now if we play it,
we should be able to jump around. Whoops. Let's go into our main scene. And try that. Down
down. We can jump down. Then get squished down. Down down. As well as
ground in the water. Down, down, down, down, down, down, down,
down, down, down. Down, Awesome. Now, all we have to do is
turn the music back on. So on our main scene,
audio stream player, autoplay, turn back on. And just like that, we have
the Frogger game complete with our audio and gameplay. Thank Thank, I got hit by the back of the
car there, but there you go. We have added sound to it, and now our game feels
a lot more complete. A, there's nothing else
we can really do here. You can feel free to
add more onto it. You can try adding pickups. You can find new sounds
and replace them. Maybe if you want to create your own sprites and use
those to change it up a bit, makes it a little
more custom for you. Or if you want to
just keep it as your own little arcade
remake, that's awesome, too. But that'll do it for this one. So take care and have
yourselves a good one, pat yourselves on the back with completed frog and next week, I think we'll start talking
about some of the differences and similarities
between two D and three D and start
getting into that.
42. Transitioning from working in 2D to 3D: All right. Welcome everyone to this week where we're
going to talk about our transition from
two D into three D. So as game developers, it's important to understand
the unique challenges and opportunities that arise when working in three
dimensional space, as opposed to two dimension. To illustrate this I'm sorry,
let's go back in a moment. When transitioning from two
D to three D development, there are several key
aspects to consider. Let's talk about the fundamental difference
in perspective. In two D, we work with
flat objects and layers. As you can see with our example, on the left hand side here, everything is really flat. It's just a matter of
what is in front of or what is rendered in
front of what, right? So we can get different layers, kind of like when you're working in something
like Photoshop, some kind of image
manipulator or image editor. I Well, in three D, the ones on the right, we introduce depth and spatial relationships
between objects. So you can completely see we have that third dimension
on the two D side. We can't see the ground here. We just have the side of this dam or bridge or whatever it is that
he's standing on. Well, in three D, we can see that depth going
across the top there. We see the depth of that arm coming straight out
towards us with that spiked end versus in the two D where it's clearly
just moving down screen. And again, with
depth, you can see in the top one where you can kind of try and simulate that kind of feel
with two dimensions. However, in three D, you can obviously tell there's
just no comparison. It's obvious which
one actually has depth and which one doesn't when we're looking at
the top example there. To illustrate this
transition, again, you can take a look
at our examples here, two screenshots, one from the two D version, one
from the three D version. In this case, we're
using Mega Man, which is a platformer
side scroller. And here this will help you with imagining transforming this
two D game into three D. You can see just the kind
of difference that has. Just making that I have one decision whether
to go two D or three D, the art styles are
completely different and stand out uniquely apart. Now, with this The
D environment, we would need to create
three D models for the characters, the platforms, and all the other
objects in the scene, which could be a lot more
time consuming than, of course, if we went
with the two D option. With two D, we kind of draw it out and we're good. We're done. Whereas in three D, we kind
of got to get those models, and then we have to
unwrap the model, and then we have to create
the textures for the model, and then we got to create
the material for the model. So we have all of these steps before we can even
put it in the game early for testing or
implementation, things like that. And then we also have
to we also introduce a camera that
typically in three D, when it's not just
something stationary, such as what appears to be
a boss fight on the bottom, it has a camera that's going
to move with the player, whether that's moving around
in a full 360 degrees space, which could happen in
those three D versions. Or if they just remain
more stationary on the side to give us more of that side scrolling feel like
we're clearly seeing here. Now, as you can see, transitioning
from two D to three D requires a shift in how we
think about game development. We need to consider
spatial dimensions, depth perception, the
cameras movement, and object modeling. It opens up a whole new world of possibilities for creating immersive and visually
stunning games, although some people will prefer two D over three D the
majority of the time. So keep that in mind that the
type of game that you are creating it might be
better or work better, either for the vision
or mechanically, whatever, in two D than three D or might work better in three D than in two D. So there you have it with the transition
from two D to three D, we need to understand these differences and challenges that arise during this
transition process, and you'll be well prepared to embark on exciting
three D game projects. Remember to practice and always experiment with various
techniques to help you with gaining confidence in working in this new dimension
of game development. Alright. Next, the
net lesson here, we're going to go
ahead and talk about and help you understand some of the differences between
two D and three D. And then we'll talk
about the similarities between two D and three D.
43. Understanding the Differences of 2D and 3D: All right. In this example, today we have a Mortal
Combat shown here, both the mythology side
scroller and two D, kind of almost a pseudo three D, as well as the three D
iterations that came later, both with a three D menu and a three D store mode
that allowed you to run around and explore. Now, today's video,
today's lesson, we're going to talk about some of the differences between
two D and three D here. And it is important for you to understand these
differences as it can be crucial when it comes to
creating games effectively to help you utilize the
strengths of each dimension. So the primary difference
between two D and three D game development lies in the visual representation. As you can see here, it's pretty obvious and
gameplay mechanics. In two D, we work
with two dimension, just the width and the height. Where objects are portrayed
on a flat surface. In contrast, three D introduces the third dimension of depth, as we can see here,
allowing for more immersive allowing for a more immersive and
realistic experience. So let's examine some
key differences in two D game in a two D game. The gameplay typically
occurs on a single plane. While in three D,
objects can move in three dimensions up down, left, right, forward, and back. Enabling complex interactions
and exploration, which is why we have something
like conquest mode up there in the top left because you're
encouraged to go out, not only follow the story, but explore and do
some side things to help or to unlock some secrets and hidden
characters and things like that, which you wouldn't
really get in a TD game. And if you could kind
of squeeze that in, it wouldn't be the same
overall experience. Additionally, in two D, collision detection
is typically simpler, as it involves mainly just checking if two
objects are overlapping. In three D, collision
detection becomes more complex requiring
consideration of object boundaries
and the surface. And as you can
see, understanding the differences between two D and three D game
development will help us make informed
design choices and utilize appropriate
techniques, whether it's the visual style, gameplay mechanics or
the user experience, embracing the
unique qualities of each dimension enhances each
qualities of each dimension, enhances the overall
game experience. So remember whether you're going to go in two D or three D, embrace the strengths
of that dimension. So there you have it briefly the differences between two D and three D game development. By recognizing
these differences, you'll be more
equipped to create games that leverage these
strengths of these dimensions. And remember to, of course, experiment with
various techniques and stay creative in
your game design. All right. In the next lesson, we'll go ahead and
talk about some of the similarities between
both two D and three D.
44. Similarities Between 2D and 3D: All right, let's go ahead
and talk about some of the similarities between two
D and three D development. Now, despite their
unique features, both dimensions share certain core principles
and techniques. Let's go ahead and jump
in and take a look. While two D and three
D game development have their distinct
characteristics and strengths, they also have
several similarities. Firstly, of course,
both dimensions rely on key programming concepts such as the variables, functions, logic. Whether it's two D or three D, these fundamental
programming principles will remain unchanged. So if you have, for example, a character picks up an item. Well, that character,
you're going to go over to the item and touch
it or interact with it. And the logic will
remain the same, because you're going to
take it, you're going to make it disappear and
then in the code, you're going to add it to
the player's inventory or their collectible count or whatever it is that you're
going to do with that. That logic remains
completely the same, whether it's two D or three D, is just going to be written
slightly different. Secondly, the importance of game design principles holds
true for both dimensions. Concepts like player
interaction, level design, and balancing gameplay
mechanics are crucial elements that impact the player's
experience regardless of whether it's two
D or three D. So if you're bad at game
design in two D, you're probably still
going to be bad at game design in three D.
It's not going to make any difference which
dimension you're working in. If you're bad, you're
bad, and all you can really do is practice
your skills, maybe pick up some
books and just enhance your game design
ability through practice. Additionally, both two D and three D game development
involve the use of assets, whether this is going
to be sprite in two D or models in three D to bring
the game world to life. Whether it's a two D character
Sprite or three D model, the process of creating and
integrating assets into the game follow
similar principles of design and implementation. Again, notice I said
similar, not the same. Furthermore, the
importance of optimization will apply to both two
D and three D games. Regardless, again,
of the dimension, developers need to consider performance, memory management, efficient algorithms to ensure smooth gameplay and
optimal resource usage. For example, I mentioned when we're looking at Boger and we're fixing our
memory leak issue, I mentioned object pooling. This is a very important thing. That can help with managing our resources and
memory management. And depending on the game
that you're creating, this could be a very
very optimal way to approach a situation. So as you can see,
while two D and three D game development
have their unique aspects, they still share the core
principles and techniques. And by understanding
these similarities, developers can leverage
their knowledge across dimensions and
create captivating games. And what's even crazier is you could mix both of
them into the same game. You could maybe
create the same game twice in a sense and give
the player the ability to choose whether they want
to play in two D or three D. That's something
that could be unique to your game specifically
or have some kind of mechanic where you
jump between going in two D and three D.
You can you can use the multi dimensions as a game mechanic or just
part of the experience. And there you have it,
the similarities between two D and three D
game development. And by recognizing
these commonalities, you can apply your skills and expertise across
different dimensions, making you a versatile
game developer. Remember to continually
learn and experiment to enhance your game
development capabilities. And although they are similar, I do want to I'll note here that personally, my preference, I prefer to work in two D, even though the
similarities are there, and a lot of that
logic and everything still transfers over and works. Across dimensions
or dimensionally. It's kind of weird
way to phrase that. But just out of
preference, myself, I thought I would enjoy
three D. But it turns out, I actually enjoy creating
two D. So you might find that you end up after
trying out three D here. You might find out
that you have a preference for two D as well, or maybe you'll prefer
three D styles. Or working in three D, rather than creating anything in two D. So it's okay to
have that preference, but it's also good
to know that you have both the knowledge and technical capabilities to go between two D and
three D at any point and acknowledge all
the commonalities, the skills, logic and everything transfers
between dimensions. Eight. Alright, let's go ahead and dump into
the next lesson and see some things that are a little more unique to three D that you
can't really get around.
45. Materials: All right, everyone.
Welcome back. Today, we're going to talk about something
that is exclusive to or I shouldn't say technically
exclusive to three D, which will be materials. So let's go ahead and explain
to you what materials are. Here in the goto Inge, materials play a crucial role in defining the visual appearance
of an object in your game, and we'll dive kind of deep
into materials and at least discuss the different
texture map types that are available when creating and applying materials to objects. Materials are used to
control how light interacts with objects and how
they are rendered. They define properties
such as the color, transparency,
reflectivity, and more. One of the key aspects of
materials is texture mapping, which allows us to apply
images or patterns to objects to give them realistic
or stylized appearances. So I'm going to go
ahead and just open up this you inherited Mega Man here that I just found online. And before anyone asks, no, I cannot share this. But if you look online,
you'll probably find it. I'm just going to select
Object four here. And if I open it up, I will find this one specifically
as surface zero, so it just has one surface. So one material.
If I open that up, One moment, I got to
make this unique, so I can at least
tweak it to show you some examples and make unique. All right. All right, so as we go
through the Albedo map, which is right here. It's also known as
the diffuse map. Why are there multiple
names for the same thing? I don't know, but there are, so it's just kind of keep
that in mind if someone says albedo and you are
given a diffuse map. They're the same thing.
And this texture map defines the base
color of an object. It provides the primary visual
appearance of the surface. And as you can see
here, this is where the main texture is applied. Now, this does affect color. So I can always come
in here and change the actual color being applied
on top of this texture. So if I want to, I can come down here and I'll have
a green mega man. Maybe I want more of
a purple mega man. Or pink isn't really
not too pink there. We can get ourselves
a red mega man. You get the idea at
this point, right? So the albedo is
the base texture and color, that can
be tweaked on it. Normal maps. Let's see,
where are they in here? Normal map. Here we are. Now, in Gatto here, you have to actually
turn it on before you can apply a texture to. And a normal map
adds the illusion of surface details by modifying the lighting calculations or it creates the
impression of bumps, dents, wrinkles on
a smooth surface without increasing
the polygon count. So it kind of bait
geometry in a way by manipulating the light and
how it affects our objects. Now, I don't know Mega Man might not have a whole lot here, but if we go ahead and
play with the scale of it, you can kind of see it here happening especially
down here in the lower body. We go back to the default
scale and then we tweak it, you can kind of see
how it's really affecting the way the light is reflecting off
at the top here. The roughness map. Now, you may also
get this in the form of a smoothness map, and smoothness and
roughness are opposites. So if you have a smoothness map and you need a roughness map, then you can just invert it and it should be
fine and vice versa. Now, in this case,
this mega man, it has a color texture here, and it's specifically using the green channel for this rather than the
standard gray, that's fine. Now, the roughness map, this texture map controls the surface roughness or
smoothness of an object, and it affects how
light scatters and reflects off the surface, creating variations in
an object's appearance. Now, I know this is going to affect the helmet a good bit, so I'm going to come up
here for showing you it. So if I were to take
the roughness down and make it smooth, look at that. That is, like, super smooth, fresh out of the factory. That's a beauty right there. That is a brand new
helmet is what that is. And as you see, as we start
get back up to the roughness, all of that lights kind
of dissipate once it hits it rather than kind of
reflecting off of it. And this worked hand in hand
with our metallic map here. This texture map, and again, they're using the same
texture for this, but they're using
the blue channel. And the metallic map here or
non metallic properties of an object and it
turns the light or the level of reflectivity
and shininess of a surface. So if we were to have a
super smooth surface, as you can see, with our metallic
being all the way up, it looks like a nice
shiny piece of metal. However, if we start
bringing that metallic down, we can see we start getting
to some other materials, maybe like a shiny or glossy
plastic, for example. Until we get all the way
down to where we have no metallic, which
isn't realistic. Every object at least has a
little bit of metallic in it. And specular kind of goes on
that. You can see it there. So specular might be
something that we use in maybe eyes when we want to have a little more
shine in them, for example. Or if you have a wet object, that could be good
in there as well. So just going to turn
metallic back up and roughness back
up to its default. And ambient occlusion, does this model have ambient
seclusion? It does not. So ambient occlusion is like a shadow texture that you can put in to add
a little more detail, say, right around
the edges here to get it more of an appearance of a helmet
sitting on top of a head. And it works like
that inside of, all of these little creases and crevices that would be a little difficult
for us to get into. But in general, that's
what it's doing. It's basically simulating
the shadowing effect caused by the presence of nearby objects or occlusion
from indirect lighting, and it overall just adds some depth and realism to
the object's appearance. Now, one more map
I do want to go over is located here, emission. Now, the emission map,
there is a texture here, and you can see it's
almost completely empty, but there are a few
objects on there. And what the emission map
does is emission map is glow. Basically of your object. So if you had, say, a character with a robotic eye and you
wanted that eye to glow, especially in the dark, this is where you would do
as an emission map. Now, you might not be
able to tell too much, but it's this little spot inside the cannon and the light here. Those are the two main points
that we're going to notice. And if I just increase
that energy multiplier, Look at that, you can
really see that now on there and especially
inside the cannon. You can see that red glow
happening as we start getting closer to
looking directly on, and we can see that tweak
here as I turn it down. And as you see all the way off, that's how the texture
looks normally. And then when you add that emission texture to
it, it all lights up. So if you have lights on an object or you need
some glowing or anything, the emission map is what you're going to
want to use for it. Now, we do have a bunch of other little things here that can just add
to little details like refraction
of your lighting, a little bit of backlighting, some subsurface scattering, which is as if I'm not mistaken, light, the way it's
interacting with, like, skin. We've got height here. If you wanted to mess around
with things like there, which I don't know I haven't
messed with the height. I know we used to
have a depth map. We got billboard,
grow, transform. We got all these new things
in here that came with four. And I'll mention something
that goes hand in hand with proximity fade here. Hoops. So if we were to
turn that up a bit, we could see all these we see these distances here
and all the stuff is going to be affected based on how close
you are to an object. As you can see here, that's
something that would help with performance, for example. That way, when you can set up so that when you're
far enough away, it just completely disappears. Maybe something like that, zero, two I'm not getting it in there, but you get the idea, right? So you can best round with all of that kind of stuff going on, as well as if you were to go on, do they have the
second pass here? Side of this matures kind of hard with everything
opened up here. And I do not see
the second pass, which is interesting.
But here we go. We got shadows that
you can disable, whether or not it
receives shadows. We got UV one and two, which can be used as different have different
things here we go. Next pass. So you can add another material directly
on top of this one. For example, this is
one way you can get a blackoline round a character to give more of an anime look. There are some things
you could do that, and you would put the outline
in a second pass there. Here we go. The
visibility range, this is more so what I was
looking at, I do believe. So we'll say a minimum of one, and then we'll say it ends
at ten. So there you go. So you see as we get closer, the object is in
and you back out, and the object is
no longer rendered, or at least that part of the object is no longer rendered. So you can keep that in mind when it comes to
some optimization, especially if you have
an object that might be really bogging down
your performance. That's visibility range on that. But that should wrap up materials and the different
kinds of texture maps. Oh, I should mention one more thing inside
of the materials here is They did change it. All right. So now we just have all these extra options
like vertex coloring, shading, transparency
and all that stuff. So if you want to have
transparency on an object, say you're using a PNG
image for your texture, then you're actually
going to have to tweak this and set it to, I believe Alpha, and it does
not work with this texture. But instead of using disables, so you actually have to enable the transparency if you want to have transparent portions of your texture or mesh, whatever. All right, so that
covers materials here. And hopefully that gives
you a better understanding of what materials are and the main texture maps that
you're going to come across and that you're
going to be using as you create three D games. And always remember, of
course, to experiment, combine different maps
and see what kind of different visual effects
and looks that you can get. Maybe you'll find
something that you like that is just completely created from
just messing around. Alright, that'll do it for this section or
at least this video, and hopefully you learn a bit about materials and what they're
46. Lighting: All right. Greetings, everyone. And today, we're going to take a look at world, the
world of lighting, and we're going to talk about
the basic three point setup that is used when it
comes to lighting. Now, obviously, when it comes
to lighting up a scene, there's a lot more
that goes into it. You have to take a look at things like the
intensity of the light for each individual thing that's going to be
emitting light. How many lights do you want to incorporate into that scene? That's going to affect your
performance and so on. But for now, let's go ahead
and take a look at how lighting is a critical
element that can greatly enhance
the visual quality or affect the atmosphere
of your game. Alright, I Goto lighting plays a vital role in creating realistic and immersive
environments, which can be said about
pretty well any game. And the important thing is,
you can have something with photo realistic textures and all your photo realistic
maps all set there. But if it can't be rendered well enough or your
lighting isn't good enough, then even though
it's photorealistic, it may not even look
realistic still. So lighting is just as crucial to your materials and
your overall scene as, say, shading is in a drawing. I can completely transform
what you're looking at. Lighting also helps set
the mood and emphasize the important elements and
bring your game world to life. Now, when working with lighting, there are several key
aspects to consider, such as your light sources, the shadows and your
light properties. One popular technique is the
three point lighting setup, and it involves using three lights strategically
placed around the subject to achieve balanced and visual
appealing illumination. Now here in this scene
that we're looking at, I just have mega man here
from the material section. Again, I just went online
and just found this model. Just online, he was
free for download. And you can see, even
though he's not lit, we have the red portions lit up. We got this bar lit up and the inside this little
cannon here, all lit up. And those are from the emission
maps that are kind of I guess you could say
lighting that portion up that has nothing to
do with our lighting. That's just all texture. Alright, so let's break down this light three lights that you use in a
three point setup. The first light is going
to be your key light. And while we're doing this,
I'm just going to click on my camera and click on this
perspective button here. This will let me see what
the camera sees here. So the first light is going
to be your key light, and the key light is the
primary light source and provides the main
illumination on the subject. Alright. It creates the primary
highlights and shadows that define
the overall form and shape of the object. Now, do note that if you
want shadows on your light, you actually have to
go into the properties of your light and
enable your shadows. And then, of course, you can tweak some of
your settings there, which is going to be
up to you on that. Next, we have our fill light, and this is generally
positioned on the opposite position opposite to the key light to
balance out the lighting, and its purpose is to soften the shadows that are
created by the key light. It helps to reduce the contrast between light and dark areas, which result in a more even
and pleasing illumination. So if we go ahead
and take a look, say, right around
the helmet here, I know we can't really
zoom in on that section, but I just want to make sure
I wasn't moving the model. We go ahead and
take a look here. Just looking from the front. We can see how harsh, like this darkness is
here in the helmet. And this along the side here, depending on your
monitor's brightness, could be pretty dark as well, especially considering
our light sources coming from the top left
here and coming down. And if we were to again, come down and look
more at the feet, we see this harsh
contrast that we have going on the feet
and legs, as well. All right. And if we
enable our fill light, we can see those
portions all light up, but it gets a lot softer is not as harsh
of a contrast in here. And obviously, that's
going to come from tweaking your energy here. And generally, you
want the energy to be less than your
fill light because remember than the
key light remember the key light is your main
source of energy here. And depending on your situation, you can use the fill
light to either go colder or warmer and have a light that complements
your key light. And the last light in a three point setup is the back light, and
the back light, also known as a rim light or hair light is placed
behind the subject, typically at a higher position, and it adds a sense of depth and separation and
highlights the edges of the object and creating that sense of depth
and dimension, if I go ahead and enable that, we can see we get some lighting right around the edges up here. And again, we could come
in and we could tweak, play with these numbers, find something
that works for us. But you see how
that rim light is really highlighting
these edges here. On this back light or
using this back light. So I'm just going to
tweak this right back down to its default
numbers here. But you can see here
are before and after, when we're looking
at no lights here versus just a very basic
three point setup. That looks miles better already, and we're not even taking other things into
consideration like the world lighting or the lighting of the environment that is around us or anything. And we already have a
beautiful enhanced version of what we start with. So I hope this help with illustrating the three
point lighting setup. I'm going to go ahead and
exit the camera preview here. So if we were to take a look, we can see we have our
key light over here, again, on that angle
coming down on us. If we come up from above, we have our three point setup and it looks just
like a triangle. So we have our key light here going opposing
in the opposite. It's going to be our fill light, and then our back
light is always directly behind our character. Now, in this, I'm just
using spotlights. But of course, if we're outside, we could use things like
like a directional light, for example, or you might be using spotlights
depending on your scene. So these are things that you
can take into consideration. The third type of light that we have is called the omni light, and that basically
emits light in a full 360 degrees area. So this is that would
be more for things like light bulbs, candles,
things like that. Now, I can't finish talking about's come back to
the camera preview. Lighting without at least
mentioning a environment. Now, a camera can
have an environment, or you can have an environment that's related to
the scene itself. So, for me, I'm just going to add a world environment
to my scene here. And it's important that you at least know how to create a basic sky cause with Goto four. You're not going to
have a sky of any type. It's just being captured
anymore. It's not. Go. So as we can see, we just have this
gray background, and that's not very nice when you're talking about Ampeily if you're
outside in the world, you kind of at least
want a sky, right? So you're going to see how to make at least
a basic sky here, so we go to the environment
and our world environment. We created a new environment. And click on that to open that up. Then we
have our background. We have a clear
color, but what we can do is we could
do a custom color, Canvas, camera feed
if you wanted to. But importantly, we're just
going to go with a sky here. And then inside of
our sky section, we can go ahead
and click New Sky, open that up for
the sky material. We can say, we have
a panorama sky, procedural sky, and
a physical sky. And with our physical sky here, you can see you got
a ground color here, and our color is
appearing a little dark. Seems like it might have
been a problem there. Let me just go
back in. And let's go with a procedural sky. Here we go. That's something more
normal that you would see. Now, the important thing here is this skylighting can
affect your model as well. So this is what I was saying. We were just looking at
the three point setup, but your sky can
come into effect. So let's say that we're
sitting here in a Let's go with a, I don't
know, a sunset, right? So our ground, maybe we're going to be more
on the green side, doesn't really matter
too well on that. For our Sky, our top
color is going to be more on the purple side, right? And then the horizon is where we're going
to get our orange. Right. Now, it may not look like we're having a
whole lot of impact here, but we are getting a bit, as you can see in
the lighting here, right across the
nose, for example. So if I take this, I'm just
going to copy that color. If we come in, there you go, you can see how it's
affecting our model here. I'm just going to put
that back in there. And inside of this environment
is where we can also get other features that can
have an effect on our world, such as the glow. And of course, your options
of where you're going to go ahead with that bloom. So that's going to go with your excuse me
there for a second, the post processing. That's
what we're going with? So your bloom, your strength of all this stuff,
the intensity. So you got all these things
that you can play with, but turning that off, you got fog which can
affect your lighting. And then we also
have volumetric fog, which can affect your lighting. So we got all different things here to take into consideration. And most importantly,
SDFGI here. This will have a performance
impact on your game, but we are going to also have a more realistic
light simulation here going on with
our character. Here we go. And, of course, you can always tweak whatever little effects that we can have in here and come up with
something that you enjoy. Obviously, density
is a little insane. Oh, that's og, my mistake. Clicked on the wrong one, SDFGI. Here we go. So that's calculating all of
our light bounces. And there we go. Now we can have something that's going
to be a little more realistic and it could
be more dynamic. For example, our
bounce feet here. You can tweak with
that. Cascades This goes from one through eight. The lower the number, the more performance
it's going to be. Then you can see it
calculating these bounces out as we get a slight change
and then going up to eight. Then you go see we calculated in some more of those shadows, like in here with
the neck and then it in the little it's not
a clapping in the back. That would, I guess, be our boys traps. Trap Zoids raps
always no trapezius. It's like, wait a minute,
that didn't sound right. But you get the idea. With that, we can
create a basic sky that can have an effect
on our character, as well as I showed you how to do a basic
three point setup. So you're going to
have a triangle. Back lights always
directly behind. Wherever your key light
or your main light is. The fill light is going to be on the
other side of it with a lower energy level just to make the
shadows not as harsh. Of course, word environment,
create a new environment, sky for the mode, create a new sky, and you'll go with the
procedural sky material. All right. So
hopefully I gave you a pretty good idea on that as to how well light
can really affect your object at the
end of the day and just how important
lighting can be. I'm going to go ahead and show you just a couple of comparisons here
at the end of things with no lighting versus after
they've been All right, so here on screen, you're
saying the wrong window there. But here you're
seeing a before and after when it comes to lighting and just really helping with setting
that atmosphere, especially with an
image like this, you can see just how
important getting good at lighting can really be and just how much you can
really affect or seen. I'm taking it from
something that looks maybe old or just kind of okay to looking newer, maybe a little more realistic. And if maybe going for
more of a spooky vibe, and that just gives you
a pretty good idea here. So before and after when
it comes to lighting. So don't slouch when
it comes to lighting. It's very important, and
especially if you're going to be working alone and you want to do something
in 380 like this. We sure put the
time and attention into really learning lighting. And there are people
out there that purely focus on lighting environments and
scenes and things like that as their job,
I'd say, right? Now, they may do
other things as well, but they focus on all the small things
that you may not notice as a player in a game, for example, or if you're taking lighting into consideration
when lighting a scene, maybe for doing some
visual effects. But there you go. I'm not
going to rant on any longer. I just wanted to let you know how important lighting
is going to be when it comes to three D as
opposed to two D, as well as show you how
you can at least create a basic sky and visually show
you the huge difference, something even just a basic three point lighting
setup can make.
47. 3D Assets: Alright, welcome April 1. And this section, we're
going to go ahead and we're going to
create Frogger again. Only this time we're
going to create it in three D. This way, you'll have a fair
one comparison, I guess, could say, of working
in two D versus three D, and that should
give you an idea of both the similarities,
the differences, and maybe give you an
idea of your own kind of personal preference that
you would want to irk it. Alright, so I'm just
going to use basic cubes, just basic meshes when I
go ahead and create it, but if you want to use three
D models in your program, you can go ahead and do that if you want to create
them, go crazy. If you have some
already, that's great. But if you want to use some
three D models and you don't have any available to you, you can go online and you can find three D models all over. For example, this place
here is Sketchfab, and they have both
free and paid models. All you got to do is
you can go ahead and make your search up
here at the top. Hit downloadable so that all your results
can be downloaded. And that way it
removes any situation where someone's maybe just
showing something off. And now if you don't want
to put through any money, there are plenty of
free options out there. And these ones here
with the dollar sign up in the top ight corner. Oh, I can't see
that one. So we'll come over here with
the dollar sign, top ight corner here. Here. Those are ones that
are going to cost money, but the ones that do not
have that dollar sign. And that will just
take a second to load. And you can go ahead. You
can take a look at it. You can view it, which
is great about fab. You can go ahead and just hit the download button
here on your free Moth. Obviously, if you're
willing to spend money, then you have to go through the whole putting in your cart, checking out and all
that stuff first. But that's only if you want to. I did find some free frogs
here that you could use. I don't know if any of these
come with animations or not. You'd have to check
individually. And for that, you'd go to
more model information here, and then you can get
all the information, all the different
model types and GLB, GLTF and FBX, as well
as OBJ will work. However, OBJ, I can guarantee
you has no animations as an OBJ just for a static object. And you
can actually come down. You can see PBR. It's
all your materials. It's got four textures for
the sproc specifically. So you'd have to if it
doesn't apply automatically, you'd have to go
into the materials and load these textures in, like we saw in the
transition section. And as we come down, we
can see, in this case, this one has no animations, and it is not rigged. So you would have to rig it before you can animate it if you wanted to make
your own animation. And there are no animations
that come with it, obviously, it's not rigged. Alternative, we also have
some logs here that you can get here's a truck
here, perfectly free. So if you wanted to get models, you can head over to a
place like Sketchfab here and you can take a look
for some free models and download them. If you just want to
use the basic shapes like cubes like I'll
be using for this, then that's perfectly fine, too, because we're not
working with three D models. We're not doing anything
fancy or specific. We're pretty much just moving things around
on the screen. We don't need any fancy animations to make
any of this work. Alright, it's up to you which route you want to go, whether you want to make some, find some free ones
and download them, or if you just want to use the basic shapes that
come with the engine. Up to you. Now to do it for this one. It's
up for you to think about. And if you want to
use three D ones, go ahead and spend your time now collecting them and
getting them together. If you want to import
them, it's just like your other assets to drag them
in to your project folder. Alright, let's get started.
48. Gridmaps: Alright, everyone. Just
like in the two D version, we're going to
start with creating the background for this. And in order to do this, we're going to
need a few things. First of all, we're going
to need a camera here that is pointed down so we can actually see
what's going on here. So go ahead and preach
a three D scene, which would just be a no
three D for your root. I've renamed mine to say Main. Add a camera three D in here, and you can go ahead
and add a grid map. Grid map is the three D
version of a tile map. And with your camera three D, you can go ahead and set
your Y position underneath the transform section to 25 and your rotation of
the X to negative 90. That way, you can
look straight down. Now, if you were
to run this scene, you'll see a gray box. Fantastic, but at least
we know the cameras working or at least
shut by default. If you're paranoid about that, you can go ahead and tick
current inside the inspector. But since we only
have one camera, this should be the only one that activates right now a grid map. NRT is a grid map. We must have our tile set, right? Art is a tile map. We need a tile set.
Well, for a grid map, we need a mesh library. And we can create a new one, but it doesn't have
any resources in it. So what we need to do actually
is create this library. So to do that, we're going to go ahead and create a new scene, and you can just
make a node three D as your root node
again for our scene. And again, that's just
new three D scene, and you'll have one. And all I'm doing
for the road, water, and median is I'm
just bringing in the textures from
the two D Frogger, bringing in the
sprites and using them as the albedo texture. And I'm just leaving their default position
in the middle. So I'll show you how I do that. So I went in and I create a mesh instance three D.
I go ahead and rename it. This is going to be my
brass block for my mesh, I go ahead and open this
up and select a box mesh. Now, if you had a custom
mesh, a custom model here, if you wanted to bring in
specifically for this block, you could go ahead
and drag the mesh into this specific spot. This mesh, this object. This
is where you would do it. Now, for just these
blocks and the grid map, you shouldn't need to unless you're bringing
your own custom, again, meshes in for
each of your blocks. Now, this block is just
completely white here, and you'll notice
it's much smaller. I'm just going to hide
the other ones here so we can focus on this
one. All right. So the first thing is we
have to go to scale and set XY and Z all the way to
two times on its scale. And the reason why we're
doing that is so that it fits an entire block of our grid map instead of being off to the edge or off to the side in some weird position. It's just easier for us to go ahead and do this, just double. Alright, so we have
our little cube here. Now, what we need
is a texture on it. So what we're gonna do is
we're going to open up the surface material override. And the reason why
we're going to do that. Oh, no, this mess comes with it. So we can just open
up the mesh section, and there's the material. And we just add a standard
material, open that up. And here is our albedo texture. And this is where we would
go into our Frogger sprites. And for my grass block here, we could go ahead and bring
home in if we wanted. We could do that, but it
doesn't look all that great. It's kind of weird.
And personally, I'm not that big of a fan of it. So, personally, what
I'm doing with this is I'm going to grab
the median texture, and I'm going to
place that on there. And then just out of
personal preference, I'm going to come
down to the U V one, specifically, and I'm
just going to set my scale here from
my UVs to two. I think that at least
looks a little better. Now, the problem is, this
looks exactly like our median, and we wouldn't be able
to tell the difference. So this is where
I'm going to use the next pass here
inside of our material, and I'm going to add another
standard material here. Now, when I open that up, I'm going to set
the albedo to being a nice green that's
semi transparent. I'll go up to the
transparency section and set the transparency to
Alpha. And there we go. We have, like, a green
version of the median, so it stands out and
it's different enough. Now, you would only have to do this for the grass block if
you're copying me with this. And the median, you just use, of course, the median texture, double the size, water. You can do the same thing
and same with the road. And once you have that, I
would recommend saving this, so Control S. Or, of course, you go up to
your CN and save and save this as your mesh
lib, mesh library. And this will be just
in case you want to come back and edit
this in the future, which we probably will at some
point, just the heads up. And once you've done that, we can go up to SN
and go to Export As, and you'll see mesh
library as an option. I know you can't see
it on my screen now, but just SN export
as Mesh Library. And when you do, you'll be
presented with this screen. Not is big. There you go. And just for safety, I'm
going to go ahead and make sure fly meshed
instance transforms us on, even though we should be fine. And just save it somewhere. I just called Min MAP, and I use the mesh lib extension just to keep things
organized because I don't want everything
to be named Res or Trez, for example. I like to keep things
named properly so mesh lib or material, shader, things like that. I like to keep them keep the extensions relevant
to what it is. So once you have that,
go ahead and say that and hit the Save button. If you already have one created in the future and you
come back and edit it, you can go ahead, just
overwrite it. You'll be fine. And back inside of
our main scene, we can actually go
to our grid map. And you find where you
saved your mesh lib, you can go ahead
and drag it into the mesh library section of your grid map, and there you go. You have all your pieces there. Now, I went ahead and
I've got Grass block and grass end just
because of my naming, and I went ahead and just
have my set to add instead of overwrite what I'm going to do is I'm just
going to come back in, go to export mesh library. And I'm going to say I'm going to uncheck, merge with existing. That way, I just completely
overwrite it and replace it. And now when I come here, I
just have my normal blocks. Awesome. Alright. Now, for the project, I'm using the same
resolution that I use on Frogger on r2d3 36 by 256. And if I go ahead and run that, I'm going to have an easier time when it comes to
placing my blocks. All right. Now, you'll see while we
have the gray block there, or it doesn't look like we
have anything on our window. You'll see if we go ahead and place something, it'll appear. And that's how we're going to determine where our limits are. That's what
we're going to do. We're going to outline our
limits if I come down here. That's the top, which
means I should be looking this way on my camera. Let's see. That's
still on screen. That's a little too far. Okay. So that's going
to be that block. You can go over one. And I'm going to call it
there on that block. And now, it's just a matter
of finding the other corners, which if you count
out the grid spaces, you should be able
to find it easy That should be my corner there. And then our corner should be right on here, one more? Yes. All right, so there's the
corner of all of our positions. Now, if you want to
place it left click, if you don't know
how to delete it, you didn't figure it out. It's a right click. And now we can start placing
our objects. So our median is our
second row here. We had the road
on the first row. We had road on third, fourth, fifth,
sixth and seventh. Then we had median again. We go across, we had another
five rows for water. One, hooks two, three, four and five. Let's see what do we have next? We had our wind zone. So for these, I'm going to
double up here on the ends. This because it's Oops
an odd number here. And we'll have doubles, like so. Three bone, one,
two, three, down, one, two, three, down, one, two, and three down. I'll fill in those empty
spaces with water. And then we had the back row, which was just water
where some of our UI was. Now, let's go ahead and
fill that in again. And there we have it. We
used the camera to make sure that we filled up our
entire viewable area here. Now, this is kind of dark, as you can see, and that's because we
don't have any lighting. So I'm going to click
on my main note here and I'm going
to add a light. And specifically, we're going
to add a directional light just so we can kind of
emulate a sun coming down. I'm going to lift that up above, zoom in so I can see
what angle it's pointing at and point it down. Here we go. Now we have some
light shining on our tile set or grid map that we can view and actually
see what's going on here. All right. So that's
all that we need to do here. In this video. Now, I will note that we
are on floor zero here. However, if you wanted to
drop down to negative one, you'll see we'll go
down space here. If you wanted to go down one, you can certainly
do that just so it levels out so that 00, zero would be sitting
on top of our objects, or so that we can have, say, a frog sitting at zero, zero, and would be on
top of the ground instead of having
to raise it up, which I think I'm
going to go through and do real quick here. Alright, so I went ahead
and lower mind by one, and as you can see
in the camera, I am now just slightly
off on my numbers. So we can come up and we can just fill those extra spaces in. Just make out one wider. And that'll fix that. Boom. Boom. Simple
fix. Easy to do rs. You know, I think I'll
just bring in more water there on the edges. All right. So there we
go. There we have it. I need one more
road on the bottom to cover up that bottom grid. Here we go. All right?
I screen is fall again, change my floor down
to negative one. So now when we sit at 00, we'll be directly on top
of it. And there we go. We have our grid map set up. We have our camera pointed
down at our grid map so we can look at it from
the bird's eye view. And that'll do it
for this one here. Now, you can see that's very easy aside from having to
create our own mesh library, which I mean, to be fair, if you're in two D and
you're working with tile sets or tilemap, you kind of have to create
your own tile set, right? So it's not too big of a difference going from
two D to three D so far. We had to add a camera in, and we had to add a light. Other than that,
our process has, for the most part, been
just about the same. I mean, with a mesh library, we had to export that
to get that set up. Was a tile set, we had to mess with a special tile set section
down here at the bottom. So small differences there, but a lot of that was the
same. Not too different there. All right? Once you go ahead
and get your map set out, get on the floor that you want, your camera set, we can go ahead and move on to the next section. I forget what we did second on, so I'm gonna have to go
back and take a look.
49. Creating the Player: Alright, so here
we're going to go ahead and create our player, and I'm going to show you if I go ahead and
stop this real quick. I'm going to go ahead and
show you if you choose to use a three D assets here and maybe downloaded
some or created some. You see, I have a
GLB for ug here. With three textures here. Now, this should
automatically be applied, and I'm just going to
right click on it, and I'm going to select
new inherited scene. I know you can't
see that, but I'm going to select new
inherited scene. And you'll see I now have my
new froggi as its own scene, and it should have all of its textures completely
applied for me. Now, if you wanted to use the model, by all
means, go for it. If your model had animations, you will see an animation
player inside of its scenery. And if this is what you
want to use as a player, you can go ahead and
save it as a player. Now, this is, in this case, a Node three D. So we would have to
change that out. What you do right click and change you have the
change option there? Now, if I go ahead
and double click on my frog here before
we open up the scene, changes to C, I do not
have an option for that. It is interesting. Let's see if I have an option
if I'm going here. Okay, so you double
click on the scene. We'll get the importer
for three D frog. And we can just come
into the root type here. Click on that and select Character body three D. There's no reason
for me to capture. It's the same thing as creating
a new node, same screen. I can just click on Character
body three D, hit Create. And now that I'll
have a character body or it should hit the reimport button down
here at the bottom. Close that old scene, right click and do
inherited scene. I can see that my new froggy
here has a tendematic body. So if you want to use a three D, you can go ahead and do that. Make have yourself a little
happy frog, move around. Like I said, this one does
not have any animations. So he would just be jump Well, I'd say jumping, but not
really jumping, right? He'd just be moving
one space at a time. And if you want to go with just the basic, the basic version, maybe you're not super
instant in three D, but, you know, you got to at
least learn a little bit, dip your toes in a bit. What we're going to do
is we're going to go into cred a new scene, go to the other node, do
a character body three D. And we'll add a mesh
instance as well. The mesh instance
where you can just use a box and to keep it in
line with everything else, we'll set the scale to two. I'll add a standard material. And since he is my little froggy I'm just going to go with
this, like, yellowy green. And that's all we
really need to go with. Now, if you wanted
to, you could come in and tweak some of
your other sliders here. See, we got kind of a shiny
froggy going on here now. Specular going up, and
frogs aren't super metal, so just have a little
bit of metal in there. And you could just do that
with a little froggy. Now, if you plan to have just the top down look like this, and you don't at any point, plan on moving the
camera maybe down here. But if you do move it down here, I would suggest adding
a second layer to the wind the wind
area on the grid map, just so that we have
it popping out of the ground But if you just
plan to go from the top down, uh, what are we looking for? Material. What you could do go into
your frog or sprites. Hey, you can bring the
little froggy in there for the texture, and Oh, he's not looking too great, so maybe we don't
want to do that. Hmm. Well, I expect that to
go a little differently. But I guess not. But I guess we could
go ahead and just use this texture for the froggy
color if we want it, or you can just make
it green, or again, you can bring in your
own three D model, make sure that your root node here is a character body two D. Whichever route you want to go with it is going to
be completely up to you. I said at the beginning
of this that I'm just going to go with the
basic shapes that are already in here instead of looking for and finding
a bunch of three D models. But if you want to do that,
make your look extra good. Fantastic. I encourage you. Okay, so I'm just going to
go with this and rename my character body to Frog,
or do we want to go play? I'll go with renaming my player, and I don't really need anything else other than
this at the moment. I'm going to go ahead and save
my scene as player scene. I can go into Maine and we
can bring in our player. All the way back to the start. Since we got all this
snapping with the grid, perfectly lines up. He's
right in the middle. Alright. So let's see. Would he would indeed line up
with that? Perfect. All right. So with that, whichever
player route you decide to go or I'll pull our
little buddy up here. You. Alright, with that. Go with whatever frog or cube, texture, whatever you want
to go with your frog. Once you have that,
go ahead and save it. Do that right now. And I'll see you in the next
one where we'll go ahead and start getting the
little movements in.
50. Player Movement: Alright, let's go
ahead and create the basic player movement
for our little froggi. So I've just gone
to our player scene here and slap is script on. Our little froggy and inside our script,
we're ready to go. We can jump right into
our process function. Now, since we are
working with three D, I should say that anything
that has to do in the future with collision
detection and physics bodies, it would be best if you stuck things that had to do
with them specifically, like movement under
a physics process. Instead of the regular process, these are two different
times in a frame. And again, for this game, shouldn't be that important, but I figured I'd just let
you know for the future, if you do decide
to continue with developing three
dimensional games that anything physics related
like movement should be under physics process instead
of just regular process. All right, so I'm
going to go ahead and we'll create our
movement function. So movement this
will return nothing. Now, I already have my functions
or not functions, sorry. My movement still set up since
I'm in the same project. Remember, go to your
project project settings. Go to your input map. And from there, you can go
ahead and set up your inputs. If you don't have that set
up for whatever reason, maybe you're doing this in
its own separate project, which again, would be
nice would be good. But yeah, I just wanted to have a still mine setup just like it was from
the two D froger. All right. So inside a movement. All we need to do, of course, we need to check say I input
dot is action pressed. Say just pressed because
we don't want to spam it. The action we want to
check is going to be up. That's what I named by action. And in order to move our little
froggy I remember before, what we did is we moved
self dot position. Do, in this case, we're
in three dimension. We have to go with
a z or z axis here. And let's see what
happens if we do this. Whoops, egg on my face. I
was never calling movement. That's why it's not
work. So, you do have the position way
of calling things. We have the transformed
basis way of calling things, and that's going to tell us that we can't use a single number. We have to go with
a vector three, and that's for a far
more advanced topic when we start going to
things like matrix, matrices, and things like that. So transform dot origin dot z would be the other simple
one that you could use. You can see, to us,
they're working identical. Although, depending on your
situation and your game, you may need to use or prefer
to use one over the other. It's one of those things
that may be situational. Now, if you want
to keep things as close to the Tut
version as you can, you can go with position
D, position DZ. I'm going to go
transform.org just because it's something that we want to go with typically when it comes to
three D, I would say. A lot of times this is what you're going to
see on the back end. You're looking at
other people's code, at least through my experiences
when I see other people. So in this case,
you can go ahead and I guess use whichever one
you want to go with here, and we can leave that
to personal preference. I'm going to write
the whole thing out. That's up to you. And we can go ahead and fill in the others, these last three for our
updwn lefthand All right, so now their axis have
been changed to down left, right, and they are all
else if statements. Now, if up is going
to be negative, then down is going
to be positive. Now, left is going
to be negative, but it's not going
to be on the z axis. It's going to be on the X. And if that's negative on the X, then right is going to
be positive on the X. So we can go ahead and try
that. And there we go. We should be moving around
in all of our directions, since we need and
fit inside all of our wind zones. There we go. Awesome. All right,
so far so good. Now, what if you want to
rotate a little Froggi? Especially maybe if you're using a brought in your
own three D model, then you might want to rotate
him again as he moves, just like we did with
our two D froggi. Well, here we're going
to go ahead and get self rotation degrees Y, I believe it's going to be here. And I'll set it to zero on
down is going to be 180. Left is, I believe it's 90, and then right is negative 90. Let's go ahead
and check that. And every time we
move, there we go, our little froggy rotates around in the position
they need to be in. Now, again, that's
going to be completely up to you if you want
to set it that way. And again, if you
really want to, you can come in and you can
have an s to default it back down to looking forward on its rotation so
that when you move, you can see it doesn't we're not getting that
instant flip around, like we would expect in
two D. So we'd have to come in and put just
a slight pause in it. I don't mind it myself. Might just be because
I'm doing the cube, but I'm just not going to
have that s block in there. But with that, we have
our basic movement, and we can start getting
things like like cars, getting squished by our cars, and then getting our platforms
to jump on death by water, wind zone, get our
gooey set up again. And unless I'm
forgetting anything, we'll have our three
D version all set up. Oh, well, not the respond will be part of the death, yeah, so there we go. Alright, so there's
the controls here. That we're getting for
our three D broger, remember to call you movement
function inside of process. And remember, in the future, if you're going to continue
doing with three D games, anything to do with physics, like movement because I'm sure you'll have collisions
set up in there. You're going to be preferably sticking in physics process
instead of process. But right. There you go. There's our player movement. And let's go ahead and
jump into the next one.
51. Creating Vehicle: Alright, so let's
go ahead and build our little vehicles that we can use to spawn
in to the game. Now, of course, again, if you went and got some
three D models for vehicles, and then just like the frog, we can go ahead, bring them in. Make sure they're facing
the right direction, which should be obvious by the time we get to the end
when you see them moving. What? Go ahead and spawn them in or create an item out of that scene. Save it
as your vehicle. And if you're doing the
basic blocks with me, then follow along, we'll go ahead and we'll
create ourselves. We'll make ourselves
a little truck. Going to stick to the two D
version as close as I can, and we'll create
our character body. It's named this truck. And of course, this needs
a mesh verus the add here. And I'm going to go
ahead and add a box. Go. Now, to keep in with
our two by two, I'm going to increase
the scale here by two and I will lift it up. I all right, so that should be on par with
our player character. I'm going to make sure
all this is evened out flat even position. Now, you, of course, don't have to name
any of this stuff, but that's going to be the tab, I'm going to create
another mess here, and this will be my trailer. Transform scale goes up to two. That's also going to be a box, position, one on the Y. I'm going to pull it
back to two on the X. And let's see. I'm going
to go ahead and give it a different color. And we don't have visibility. We do modulate. So I'm going to go
ahead and add a material onto this mesh. That's going to be my trailer. Let's say standard material. Open that up and
go to my albedo, and I'm just going to go
ahead and give that a color. I'm going to go with
something in the orange hue. And now if I want it, I can go ahead and I can change tweak some of these valves, so I can set my X to two, and now it's longer, which now it'll look a little
more like a trailer. Set my position back down on my transform three so that
lines up a little better. And as a bare essence, going from a top down view,
that'll be our truck. Now, if you want to
go the extra mile, you can go ahead
and bring another messin If you want to you can use as an example here, we go to cylinders Great. So we can bring
that in and you can see how we have our sides. And then we can go and you could tweak the size of all of this. Let's say you take our
height down to one, 0.5. We're getting there maybe 0.25. And there we would have
a wheel from the side. So if you wanted to go
that extra mile and use another mesh to
create your wheels, give it a shader, color. It's like that. You
can certainly do that. And then, in that case, I would say to just
move the entire mesh up a little bit more so that the wheels are what's going
to be on the ground here. So if you wanted to do that,
by all means, go for it. Go crazy. If you want to again, bring your own
truck in, you can. And when you use these shapes
and create your own truck, then go ahead, come back, and we'll finish up the next piece that we're
going to add onto the truck, and then we'll create our
spinners and write our scripts. Alright, so I've gone ahead. I've added some wheels onto it, and I've just lifted
the whole thing up just by selecting all of
our meshes and raising it. I'll hit escape so I can
unselect everything. And there's my simple truck. Now, if you want, you
can go ahead and you could follow through with this, of course, and create
yourself more vehicles. I'm just going to go with this
easy truck here get going. And to keep through with the with the two D aspects for that fair side
by side comparison. That way you can have an
easy or a better idea of the transition of what it's like working in
two D versus three D. We're going to go
ahead and continue and do this with area detection. So we're going to add an area three D just like
we did in two D. And on that area, we're
going to go ahead and add in a collision shape here. You can see here
I've had an area three D and a collision shape. That collision shape, of course, it's going to be a box. There's no reason not to. And then just make
sure that your box covers your whole vehicle. But there's no mistake when your poor little
froggy gets squished. Grabbing these orange handles
and pulling them out. Somewhere about the middle
of my truck close out. There we go. Now,
there's no mistake. If my frog gets hit,
then he gets it. I'm gonna shrink those
in a little bit. Yeah, 'cause we got a lot
of base on the side there. Alright, for now,
I think it's fine. If you want, you can
always come back in and tweak this later. Alright? So I'm going to
go ahead and save this my three D forager
just says truck dot C. And now we need our truck
to have a script, right? Because they need to
be constantly moving. And let's see. We're going to be
moving on the red line, so that's going to be
on the X axis across. That's fantastic. Et's go ahead and add a script.
Get our truck script. And again, we're going to
keep things as similar as we can for our three
D as we do two D. And we don't need to
worry about any of this. If you got all
this, just go ahead and delete that portions. These are for a completely different completely
different kind of game. Yeah, what was there if you didn't pay attention and you just clicked through
it like I did there, and you didn't have an empty
or a no default script. That was a character controller. And character controller is
typically one that has well, these aspects you
can think, I guess, more of like a first person
shooter or a platform or things that are more along
those lines in terms of RD, para can run around, run
around and jump around. In our case, our
truck doesn't need any of that. So let's go ahead. L the same thing we did before, like export our
variable of direction. Which was an
integer, and we used the default as one last time. We then had a
variable for speed, which was also an integer
that we had at 32. That might be super fast, now, but I guess we'll find out. So I guess for now, I'm going to set it to one. I can change that later. Inside of our process. We'll go ahead. We
got our velocity. We got the X property of it, and we set that equal to
our speed times direction. And, of course, we need moving slide otherwise our
velocity won't do anything. Let's go to our main scene, bring our truck in and see if
it works just as we expect. I'll go ahead and place
it there and run it. Okay, we're set on
a speed of one, and it's going in the
opposite direction for us. But, that's fine. On this truck, that
means our direction is minus one because we
want to go to the left. And there we go. We can see
our truck going across. Awesome. And, of course, we can run into it right
now because we don't have any death scenes for little
froggy to get squeezed. But our truck is moving Now, let's go ahead and now that we know it's
working in the right way, let's run it, see if 32 is too fast or if
it's still good. To me, that looks like it
might be a little too fast. For you, you might
like that speed. So I just put it in half to 16. That might be a
little quick for me too still might want to go with eight my speed and
give it another run. Okay, I think I'm going
to go with eight, at least for now, again, you can always come back
and change it later. And now let's go ahead and
get our spanors created here. All right? So I don't have vehicles going
in the opposite direction, and it would be boring to have us all going in one direction. So I'm just going to
have this one truck, and I'm going to have it go in, you know,
different direction. We're going to have some go
left, some go right for this. Of course, if you've got
multiple vehicles, by all means, have a different vehicle for each sponner so we're going to go ahead
into our main scene, and we're going to add the
same thing that we did in Tot, we're going to add a marker D and this is going
to be our spaner. I believe we use a marker
or did we use a node? I think we used a node. Let me just go ahead and
right click Change type and change to a Not change it
to a plot spanner now. And what is this
truck's position? Pull it back here a bit. So we can say 32 and 12. Yeah, that looks good. So spanner, transform position, 32 on the X, 12 on the z. And that's where
we're going to spot those vehicles, right? Let's go ahead and add a
script for our spawner. And again, keeping as close
as we can to the TD version. We're going to have
our truck variable, which later we just
called a vehicle. You know what? We'll just go ahead and call a vehicle now. Why not just in case maybe
you guys have extra vehicles. I go to equal a reload, right? Of our truck. But of course, you may want
to set this separately. That way we can use the
same script on everything. There we go. We just jumped ahead and
exported it for a packed scene. And in this case, of
course, I'm just going to inside of my vehicle. And inspector, I'm just
going to drag my truck in my truck scene. There we go. And ready, all we
need to do is call our function that we're going to create
here, spawn vehicle. Okay. Rate that
funk span. Vehicle. And we can do what we did again, previously where we can get
a random wait time here. And this is a random integer. And we use percent
three or at least I use percent three plus one. So remember, this percent three is going to
give us zero, one, two, and adding one that'll give us a random integer
of one, two, three. So one of those. And since
we're using this as seconds, it's going to give
us one to 3 seconds in between each car. Looks like tree
like we did before, create our timer, we'll pass in our wait time and
get our time out. So after we've waited that long, we'll create an instance of
our truck or our vehicle. VI equals vehicle
dot, instantiate. And we need to add
to the scene so self dot ad Child, our vehicle. And since this sponsor is
on the right hand side, you need it to go to the left. Now, since I'm just working
with this one vehicle, I need a way for
this vehicle to be set by default or
rather by default, when it spans in
in order for me to have them going on both sides. Because if I don't, it's going to come back to the
span here for a second. And when that's done,
we're just going to call it self Curt span. So if we go ahead
and take a look at this now, what three D. Make this truck, delete it. If we spawn it now, here we go. There's a truck.
It's another truck. Here we go. See, I think that
is a decent speed for this. But you can see here that all my trucks are
obviously going to be going to the left. So if you're going to
use one vehicle like me, just to help with learning here, then you can go ahead and you
can set an extra parameter, specifically for your spinner. And that parameter here, I'm just going to
go ahead and export I'll call it VD for
vehicle direction. That'll be an integer and by default, we'll
set that to one. And specifically this spotter, we're going to have it
set to negative water, obviously, because
it needs to go left. So all I would do here
is I would just do V dot Direction, right? That's what we named it. Yeah. Direction. Equals BD. All right. So now if I come over
here to the truck, if we come over here
and if I were to set my default direction back
to positive one, save that. So now still move in the
negative one direction because my sponsor should be setting
that direction for us. Here we go. So there's
the truck coming. So now I can use the same script if I'm going to use
the same vehicle. Now I can just set
it between negative one or positive
one or direction. All right. So now if we were to
do the same thing with more vehicles, well, if we had the same thing each vehicle going in
different directions, we obviously going
at this variable. But let's go ahead and
get our other sponsors set up here real quick. All right, have all
my sponsors here. So sponsor four is going to have since
I'm using one vehicle, I'm going to set up
a VD set to one. Sponsor two is also
going to be one. And of course three and my original spon
are all going to be negative one because
they are on the other side. And now if we were
to go ahead and take a look we should have
something following, and that's going to be
a lot of traffic to squeeze through for our
poor little froggy. So again, you can come in here, you can tweak with things
like the wait time. Oh, boy, that one's
a little messy. But, yeah, there you go. You
can come in, tweak that. It looks like we might be able to squeeze another
truck in at the top, maybe. There you have it. That is awful dangerous for our poor little frogie
That is really close. We have to see in testing if maybe that's a little too close, and if so, just delete that row. That is, it looks like it
might be touching our froggy. Alright? There you go. There's as close as we can get it for our
three D version. In relation to our two D, so we have our poor
spinners all set up. We have our rock that has our area three D and
a collision shape, so we can detect it when
it comes to squishing our frog and there you have it. We have our vehicles set up. Again, if you have
other vehicles, go by all means, bring them in, take a look at them, use them, have different ones set up
for different directions. And I'll see you
in the next one. And what is it that
we are doing next? After these vehicles, we take a look at our player
death of response. So next up, we'll be
squishing our frog.
52. Player Death and Respawn: All right let's get
our player death and respawn all situated. Let's head on over
to our script, and we can go ahead and connect our signal
for our truck now, our signal is going to be
connected through script, again, keep it just like TD. Although as normal, you can always come in,
select your area, go to the no tab at
the top and go ahead, come down, take a look for the signal that you
want to connect. But it is good for
you to know how to connect them through code, just because in the future, you'll probably have
to deal with creating your own signals at some point, and then you'll have
to connect those, and it's just nicer if
everything is in one place, like inside the code to look at, especially if anyone else
has to look at your code or maybe you have to come back and look at your
code in the future. But let's go ahead. Let's
get our nodes get our area three D. And we're going to connect the body
entered signal, the body entered dot. Connect, and we're going
to connect to a callable. And just like in Tutti, we're going to call
it player hit. This has a body. We'll
make it up tight node. I forgot the E at the end of the word callable. There we go. So we just had a little bit of spelling error
there. No problem. All right, so we should be in a very familiar situation right now just like when we
created it in two D. So we're going to check if player. Now again, keep my
capitals lowercase tier. If I look at my
main, I see player. I have it spelled here
with a capital P. So if player and body name. I would say, I body dot has method and the name
in the form of a string, we'll call it death
just like previously. And we'll say body dot death, so we'll call it.
And there we go. So far, this side is exactly
the same as in two D, except for we use three D
instead of two D for the area. Everything else is identical. All right, so now our player, we don't have that
depth function. It doesn't exist, so it's
never going to be called. So let's go ahead
and call it for us. And all that's going to
happen is we need to disable the shape that was used to collide
with the truck. And then make sure
that it's facing the right direction or a
little froggy just in case maybe you're using
a three D model and then respawn him in a
different position, right? So let's go ahead
and we can do that. So our player, we need
to open up that scene and give our player
a collision shape. That we get rid of
that warning triangle that our player has
had all this time. Our collision shape is
going to be a box for you. You might want to go
with a different shape. You might want to go with
a box. It's up to you. Can I just come down here and this to fit as
a perfect size. Now that our player
has a collision sheet, he can be detected when
he gets hit by the truck. And when we get
hit by the truck, we want to call our function
that we call death. And on death, we want
to set our rotation, just like we do when we move up, so I'm going to set
my rotation to zero. Now, if your model is facing
in the opposite direction, then obviously your up
would be 180 and your down, it would be set to
zero in your movement, and that would be
reflected in depth. So whatever your up is, it's the same degree that you're setting yourself to upon death. We want to disable
our collision shape so that we can only
be hit the one time. All right. Let's go ahead
and do call deferred. So let's get our collision
shape and call deferred. And that's a lot of
stuff to go through. I'm just going to start
typing it set disabled. Second argument will be true because that's what
we want to set we want to set disabled to true. All right. The next thing we're going
to do, if I remember right, we went up and we created
our alive and dead states. Added that to this. So
let's go ahead and head up top and create our states
until we have our Enum state, and we had alive and dead, and later on, we
added another one. We'll create another variable
here called current state. And the type that we're
going to declare it as is a state All right. Now, we can go ahead and set current state down in our death. Let say current
state equals right? State dot dead. And let's go ahead and
get our respawn set up. So funk respawn. And just like this, we're going to be setting
our collision shape and our current state. All right. So we want to
do, we'll move it first. We'll say set disabled, it's set to false. Our state will obviously be
changing from dead to alive, and we need to actually
change our position here. So for this, we need to get
a player position in here. I'm going to add a new node. You've seen all this before. We can go ahead and use marker to node, whatever
you would like. I'm just going to use
the marker three D. And let's see what is
my position at here? One, one, 15, so I'm going to set the same
thing to my marker, so I'm spawning in the same
place that I'm starting at. One, 115. Here we go. So where I start at the beginning
of my game is where I should be starting
when I respawn. And we'll go ahead and call
it player, spawn, location. And we'll set our position. Self dot. Position equals and we need to get Node
of a player spawn. Now remember, our script
is on our player, so we have to go up one. So we can write Get parent
or we can just say get node. And for the path here, we can dot dot slash
as a short form of G parent and then
type in node here, player Bond Jason Got position. Alright, now when we
get hit by a truck, we should be able to respond. And hopefully this
truck isn't too close. And whoops. We got
one thing here. We're not actually
going to have a response here in our process. We need to change
this, so we say, we need to check if
our rockie is alive. Almost forgot that.
And in two D, we also had a timer in our
respawn, but that's fine. So let's go ahead and end
up. So we're ready up there. I say if current state
equals state dot alive. We can do our movement.
LFOs that's a W, LF current state equals
state dot dead. R spot. All right. Now let's
go ahead and try it. Alright, we can move
ahead, left and right. And yeah, that
truck is too close. Okay, so it looks like I'm
gonna have to remove one of my sponsors or
tweak them a bit. But I think for myself, I'll just completely
get rid of it. I'll just remove it.
It's not a problem. And now we should be
good. We should have a little space at
the top and bottom. My froggy is not
going to get squish, and you can see from the looks of it, we were moving fine. As soon as we got hit
by a truck, we respond. Hope. Okay, so we don't have
a whole lot of wiggle room, so I might want to go in and tweak my collision
boxes on my trucks. Hyloiss gonna be
pretty difficult, spicy with this mouth going. But that's just comes in
from doing some tweaks. I'm going to go ahead
and go do that. I'm not gonna keep
you guys here. But there we go. We
have a death and respan working here
on the road portion. And the next thing up is we can take a look
at dying on the water, creating our water platforms.
53. Water Death: Alright, so just like
the two D version. We're going to determine if
we're on the water by getting the ID of our grid map in this case, because
we're in three D. It was the tile set, the tile map in two D. So first of all, just like in Tut we're going to start with an ready
variable, which, again, basically just sets the variable inside of
the ready function. So in other words,
this variable does not get spit until after the
game is already running. And since we're the
player, we have to go up one to our parent and then
come down to get our grid map. So we set it to G node, and we have our dot dot slash our equivalent of Get
parent and grid Map. And then we come down
and we have our check Bell ID down here. Function, ready to go,
ready to code up here. And this is going to be very
similar to our TD version. Now, for our TD version, we had a variable for MAP pause, which was our grid Maps
translation would be gridmp dot Local TMAP and that map took a position. It took sorry, one argument. And that was our player's
position that we passed in. And we also had a
variable for ID, which was the equivalent of our grid map Yet sell source ID. But instead of source ID, what we're doing
is we need to get sell item when we're
dealing with grid maps. And this doesn't
take two parameters. I only has the one,
and that one is going to be our map position. So we don't have to pass
it any layers or anything. Now, at the end, this is it, and this
is all we needed, and we would say if our ID, in our case was equal to
three because three was the ID for the tile
map, the tile set. In this case, if I
go ahead and look my grid map and I open
up the mesh library, I can see water is associated
with the ID one here. So I'm going to say
if ID equals one, and this is where we would call. And then we check cell ID pretty much every
time that we move. Boom, but a boom. But a boom. And I'll just pull it out of the process for now, so
we're not spamming it. Now, we're going to
go ahead and run it, and we're going to see an issue. See, nothing is really
happening here, okay? But we're not printing anything. Just get a le on there. And
when I step on the water, you would expect me to
die here, and I do. Now, is that because
I forgot to I did? So I forgot to reset
my player here, and that is why it worked. Now, normally your
player, again, should be up and above the map, and you'll see here,
I'll just go ahead and rush it that it doesn't work. And the reason for
that is, well, the reason that
you saw my player was sunken in down there, we're checking too high. So in the position that
we're checking, it is zero. So we actually need to pass in a lower position than
what we're using here. So I just create
new variable called cur pause for our
current position. And this will be a vector three specifically,
it wants a three I. So we're just going to go
ahead and pass that in. And for that, we'll
just use our self deposition X or our Y, we can use negative one. That'll be low enough, and self deposition Z for
the third argument. Then instead of passing in our self position to the local map, we pass in the current,
right, curve pause. That way we can
get our position, but one block lower, which should give
us the location of where our cell ID is, right? Were the grid map is sitting. So now when we hit
water, There you go. We go ahead and we die, and our respawn doesn't
screw that up because we're checking one block
below the player. All right. So we have our
water depth all set up now. All we have to do is go ahead and get our water
platforms in our wind zone, set up our score system
and the overall I. And then if want,
maybe we can set up an alternate camera that goes behind the frog so
we have more of a greedy experience. All right. But that's it. We have
our water depth working. So you can see it's mostly
the same all except for this line where we just have to check one block
below our player. But most of that,
again, it's the same. So if you like working in two D and you're asked to
do something in three D, you can see that by now, we've done a lot of roger here. And with keeping things
mostly the same as we would when we
made it in two D, you can see the majority of
everything transfers over. We had to write our position. We wrote our position in Little different and our rotation. I was written a
little different, but I mean, it
still makes sense. It's not a whole lot different. And we had to add one line here to check one below our player rather than
our player's complete. So if you do prefer
two D and you have to do something in three
D, don't feel intimidated. Pretty much just about everything you
learned in two D will transfer over to three D.
We just got to remember, like when setting doing
the current position here, we do have that third
dimension to work about X, Y, and Z or X Y and Z. All right. So that'll
do it from here. Next, we'll go ahead and
jump into the platforms.
54. Water Platforms: All right, let's go
ahead and get our platforms all set up. Now, I've gone ahead and
I've created my log here. It's just a cylinder with a material on it on
the mesh instance, and I've colored the
albedo, the brown. It also has an area three D
holding a collision shape, and this collision shape
is just a box shape, and I'm just covering the
middle piece of it so that there's no issues when
it comes to hopping off it, and the game somehow thinks
in that we're maybe still on it just because we might be
barely touching or anything. So I just went with
the middle plus. When we jump on it, we should
be on the middle anyway. So, I'm going ahead
and done that. And I've also
connected two signals, the body entered and body exited signal onto
my log script. And just like in
the two D version, we have an exported direction. And in our process, we just have position dot X
plus equals one times Delta. And if we were to take a
look at that in three D, you can see with the scale, remember of the
logs because it's got to match all of our blocks. I scaled it up to a scale
of two instead of one. And you'll see what
position dot X. There's how far
removing with that one. I believe one is what
we are using, correct? Yes. 01 times Delta. That's how quick our
logs are moving. You can change that if you
want to do two times Delta, three times Delta, whatever you feel is necessary for you. For me, I'm going to leave it on one times Delta for
now just for testing. And then just like my trucks, I can go back and
tweak things later. All right. So if you want to
go ahead and take a moment, make sure your logs are created. You've got your areas set up. And if you want to go
ahead and just lay out perfectly five of
them across like this. Go for it. You can. Go ahead and pause the video,
go ahead and do that. And when you're ready, let's
go ahead and continue on, and we'll get the actual
platforming part of it done, because as you see,
if we jump on it, nothing happens, we just kind of die standing on the water. But as I said, the first
one in the Tut section, it's kind of weird,
considering we're a frog, we shouldn't be dying in water,
we shouldn't be drowning. But there we go.
We have our logs. We have our froggy
now the question is, how are we going to
get on top of it? Well, we're going to take this just like our two D, right? We have our body entered and
body exited on our player, we have our three new
variables platform, which is a boolean, set
to false by default. Current platform, which is a character body three D
this time instead of two D, set to null by default, and a platform direction, which is an int, an integer, and that's just set
to one by default, and that one will set
us going to the right. Alright. So on here, we don't have to do anything necessarily
at the moment. Although we could go ahead
and Y, let's go ahead. I'm going to set our
ID here or not ID, but our second parameter, our second condition, rather, if ID is equal to one. So if we're on a water block, and our current platform
is equal to null, right? So basically, we're
not on the platform. Actually we switch that around. We use disuse platforms. So we said platform false. So that's just a shorter way
of doing everything here. So if we're on a water block and we're not on a
platform, we die. Well, how do we know when
we're on the platform? Well, when we hop onto our log, which I should rename
that just being platform. Do GD instead of log. So just give me
one moment there. All right? Everything
seems to work, and I went ahead and
renamed it platform. That way, if I want to
create little disks for representing my not frogs, the turtles, I can go ahead and do that still
use the same script. So what we're doing is as
we were going over here, we got a platform is false, then we will die if
we're on the water. So we got to change
platform to True. So once our Brogi
enters this area, let's go ahead and
set platform to true. Oops, I butchered that bit. It's body platform. So you want to access
the platform variable that's on the body touching it, which of course is
going to be our player. And again, if you want to
be extra careful here, you can say player in body dot name and tab everything in. That
would be okay here. To the embodied platform
equals true. All right? And what else do we
have? Well, let's see. Current platform. Well, if we look back at our two D version if our frog is alive during
our process section, then we also have a check for I curve platforms
not equal to null. And then we moved
our frog, right? So we would change our
position dot X equals, and then we had a
bit of math here. We had our platform direction. Times our speed, which
I'm just going to go with one so that we
can match our logs, and we can come back
and change it later. And then we multiply
that by Delta. Okay? So if our current
platform is not null, I mean, we should be standing
on a platform, right? Then we'll be moving. We should be moving
with the platform. Okay? So we're going to go into our log, and when
the body enters, we're going to say
body dot her platform. Make sure that I
spelled that right. Per platform, yes. And what set that equal to
self. Now, remember your log. Your log here should be a character body three D. I'll go ahead and
just reopen mine here. I didn't change anything. Interesting. Must have
to restart the project. My log is a character
body three D. And, of course, the ion see
the log and the area three D, which is rousing our tear. Okay, so let's see what
happens. It's just our log. Let's go ahead and run
the tire game here. T's run up and get those
logs, we see they're moving, hop on and we died. Well,
that's interesting. Why did that happen? Well, that happened because we're
actually moving too quick. Oh, that's the two D one
it's up for some reason. Yes, come down, and that's because our death
is happening too quick. We need to have a little
bit of pause in there so that there's enough time for
things like our platform, that to change in between. So it's just having a wait, get tree, great timer and 0.2
should be all that we need. I know we use 0.1 in two D, but was 0.1 I tried,
and it wasn't enough. So we're going to go with 0.2. And if we go ahead
and try that now, we should be able to Ooh.
What happened there? Oh, it's 'cause I
sent position dot X equals Intent a plus equals. Here we go. Now we're
going to hop on this log. I can go ahead and
ride them across. Fantastic. And as soon
as I hop off, well, if I hop off onto
this spot here, Oh. Well, we're not safe because we've never calculated
getting off the platform. This means we're also forever permanently moving to the right, so let's go ahead and fix that. When we get off the platform, we obviously need
to reverse these. So platforms false and
our current platform, it's going to go
back to being null. And just that one change to
solve this riding along. Oh. And we just died there. A, well, that's not. That's not great. Let's find out why. Well, if you remember,
back on the two D version, we had Well, two more
things missing out of this. The first one, when
our body enters, we actually had another timer, and that's just set to
0.1, which is fine. Us now when we go in, we hop on. There we go. And we can hop
across without being killed. And as soon as we hop
off into the water, which would be our wind
zone, we get killed. Hop across, and into
the water, we die. And it still happens when
we get hit by our trucks. Fantastic. So everything's
still working fine. This one tiber is enough to fix that one
small bug that we have. Great. And the only thing
we had left is I believe we created a function to set the direction here. So that would just pretty much depend on whether we're
going left or right, what we're setting a great. And that would be direction
that we can pass in. Which for this log is zero right now, but
it would be one. And in this case, on our player script, we can go ahead and
create that function, funet direction,
and you take an ID, which is an int and you just have our platform
direction equals ID, we call it IDA, I
think we call it DR, so let's just keep it there
DR. And then on our platform, we can go ahead and
body dot set direction and pass in our direction. Alright, so now, it
wouldn't matter on our play if we came in here and changed platform direction to, there we go, 8,967. Wouldn't make any
difference because that will be set once we hop onto an actual log here. There we go. So if our logs were going in
the other direction, then we're going to the
right, keep ending up. How does that keep happening?
So we go in there. So if we set this
to negative one, That would be negative one
on our speed here as well. So we could just completely
change this and say direction times Delta
for the moment, but we can see that log is moving in the
opposite direction. And the only reason that is we changed one log specifically. For example, we can come in here and set this one to
negative one, as well. Now we've got two logs going in the other direction.
Well, we should. Why didn't this one change? I did get the right
log. That is negative. Mm. Hmm. Let's have to
go ahead and read see. That's fine. We saw are the logs completely moving in
the other direction? And let's just go ahead and set that for our main log here. And we can see they're
going that way, we hop on and we are
moving that way. All right, so all we need
now is if you want to, you can create little
disks at a scale of two to represent your
little hurdles or lily pads or whatever you
wanted to do with them. And basically just use
this script and set the direction. There you go. This our little platforms
going on there. For our logs. And these sponors
we can go ahead. Just go to call set
these positions here. So remember, we're going
to alternate on each side. Left. And then to the right. Alright? Now, all we
need is a spawner. Set up. And for that, let's see. Could we use our
spinner scripts? Well, those are vehicles,
so it wouldn't really make sense in terms
of that code. But the rest of it, looks
like it would make sense. That's what we're naming
here, right direction. Yeah. So we could use the same spinner code and just create more
of these spinners. And that is perfect fine. I think we do that. Go ahead
and create this spawner. Is this sponnorFive,
clear out your vehicle, find my log, bring that in. And we may actually have to set, I'm just going to
run this real quick. I think we have to set the
rotation of our log as well. Where's my log? I'm
kind of confused here. Yeah, okay, so there's the log. It's going completely vertical. So we would need to set that up. All right, so let's just
go ahead and create a new script then
platform spawner since we have to tweak
a few things with that. So we've gone ahead and we basically have the same
stuff here although we have platform and spawn platform,
PI platform instance. Oh, that looks good.
Let me just go to my sponsor and pull
the log scene in. Again, platform. Yo. And now we have to take
a look at our logs here. What is the rotation
that I have it set? Y is set to negative nine. Okay? So we have to
make sure to set that. So say pi dot rotation
We can do that, right. It's a rotation R Y
equals negative 90. And let's just see if
that sponor is working. Remember that sponer down here. Matt on a close type int. So I just had the idea. Now, first of all, I
completely screwed up. I was trying to load in
the wrong log scene. I was trying to load in from the two D instead of three D, so that's part of why I
was getting some errors. But then on our platform here, we can go ahead and just we could inside of our ready here, go ahead and just set our
rotation degrees here. If you wanted to do
that, you could. Just hopefully that
doesn't affect any of the other platforms
that you create later. But just to well, prevent that. Actually, I guess I
wouldn't really prevent that because it's gonna come
up with the same situation. It's going to spawn
and be rotated. I'm just going to go
ahead and down one. I'm just going to go
ahead and put it here in my spot so we're just taking i BI platform instant and
setting rotation degrees, and I'm setting it
to a vector three, which is just three
pieces of data, right? X, Y, and Z, or in color, it'd be like RGB, right? So zero, negative 90 and zero, and this now positions it correctly on the
orientation, I would say. So now we just got to get our logs moving in the
correct direction. I as well as the Well, correct direction as well
as the sponor position. So for that, I'm just
going to pretty much look at where my logs are set. So example, this one, the transform here, negative
29 and negative one. That's good enough.
Position, negative 29 and negative one. Now that log, I can completely delete and we can have another sponnor
with this transform, which would be negative five
and negative 29 as well. This is negative 29 and
negative five. Here we go. Now that log should be
able to be deleted, and we should still have
our two log sponsors from the right,
going to the left. Except my direction is off, so we're actually moving off screen continuously to the left. Okay, so let's just go ahead and you don't have
to do this part, of course, because
if you're creating different platforms, you're going to have
your turtles going left, your logs going right. So that's going to
be perfectly fine. But since I'm just going to use the logs here instead of creating multiple
things right now, I'm just going to create
a variable for direction. By default, we'll
just set that to one. And when I spawn them in, I'm going to say
it diconolrecon. I set these two to negative
one lock spawners, they should go to the right now. So as the spawn in hopefully they're
spawning in here. There they are. No. All right, so where are my logs? No, the log is here. Direction is negative one, so it should be going
in the other direction. Oh, I set the logs that way. Whoops, that was a
me mistake then. And better set them all in a negative one
by default, then. And we got this
platform time here, which is a little
annoying, but there we go. There's my logs going that way. And I can just set three up on the other side and have negative
one as their direction. So I'll do that bro. All right, so I just set up my sponsors on the other side, so we can go ahead and
run the game, pop across. We're all good. And we just wait for
these logs to appear, and we'll see if we can
jump all the way across, even though we're going
to die when we get to the side because we don't
have our wind condition yet. So at this rate, yeah, I think I would want to speed
my logs up now, for sure. And I got to reset
those directions for three, four, five. I do believe three, four, five, that's positive one. To should be negative now. Awesome. And I said
I wanted to change the script say direction times. Let's do three. We'll see how fast that is too fast, we'll drop down to two. The top across. Let's see
what three will give us. Logs. Where are you at?
Okay, threes not too bad. We can go ahead
and hop on there. And now, my froggi isn't moving too isn't
moving fast enough. I'm kind of hopping along
here. Stay caught up. We got to fix that. Here we go. We could make it across,
and that would be a well, a theoretical win.
So on my player. I'm just going to go ahead
and change that one, two or three, cause
I think I'm going to stick with three. Try
it one more time. Just to make sure
everything is going good. Bring me my log. Here we go. And now our speed matches up. I can hop onto the next log. Poop Poo. Here we go. All right, so we can make
it all the way across. Excellent. And everything's working out. We have our platforms working, and now all you have
to do if you want to create your turtles,
do the same thing. You can just create your little
spear over years, right? Your little cylinders and squish them down to
like little disks, and then have an
area just like this, just the spot covering the
middle for that detection. And just like that, you'll have a new
platform all set up. Alright, so that does it
for our water platforms. And next, I believe
we have our winspace.
55. Memory Leak FIx: All right. So before we jump
into our wind condition, now that we have
our vehicles and platforms are all
done, let's again, come back to this memory leak, where we have infinite
platforms and vehicles that are constantly moving in the void and constantly taking up memory. Let's go ahead and get rid of them when we
no longer need them. All right, so let's
go ahead and open up our platform script and our
truck or vehicle script. And we're going
to solve this the exact same way, very simple. Inside of our process
here for our truck, we're going to go ahead and
we're just going to do if our global position
dot X is greater than 436 or however wide, right? However wide your window is, I'm going to say plus 100 is
about the space that we're giving or global position dot
X less than negative 100, self dot free, and
we're going to do the same thing for
our platforms. And let's just run this and see if we have any issues here. Okay. We're not
running into any. And let's just see at what
point do they de spawn on us? Okay. Now, remember that 100 off quite is going to
be hugely different than in two D. So we should probably turn that
down from 100 work with you. So let's try ten So say 346. We've got a try and ugly
looking at platform there. But let's just copy
that over to our truck. That's right. See our
trucks spawning in. On the other side,
that's not enough space. We can kind of see our trucks and our platforms
glitching out there. So they clearly need
more space than that for the negative ten here. So let's go with negative 20 and see if that's
enough space for them. Not enough for our trucks. It doesn't look like it's
enough for platforms, but no. So now we're just
kind of dialing. So that negative 100 seemed
kind of ridiculous, though? Let's try negative 50. We're just going to
kind of dial this in. See if our platforms
are able to spawn. And our trucks do
go faster, though. So let's see if they can
disappear on screen here. If we just open this up so we
can see the outside of it. Okay, so the trucks
go a fairer distance. You see, they disappear
right about here. This is about where
our platforms should be disappearing as well. And the other side, they just keep going
and going and going. Okay, so we'll add 50
we're on that side, 346. How is 336? 336
needs to be fine. Will the trucks disappear? They'll disappear at some point, that's the important thing. But if you want to
come in and kind of dial this side down now, certainly, go ahead and do that. But the important thing is that we have our
objects deleting, so we are freeing up the memory with the objects that
we no longer need. So with that, we've fixed the memory issue that we had in the two D version that
we now had three d version. I didn't forget about it. I was just putting it off and we're getting our
main components in first. Alright, let's jump on
to that one condition.
56. Win Space: All right, let's go
ahead and create the wind space for our player. I kind of clear up all
these areas as we go. So we're going to need
our player script, and I have a winspace
here I created. It's just an area three D, and I'm going to rename
that to win space. It also has a collision
shape three D that I added. Its shape is a box, and to match everything else, we gave it a scale of
two on our three axes. So now we should fit in with
anywhere that we place it. Let's go ahead and
add a script to this, our wind space script. And this is also going to have a couple signals
connected to it. It's going to be
our body entered. And I believe that's actually all we're
going to need here. And on our player, this
is where we added in our new state, our win state, which means we have another
LSF condition down here, LF current state equals state, win and this we would do our respot
and then set win zone, I believe is what we called it. Go ahead and add
our new variable, our win win zone. That is a bull set
to falls by default. And let's see, in our death, we say if ID is one
and platform is false, and wind zone is false,
so we're not winning. So we're not in the wind space. We're not on the platform, and we're in the water, then
we end up calling it death. Excellent. And let's see. In
our wind space, we call two things. We need to get our
body dot wind Zone. Equals true. And then our second spot is setting our current
state body dot, current state equals stat win and make sure I type that right. Current state, I believe so, but I'm going to
copy and paste just save identifier state not
declared current scope, right? Body stay dot win. There we go. And for now, that should do that shouldn't
really do anything. So in our death, let's actually you're going
to say print dead. So we'll just make sure that everything's triggering
the way it should. Respond print out
the word respond. And in our winspace Well, we also need to set wind
zone back to Walls. But also print out Win. And we can go ahead and test it. We can go to our main scene now. Main, instance in with this
little chain icon, remember? And just go ahead and perform a search for your
winspace. Bring it in. Hooks. Here's mine. Back it up. Gonna be two wind
spaces for these zones. To fits the whole thing. Awesome. And now we just
duplicate it. Second slot. And I'm just gonna keep
going all the way over. Fill all my zones. All right. So I've positioned all of my little positioned
all my wind spaces. Let's go ahead and see make sure our text is being printed out
to our console correctly. Let me just fix that game now. I'm back down to a small thing. Here we go. Alright,
so let's see. We squished by a car.
We died and respond. Excellent. Okay, we
jumped in the water, and we died and respond. We hop on the log. We're good. Pad, and we're good. Turtle, log, pad, log. And we jumped in. We got a win. I see a win, respawn,
dead, respawn. That doesn't sound like
how it's supposed to go. Let's make our way back up. Go ahead and pause it here. So I can clear out
going on there. And continue with this.
S. Okay, so far so good. We jumped in. We got a win, a respawn, a dead,
and a respawn. Okay, so that's not great. That means we have
a bug in there. We should have got a
win and a respawn. We should not have
gotten a dead. I'm guessing our respawn
hasn't gone off yet. It hasn't changed our
position or any of that. We should set our collision first. Yeah. Death recalling. So the only thing I can think at the moment
is possibly something here. But we'll try with just disabling that earlier.
See if that works. We'll find out. My
logs, let's go. This is probably the one thing I dislike about testing the most. Is constantly doing the
same thing over and over. And we wait for a
log. There it goes. When Respawn then we
got a dead and respawn. Okay. So I'm going to try a few things and see which
one of these fix it. Maybe it'll just be maybe
I'll be back in 2 seconds. And let's see where
the source is here. I Alright, I had to look
at the two D versus, see what we might have
done to have solved that. And I was just a short delay here at the top of heckll ID. We had a small 0.1 timer before getting our position
and everything here. So there you go. Not a big deal. But with that, you'll
see that we can now go ahead and jump all
the way across the screen. Enjoy being a little froggy. Come on. Bring out the logs. Let's go. Here we go.
We hop on the log. We wait for little
turtles or lily pads, whatever you want
them to be the log, the next pad, the log,
and the wind zone. Here we go. We got a win
and respond, no death. Oh, I ran into that truck. And Z, we still die if
we jump into the water. Alright. So there we go. We now have our wind
space all set up and the last thing for us to do. Am I supposed to set up a scoring system
and our hut again. And then we'll have our
three D version all set up.
57. Score GUI and Timer: Alright, so here we're
going to go ahead and get the score lives and
our Hud all set up, and this is going
to be much easier because we can reuse the HUD that we created in
the two D version. So the main things we're
going to do is we're going to reuse our global. Then we use some of
the TD. And we're just going to have to rename
part of our path here, and we can make this work with both the two D version and
three D version if you wanted. But we're basically going
to use the same script. So if you have three D version and two D version in
two different projects, you can go ahead and
just copy that script over and then head on up
to your project settings and set it up as an
autoloa All right. So in order to make this
work in three D for global. Now you notice mine says
main for the root node of my main three D scene here, which is a node three D, and in two D, it was a node two D. So
I'm going to go ahead and re rename this to Min because
that's what I'm called, and I'm going to go
ahead and replace that in Update Lives, as well as update score. Alright. And for our Guy, I'm going to head on over
to the two D version, open that up again. And I'm just going
to right click just so I don't have to
recreate the Guy again, since it's just going
to be exactly the same. I'm just going to right
click and I'll select the option. Where is it? Save branch as seen. And when you do that, you
should have an option. You should have this
screen pop up here and you can go
ahead and save it. I'm going to go into my
frog or three D scene here and just resave
Gooey scene in there. All right. And that's all
we need out of the two D. And of course, you don't have to do that. You can go
ahead and recreate it. Just add the canvas layer, the texture progress, labels
and everything again. If that's what you wanted to do. I'm going to go ahead
and add this in now, add my Guy scene. And notice we
cannot see it here. If you are recreating
your Guy from scratch, you're going to have to
click into the two D option here and take a look and recreate it this way because the canvas layer is a
two D object, right? Something rendered to the screen on top of everything else, but it is two D regardless of whether the rest of the
components are two D or three. So if we were to
run this right now, we can see everything is on
top and the way it should be. So just remember if
you are creating this yourself, keep that in mind. If you're going
to recreate this, that you may have to
run the game to give yourself a good estimation
of where things are. And the good thing is, is
if I wanted to come in here and edit some
of these components, I could come in and move
things around like, and you can see update
live in the game. So you could always make
sure that you have things in position that All right. I'm going to stop
running the game there. So if you recreate the Guy, I'm just going to go ahead and show you it
right here again. Hand this layer at the top. To labels for the label
and the score text. Our lives bar is a
texture progress, and we have those Frogger lives texture that you can bring in as the progress texture if we open up textures
here for progress. We have a timer bar, which, again, is the same thing. It's just a texture
progress bar, and it's got the green
square rectangle, whichever one it
is that I created, just to use as the bar here. We have a label that just says time so that the user
knows what this is, and we have a timer node with the default wait time of
one auto statrt turned on, and the timeout signal is connected up to our
Guy that has a script. Our Guy script is
simply on timeout. The timer bar value
is minus equal one. So this will make our bar
continuously go down. And then if the value is zero, then we get our player
node called death on it, and then we reset the bar to 30. All right. Hopefully, with that, you had enough time to either save your Gui as it on scene, bring it over or recreate it. And I will note here
that in the Lives bar, our film mode is left to right, and in our timer bar, it is right to left. All right. But once you have
those two things set up, remember on our Global, we have to change this
from no TD to the main. And that's just because
mine is labeled main. We could just label it no two D. It be confusing, but could. Or if you left it as a default, then instead of main here, you'd be writing no to
three D. All right. So what are the things
that we have to change? Well, that's going
to be on our player here and on our windSpace. But let's start with the player. That's going to be remember
every time we move up, that's going to be in
our movement here. It's when we go up, we get points, right? So we access our same global
or if you copied it over, update score, and on the two D, we went by ten points. Then on death, we go ahead and we have
to update our lives. So global update Lives. And this was set to minus one. And the last thing we update
on DEF is our timer bar. So with this, we'd have
to get node, right? And we'd have to
remember our players, we're going to go
up to our vein, so get parent level, and then we can come
all the way down to our Guy get parent one
level and then get our Guy. And then from there,
we're able to grab our timer bar here. Timer bar. Just make sure I
spell that right. Capital T, capital B, timer bar dot value equals 30. All right, so that'll be reset. And now we just have to
go to our Winspace here. And on our wind space, we just have to make our
few cheap weeks here. So we need to update
our multi frog value. So our multi frog
plus equals one. You remember in our global, the way Frogger works, we
increase our multi frog, and once we get to
five multi frogs, we get a 1,000 square bonus, and then our Multi frog
resets back to zero. The wind space, right? So we add to our
multiplier there. We add to our SOE Global
dot update score, and we're going by
40 points here. And then remember we had
the timer bonus as well. So based on the
amount of time left, we got additional points
added to our score. So let's go ahead and
get the time bonus. That was VR and we just
called it time bonus. This was an integer,
we said it equal to node and we had to go up one, get our parent, right, and
then it'll take us all the way up to our main node at the top. Then we can get our Guy
and get the timer Bar. And we want the value of that multiplied by ten
is what we're using. That gives us a theoretical
maximum bonus of 300 points, but that assumes that
you get up there in less than a second,
not going to happen. And that gives us
a minimum bonus, assuming you got 1 second
left of ten points. So again, that's pretty decent on the bonus,
somewhere 10-300. Although realistically,
it's probably going to be more 10-200. All right. And now that
we have our bonus points, we can go ahead and update, call the update to
our score again, global dot update score
and use our time bonus. Now, going through
this again, of course, we could just do
time bonus plus our 40 for the update score. If you wanted to
combine it all into one instead of calling
our Update score twice. You know, personal preference, and that's something that
you can do on your own. When we talk about clean code and giving you the
ability to come back and brief actor code and clean up areas that you think
maybe are a little messy. So you are going to have
that option later on. And the last thing that
we have to do is reset our timer bar to 30. So we're just going to get node, in our parent into the Gooey, get the timer bar,
grab the value. I'm just going to copy it there and just reset that to 30. All right. And just like that,
our game should just work with our old global
and Goey scripts and check. Every time I go forward,
I gain a point. I die, I lose a life. T got reset. See if we can make it across, wrap on our log or hanging
out, de da de dah. We start hopping across. And we get into our wind zone, let's see what we're
going to have. Went from 180 up to 320. So we got a pretty good
bonus there in our time. The time reset, and we did
get one of our lives back. So that's fantastic. Everything seems to be working perfectly fine with transferring
our tote stuff over. So again, Guy, that
is a canvas layer. With a label with a score label, a label with a score text. Our Lives bar is a
texture progress, and we set the progress
texture to our lives texture, let me get the exact name
of health bar dot PNG. The timer bar, I just
called Tr dot PNG. It's another texture
progress bar, and the progress
texture is set through the timer dot PNG. We then have a label the
word time beside that. We have a timer node
with auto Start turned on with a default
weight time of 1 second. It has the timeout signal
connected up to the Boy script. On timeout on our Gooey script, we subtract one from the
value of our timer bar. And if our timer bar is zero, we call death on the
player and reset to 30. On our player on death, we call Update Lives on our global that we
were using from the two D is minus
one, subtracted life. We also get our timer bar so
we go up one, get parent. Then we go through our
GUI to the timer bar, access the value property. We set it 30, and when we move up and
only when we move up, we access our global again, update SCOR function
and pass in ten points. And our global script will take a run through this
again just in case some reason you
couldn't find it in your own for whatever reason. Here you go. So we have
a couple of variables of the top scores an integer
set to zero by default, multi frog, an integer,
zero by default. Lives, you set it to six by default, again,
another integer, and multiplier is an
integer set to one, our function update score takes one parameter of new amount,
which is an integer. And we have our ILS check if
multi frog less than five, then just score plus
equals our new amount. So we just add the new
amount onto our score if we do not have the five multiprogs. So the only way else we could have here is if
we have five or more, then instead of adding
the new amount, we add 1,000 points and
resettle Multi frog to zero. And then we check
if score divided by 10,000 times our multiplier is greater than or equal to one. Then we update our lives, we call it update life
function and add one to it, and we set our multiplier,
plus equals one. Okay. Now, after that, outside
of those FL blocks, we get our score text, and we just simply update
the text with our new score, and we convert our
score into a string, and we call PAD zeros, and we add five of them. That's going to give us our
padding here at the top. Make sure that we always have
all five of these zeros, even if our score
is only one digit. Then our update Lives function, we have an amount as a
parameter, which is an integer. If lives are zero, we're going to get Tree and
reload the current scene, so effectively
restarting the game. Otherwise, we're going to do
Lives plus equals amount, and we're going to get
node, go up our parent, go down our main node, down our Hoey, to our Lives bar, get the value and add plus equals the amount that
we're updating our lives by. Alright. So that's our
global script, again, if you didn't catch it
or you couldn't find it, somehow lost it. There you go. There it is again,
quick run through, as well as the Goey
script and the Gooey setup in the scene
as you can see over there. As the small changes that we added to our player
to make it all work. And if for whatever
reason you're struggling with enabling your global, if you rewrote it and
you brought it in, let me just see if I can
capture that real quick. So you go up to your project, go into your project settings. Don't you autoload, hit
this little button here, and you can select your global
script from the pop up. The node name that automatically fills in here is going to
be the name of your script, which would be global. And you just hit the ad button and it'll appear down here. Just make sure you
have it enabled, and the name is
how you access it. That's why we can
type in the word Global and have
access to the script. But there you go. There's our score system, the timer bonus, and the Gei
all re added into our game. And now we can go ahead and
we can play some Ride Boger. And not have any
issues as we go. All right. So that's
it with this. Take care, have
yourselves a good one, and we can move on
to the next week. If you wanted to add audio
in, it's the same thing. Just add a stream
player and load in the what are they all MP
threes or some waves vv? Files. Yes, the two P threes
and the files. So you can go ahead and
use those the exact same as the two D. Just add
an audio stream player into your main scene
and the background and your main theme
for the background music is sent it to autoplay. And for your player, you
can go ahead and just add an audio stream
in there and load the audio sources and play as you need it from
squish, punk and all that. Exactly the same as it
is with the two D. So if you want to add that you forgot, you can head back up there. Week three, take a look. But I think that'll wrap
it up for this week. We now have a three D version of our little Frogger game here, so we can hop across
the little road and get to our little wind zone, hop through our
little platforms, and hopefully not get
squished by the trucks.
58. What is an API: Alright. Hello,
everyone. And today, we're going to embark
on the exciting journey into the world of APIs. If you've ever wondered how different
software applications will communicate and
exchange information, this is the perfect
place to start. Now, imagine you're at a restaurant and you want to
order your favorite dish. Well, in the world
of programming, this process is similar
to how APIs work. Let's dive in and explore this fascinating
concept together. Firstly, let's understand what an API or what API stands for. API stands for application
programming interface. Think of it as a
menu or a set of instructions that allows
two software systems to talk to each other
and share data. Just like you order a meal from a waiter and a waiter takes
a request to the kitchen, the API serves as the intermediary
that facilitates communication between
different software components. So to make this
concept even clearer, we're going to use the
restaurant analogy, which you see on
the screen here. So you, the customer, represent the
software application, and the kitchen
represents another. Now, this could be your
own tool that you make, and you want the
other application, the kitchen, maybe
being Spotify, for example, or Twitter or
maybe an Aime database, something that you want to talk to and get information from. Well, you want to order
a delicious meal, get the information, but you don't have access to
the kitchen directly. So instead, you
communicate your order to the waiter who acts as
the API in this scenario. The waiter understands
your order, takes it to the kitchen, the other software
application on your behalf. The kitchen prepares
your meal according to your request and gives
it back to the waiter. The waiter acting as the API, then brings a freshly
prepared dish back to you. In the world of programming, APIs work in a similar fashion. They define a set of
rules and protocols that allow different
software applications to request and exchange
data seamlessly. APIs can be used to access
data from web servers, integrate third party services, or even interact with
hardware devices. So let's say you walk in
to a restaurant, right? You sit down at the
computer, what you're doing. You're using your application, and then you tell the waiter or the API what you want by
formatting the data correctly. The API or the Witter
then goes back to the third party
software application, database, whatever it may be, gets that information and
then brings it back to you. So then you have the information
to do with as you will. So in summary, APIs are
like intermediaries that facilitate communication between different
software systems. Just like a waiter takes order to the kitchen and a restaurant, they allow applications to talk to each other, share data, and perform various tasks
without needing to understand each other's internal
workings. Alright. There you have it. A
quick introduction to APIs using the classic
restaurant analogy. I hope the analogy
helps you grasp the fundamental concept of APIs and their role in
software development. Remember, APIs are
powerful tools that enable seamless integration
and collaboration between various
software components.
59. How to Use an API: All right, everyone. Hey, we're going to take a look at where to get an API, as well as how it
is if we can use them and specifically the
one that we're going to use in our code example to
help with learning, it's going to be the
open weather API here. So if you go ahead and come
over here to open weather, you can go ahead and
sign up for an account, and you might notice that you might have to come
to pricing and actually select a plan here, but they do have a free
plan that gives you 1 million calls a month,
60 calls a minute. And we're able to see the current weather and that's going to be the
more important thing here. Now, all this other information and all these calls and
everything, of course, you can always feel
free to do those, but those APIs are
pretty expensive. You do get a lot of features and a lot more calls per
minute and per month. Obviously, you're not really going to get anything
anywhere near that. Unless you have a publicly
released application that is quite popular. So for learning
and especially if it's one of your first applications that
you're putting out, the free tier is probably way more than enough than you're
ever going to need. So if you need to, go ahead
and subscribe to that. I already have mine, which, as you see,
it says, get APIK. Now, how is it we actually
use these APIs, though? Well, if we take a
look at the top, we see we have guide here. And click on that, give it a second for it too. There we go. We here. And it's interesting that
they called it Got here. Most places we'll call
it documentation. And this is where should
be where we can go ahead and use the come down here
and we take a look around, see if we can find the
exact second for using it. Specifically the open
weather torsion. By call. So here we go. So now we're on
the page here for the documentation specifically
for the weather here. And we can see the
product concept. We have our how to start, current forecast
on weather data. We have our API call here, which I see, we will need
an API key for this one. We have all the
parameters listed here, which ones are required,
what's optional. And then we have an example
of an API call here. And an example of the type
of response we would get. Now, when we get a
response like this, we're getting a JSON response. And if you look closely, we can see it's a lot
of key value pairs. So we can treat this response
and get information out of it the same way as if
it was a dictionary. And you can see
all the different information that we're
getting out of this. Which is a lot of info
for us to go through. So once you go ahead and
sign up for an account, you can go ahead head on up to your user in the top
right hand side, go to my API keys, and sure to see a key there. If not, you can go
ahead and generate one and keep this
in mind or keep this page open because we are going to have to
come back here and grab your API key going forward. All right. So let's go ahead. One more thing I'll mention is, if you're looking for free APIs for you to use free
and open APIs, you can just do a simple
Google search and you'll find there's places that have full list of all
the different kinds that you or different kinds that there are with links
going out to all of them. So feel free to, of course, always practice and check
out some of the others, see how maybe one company's API operates a little
differently from another. But that's it for this one, we're going to go ahead and jump into Goto on the next one. Keep our API key up? Oh, I hide it a bit, so we don't really see it for
the majority of our code. And well, we'll
take it from there.
60. Script Setup: All right. Again,
you can go ahead and create a new
project if you'd like. I just created a new folder for the API and
websocket section here. And obviously, for
the stuff to run, we're going to need a scene of some sort to be running here. So I'll go ahead and
create a user interface, which of course is going
to give us some control for our start here, going to call this API
demo or you know what? This API. That's fine. Then I'm going to save it, keep the same name and
store it in my folder. I have a scene called API. And of course, this is
going to need a script. Now, the the actual scene here does not matter unless you want the user to be able to input information here,
such as, of course, a text box or a line edit
route, I should say, for the user to type in
the relevant information, and then maybe you
have a button that grabs all the text
out of those boxes. But for the most part, we don't really need
anything in there, but we are going to need one more piece to
this scene here, that's going to be
an HTTP request, so we can add one of
those into our scene. I and an HTTP request is actually what's
going to allow us to make a call to an API, to a website or web
service of some sort. And then once that
gets completed, some information gets
sent back to us, and based on that info, we can use we can either parse that out to get the data
that we're looking for, or we can take that information and maybe assign it to
some variables to send out another request to
a different section because some APIs will require extra data in the form of something called
headers but for this, with this being a simple API, it's not too difficult
to follow along. All we have to do is
make the one request, and we'll get the
JSON data back. All right, so on our APM, I'm going to go ahead
and add a script. And we're going to have
some variables here. So variable, I'm going
to have the API key, which I will say
that you should have your API key. It
should be hidden. It should be never
uploaded anywhere. This is something that
you should keep as secret and as hidden
as much as possible. So API key, that's just
going to be a string. And you can get that
again from the website. I can just copy and then you can go ahead
and just paste it in there. Now, you can see this one. It's either going to be
blurred for the video or I can just disable it
so it no longer works. After recording this, so it's not that big of
a deal right now, but just keep that in mind, this is something
that you should keep as secret as possible. Okay, what other information
are we going to need? Well, if we go back and take a look at the
data, sorry this one. Let's see what's required.
We're going to need a lot, so a latitude and a longitude. App ID, that's going to be
our API key. We have that. Exclude is optional, and
everything else is option. Okay, so we can just put it in latitude and longitude for this. All we're doing is looking at the documentation
for this Davar Long, and that's going to be float and we're also going to need one for
lap, sauce float. And these are the minimum pieces of information that
we're going to need. Now, if we were to take
a look at the API call, how we would do this,
this, copy it over, trade another variable
here for the URL string, and there we go one
really long string. So we have HTTPS colon
slash slash gmther or this the example call
that we saw earlier. So you see we're going to have
the latitude put in here, the longitude here, exclude, we saw that that is
completely optional. And since we have no additional information
here right now, I'm just going to delete
that portion and app ID, which is where our API goes. Okay. So what we're going to
do is we're going to use a placeholder that
is a percent in a lowercase S. And
we're going to use that for getting rid of these curly braces
and what's inside. So we're going to have
the latitude, longitude, and API key, so that's three things that we
need to remember. So the first thing I want to do is we're going to need
a latitude and longitude, which for now, we can give
it a default zero, zero. And inside of our
ready function, in order to make this API call, we need to go ahead and
get our HTCP request, but we'll just call
this the setup portion. We'll split that the next one. So we'll go to our HTCPRquest and we're
actually going to connect the request completed
signal to the API. And you'll see we get a result, a response code, we get some headers, and
we get the body. The body is going to be
the important piece here. I'm just going to go
ahead and save that, close all the other tabs. Alright, so I'm going
to end this video here, so we can just split
this up here next. And the next video, we'll go
ahead or the next lecture. We're going to make
the actual API call, and we're going to parse
out the data that we get back so that we can actually
use it and see what we have.
61. Making API Calls: All right. So I do
want to make one note here is one we're looking
at was for one call. So the URL is
slightly different. It's api.weathermap.org
slash data. Then slash 2.5 slash
WE Question Mark. And then that's where we
have our parameters to Lat Long, and App ID. So it's slightly different
the URL here now. For this version, it did yell
at me when I was testing, but one call being having to subscribe to
a different service. So it's just a little weird trying to find the
documentation on this one, but we go ahead and we get
our HTTP request node, and we call the
request function on. We pass in the URL, and in order to fill
in those placeholders, we do a percent sign. And then we have a pair
of square brackets just like an array, and we pass in our
variables lat, on, and our API key. Now, you'll notice if we try to just print
out the body here, that well, we have
a lot of data here. None of it really
makes any sense to us, but we're getting something
back, which is great. Now, generally, you'd
probably want to make an F check here with a response code to make sure that what's being returned back that we're not
having any errors. So if we just print
out the response code, you see we get code 200, which means that
everything has gone fine to go through it. Now, if we got a 400 error, then, well, I just spoiled
there, it's an error. So that means something went wrong, something's not working. The data didn't come
back, the service is down on their end, the request is not
formatted correctly, incorrect information, whatever
it is, there is an error. So we could check if response code is 200
just to be safe. If response code
equals 200, right? So we can say if
everything went well, now, how do we actually
get this data? Because we saw it
it was an array, but an array of just a
bunch of random numbers. Well, we have to parse that out. So the first thing we're
going to do is create a new variable for our response, and that gets set to our body, but we want to get
the data from. So we say dot and if
we type UTF eight, we'll see it string from UTF eight with an underscoring
between each of them. So now if we go
ahead and print out our response, let's
see what happens. Okay, well, we have information. However, in many cases, you are going to take the
extra step here, Anine. I'll just create my
temporary variable here, TD for temporary data. And for this, we call
our JSON parse string, and we can pass our
response into there. And now let's take
a look at what we get back after we've parsed
out parse the string. There you go, something
that's a little easier to look at spaced
out a little better. We have comas in
between, everything. It's it's nicer to see, but it could always make it even nicer to really want
to just looking at things. But at the base right now, TD now represents all of our information that
we need or would need. Right. If that was hard for
you to see to read, I get it. That's fine, but we can
pretty it up a little bit just to make it
easier for us to look at. And here we just
go ahead and call the JCN class and we can
call the methicon stringify, pass in our data, TD and a second argument of a string that only
contains a space. And if we were to look
at the output now, everything's going to be a
lot easier to follow read. So if that's what
you need, fantastic. That's how you can make it
nice and clean. All right. So now we would know
that if we come in here, we could print out TD and we can get a piece of
information out of here, such as see Maine is
what we're looking for. So we can get Maine
and print that out. And we see down here, if
I just comment that out, comment the line with Control K so we can not you
confuse the old information. We can see here's
the temperature. Here's what it feels like. Tempman Max, the pressure, humidity, sea level,
and ground level. Now, I mentioned before that we need latitude and longitude. So a place that we
can go for that, if I just go back to the
display capture here. Is this website here
called latlondt net. And as you can see, you can just click anywhere in the world and you'll get a latitude
and longitude position. So for example, if we
were to come down, I'm going to go with
Vancouver here, and I'm just going to
click in there. We've got 409-25-6791. Just going to go ahead and
copy that over and set that to my operation here. So first is at. They side
in and my longitude here. Makes s. So you can
go ahead and get anywhere in the world here, get your latitude and longitude. As you see, you
can also just type a place here and it
should pop up for you. Alright. So with this
information put in, let's go ahead and run this. See what we get now temp
288.11 feels like 288.14. Now, obviously, these
numbers seem pretty high. So the question would
then be, why would that? Well, this is where comes into play with the data
that we're getting. Here you go. I just
brought us on down to the fields in our ATI response
here on the documentation. I scroll in here, we can see where are we at here? Dot right here. So the temperature
inside of Maine, the unit default is Kelvin. So that is why it is so high for us for the number that we're seeing at 200
and something degrees. Remember, optional,
you had the option of putting in metric or imperial inside of our optional if
we go to units here, right? You see we can put in
standard metric imperial. And standard units will
be applied by default. So standard would be our Kelvin, and then we have our
Mexican imperial, right? So how would we add these
in for information? Well, we simply just
as you see here, if we follow the pattern, we just have the ampersand, parameter equals, and then
whatever we're looking for. So if we want to add in units, then we should just have to
do ampersand units equals, and I believe it is a
spring that it takes. So let's go ahead
and hop back over. And let's add units or units. And like I said, I believe that's just
going to be a spring. And for us, let's
go to something like could go to Celsius. And I think that's what I'm going to go for.
It's not Celsius. We need to go with
Mexico or Imperial. Let's go ahead and go
ahead and type in metric. And I'm just getting that
from looking at the API. I see a metric in all
lowercase, as well as Tempio, so I'm assuming this
is all lowercase. So we need to add
that into our URL. So I'm going to go ahead
and after my longitude, but before my app ID, I'm going to put
Ampersand unit equals. And then we'll have our
placeholder here again. Now in my request, we
have latitude, longitude, and before the API key, I can pass in units. And if we were to take
a look at it now, you see we get back 14.85. And same thing if we were to replace metric with imperial, we should now get the
Fahrenheit equivalent 58.44. All right. So that's how we can
get this information. And now you can set the text of, say, a label on screen, or you can have
different images inside of your application
and you can change or display the image based off what kind of weather
it is, right? So we can see the temperature, the pressure, the humidity. But remember, that's
all that's not all the information
that we have, right? We can take a look at the temperature is
weather dot Main? I might have this
wrong, hopefully not, but if so, I guess we're going to get an error in our print. Yeah, we got an error in there. I'm just going to take a look at uncomment my string of fine information so I
can take a look at it. Wind, weather. Okay, so it looks like
it's just weather. No main. So TD and I'll grab the weather
attribute out of that. Clean that up. And actually, the ID
is 81 main clouds. Description, few clouds. So you see now we can see, okay? The main weather here is considered clouds, so
that would be cloudy. So now I could display maybe a cloudy image on the screen to go with that or change the background of the
app to be cloudy. As you can see, there is an icon here as well in this data. I'm not sure where this
icon is coming from. But if you knew where and they gave you a link or an ID
or something for an image, it is possible for
you to go through and fetch that image
from the Internet, so you could use that,
which would be more ideal. But again, I don't know where
this icon is coming from. So I'm not 100% sure of where to bind dynamo gar to do that. But that's the basics there making these
simple API requests. And some requests will get more complicated than
that and will require you to really sit down and
look through documentation that they may require authorization, certain
permissions granted. You might have to wait for
the user to authenticate. You might have to
have a bunch of information that are put
inside of your headers, which the headers would
come after the request. So we have the URL here. We would just have comma and
then our custom headers, which would be in the form
of, I believe, an array. That you could pass
in, and then we can get other information like G, post the method that
we want to use. And G is simply the default, which is
what we're doing here. We're asking the API for
information from the database, and post would be like sending information
to the database, such as a leaderboard,
for example, if you have some kind
of leaderboard setup where you work with an API, then you could push
information there using the post post method instead
of the default get here. But there you go.
There's how we make these This is essentially the
core of making an API call. Anything past this
is just a matter of making calls to get information for you to use as headers in order to get
the data that you want. But at the CR VIT, this
is what you'll be doing. And if it's simple,
this is all you need. If it's more complex,
such as Twitch, for example, you're gonna have to go through
the documentation, but Twitch's documentation
is not that great. So you're probably going
to have a headache and give yourself
problems trying to go through Twitch's
documentation phases. But there you have it. There's the basics of
how we make API calls.
62. RapidAPI Python to GDScript: All right, everyone. You can ignore the error that's
on screen there. That's just because the
variables don't exist yet. But I wanted to talk about
here and I'm going to be using I have a separate scene open for this. It's
identical to the first. It just has a dk script, and this is going to be going
into an anime database. I pick this one just
because anime popular. So as popular as Anime is and the amount
of shows out there. If you guys are watching, probably a good
chance that you like anime or you've at least given
it a shot at some point. But this is the actual
topic here is relevant? It just happens to be what
I'm using here as my example. Now, what I want to
talk to you about is using APIs online and
when you're looking around, because you're not going
to find anything for Goto or GD script. The closest thing
you're going to find is something like Python, which is pretty close. So I'm going to show
you how we can take the Python example that it gives us and use it in GDScript. Now, what we're using
here is from rapid API. And Rapid API has a lot of free APIs out there
that are well, both free. This one, as you
see, is premium. So if we go to pricing, we
have multiple options here. The basic is free, which
is what I'm using here. And you see I can
make 100 requests a day and only two
requests per second. So these obviously
wouldn't be that great for a deployed application because you might get more than
two requests per second, and if you start getting any popularity or you
have a really heavy user, you could easily surpass
that 100 per day. So obviously, up there, if
you're going to do something and pass it or it's
going to be passed out. And, you know, the $5 or $10. Seemed like some
pretty good plans. So $10 completely unlimited, and the $5 is 5,000 a day. But you notice we
don't have any you don't have a limit on how
many requests per second. I also pick this one
because the latency is only 591 milliseconds, that's approximately
five or 6 seconds from making the request to
when we get our databa. Popularity, 9.8 out of ten, so it's a very popular one. It was updated two months ago, so it's still kept up. Service levels been 100%. So there's a lot of
reason as to why this API makes a good one
for our example here. All right. So all you can do is just go up to the Rapid API, sign up for an account,
and you can come in and just make a search for
whatever you're looking for. In my case, again, I come
up and I search anime, and then we have all
these APIs here. Some of them might
be mandatory money, some may be completely free, and some might be premium, like I showed you
with the other one. Now, the first result here
is the one that we're using, and we see if I help
role but we can get information by ID. We can get all, we
can get genres. So there's a few
things that we can do and this one here
called A Animation, we can get something
about a gift or GF, however you want to
pronounce it, an image, which information it's
not too much for us. In this case, it starts going
a little past scope here, but you can see, they're
not all the same. They all offer different
services here. That's what you
can get ahold of. And see, as I'm popping up, some of these say
premium, some say free. You might get a premium
somewhere where it's paid only, I don't know, but it's
not looking like it. It looks like these are all
either free or premium, at least on the first pagier. So I'm just going
to go ahead and click on one just to
show you an example. So once you decide
what you want to do, what you want to get, you'll
notice on the right side, these are all the
things that we can use. So let's say we wanted
random wallpaper. We would click that and we
would get our information on the side here
with our example. And you can't really
see any of that. So I'm going to
readjust this now. So one moment. For now, that'll do for us. But you see on the
right hand side, these are all the
different I guess can say services or information that you can get out of their API. And just by clicking on one, you see the information changing on the right hand side
as well as middle. So that's essentially how
these are going to work. And you can see these
ones are all get, but some of them might be a post depending on
what you're trying to do. And that's the method that I mentioned at
the end of last video, where a lot of times we're going to use get
to get information, but there may be
occasions where you have to post and push information. And if you decide this
is one that you want, you just go ahead and hit the subscribe to test button here. And that should bring you to the pricing phase pricing page. You can also just come
to here and you can select which plan that
you want to subscribe to. And these all have a hard
limit here, as we can see. And you want to be careful. Some of them aren't a hard
limit, as you can see here, in the case of this one,
you're going to be charged, which will go to your account, you get charged that
you have to pay. This 1.5 cents for each other. Each additional request, right? That fall in line with that
one and $0.03 on this one. And that's of course on mega. These obviously go up higher, as you go, but the basic
plan only has a hard limit. So just be aware of
that some do have or do extend past a certain limit at the cost of you
actually paying them, even though it might
be a free plan. Alright, we're going
to jump to Whoops, that's the rapid API.
We don't want that one. Just gonna go back here. Go back into the anime
DB that we're using. And I'll just reposition
this better for us. So, just for this, I'm gonna be using get all
on the right hand side, or sorry, the left
hand side here. So that's the one
I'm gonna be using. I'm now going to just slide
the screen over so see things better for our use. There we go. All right. So for this, what
we're going to use, and I said Python. And specifically,
if we open this up, we can see examples for all
these different languages. And Python is the
one that we want. And we'll be looking
at the HTTB client as well as the request library. Now, in Python, you can do
this either way, but for us, we need to do this kind of looking at both versions,
to give us an idea. And you see here,
we have headers. I'm just going to copy
the headers out of there. And if we go right
back to Goto here, we can go ahead and create
our variable headers. Now, theirs has curly braces
and it's a dictionary. Ours has to be an
array for our headers. Those are square brackets. I'm just going to paste that in. Now we're going
to have an error. Simply because well, we
have key value pairs. That's not how a an array works. What I'm going to do is I'm
going to go in the middle, highlight this quote, the colon space and
the other quote here. And I'm just going
to put in delete that colon space there. So we're basically removing the quotation marks around it, making them one single string. And you see at the end by
devolve, you copy both of them. We've got that separated
by a comma already, and we're going to do the same
thing here in the middle. Delete, coal in in space. So we have two pieces
of strings here, and that's going
to be our headers. And I got that from the you should be able
to get that from either the request or
HTTP client from Python. They'll both be exactly the same here for this piece
of information. And I'm going to go ahead and
just zoom this in further, just because this is the only piece of
information that we should really be
focusing on here. Alright. So again, the headers here. I went ahead and just copy
the information here. And this is essentially
the as it says here, our host and API key. That we're going to use
specifically for rapid API here. And this is going
to change per my brain's having a pause in it
there per database, per API. So this is always
going to be different. Now, the URL that we want, well, we can see connections
animated db.p.rapidpi.com. And then in their request, we have this whole
big thing here. Well, that's not
going to do for us. So let's just drop down
and go to Python Quest, and this is going
to be our base URL. If we just copy that and
take a look back here. We can create var URL. And that is our base URL. Now, I said we're
going to use get all, and that's where this
last variable comes from. Just creating that there. And this is where you have to
be a little observant when combining things
because you could merge everything into one URL, and then you can have a
merger of the get all go around the genre to
go around, et cetera, but what I'm going to do
here is we're going to go we're going to
head back over here, and we can see this
ends with slash N, rapid api.com slash anime. So we need to keep that in mind. We're going to go back
to Python HTTP client. And we can see down
here at the bottom, we have slash anime,
question mark, page one, et cetera, right? So we're going to ignore the slash anime and grab
everything after that. And we're going to
jump back over to Goto. And there we go. Then we can see the searches, full metal, genre, fantasy, sort five ranking, sort order ascending, there
we go. We have all that. So now we can just
merge our base URL with whatever we have here. So as another example, if I were to come down
to the G one anime. G one anime, by
ranking. All right. And I jump back here
just to show you here, and I go to HTV client. Wills anime, but
then right here, B Ranking slash one. This would be as an example. Read another variable here. Right? We'll say get ranking. That's a string. And
we could do that. So now we can just swap
this out with get ranking, we want or put back in. So that's why I like
separating here then I can just change specifically
what I want there. And of course, if
you were going to implement search results and
things like that in here, I see search here, the
genre and all that. You can put that in as
placeholders like we did in back here with
the weather, right. With this, we have
that, and then we can see what is it that
we need to get? Well, if we take a look, it's going to go back to
the get all here. If we look down here
in HTTP client, we see G response, and we're looking at all
this, and we see down here, all they're doing
is decoding UTF h. So that's all hoops. All they're doing is
they're decoding UTF eight. So that should be all we
have to do for this API. Now, if you're working
with a different API, you might have to do
the full JSON parsing, like we did on the open weather. So here, we just have our response and all we're doing is we're getting the
string from UTF H. Now, if we print
the response here, we run this, and remember,
we're getting all. We got to wait a couple of
seconds. And here we go. We have a whole list, so we can see comedy fantasy episode 16 that does have the
episode ranking true. We can see the
image here to WebP. We have a link that
goes directly to it. So you could take that link and provide that
link to your users. If that's what you want, but
you can see everything is in here as their data. And we can access all
of this individually. And just to show you that we have curly braces
here at the beginning. If we come in here,
we just get data, it's coming through as right. So we would have to
find a way to actually sort through the information
that we're looking for. So in this case, since we're not
getting Jason back, that's a little
annoying, I suppose. But as you see here, since we
need to go the extra step, even though the API or the page, told us all we have to do is
parse the UTFA. That's fine. But since we want to
get the extra data, went ahead and parse the
string using the JCN class. And as you can see, now
I can get that data, the first item of it because
data was an array of items. And then I can grab the
title of that first one, which is, I believe would be
the first episode, right? At least the result. And if we change this to the second item, we should get a different
name down there. Yeah. So we've got Brotherhood. I'm going to go to
the next. We have the conqueror of Shambala,
whatever that is. I've never seen this. But there you go. You see, it's not too difficult to work with this Python or converting the Python
example into it. So our arrays, we copied them in and put them in GD script here as an array
instead of a dictionary. We deleted the quotes
in the middle. So that our API key
is one long string, and our API host is
one long string. We switch back and forth between HTTP request and
http dot client and the request library for the
two Python options here in order to get our base URL here, as well as the
different searches here that we can
actually put in. And all we do in the request, we pass in our URL, and in this case, I'm
just going to add to plus my G A and the headers. Now, if you have more
than that, for example, if you have one where
it tells you that you need to push, right? You need to post instead of G. This is where these
defaults come in, right? So we can just come in HTTP client method under Square Post. Now, the default is G. That's why we don't
put anything in there. But if you ever need to post, instead of G, that's
how you would do it. You would just add it
in after the headers. Alright, so there you go. There's how to There's both a large collection of APIs that you can look to
work with, practice with. And if this is what
you want to do, provide things for your client. As well as how do you use their Python
examples and convert them so that we can
use them in GD script. So now you've gotten a wider collection that
you could work with. You now know how to
work with headers here. And I've shown you how
to do a post instead of G. Now this will air out
because we don't post. We get for these. Yeah? And that'll that
should round us out there for the API portion. And next, we'll
go ahead and jump into taking a look at
what web sockets are, why they're useful
and how we can use them and why we might
want to use them.
63. What are WebSockets(filled space): Hello, everyone.
Welcome. And today, we're going to talk about
what are web sockets? What are they? What
are they poor? Well, if you knew
the programming, which probably are here, you might have heard
this term before, but what exactly are they? What are websckets
and how do they work? Well, by the end of this lesson, you'll have hopefully a
self understanding of what web sockets are and the magic that they can
kind of provide to us. To put it simply,
web sockets are a communication protocol
that allows real time, bi direction data or bidirectional data
transfer between a web browser and a web server. You can think of it as a virtual persistent
connection that remains open enabling
instant communication between the two ends. To understand this better, let's imagine you're chatting with a friend on
a messaging app. When you send a message, your friend receives
it instantly, right? That's because the messaging
app has a similar concept. It establishes a
connection between your devices allowing for
real time communication. Now, how do web sockets work? Well, when a web page that supports web sockets is
loaded in your browser, it sends a special HTTP request to the server requesting to establish a web
socket connection. Once the server
approves the request, the persistent connection
is created and both the browser
and server can send data to each other in real time. The magic of web sockets lies in their ability to handle
two way communication. This means that not
only can the server send data to the
browser instantly, but the browser can also send data back to the
server in real time. It's like having a
live conversation between the browser
and the server. Web sockets are
incredibly useful for building applications that
require real time updates, such as live chats, online gaming, stock market
tickers, and once more. They eliminate the need for constant page,
refreshing, pulling, making your web applications more efficient and responsive. So if you need another kind of explanation to help
understand with this, you can think of it
as you think of it as two people meeting, possibly for the first
time, person A, the client, person B, server, they
meet, they shake hands. And they try to establish
a connection, right? They meet up, shake hands, and they determine from that point if they want
to keep this connection, and exchange information, have a conversation with each
other or to walk away. If they don't wish to talk, then the connection
we can say is closed, and they go their separate ways. However, if they decide to
continue their conversation, then the connection was
accepted between both members, both parties, and now they can exchange information
live in real time. Hopefully one of those
three Sho examples will help you with understanding exactly how it is
that they work. And though you have it, that's a simple introduction into
websocket is what they are, how they can be used. And they're an essential
tool when it comes to a lot of modern
programming, and again, this is going to really
depend on what kind of field, I would say that you want to go into with your
development skills. But they do help with enabling that real time communication between your application
and the server. And as you dive deeper
into programming, you'll find web sockets to be a powerful
and versatile tool. Create interactive and
engaging applications. But remember, they
don't only just work with servers that are
off somewhere else. There are some existing
applications that use websockets that you could create your own
tools to work with. We'll take a look at
that in the next video.
64. Establishing A Connection: All right, so let's go
ahead and take a look at how we would set up a web socket connection
with ourselves here and how we could
connect to something. And the thing we're
going to connect to is going to be OBS. Now, if you want, you can
go ahead and look for the websocket server plugin, the websocket plug
in for OBS Studio, if you want to follow along with this and just run
through the installer. I should only take
you a minute or two. And what you're going to see is if you go up to Tools on OBS, you should see a web socket
server settings option there. And by clicking that, you'll have this
window here Popo. Make sure you have
websocket server turned on. And all we need is we need a little bit of
information here. So if we go to
show Connect Info, Then what'll pop up is your
server's IP and the port. And the IP is the main thing that we want out
of this because we can already see the port
right here in this window. Now, down here at the bottom, you'll see when or however
many people connect to this. And as you see, you'll also have the option to kick
a user from here. So this is where
we're going to get our information from
just so you know. And again, we're going
to want the IP and the server ports right here. So you can go ahead and
take that information, remember it, have
it off to the side. And let's get started here. All right. So the first thing
we're need to do is I just have a control node here, my scene, nothing big to
something that we can run with. And I'm going to add a script to it and just call a websocket client.
Doesn't really matter. And now we're ready to
create this connection. Alright, so how do we do this? Well, we're going to we're
going to need a new socket, right, in order to get started. So we can create a
variable called socket. And this is equal to a
web socket peer dot no. We want to create
a new item, right? A new object, this web socket. And I'm going to go
ahead and put in the socket URL here as well. Just store that as a variable. Socket RL. And that's going to
be your IP address. But not just in any way. We're going to have WSS, ClonAS then our IP, and I can't paste it in, so I'll have to type it
100 dot zero dot 19. This one is I don't
know if it fails, then we'll take a look
at the other one. So inside of our ready, this is where we're going to
make our connection. So socket dot connect to URL, and we'll just pass
in our socket URL. Now, this can take
optional parameters, but we don't This is not a
thing for us to put in here. Next up, that gives us our
process function here. And the thing you're going
to need to do is whole. And what that is is
that's basically constantly you can think of it constantly as
exchanging a very, very tiny amount of information just to keep up the
connection on both sides. Otherwise, if
nothing is received, then the connection will be dropped and you'll
be disconnected from that web socket, right? You'll be disconnected
from that server. I and nobody likes that. All right, so now to use these, we need to decide what
we're going to do, and we can determine
that based off of the state that our socket is in. And the states that it get
lets us know if it's open, closing, it's closed, or
if it's still connecting. So let's go ahead
and store that. Bar state equals socket
dot get ready state. And now that state will be
able to tell us what it is. Now we can say if state
equals websocket here, t and here's all of our states. So we'll say state open. And I'm just going to
pass there for a moment. And we're going to create
our other ones here as well. We're going to say, s if state
is equal to state closing. And that leaves our
last one to be closed. Now, we could have one
for connecting as well, but there's no real point board. Now, when the state is closing, we don't have to
do anything here. We just got to make sure
that we're still polling at this point in order to
actually close properly. And let's see, Let's start. Let's go ahead and do
when our state is open. Well, here we're going
to have a wild loop, and this is where
we're going to get our packet information
that's being given to us. So we can say Wil socket
available Pack account. While there is data
being sent to us, right? So we have packets. We're going to go ahead
and we're just going to print out what this is, so we're going to say pack Base. And then for the
second argument, we're going to pass in whatever that packet is, right? Socket. Yeah. Packet. All right. And that's all we need
to do while it's open. Let's take a look down here where our socket will be closed. And bar information, we can
go ahead and do bar code, and that'll be able to
socket, get close code. This way, we can have
some information when we do get disconnected as to why or maybe our
connection fails. So it tries connecting, and then it just
immediately closes. We can again find out why so we can get some
information back to us. And speaking of reason, that's going to be
our next one here, that's going to be
socket Get close Reason. We can then go ahead and just
print out our options here. And this is just going to be
websocket closed with code, placeholder, reason,
placeholder, clean placeholder. Go. There you go. You can see it there, webs
closed, code, reason, clean. A one extra there on the end. And we're going to fill
those in with code, reason, and then code
not equals to minus one. All that leaves
us one last thing to do is to stop polling, and we can do that by just
calling set process false. So when you set that to
false, whatever is in here, this process function
is no longer going to run until you set it
back to true again. All right. So with this, we
should be able to connect to our we should be able to
connect to the OVS in there. So if we just We
do our window go? Think our window closed. Just go ahead and open that up. There it is. Alright, so I'm just going to go
ahead and hit Run here. But I'm going to
make sure that we can see this side when I do it. I'm just going to go
ahead and run that. Give it a second, and we
see we have no connection. Now, the serious
part is going to be as to why. Well,
let's take a look. Well, the reason it's not connecting is because we didn't do anything
with the port. Now, the port can be if you
make your own application, it could be pretty much
whatever you want. Just about as long as it's
not already being used. And the way we add a
port onto the end of our URL here is just a colon. And then the port that was available there
on the service setting, which is four, four,
five, five, save that. And if we look back
over here and run it, give it a second
here. There we go. We can see if we're connected. We can see how long
we're connected, messages in and out
identified has not been identified because we're
not using any passwords here and our information, and we have the
option of hitting it. Now, if we take a look
at the Goto side here, we can see here's our
packet of information. It looks like an
array of numbers, but it does have data in there. Trust me. We just can't
see exactly what it is. So we'll fix that here
in just a moment. And underneath that, you can see where when we kick the user, which will be our client here, we can see that
websocket closed, and it closed with code 40 11. The reason for session
has been invalidated. For the reason is our session
has been invalidated, and it was a clean
close, which is good. But how do we get
data out of all of this packet here,
packet of byte. Well, socket dot Get packet. This is in a pull by array. So we got this as
UTF eight format, so we need to get
the text out of it. So after we do socket
dot Get packet here, we're going to call Yet
string from UTF eight. And save it. And when
we go and run it again, when it connects, we can see we got the actual data
that was inside of it. So we can see the
version that we got and the RPC version. And that information that
we're using here that I got here with the current version of the server that I'm using. Yours might be
different because I'm assuming you're going
to get it brand new. I've had this installed
for quite a while now. I'm just going to go ahead
and stop running here. And you see we did not get
any kick message there. But if I run it here and
if I hit the kick button, you see, there's
our kick message. All right, so unfortunately, I can't really help
you past this point. Past how can you get
a connection here as getting information or sending information in a particular way is
going to be dependent on what you're connected to and
how they want their data, I guess you could
say structured, and how they send
data back to you, you may or may not have to get data in different
ways out of it, but going forward, which you can do is
if we hold control, we can click on websocket Peer. And if we come on down, we can see here's all of our
properties, our methods, and all our information
has to do with this specific thing here and how to use
everything in here. So you can go ahead,
you can run through, take a look at that and
I guess cross that with looking at documentation or whatever you're trying
to integrate with. And at that point, I guess it's kind of
like best of luck. I kind of sucks to say,
but we got you connected, it's up to you to read your
documentation and that to figure out how to exchange
that information.
65. Sending Data with WebSockets: Alright, so I have a
button and a line edit here added into my scene
just for some visuals here. And the button has
the press signal connected up to my
web socket client. And I'm going to show
you at least the idea of how to send, say, a message across
this websocket. Now, ours is well,
I'll show you. Fact you can see it down
there at the bottom, but we'll see it
here in a minute. So on the press, we're going to have a message
screen for this variable, and this is going to be
set to our line edit text. Text. Stop with the autofill. Stop it. So we have that. And now we need to
actually send this. Now, you could put this send portion into its own function, which would probably be a smart idea because
then you could just call send whenever
you need to send data. But this is how
we would send it. So we say sock it, put pack it, and then we have to
put in our message. However, we can't just put in our message like this.
That's not going to work. But we could come in
with our UTFA buffer, for example, and this
is going to encode it. So if we go ahead and run this, now this is still
connecting to OBS here. If we type in, say, hello, send, we can see our wipe socket was closed because the
encoding is sent to Jason, but binary message was received. So you can see we're sending
the wrong type of data. So this is where this
is where the type of information needs to be
or is based on your project. It's based on what
you're connected to and why you need to look
at documentation. Alternatively, doing
it this way is also JSON dot StringfiO message. And then we can encode
that to UTF eight, like so, and that's going to give us the same result
in this instance. Our socket is going to close. And of course, when
you're sending, you probably want to
make sure that the state is open state here.
But there you go. There's the idea of
how you would send data across this web socket. Now, like I said,
didn't really work. We were closed because we
sent the wrong type of data, so we lost our connection. But you're just going to have to read documentation
of whatever you're trying to connect and whatever program it is
you're trying to talk to. Right? So if you guys
have Python installed, feel free to take a look at this and
copy this code to make your own little web
socket server in Python to mess
around with things. But ultimately, we're using
Async and web sockets, of course, web sockets
would have to be imported. And all we're doing
here is we're creating an async function, and this is basically just
starting up our server for us, or sorry, down here, we'll
be starting our server. But up here inside
of our server, we're looking at four
message in web socket, so right, every time we
send a message here, our message is going to get
decoded from UTF eight. Whoops. And then we're going to print out
the message that we got from the client. So if this was, say, a chat app, then you would take this
and you would send it to whoever they're
talking to, right? Based off their ID or whatever. And here we wait a moment
and send the message back. We're sending the message
back to GOTO here just so we can take a look at it and we can see that we can both
send and receive data, right, back and forth. And then we're just starting the server on the local host, which in GoTo, if
you were unaware, the IP address
have a local host. It is 127.0 0.0 0.1. We're also using the
port 5,000 for this. That we're just printing
out to our console down at the bottom down here that
the server has started, and then our two loops here is basically just having our
server continuously run. All right. So if I were to
come on in and run this, we can see server started here. And I'm going to go
ahead and run this on the gatto side so we can
get that nice connection. Oh, and we can't see that
now because of that layer. That's fine. I'll just
lower it down for this. Okay. So there it is. And you'll see I'm going to go
ahead and type in here, say, hello, new person. Welcome to the chat. And I'm super excited. I'm going to hit my Send
button, and there you go. We can see message
from our client. So we can see that
we receive data on our web socket server over here. And if we hide this, we can see it on our GTO version here. The packet that we
got back, right, was a message that the
server sent to us saying, Got your message and repeated
back what our message was. So you can see this works, it's just a matter of having or formatting what
you're sending, right? You message that correctly based on whatever it is
you're connecting to. So you see this method here
works or this set up here works with a simple web socket
server and Python here, but this format does not work when connecting or
sending data to OBS. So that's where some of
that reading comes in, but I did want to show you I did want to show you the working
web sockets with a server. And you see what we have
here is our base set of creating a chat bot or creating a chat room that
we've done here already, just with our server and client. You just need to
differentiate which client is who and who they're
sending each message to. I mean, you kind of
got a chat set up, at least between a
server and client. But before I start
ambling on, there you go. There's some proof, I guess, you can say that sending
this data does work. It just depends on how it's formatted and what it is you're
connected to. All right. I'm going to put
that up there again. So if you want to pause the video and go ahead and copy that
out if you would like. And you have Python
installed on your computer. If you want to do this, and create your own
server, go for it. With that, take care have
yourselves a good one, and that's how we connect
and use websockets.
66. How is Desktop Development Different: All right, everyone
welcome back, and we're going
to be diving into the software development
section here. Now, what makes
software development different from
gaming development? Well, let's discuss that. Software development or
desktop applications involve creating programs that run directly on a
user's computer. These applications serve a
wide range of purposes from productivity tools
to creative software and everything in between. As a desktop
application developer, your focus will be on designing intuitive user interfaces and crafting efficient solutions
to meet users' needs. One of the primary differences between game development and desktop application
development lies in their intended purpose. While games are designed for entertainment
and interactivity, desktop applications
are built to solve a specific problem or
improve productivity. In the world of
software development, you'll encounter a diverse
range of applications, such as word processors, spreadsheet tools,
image editors, video players, and more. The possibilities are limitless, and you have the power
to create tools that can positively impact
people's lives. Additionally, as a desktop
application developer, you'll be able to work with different
programming languages. Some of these popular choices
would be Python or C SHARP, that you could use alongside
GDScrp to enhance or bring more features to
your application that you may not normally have. Obviously, this is optional, but the ability would
be there for you. Another key aspect of
software development for desktop applications is
the user experience. Unlike games where immersion and gameplay take center stage, desktop applications prioritize
usability and efficiency. You strive to create intuitive interfaces that make users' tasks simpler
and more enjoyable. Now, one thing that's
also going to be very important when it comes to software development is how
everything looks overall, the way you've presented
your application. If your application
looks like it was built back in the
days of Windows 95, then it's going to
look old, dated, and it's not going
to be attractive in comparison to
another application, even though yours
might be far superior. If it doesn't look as good, not as many people
are going to try it. It's just the unfortunate
reality of the world. Not only do you have to make a program that work
exceptionally well, it has to look good as well. So it won't hurt for you to take a user experience or user
interface kind of course as well to go alongside this
afterwards to enhance your user interface design
skills, if that makes sense. And that is, of course, only
if you choose to go down the software route
going forward. But there you have it
simple introduction to the software development
for desktop applications. As we dive deeper
into this section, we'll explore some of
our essential tools, I guess we can call them
while using TDScript here. And some of the things I
can help you with some of your design principles to help make a user friendly
desktop application.
67. Anchors: Hello, everyone. And before we get started with actually
creating anything, we need to talk about
anchors. What are anchors? Well, anchors are powerful
tools that help you create responsive and flexible
user interfaces for your games and
software applications. Anchors are effectively
used to adapt your UI element to different screen sizes
and aspect ratios. Let's dive into that. In Goto, anchors are
invisible tethers that attach UI elements to the edges of the parent
container or screen. They define how the UI element
should scale and position itself when the parent
container or screen resizes. This ensures that your
UI remains consistent and user friendly across various
devices and resolutions. To better understand anchors, let's imagine you
have a UI button on your game's main menu. You want the button to stay in the bottom right
corner of the screen, regardless of the screen
size or aspect ratio. To achieve this,
you would anchor the button's position to the bottom right corner of its parent container
or the screen. So to this, we would
grab our button, and these little green
pins are our anchors. So if we move them all to
the bottom right corner, and we were to take a
look at the scene here, no matter what size we make it, it's always going to remain in that bottom right
corner consistently, whereas if we left
it at its default, which would be in the
top right corner, sorry, top left corner. And we set that. And if
we were to run that now, you'll see it's staying in this position relative
to the top left corner, regardless of where
the bottom corner is. And as you can see, the bottom of it does not matter and we can completely remove it off the screen just by
making a small. However, if our anchors were in the top left
and bottom left, and we were to take
a look at that, it's going to remain
in that position, but it's also going to
stretch out on the bottom, because it's going
to be that close to the bottom and that close in the top towards
the other corner. And we can still,
of course, go past. So you can see how the anchors
can affect how your UI is going to look at
the end of the day. So if we wanted this in
the bottom right corner, we're going to put our
anchors in the bottom right. And now that part of our UI will always remain in that position
relative to that corner. Now, when you run the game on different devices or resize the window like
you're seeing there, the button will
automatically adjust its position based
on the anchors, ensuring it remains at the bottom right
corner at all times. Now, in goto, you can use the anchor presets to set the desired behavior
of UI elements. These presets include
top, left, right, bottom. Anchors are elements
at the specified edges of its parent
container or screen. Vertical center,
horizontal center, anchors the elements to the vertical or
horizontal center of its parent container
or the screen and fill our last option here, anchors the element to all
four edges causing it to stretch and scale with the
parent container or screen. So if you wanted,
say, an image to always fill in the
back, for example, if we came in and we
made a color rect here, and we filled up the screen. We come in. We have
this nice dark color. We have a dark brown here.
Maybe we want to go with a subtle dark green
for our background. And if we don't
touch the anchors, we leave everything default, and you can see we
have a problem here. However, if we use in this case, we can just use the preset to bull wreck to put our
pins in all four corners, we are now always going
to have our screen entirely covered with
this background. In our case, our color. So by using anchor presets
and customizing their values, you have full control over how your UI elements respond to changes in screen size
and aspect ratio. All right, there you
have an introduction to anchors in Gato. By leveraging the
power of anchors, you can create responsive and
adaptable user interfaces for your games and software. Now for games, of course,
this is usually only going to apply to your heads up display, ensuring a seamless
user experience across different devices.
68. Search Layout: All right. The first thing we're going
to do is we're going to create we're going to create our search bar first and what we're going
to be creating here. Is we're going to create our own little desktop application
that will allow us to search for an anime and it'll give us
a list of results. It'll have all the images for all the results for
each individual anime. I'll have the title.
I'll have the genres. And if we were to click
on one, it'll open up. It'll give us a synopsis. It'll have a bigger
version of the image. And if we want to take a look at, take a
look at it further, we could click on
an external link to take us that'll open up in
our default application, which would be your default
web browser if you're on PC. And open up the
anime page for it. And the first thing we're
going to do in this video here is we're going to
create the search bar and button sent you for it. But we're going to
start out with putting a background in here because this is kind
of boring, right? We open it up and we have
this boring, gray image. Here we go. We have
this boring gray box. It's not too exciting.
And even if we put, like, a line at
it in the middle, it's not gonna be
all that appealing. It looks kind of M, right? So the first thing I'm
going to do is I'm going to get my brand new scene here. Of course, I named it Main. It is a UI scene. So my root node is a control. And I'm going to go ahead and
add in a texture rect here. I'm going to rename
this as my background. And for the texture, I just went online and I found
an anime background because it's an anime
background would fit for Anime. So I just went ahead and
found one, brought it in. Now, that's obviously
way too big for my application here. So you'll notice if
we grab the handle, we can't change it, but we can make it bigger, but we
can't make it smaller. So I'm going to go
into the expand mode on the inspector on
the right hand side and change it from keep size to you could say ignore size, fit with portion, fit height. I'm just going to go with
Ignore size and shrink this down until it PS
covers all of our sides. Something like that. And then
I'm going to go ahead and set its anchors to bull
wreck. Here we go. That'll set. Now, that's going to be too bright for us to
display anything on. So I'm actually going to go into the visibility section
on Min Spector. I'm going to go
into the modulate. Actually, I'm going to go
self modulate on this one. In this case, it
wouldn't matter. But if you use modulate, it would also affect
all of its children, with this being the
background, it's not going to have any children. So it'll be fine, but if you want to just affect
this one node, you're just going to
use self modulate, and I'm just going to darken it down because mine's
pretty bright. I think something around
there will probably be good. So if I go ahead and run that all right? That is my window. That's not too bad. It's not too bright to take
anything away, even though we have a lot
of whites in my case. All right. So that's going
to be my background. Now, what about
the actual search? Well, the actual search,
we're actually going to stick that inside of a container. And this is going
to be put inside what's called a VBox container. And this is a vertical
container, right? So everything you put
inside of it is going to be placed are equally
spaced out vertically. So if I just go ahead and
I bring in a texture, let's say this texture
right here, right? Use this as an example. So as you see it, we're
just going to keep going like that in
the following way. So there you go. Now obviously, we're not going to have
all of those in there, but you get the idea here. And just to take a look here, if we had a control in there, that in there, it wouldn't
make any difference. All of these would
remain the same. I delete all those go. Now that's because our
control by default, has a size of zero. Put it under layouts. There
it is. It's transform. So you can see our Y sizes
completely zero in this case. And we can see that with our transform is
actually the bigger, so we can't have it control. So what we would do is have our own container
inside cert. So in our case, let's go ahead and although containers
could be nice, I think we're just
going to go with a Mrvust setup I suppose here. So let's go with a line
it for our SRT now, I can see that my
background really hides up, so I'm just going to
tweak this still. Darken a little more so my line at it actually
stands out a bit. Placeholder Text,
search anime here. And we'll go ahead and add
a button with that as well. And the text on this
will just say, sir. That a little wider. Here we go. Now, you can see we do
have gray on black. It's going to be. It's
a little hard to see. However, the only thing
we can really do about that at the moment
would be to go in the opposite direction and
go with a lighter approach, which is perfectly
fine if that's what you wanted to do, something
like that, maybe. Obviously, this is going to
depend on your background, but this is something that would be fixable when we get to the next section when we really talk about customizing
everything. So nothing looks very
default and everything looks a lot more
professional, I would say. Now as a little tip here
when it comes to doing UI, if you actually come
up to the top here, we have two magnets. One is going to be a snap here. As you see, we've got some
smart snapping going on, and the other one
is going to give us a nice grid that
we can snap along. And this is what's going to help with making things look nice. We see this goes all the
way up to middle there. Let's construct this to be in
relation to the center top. And I'll do the same thing
with my button here. A Okay. And now in relation to that, I obviously going to
be a little too high. How's that gonna feel? Let's see if I run
that. Take a look. Okay. I'm feeling that
though maybe I bring that in there and extend that out so we can fill out
our full box here. Then we bring our
search button down. As small as we can
go, so maybe we go like that with
one box in between. If we get something like that, I think that's fine for
what we're going with here. At least, in my opinion, I'm no UI or expert, but at least everything's
lined up with the grid. So we got a nice start going. Now, notice how my button and my line at it is also
the same height as well. That's just another thing
that's going to make it look a little more cohesive and give it the appearance of being nicer than maybe what it is. All right, so I'm going to
go ahead and name these, so I'm going to call
this my search bar, and this is going to be
my search button, right? That's going to take
up the top here. And is there anything else
for us to cover in this book? I'm going over search. I believe that's it,
and then we're going to have our search results. We'll do our search results in a separate video. All right. So there's our basic search. We can now come in and start typing things
in. We got one. Attack on Titan
is a popular one, and we can hit our
search button. Now obviously, it doesn't
do anything right now. But you get the idea, right? Now, just make sure
this looks nice. So we know where the
center line is right here. S one, two, three, four, that way, one, two, three, four, so you notice that. We're four blocks
out to the left, as well as four blocks
out to the right, so we kind of keep that balance going on in the imagery as well. Thought I'd mentioned
that as well real quick. So we do have expanding
out from the same size, so we are staying
relatively balanced. And aside from this empty space, we're pretty balanced visually
on both ends. All right. That's it for the search. In the next video, we'll
go ahead and set up the section to show our results.
69. Results Layout: Alright, we're going
to go ahead and set up our search result area. And I just want to note
here something afters. We're going to have an option
button in here as well. And this is going to be for our genres that we'll have
a drop down selection for. And I'm going to go ahead and
rename my option button to genre Optas and you'll notice
that I just move my search, my button out to the right more and line at it to the
left a little more, and I've got to set the anchors for my
option button here. I believe that was centered. It's like so. Now we can
come in and I can resize this and be good. Test. Now if we want, we
can go ahead and get completely based across the top. That would
be fine, too. All right. So let's go ahead and set up our results section. So for that, I'm going
to go ahead and add in a scroll container here. And what this is going
to do is going to allow us to or allow us to be able to use our mouse wheel and have that scroll bar on
the side like we see here. Right? And that's going to be whenever we have
something inside goes, extends longer or wider than
the box we are using here. So, for us, I think
we'll be fine at that, and that's going to be
too ours out. There. Now, even this I think
is going to be a little too much for the info that
we're going to have here. But who knows? Maybe we can make it work. So I'm going to rename
my scroll container to be salts Container. All right, so with
our scroll container, we can see that we have
this little triangle here. And if we were to
hove our mouse over, it's just going to tell us
that a scroll container is intended to work with a
single child control. This would be like a V box
or an H box, et cetera. In our case, we're
going to use a V box. So it's going to be a
vertical box container. And that'll allow us to keep
adding items vertically, and we'll be able to scroll straight down
when we exceed it. So we're going to do we will add that VBox container here. And we can't really do
anything from there. So what we'll do is we'll
head into a new scene. I'm going to select
other node here so I can create an H box
container as my roof. I'm going to create two blocks I and let's see, two or six. We'll just go six wide for now. Now, this is all going to
depend on how you want to sort yours, of course. Now my alignment is going
to be from the beginning, which means going to
start from the left and pile out pile
out to the right. If we start on the end, then our items will
start from the end. So see once I add a
texture rect in here, I'm going to give it the
goto icon as a default. So you see starting from the end, it'll
start from that side. Start from the
beginning. I'll start from the left and
start from the center. I'll build out from the middle. All right, so I'm
just going to use it to start from the beginning. That way, our image of our anime is always
going to be on the left. And this is going to
be anime thumbnail, anime Image, Anime image. Call this anime result, I suppose, from my container. And now I want to have I think directly beside
the image here. I think we want to
have the title on top, and then directly below that, have all of our genres. So if we go ahead and do that, we're obviously going to
need a V box because we need to take up one slot
inside of our H box, right? Otherwise, you can
come in and we can add some text here and
we add another label, it's going to be directly
beside it like that. But we want it directly
underneath it, right? We want to go vertical. So if I just leave it that, for example, and add the box in, you see when we add these two
labels inside of that VBox, it becomes a vertical
stack like that. Right? So we're
going to do that. But we're going to
set the alignment here to be in the center. And we'll set the first
label will be anime title. Second label will be if I
can rename it, Anime genres. And we'll just call this
container Anime Info. Now, I don't like how close
this is to that area, so I'm going to go
up to my H box here. And inside of the inspector, I'll go to the Mvides Constance. Check the separation box, and I can add a custom
amount here. 20 pixels. 30 pixels, who knows, right? It's going to be completely up to you taking a look at it, testing, and seeing
what it is you like. I'm just going to leave
it on 30 for now. And I'll save my scene
Anime result. That's fine. Now when I go back
to the main scene to our results container, click on the VBox container. Now when I come in
and I can instant in my anime result and you'll see if I use Control D and just duplicate it through. We get a whole bunch
there. And when we run it, it is what it would look
like, and we can scroll down through all of our results thanks to the scroll container. All right. Now, just like the eighth box, how we can have a custom
separation there. We can have a custom separation
with our V box as well. However, I don't want
to touch that until after we get our thumbnails
and that in there, and then maybe I'll
come back and tweak it. But with that, we have
our results screen setup. All we have to do is just
instance a result for every result that we have
and fill in its information. So for now, go to select
all my results here, and I'll just delete. Okay. And that'll do it
for this portion. Next up, we take a look at actually making a
search in order to make a cert we might fill out our ondas as
well in the next one.
70. Making A Search: Oh, boy. Alright, let's go ahead and take a
look at our results. Now, for the results, we're going to use
that anime database. If you go back and take a look
at the API section when we talk about rapid API and how to convert from Python
to GD script, we're going to use
that database. And as such, I've just copied
the code from that lecture. So you didn't do that, or you need to go back and take a look to
remember how to do it or to see what database
it is, go ahead and do that. Get yourself set up. I'm
just going to put a script on my main node here. A and I'm just going to paste
in all of my variables. So we have our headers that
we looked at. How to set up. I have my base URL here, and I have my three gets here, right? It allowed us to get. I think it allows us
four different ones, we got, two of them,
three of them, sorry. We have get all, get
genres and ranking. Now, I think we're only going to need get all for this
rather than get genres. But who knows, maybe? Maybe we can Oh, no, we're going to need our get
genres in order to fill out our drop down menu. So I think ranking is the
one we're not going to need. We're just going to get
all and get genres. I'm going to get rid
of the ranking one. And then we have our search
or search bar text here, our genre that we're
going to be searching, and EXT stands for the extension of the image
that we're going to be getting now let's see what else are we
going to need here? We need anything
else by default? I don't think we
need anything by. So let's go ahead and I guess, the first thing we're going
to do is get our genres and fill up our option button. Let's do that. We're going to need
an HTTP request. So I'll add one to the scene. And I'm going to name
this my genre request. Just like that. And as well with
that, I'm going to go ahead and connect
my signal for that, the request completed
signal into my main Script here,
delete process. We don't need that. So now in our writy
function here, I can go ahead and I can
get our genre request, and we can make that
HTTP request, right? And that's going to be our
URL plus our et genres. And we can pass in our headers
as the second argument. Now, when we get that data back, remember, we need to
parse through it, so we're going to say, we're going to create a new
variable called response. We're going to set
that equal to body, string from TFight and we'll see what
happens if we just print the response, and
see what we get back. Okay. So we can see all of these individual little
dictaries of one key one value, and it seems that all of our genres are values of
the key underscore ID. Okay? So inside of
our response here, we need to actually have
this Jsonified right, because we just have
one long string at the moment by technical. So we can call this our genres, if I can spell, JSON string and put in our spot, right? No error is good. And now
we can come in and we could print say response. We can say four genre and genres print genre, and we want we want remember
the key for underscore, lowercase I, lowercase D.
So if we play this now, we should have all
of our genres. There we go all printed
out for us here, Award winning action suspense
for Etti Avant garde, sports, supernatural fantasy,
gourmet, drama, comedy. We get it. So we can see
all of the genres here now. Fantastic. So now we need
to actually add these into the options menu
that we have, right? Or genre auctions. So we have printed them out. What we need to do is add them. They'll say genre, auction we need to actually
get ahold of that. Genre Options. At item. And now we're going
to add is that genre ID that we're printing out. And now we play it now, we can take a look, and
there's all of our items. Now, we see this is a little
bigger than what it was. So it's kind of bumping
into our search bar there. So in this case, I might
want to take a look at it and then maybe slide it over now that
I know how big it is. How to find a balance
somewhere in there. Does that look I think
that looks good. When we're actually in
side of our project now. Here we go. Now we have all of
our options here. Always take a look at these at all of our
options. Fantastic. So we have our genre set, and we're able to type
in what we want there. Now, we want to have a
noun octen at the top. So I'm actually going to add an item before we even start. So in the ready, and I'm
just going to set this to. Non I like that. And that should automatically
be selected by default. I'm not mistaken? Yes. There you go. And instead of none,
if you wanted to, you could make it select
genre if you wanted. The point is, if we
have that selected, then we're not going to be
introducing any genres, right? It's going to be empty in
our search. But there we go. We have the genre portion filled out and ready to
create our searches. And now we need
the actual search to get all our
information, right? And you can see here,
I'm getting one page, but my size is 1,000
items per page. So that could be more than enough to fill out any of these. So we're going to use get all
in our next request here. So let's go ahead and add
one more PTP request here. And this is going to be our
call this the anime search. And we'll also connect that
request completed signal. And just like the top two here, we're going to parse the body, right, get the string from UTFA and then we have a variable, not genres, but this animes. And we'll have a list of
all of our animes now. So if we were to
print these out, and we go to I guess we can do this
hypothetically for now. Actually, we'll
set up our button. So far our search button
when it gets pressed, connect that press signal. And this is where our request So we'll get our
anime search quest, and we would have URL plus G all and pass in our
headers second argument. And before that, we need to actually fill
some of the cell. Our genres, if we have
any, we need to fill in. You do have them built there.
Okay. So we'll say get all. Then I'm actually going to put parentheses around the
or get all variable because inside of here is where we're going to add
placeholders, right? So percent and then a
pair of square brackets. And that goes into search
for the first one, placeholder and genre or
genres for the second. All right, so let's go with
what do we have to get? We have to get our search text. So our search text is
going to be whatever is inside of our search bar. So we're going to say search
equals our search bar, text. And then we'll clear
out our search bar. Or actually, we don't
need to in this case, since we're doing an
actual search search. And we'll make sure if search is not equal
to an empty string. That way you have to
make an actual search, and this way we actually get
results back no matter what. It doesn't matter if
we have no genre. It only matters if
we have a search. Now, we don't have the
genre parts set up, but let's go ahead and make sure that we can
get results here. So we'll come in here and we'll
say tack on Titan search. And there we go. We have
a lot of information, and as you see, output
overflow, print less text. So we have way more information than the output
wants to allow us, which is perfectly fine. But we can see the
important thing is, we can get we see all this information from our search so we know our
search is at least working. All right. So what
about our options here? Well, for genre options, we select our option menu. We're going to connect
the signal item selected. Connect that to our
main script here. And we're going to create
a temporary variable here. And we're going to
call this genre text, and then is equal to genre
options, our option bar. Yet, item text, and we pass in the index that is
automatically passed into our function with
our signal, right? So we get our index.
When we click on something from our
drop down bar, we're going to get the
text of that item, and that's going to be set
to our genre text here. And now we're going
to say, simply put, we can just use a
match here if we want. Say match genre text. And if it matches
whatever we put up talk, which we're using select genre. Now, if you're using none, then you would put
none in there. If it matches that, then the genres equal
an empty string. And we'll use this underscore
to act as a wildcard. So if it's not select genres, then we'll just say genres
equals the genre text. Right. Now, if we want to test this, we can go ahead and
back out there and just print genres every time
we select a new option. So we'll see down in our
output every time we select something,
sports, comedy. So we see this is
all working fine. And if we select select
genre right here at the top, nothing gets prnted
out because it's an empty string.
So there you go. We have our genres working, and we have our search text Now, the last thing we need
to do when we get our result is we need to know how many
results that we have. And based off of that, we can add our result items, right? So if we come in here,
we put a search in here. Actually, I want to make this a little bit
nicer to look at. So I'm going to use
JSON Spring Pi animes. This way would be a little easier to tell what
we're looking at. I'll do attack on Titan
again, do a search, and Yeah, I'm not
printing it out. There we go. All right, so I tack on Titan so I can get a better view of what
we're looking at here. That is not how I wanted that we'd all the
way up to the top. So we see everything's
going to be inside of data. Okay. So we're going to print animes and go into the data section. And we'll check that. Back
on Titan, form a search. And invalid get index the. Okay? What did I do wrong here? Just think, oh, that's
gonna give us nothing. That actually did
give us some things. That's interesting. Oh, it's a lowercase
D, that's why. I had a capital
capitalization matters. Let's go data. Form the
search in, take a look. And I'm just gonna scroll
all the way up. Okay. So now we have all of these. So for each result
inside of data, we can create a
new thing, right? So we can say, we could
set our animes now again, so we'll say animes
equal anime data. That way, this now just contains the data
instead of having to go through this extra
key for no reason. Now we can go ahead and check. We can say four
anime and animes. Anim is going to write
past here for a second, we do not have an instance or we do not have anything loaded
to create an instance from. So I'm going to say bar result
equals anime result here. And we're going to load that G. And come back down
to anime and animes. We're going to do RI for result instance
result, instantiate. Oh, because we're getting
it passed in there. All right. So say anime result. Yes, far because we
have a confusion here. It's trying to grab it
from the function here, so it's thinking it's
an integer instead. So let's go ahead
and call this change this anime result
dot instantiate. All right. Now we'll get a VBox that is inside of
our results container. And Child. And we're at RI, right? So now if we run
this and we make a search that should
completely fill out our result attack on Titan
search. There we go. And look at the amount of search results we have
for attack on Titan. That in here, high
school search. And we have so much more. So what we actually need
to do is we need to clear that out because
though you couldn't see it, our results are stacked
on top of each other, adding our new results
to our old ones. So before we search all those, we need to go to
our VBox container. And let's see. Do we
have a clear or anything All right. I don't see any
way to just clear it out, so we can just run through another loop as well
before we go into that. So we can do either a
while or a for loop. So how do we want to say while R VBox container dot Children. Is that going to give
us an integer back? Parents in array of references. Okay, that's going
to get to that. So we want child count. So Wilchild count is
greater than zero. We're going to get
our VBox container, and yet Child index zero, right even if we have one child that'll still
have an index of zero. So we're going to
basically constantly remove the top child until we have nothing
left and ir quarter. Put a little spacer in there. Now you see if we come in, tack Piton search we
have the L filled out. And if we were to
look at the remote Rsults container or VBox, we have all of these in here. So what it is now, what we're going to do when we
perform another search, we're going to grab the
top one here, delete it. It's going to check. Yeah, we still have at least
one child in here. Grab the next one, which
will be moved up here, delete it, and so on. If I come in now and if you
keep an eye on the side here, if you remember how
small that got, you come in, make
that same search, high school search, and we see that did not get massively smaller
when we did that. Although it is
going to take a bit to run through and
delete them all, which is a bit of a problem. So it might just be easier to completely delete
the entire VBox. Okay, so let's try just deleting the entire VBox
instead and creating a new one when we need it, so we'll say, we'll get our
VBox container u three. And then we'll just
add another one. S V NuBx equals VBox container, NuGet our results container, add child Neubox, right? So we'll see how that works now. That should hopefully be a lot faster since we're not going through potentially
1,000 results now. So same thing attack Titan search All right. We had a null value option, so we come in we say what
has come right on in here. Results container, and
we'll just say get child Child zero
BRVbx every time. Allright let's try that. All right, so we
solve the issue by changing instead of
getting the VBox directly, since it's always changing and it's having a
different name. Of course, we could have just
named it our new box here, and that probably would
have solved it as well. But instead, we'll just
change it to yet Child zero. And we do that as well up
here when we cue free. And since it seems
like we're trying to do both things
at the same time, remove and add, I
just went ahead and called and wait for 0.1
seconds, which is fine. It's a tenth of a second.
It's not going to kill you. So if we go ahead
and run it now, we can go ahead and make
search attack on Titan search. Give it a second. There you go. We see how big our bar
here is on the side. When we type in high school or any animes that
show up with that, and we search, we notice the
bar gets smaller because it's going to be more results. And we notice the whole thing
is just going to flash, which is just
completely clearing. There you go. And you see we have
this small bargain. And then to show you that
it's not stacking results, we can go back to that attack on tight now we should get
our bigger bargain. There you go. Alright, so in the next video, we'll go ahead and let's see. Thumbnail we'll do our thumbnails and
our information here. So the titles and the genres. We'll fill that
information out next.
71. Thumbnails, Titles, Genres: Alright, let's go ahead
and get those thumbnails, titles and genres
all filled in here. Just go to space this
out a little bit, to make things a little
nicer to see here. Go. Alright? So this is
obviously going to be inside of our anime here. So we're going to add
is fine. And let's see. We need to get our so Let's go ahead and we start with we take
a look at our result. See, we got to come down to animate Info and then
into the anime title. So we'll say RI and we can
say get child, get node. Fine. We're going to
just use get node here. And from here, we can see
we go down to animate Info. My case, and then
inside of there, we can get anime title text. And we can set that to anime. I think it's called
title in our results. Find out real quick, as I just test our main
scene and perform a search tack on Titan, search. And it is not nonexistent
function, it's getting nulled. I mistake, Typo, Alright, so now we have all of
our titles set up here. So now the question is, where are these
genres located at? And for that, I honestly don't know off the
top of my head here. But what I'm going to do is
I'm going to print JSON, stringify, animes and
get our first result. I'd like this to be
easier to look at. So I'll add a space here as my second
result to string of Pi, and I'll just run that again. And that's going to be a lot cleaner to look at down here. Status ranking synopsis. Really, genre is nothing.
It doesn't have any. That is quite interesting. Yeah, it looks like it's
just called genres. So much like the title. We're going to get our node and get that text property of it. And this one was
called anime genres. And that's equal
to anime genres? Yes. All right. So if we take a
look at that now, let's see tag on Titan SERT. And no. Invalt? Yeah. Oh, because it's gotten
array as a result. Okay, so we'll have to
turn this into a string. Let's take a look. So if we
go to Search help and we go to array, we take a look? Let's see. Does array
have any two strings? I don't think so. No, it's not appear
to. So that's fine. We can just convert
it into a string and spiking STR and wrapping it with a pair
parentheses like so. However, however, I believe we're not going to
get the desired result here. So if we go ahead and
complete this search, you can see we're getting
these square brackets and that still involved. So what we should do
instead is run a loop here. I'll say four genre
in anime genres. So say text plus equals genre plus I will
put a comma with the space. You know what? I think we'll do that separately
just to avoid any issue. So we'll have two lines here. So if we have more
genres in there, then we'll add a
comma with the space, and then we'll add the genre. That way we don't end
up with a comma space at the very end of our list. Now we're only adding genres when if we have genres to add. So our first result
isn't just going to be a pair of square brackets.
It's going to be empty. Oh, well, in this case, it's going to be completely have our
default thing in there, but we can see action drama, action award winning, drum, suspense, action drum, suspense. A lot of action drama. Some of these, there we go. Adventure comedy fantasy. Our default tax needs
to clear out of there. I'm so that's fine. We can just we can clear
that here, right? Or we can just go ahead
and clear it here. Either way is perfectly fine. And I think I'll just clear
mine right there. No problem. So if we run it now, we
should be good to go. And there Although we have the com at the beginning,
little unfortunate. Should be an easy fix. I should be a quick
fix. No problem. Once we're done with
all that, I should be able to just call Oops. Actually, yeah, dot text. All right. So we just
trimmed the prefix of it. So outside of our fore
loop when we're done, we grabbed our text property, and we set it equal to whatever our text is on our genre stele. And we call trim prefix, and we're just trimming
that comma space. All right. So there you go. That
should completely fix that. So if we go ahead and
form a search now, we do tack on tighten
search. Here we go. We see everything showing up
Justin should. It's great. So now we got to
look at our image. How do we get that image
for each of our things? Well, we're going to
need another HTTP here. And we're going to
call this image quest. And you guessed it, we're
going to connect the request completed signal to it
to our main script here. And I'm going to
move that on up. And I think I'm going to put
it up here with the rest of our stuff and space
those out. Alright. So now when we get this, we have what we would
have our images here. So we would need to
form our search here. We're getting a lot of it. So in our anime search request, above our for loop, we want to do it
above Let's see. Let's do it up here. Once
we have our anime data, then we'll make our request. They'll say image,
quest dot. Quest. And we'll place our URL, which is going to be animes. And I believe it's
just called Image And to check that, we can
go ahead and we'll just print out Gotcha, sure. And we don't need
our JC five fact, we can actually check it here before we start printing it. Yes, image is exactly
what we need. Perfect. See, now
we make a search. Oh, invalid Get
Image on Base array. That's a little
town, right? How is it on a Bs array? Let's see. Alright, so we'll go ahead
and request animes image. And then inside of
our fore loop here. Let's No, down here where
we get our request. We can do we can
create our tech, save our image image new. And we'll we can match here depending on what
type of extension it is. So we'll match EXT
to the extension. Is that going to get rid
of our error for now? Okay. So we'll have to
get our extension up here before we
can do anything. So say, XT just before
we make our result. EXT equals Anime'simage. Yet extension. And that's going to
give us the end of URL, it's going to give us PNG, JPEG, web P, TGA. And that way, when
we match extension, we can match EG. We can match JPEG or JPEG. We could match web P, or we could match TGA. And like normal,
none of these match, We'll go ahead throw in a
wildcard and just print out systems saying, can't image. And inside of all of
these, we'll go ahead. We'll do image, load, and we're going to be
loading from buffer, so load E and G from buffer. And this is going
to be our body. This is our body,
and we're doing the same thing in Ali,
just different types. Load from JPEG from buffer, load P from buffer, and load TGA from buffer. All right. So that's going
to give us our image. We can go ahead and after this is I do want to do Du. All right. So we'll go ahead
and get a new variable, texture Image, texture new. We do texture dot set Image. And we pass in What do you Oh, because we're still
inside the Battery. This shift and tab. Yeah. So set image, and what we're going to set in there is going
to be our variable image. And then we're going to
return texture to us. That way we can
use it elsewhere, which means when we
make our request here, say, our thumbnail equals our return value from
our request here. I can spell correctly. Right now inside of
here, of course, before we finish, we need to actually get
our thumbnail here, which is our anime image. Dot get node, Anime.
We going to add Manfo? No. We do not. All right. So what stuff. Here's
some anime image that's with api, I believe. Anime image. Do.
Texture equals texture. Actually, thumbnail.
How is here? Alright, and it looks like
I'm pointing out a void here, so we need to finish fix that. Maybe return back
in image texture. And that's only if you have
the arrows pointing, right? So if you have these arrows
here, pointing at void, saying that return void on your HTTP request for
the image request, you have to go over there and
change it to image texture. W point it because that's where you are turning here, the end. And I would show you
this working now, but I actually use up all
of my requests per day. So I'm going to
have to put this on pause and either throw it right at the
end of this video or come back at it next time
and show you it working. I guess that'll do it for now since I have no
more EPI requests. I've hit my daily limit. So that'll do it here and I'll see you in the next section. Alright, so I didn't need
to make a small changer. I moved the info that we had at the top of our Animate
search request complete. I've got these I've moved those three lines down
and added in a wait. So we're assigning
our extension right after the four loop to, of course, animate and
then image dote extension, so we know what type
of image it is. We then get our image request and perform the URL
request, right? Anime image. And we should probably be
passing in our headers as well there. We then await. And this time in the past, we've always created a timer to wait a
set amount of time. This time, we're using a wait to wait for
our image request, request completed
signal, so we're waiting until we've already gotten
the info that we need. And then we're setting
the texture of our anime image to
our variable texture, and this is where I've
made a slight tweak. I've changed texture to just
be a global variable here. Well, global in the form of being at the
top of our script. And if I scroll down, where is it here, I went ahead and we're
doing the same thing here. We're just not
returning texture. I just created texture
as an outside variable, which means I had to
come back in here and paste from a miss
texture back to void. Now the reason why I did that is because for whatever reason
this was coming back as an integer rather
than the data. So I just switched it this way so that we're
setting the data here, here, but the variable exists
outside of that function. So that's why we
don't have to return. And also to avoid issues, I really issues, but
API limits here. I went ahead and I changed my size down to three
so that I only get three results because
we are making an API call for every
result that we get, right? Or not really an API call, but we are making a UR call, which is why we don't
need the headers here. What am I thinking? Not for the image? So if you wanted to keep that
higher, you could. It's not going to hurt anything. It's just three is going
to be a lot quicker. If we come into the default, which is 100 and we take
open that up that's captured already and
we already say attack on Titan, former SERT. This is what we should
be looking at here. And we see we got our
name, we have our anime, and we have all of our
genres that underneath. Right? So there you go. Blah blah, blah, Sam, and we SERT, boom. There we go. We see everything's
working perfectly fine. And if you wanted to, if
you were doing 1,000, like what I had up there, it'll just take a little longer. I don't know why I thought
I was going to use my extra API calls there, but slight loss of
thought, I guess. We can come in and
you can see we get somewhere which I
think high school had even more results, right? We come in, go like that, and you can see, look at that bar. Just keep going real
tiny, still going, still going because we got
to get all those images go, and it's finally stopped. And you can see we
have all the images, all of these.
Nothing is missing. But there you go. So that works. We just
had to basically move our texture variable
to being at the top of our script instead
of returning it. And I can uncomment those
we can take our genres now. And basically moved
our extension and image request down after our Those are the only changes
that I made there, right? Before I ramp on and add too
Much on because I think I'm just going to add this
onto the previous video. Alright, there you go. So
it works perfectly fine. And next up, we'll
take a look at opening up our page with the synopsis of the story and our any other info like the external
link and all that.
72. AnimePage: All right. So let's go
ahead and show our panel that's going to pop up with
the details for our show, such as our synopsis and we'll have a clear
view of our thumbnail. And if we want to, we can
go ahead and put the title and tags in there as
well if we wanted to. Now, what I've done is I've
gone ahead to my results, and I've added in just a
button that says view. Now, there's a variety of ways that you can
go about doing this, but I just have one
that says view. And on my main scene,
I've added a window. I just has a text direct inside. And do note that you cannot move the window itself because you
can't grab ahold of it. So you'll have to go into
the inspector and go to the layout and transform. There it is at the
window and position. And then when you want
to move the things on the inside that
are children of it, such as my thumbnail here, which is just a texture, right? I have to go down to layout
Transform and play with my numbers here in order
to move things around. For example, the position here, if I want to move it, I got
to go like this to place it. But I'm keeping in mind on the left hand side
there for my thumbnail. I'm also going to add a label, and this is going to
be my end of a title. I'm going to put some words
in here just so I can get an idea of where
this label is placed. I'll go to layout Transform, and I'll find a good
spot to position it, say, What if we go 300 over? That might be a little
too excessive, 203 20. Oh, that's right.
We're in the center. I do believe. Let's see. I set that at 200, which would be way
up here, actually. That's interesting. So I'd want to maybe back it up
a little more, drop 50. All right, I'm going
to go with 160 and maybe lower it down by ten. So I can get it away
from the edge there. So that's going to be our title. And I'm going to go
ahead and duplicate this just with Anime
title selectic D. Call this our
anime tags, right? And this where we're
going to have drama, action, fantasy, et cetera. So this is going to be low. Our title. So come down
here, layout, transform, and we'll lower RY down to 30, 30 could be about right. Maybe 40. Just to clear
it up a little bit. And now we need
something for the text. So what do we want
to put in there? We could do label
gets a little wordy. We could do a rich text label. Well, I think that's
what we'll do. I had a writ text label, just like you see here, side. Now, the downside is we
can't really see anything. I'm just going to go ahead
and put a bunch of text in here just so we can get a good idea of our size to just
spam a bit in there, go to our layout, transform. Size. That's 100. I think 300 is
probably good there. Maybe 400 there. And let's see about
that position. Now, where exactly am
I going to want this? Do we want it directly below. It might be the best
option for that. In which case, what
are the X for these? 179. Do you have any Oops. That's the size. W position 160. And then I'm going to drop
it down by about 100, and this will be our story. Where a synopsis goes. So
we'll say anime synopsis. Alright, so that's what my
window is going to look like. I might need to adjust
this after I see the thumbnail get put in. But for now, I'm going
to be happy with that. And I'm going to go back
to my anime result. I'm going to add a script
to my anime result, and I'm going to connect
the pressed signal. I'm going to
reconnect that here. Disconnect just connect
that again. All right. And we're going to need a few
custom things at the top. So we're going to
have a custom signal here and it's going
to be show details. And we're going to
have a custom variable here called synopsis, which is just going
to be a string. And we'll have our
ready function here. And on our ready when this
object loads into our scene, we're going to go ahead
and connect it with our custom signal to our main node here
with its script on it. So we're going to do
self dot connect, and we'll go ahead
and show details callable and remember
the first argument is what you want
to connect it to, so we want to go
three parents up, say get node, and do dot dot slash dot
dot slash dot dot slash. That will take us
three parents up. And the second argument is going to be the name
of the function. So I'm going to call
it Show Window. And I place that on the inside of G node instead
of the outside. Here we go. And I'm going to go ahead and
make that function before I forget in my main
script show window. Now, when our button
gets pressed, we're going to emit the signal, emit our custom
signal, show details. And we're going to do a comma
because we're going to pass some additional details or additional information
with it, right? So we're going to
pass a texture, so I'm going to create
a new variable sort. So thumbnail, that's
going to equal our anime image texture. So that'll be whatever thumbnail this is for this
specific object. And we're taking that texture
and we're going to send it over with our signals. We're going to send
that data over, and we're also going to need
to send over our synopsis. Our title and genres. That's a lot of
information here. And we're gonna have
to done this as well. So let's see. Down here, let's see
our title equals. And we get this from
Anime title here. Anime title. And this is all stuff that
we've already set text. And it's going to tell us
that genres is not defined. Genres equal Anime genres text. And synopsis is already
defined at the top. Awesome. All right. So we're now sending all of
our information over. Now, I'm just going
to copy all of these arguments so I get
them in the right order. Go back to my main script, my show window function, and I'm going to paste
my arguments in. So what we're going
to do with this is, well, first of all, we need
to actually show our window. So I'm going to get
my window down there, and I'm going to call Pop up centered so it shows up
right in the center screen. I'm then going to get
my thumbnail here, the texture wrecked
inside the window and set its texture to thumbnail,
the data that we send in. We need to set the anime title. Anime title text equals title, Anime books, tags,
text equals genres, and then we need synopsis. Anime synopsis do. Text. Add text with a rich text label, add text and synopsis. Now, at the moment,
we haven't passed any synopsis in to our objects. So we're going to need
to take a look and see how that is structured. So I'm going to uncomment
my stringify JCN file here. That way, I can take a look at what the name of the synopsis. I'm pretty sure it's just called synopsis, but I
want to make sure. I'm just going to
go ahead and run this and perform a search. These attack on Titan again. And yes, yes, yes, that's fine. That doesn't need to be there. You guys shouldn't
have that in there. I forgot to delete that earlier. But we got the output, and that's the main thing
I was looking for. And yes, it's just
called synops. All right. So let's see. When we put in, we do our genres a text in
the extension and thumbnail. We set the texture,
we set the text. And just before we add
it in, add our object, right, our result instance, we're going to go ahead and
we need to set the synopsis. So i dot Synopsis. Sure I spelled that right. Yes, yes, all lowercase
equals anime synopsis. Alright. I'm going to go ahead
and run that again. Say attack on Titan search. Gonna run through.
We have no issues. Fantastic. Now our view is
kind of all over the place, which is a little unfortunate. But I'm sure we can
fix that just by manually setting the size. But I'm going to go ahead
and just click view, so we should get this thumbnail. Well, let's get one that's got two tags with it and genres. And as you can see, I need to shift everything
over to the right. And that's what this
testing is for, right? So let's see title inspector, so I'm just going to
leave it running here. And let's try 2025250
looks better. And I'll do the same
thing with our tags, 250, and our synopsis 250, right? So everything's
been shifted over. And let's see, we can scroll down through our
synopsis if we need to. All right. The reg. We have that set up. Now, we can't actually close our window, so we need to fix that
for ourselves here. So we'll go ahead
and close that. And for that, we're
going to have to go to our window and connect the closed requested signal. We'll connect to our main, and I'm just going to go
ahead and move that up. Go. So when we get
a request to close, that's going to be whenever we click that X in the corner. All we're going to do is we're
going to hide the window. So we're going to
get our window, and we're going to just call
Hide. As simple as that. And let's see. What can
we do about our box here? Well, we could make it wider. What about our anime title? I believe we can just
set it to click. All right. Now, what
are these auto wrap modes specifically? Because these weren't
herb force, let's say, arbitrary wraps text inside
the nose bounding rectangle, allowing break lines. Yes. Alright that one sounds good. Soft breaking, no. Alright, so I'm going to use Word Smart. Oh. Maybe we won't use that. That completely broke it
there. Arbitrary. No. Word could go with word, but that's just not going there. So, right, what am I going to do is I'm just
gonna hit Clip text. I don't like that that went a little That size
only went to one. You're not like that.
So what can we do here? So what I'm going to do
to fix that I just want my button to be inside of
my animate info box here. That way, it's just in line with our title genre then our button. And I've set my button
to I'm not a button. I set my anime info box here. I set the horizontal to
fill and turn to expand on. And now what I'm going to do is I'm going to set anime title, the horizontal
alignment to be in the center and vertical center. And I'm going to do
the same thing with the genres here, center center. And then for the button text, the button text
should be centered, though that should be good. So let's go ahead
and open this up, see what it looks like now. Let's say, attack on Piton
Alright, so there we go. So it stretches all
the way across. Oh, that one's gone
a little too far. That might be a me
problem, though. Might set something,
screwing around. That might have been
it there. Let's try that again and make
sure that that was just something that
I left in Okay, so that's just stretching
all the way across because we've got a title
or something being along. All right. Well, you can see, it's just a matter of
playing around with this stuff now and getting
something that you like. So maybe I'll just come
back to my anime info, and maybe I'll just
turn that off. Maybe I'll just turn Phil off. I just tab back and take a look. See that looks fine now. Again, our buttons just
aren't about the same size, so it's just a matter
of playing around with it and finding something that you like
visually after that. But the important
thing is, we can come down and we can pick one, boom, and there we go, unfortunately, we picked one
without tags in the SEC. Even though we've
already selected one, we can select another one, and it doesn't affect anything. We still get the title tags, and I can see all that
default text there. We need to clear that
out. So let's see. It's going to be in
our main script. Let's see before we set
that text. Where's it? Well, if I erase that by fault, we still going to have?
That's the question. Let's see. Synopsis,
delete all that. And let's see if that works, or if we still have
old synopsis in there. Right and let's go
with that again. Funny enough, I've never
actually watched it. So let's see. On his first day of junior high. On his first day of Junior. Okay, so, yeah, we still
have old text in there. So we need to make sure to wipe that when we set the title
synopsis right there a text. So before we do that,
let's go ahead and get our anime synopsis dot. Big text label has
a clear function. And I should solve that. Now, we take a look. First one on the first day of junior high, second one, Gabby
Braun and Falko Grace. Next one, Aaron Yeager. Probably pronounced
that one wrong. Centursgo Van kind slaughter. Don't threatened by the
Titans. There you go. So we've got that
completely updated now and it's getting the right
text in there. All right. So it's up to you how you want to make
this look visually. But that's what
we're going with. That's how we're doing it,
and what we've gone with. Alternatively, if you wanted. I'll show you an
alternate way that we could do this if you don't want to go with a button there. And to keep that instead of
using a texture wreck here, we could come in and I'm just going to
right click and hit Change Type and change
that to a texture button. And then I can just drag
that in for normal. And now we have that button. Let's see if we need
to tweak any text. I don't think we would, but
actually we might the text, we might have to specify
that it goes to the normal. Let's go with Narrato this time. And yeah, okay. So
that would break it. So we would have to specify
specifically that it was that the normal. I'll take a look here.
Anime Info. That. And it's going to be
texture, underscore, normal. Okay. So that would just
be a small age. So where we set our
animate image texture, do dot texture, underscore,
normal, like that. And that should be it
just one line change. And that functions
correctly, right? We got our thumbnails in there and it looked exactly the same. And since this is now a
button that has our texture, we could set it up, so that
when we click that instead of clicking that view
button, right? So we can take the
animate image there. I'm going to copy the same copy. So on our animate image,
I'll click Press, and I'm going to go to make sure they go
to the same function. And now you'll see W we go in? I can click on the thumbnail, get our Windows and
underscore normal. Change. But that's two texture lines that
we had to change. If you wanted to go this route, the button, then we can
click on that, there we go. And that might be a little more natural or a little
better for you, and then you can just completely remove this button off together. So I'm just going
to hide it from view just so you can
kind of see it this way. And then you can have
there. So there you go. Here's how you can do it with having our
buttons in there. And then if you wanted
to get rid of that, just make the actual thumbnail clickable for it in order
to pop up our window. That's all you have to do. Connect a press signal,
change this from a texture rec to a texture button, and then change all of our
animate Image dot texture to animate image dot
texture underscore normal. And there you have it. So we have this all sorted out, I'm just going to comment out it's printing
down here again. Once again, we no longer
need it. Here we go. So we can now search for animes, get a synopsis, see the tags, get titles, and we
can scroll through a big old list of 1,000 or 2000 or however
many we want to go. And it'll be one API
call per search. Um, actually, it'll be
two API was initially, because we have to add
our genres in there. I'll just uncomment that.
Put that back in there. You guys should not have
had that commented out. I just turned that
off just to save on some API calls while I was
testing some things, right? So now we can come in
and we can do, like, supernatural and frozen search. Not frozen. It's freezing that I was looking for. Freezing. Search nothing for supernatural. How about fantasy? Interesting. So we're not
getting anything there. If we go to No genre,
there's breezing. Sci fi. That's what that might have been the
one I was looking for. Di Pi action.
Breezing vibration. I would. So I was
just completely off on my secret just to make
sure that works, right? We'll go to action search. And there you go. We
only got one action. So if we have all those, if we go to drama,
we'll have even less. We can see we can filter it down more and more if we
want to use the genres. We have to fill in a search, but the genres are auction. Alright, so there you
go. There you have it. We have our little pop ups.
We have our information. We have our searches.
So there you go. You now have yourself
a desktop application that you can use to maybe
find yourself samatam. Maybe find something to
watch when you get bored. And I would encourage you to go ahead and add
more features to this. Maybe add a favorites
list if you wanted, or a watch list or something. That way you have something
that you can kee track of. Alright. That's it
for this section. And we're going to
go ahead and move on to our next week
where we're going to talk about some of the more advanced customizations
to really make your programs look more unique and more
professional looking.
73. Fonts: Alright, so one of the things that we can do
to make our application or games stand out and be more unique or be more
professional looking? Well, one of those
things are fonts. Now, fonts can get
looked over a lot, especially by newer developers, but fonts can change the whole field of your
game or your software. And it's like when
you have a font for say, a restaurant, right? If you have a font
that has just say a bit of a slant to the
right and its characters, then we get the impression, whether we realize or not that it is something fat, right? We have that sense of
those letters moving quickly with them being
leaning over like that, especially if they're
leaning over to the right. So with that impression, we can internally make the assumption that this
is a fast food place. And we have all of that
without even knowing the name of the place or what
kind of a place it is, how big it is, what
kind of food it serves. We don't know anything
except for that the letters on its
sign are tilted. That's just how
powerful fonts can be. Think about if you were
playing say dead so Oh, not dead souls. Dark Souls. Dead souls is a completely
different thing, but imagine you were playing dark souls and we had
this bubbly font. There's all over the place. It wouldn't it wouldn't fit in because it wouldn't have
that same kind of vibe to. Right? I would feel misplaced. It would distract you from
the feeling of the game, or it would take away from the game's seriousness and those serious tones
that it gives off. So fonts can be very
powerful when used. So it's important not to
overlook these things. So I'm going to go over
to our anime results, and I'm going to use our title here so we can get a
nice good view on it. Now, without touching
any real customizations, I'm just going to
come in and go to the themoide section inside the inspector with
my title selected. And you can already see we
have colors for the font, the shadow, and outline. So if I set the font to white, maybe set the shadow to a
little more transparent. Okay? We've got
something going on here. We can move down to the next section, which are constants. We can give an offset
to the shadow. Okay. So now we have text
lifting off of the page. We can give this an outline size that can really make our
text a lot more visible. Shadow to the outline. We
could do that, as well. That's really going to enhance
our shadows down there. And we could add a line spacing. We can go down to font sizes, and we could, let's go up to 23. And in this case, that's all the options
that we really have here, but let's go ahead and increase the offset here of
this a little more, and maybe we change
the shadow to be a little more purply Okay, so we can have more of
those cool tones in there. And now let's go ahead and if we run our main scene,
I'm going to go ahead. We'll do our usual attack
on HtonFmersearch. And you can already
see that even though we haven't done much, in fact, just even adding that outline
to this default text here has already made that text stand out and jump out
at you a lot more. And we've hardly done anything. So you can see just how
important even small tweaks to your fonts can be. Now, you are stuck to these
default fonts, of course. Because we can actually use
some custom fonts altogether. Just go ahead and turn
all these back off. If we head into
the fonts section, we can use a custom font here. Doesn't want to turn
off there. That's fine. I'm just going to
open the drop down menu here and select
a new font file. All right. And I'm
going to open that up unable to preview font. Whoops. Alright. It appears in four point. We don't need to select any options like we used
to in three point X. So I just downloaded
a font file here. It is in TTF format, and I'm just going
to go ahead and drag it in to the font section, and you can see, just like
that, we have a new font. Now, we don't have a whole
lot of options set in there, but as you can see, we can still come back in
here and tweak our sides and everything that's on
the outside here and still have those same
controls that we had before. And like I said, just
even putting an outline. That. Even putting an outline will
really make that stand out. Just adding that one
small factor to it. All right. Now, in
Goto four here, it appears we can add
complete variations. So we can have our base bond. You can set up some fallback
bonds just in case. And you can set different
features lining, old style figures, stylistic
sets, alternatives. So you can really come
in here and start customizing very
specifics in your fonts. So you can go almost as
detailed as you want to go. But what's great is the fact that we can
control the font size, even if we don't
have a custom font in bind at the moment. This allows us to at least
have some more control over how we want it
to look generally, and we can always decide
on a font later on, which again, is great
for prototyping, so we can quickly
get something out. But there we go. If we can use custom
fonts and you'll see if I reset this, Oh,
font disappeared. Here we go. There you see. You can have completely
new fonts just by simply dragging our
file in it uses TTF, and I believe you can
use it OTF file as well. But it's as simple as that as to dragging the file over into the font section
of the thmovides. And we can see if we
head on over, and again, we'll go ahead and run this
real quick again and we'll say on tighten search. And there you get
a look at that. Beautiful. Now, this
is obviously a little too big for some of
our titles here, but you get the idea. Now, you would have
to come in and change every single piece of your UI, and that can get extremely annoying or take an extremely
long time to end up doing. And there's a quick
there would be a quicker way to go ahead
and do something like that. And to do that
would take us into the next video where we
start talking about themes. H.
74. Custom Themes: Alright. Now, I told you there
would be an easier way to apply your font to everything, and that easier way is going
to be through is going to be through what we call
fonts or themes, rather. So we can come in and I'm just going to go
ahead and zoom in here, and a theme will apply
to the nodes on, as well as everything
that has a child of it. So if we stick it on
our main node here, then everything in our scene is going to have that
theme applied to it. So this is how you would do a dark theme and a light theme. For two examples, you
would just swap out the theme file and
everything will change. So if we just come over here
with our main node selected, which is our control
node of our scene, head over to our inspector, come down to theme, and just go to the drop down
and select new theme. And you'll notice
down at the bottom, we have this theme tab now, and we pull it up, we can
see all of our options. And these are our previews
for all of our buttons, sliders, as you see here. So we can play around and we can basically see how everything
is going to look, even if we don't have
things in scene. Alright, so that preview
is fantastic for us here. Now, we have a new theme, and we can bring our font in. I'm just going to grab our font, and as you see on
the right hand side, side of the here, we
have a default font. If I just drag it in, now everything shares
that font that quick. Everything shares. Which
is fantastic, of course. But what about
everything else, right? What if we want to
make things more unique, more special looking? Well, we can go ahead and
head on up to manage Items. And with that, that'll open up a new scene that I'll
hopefully capture here. That did not capture. One moment. Try Window
seven. There we go. All right, so we have
our manager here, and I'm just going to
go to Import items. And from Editor theme, I'm just going to hit
Select All down at the bottom. Import selected. And there we go. I can go ahead and back out of here
once that's all done. And now I have all of my items. Now, I can control everything
from the inspector here. You can see all the
different things, everything from spin box, progress bars, all
of my pop ups, panels, the option
button, menu buttons, labels, line edits,
right, my sliders, containers, and tons and tons of things that we haven't
used our butts checkbox. Everything can be modified right here on the right
hand side, right? So we can go into our colors
of our buttons here, right? And we see a font
color is white, and you can see it has changed
to white in our scene, as well as in our preview. We can say font focus or
font hover color, right? Maybe it's more red. So something like that. Awesome. Now when I
hover over the button, you can see, we can now visually tell when our
mouse is hovering over it. From our preview
because obviously, we can't do it here
because it's not running, but we can test it
in our preview here. And like I said, if
you don't want to go through everything
in the inspector, you can actually do
it right here inside the theme manager
section here them tab. So we're editing our button, so I'm just going
to open that up, and you'll see a
huge huge list here. And give me a moment for
that. I'll show you that. Alright. So as I was saying, everything that you
see on the side here will be shown
when we open this up, so you can see everything here, all the parts that
we've added in to edit. So we were editing the button. So if I open that up, we can see all the same properties are
here, but not only that, they're also organized to just how you might
imagine them to be. And you can also come in here
and you could rename them. If you don't like outline size, you can rename that
whatever you want. Here is all of our colors. So it's very easy
for us to go about. We come into font. Nope, got that outline
size, font size, that. So let's take a look at here, these little not
themes, but the style. So let's go to normal, a normal but here. I'm going to do a
flat box style. Just give that a
second. The themes seem to have this little
slight hiccup in them. But that's fine. Open that up. And you see that open up
here in the inspector, so you may just want to
use the inspector anyway, but you don't have to. And you see now come in
I can add borders here. So we can add this border
width on our buttons, as well as, of course, selecting the color of our borders. We can go in bright green and
just start adding them in. So we can do something
like that if we wanted. But what we can
do is we can come in here and we can
just add corners. We can round off our corners. And now, without having to
do anything complicated, we've got these nice
rounded buttons, and because things
like the option button all come from the base button, that's all being
rounded as well. And if you wanted to
get much more extreme, for example, that as that. We're getting closer to creating a rounder and rounder button here and getting closer and closer to just creating
a circular button. You see, it's only
going to let us go so far on these actual buttons, so just keep that in mind. But still, we have a
beautiful at least, in my opinion, buttons
that look nicer than those pointed boxy rectangles. Rounded corners just
always look nicer to me. Maybe you prefer the points, but I always prefer veeven just a slight rounded
corner to them, right? So even if we just come in
with, like, a three, right? On our corners, to me, that would still look
at least a little nicer than having those points. But you can come in
here and you can completely change those
up as much as you want. And then whenever you're satisfied with modifying all your different
aspects of your theme, you can just go
into the drop down here and save your theme. And you can do that a few times
and whenever you're ready to whenever you want to have the option to
change different themes, all you have to do is
just load your theme and put it into the
theme property here. And you can do it
in code, right? Just access the theme
property and load your theme file into
it. And there you go. You've applied your theme. You have different
theme options put in. Alright, so if you want to once you have a
few themes set up, now you can obviously
set this up with a light and
dark toggle button. So if I were to come back to
Hootie here for a second. If we go ahead and set
this to a let's see. It's not a toggle button. It is a just come in and
search button check button. That's what they're
called here. I'm going to go ahead and just
bring this over. It's not really going to matter. And the style is the reason
why we have that background. That's fine for now. So say we have
this check button. I'm going to go ahead and hit
the toggled press signal, attach it to my main script. And all I'm going to do because this kind of rose up
because I don't know, themes seem to like cause things to pause at least
on my side all the time. So if I just come down here and based on if it's
pressed or not, right, we can load
different themes. So I'm going to say if button pressed because that's the argument that's
being passed in, right when we toggle
it, if button pressed. So if it is true, if it's turned on, then
we'll set it to theme two. Else we'll come in and set
it to theme one, save that. And all we're doing is we're getting the node
that it's on, right? So we don't have to type self, but I like to do that anyway, getting the theme property, and we're just loading
our theme file. It's all we're doing. It's now when I run this. I can just simply click this toggle. And just like that, we can swap between a light and a dark mode. So it's as simple
as that when you have if you want to swap themes, it's just going to be
time consuming for you to build up and create all the different
themes that you want to have. Although the plus side is, is if you just want to
have a light and dark theme, and of course, going through, if
you want to create a bunch of other themes as well, you can keep these theme files since we save them out
as a theme, right? You can take them, and
you can bring them into other projects in the future,
and you can just apply, and now you just have a
light and a dark theme ready for everything, right? All your future projects. But it's as simple as that. It's one line of code
to change the theme. It's just as simple as that. Set the theme property equal
to load you theme file. All right. So themes
are powerful. They can be even if
you just want to set set your font for all
your different node types. Instead of wasting time,
you just create a theme, throw your font in there,
and you're good to go. Alright. Now, I will make one more note
here if you wanted to remove something
from your theme. Give this moment because
obviously this is going to lock up for a second because themes for whatever
reason, right? So let's say we want to
remove something out of our theme because maybe we don't need it or it doesn't
affect our project, whatever. All right. We can just go
to Manage Items button here and just open this up, cap to this again, right? We can just go to edit items. We can find something
like editor, troll editor pop up, color preset but,
editor the belt, right sons there,
the help on the. So all these things that are
up here that don't matter. They don't affect us,
so we can come in here and we can just Well, we can just start deleting all these things that don't matter. That way, as well, it starts
looking a little cleaner. Of course, you didn't
have to bring this in these in to begin with. You can only bring select
items in if you wanted to. But if you're going
to make a theme, I find it better
if you just do it for all of them anyway. That way you can, like I said, just bring the theme
into any project and just be good
to go right out. There you go.
There's how you can remove things that you maybe don't want part
of your theme anymore. There you go. Themes
very powerful, very useful, give your program
a more professional look, make it look less defaulty, especially among
other Goto developers and allow you to have more customization
for your users, clients, customers, et cetera. Now, obviously, this is going to fly a little more or it's the software side than it
will on the game deb side, but maybe you can think of something unique that you
can do on the gameplay side. Alright, that'll do
it for this one. Next up, we're going to talk
about making our windows actually pop out and be part of controlled by the
operating system. And what I mean by that
is when we come in, I know this is hard to see for us now because
we mess with themes. I'll get rid of those the
default this, right here. This window that we have all kinds of
messed up right now. We can't move it, right? Like, it's going to be stuck
inside of this window. So we're going to make that into its own window and be controlled
by the operating system.
75. Multiple Windows: Alright, let's talk about having windows controlled by the OS. And what I mean by that is you see how this window here is its own window controlled
by the operating system. We can't move We don't
necessarily move it anywhere. It's just kind of there. Hold on. This will
be a lot easier. One moment. Alright,
if I just come to the display mode here
and we take a look. We can see this is its
own free standing window that can be moved
around any point. It's not trapped inside of
the main editor here, right? However, Oh, that is
a little too big. However, if we were to
come in and, again, perform our search
say that Titan. That's been a thing to time. Alright, come down, whenever
we find a show, click on it. And now our windows you can see how it's stuck here, right? It's not free. And the reason that
is because it's embedded inside of
our main window here. So it's not going to be
it's not free, right? It's not controlled by
our operating system. So that's what I'm going
to show you how to do. That way you can have
your own window. So, for example, you
open a settings window, a settings panel,
preference panel when you're doing
creating software. You can take that and you
can move that window around. It doesn't have to be stuck inside of whatever application. Running. And that's pretty
much a standard thing. So it would be good for us
to know how to do that. So if we just turn
this off real quick, just jump into our script, and we can fix this with one
line of code, and that's it. So we get a viewport, and that's going to
get the viewport of our current window, right? The main window of our program. And all we're going
to do is Goey embed sub windows and set
that property to box. That's it. Now, if we run that, we can see this still works
exactly the same all time. And if we go ahead
and do our search. Plastic attack titan, whatever, we scroll through our results. Doesn't matter. Blah. Let's pick this? Now
it's its own window. We can move it around, can
have its own window title, and it's created and managed by the operating
system itself. Three size and we
can do everything we can just like our other windows. So it's as simple as that to add that little
feature in there. It would be very useful. Another instance of this
is if you wanted to have say a tab like this, to be able to undot just
as you can do in here. We just pull it out. All right. Here we go. So we open up the setting here, and we can just
say make floating. And now it is its
own window, right? And it's managed
by the operating. So this is working the
same way of what we just did with the Dewey
embed sub winds? What we have to do,
close it and that can push right back in there. And you can do this
with any here. So, for example, you can do
it with the script here. You can just click
this button here, and now the script
window is its own thing. And if you have two monitors, you can now just stick this
on second monitor on its own, and you can focus
on the actual scene on one screen and
your code on the. So you can see how doing floating windows
like this would come in handy just through development and depending
on your application, be more productive for
the end user, which, of course, means your product
is going to be liked more, it's going to be enjoyed more, and it's going to
become a preference, and that one small feature, that one line of
code could increase the user base of your
program, your application. Of course, your program
has to be good to begin with, but Yep. There you go, though. That's all we have
to do to create these floating windows
and have our windows controlled by our
operating system instead of being stuck
inside of our main.
76. Menu Bars: So let's go ahead and let's talk about how we can
make a menu bar. Now, by menu bars, I'm referring to what
you see at the top of most applications with
things like file, edit, view, maybe layer
effects, and so on. All right. Now, how can
we go ahead and do this? Well, I have a new
scene here it's using a menu bar as my root node here. And I just place a color rect in the background
because without it, you don't really have
anything back there, and you can't really tell or differentiate it from
the rest of your program. Now, depending on your design and how you want your stuff
to look, you may want that. Other times, you may want
something to differentiate, even if it's just a
slight different shade of the standard background
of what you're working with. So for me, I just want
with this dark red, kind of maroonish color going. And if you're curious, the color the hex
color is 391715. Okay. Now, what can we do? How can
we add bars and earrings? If we go ahead and play this, and I'm going to have to capture that for you here
in just a moment. Oh, no, that
automatically captures. Fantastic. It's a little big. So I'll bring it
down a little bit. But as you can see, there's, of course, nothing
for us to click on. It's just a bar.
Nothing happens. So it's not very interesting. So how we can actually add
items into this menu bars, of course, we can
do it through code. But we can actually eve
ourselves of some of this by using another node. And if you actually want to if you just have
simple menu items, this would be the quickest
way to go about it, as well. Alright, so we're going
to go into the menu bar, and if we just search menu
inside of the create new node, which in case it's been a while, and you haven't seen that
for whatever reason, go ahead and pop that
up again, right there. Let's go ahead and search
menu, and we got the menu bar, but what we want is the
menu button at this point. And now with that menu button, we can go ahead and we can
call it the Bo button, for example, give it a
good name like that. The text, of course, would
be File, Bio not Bilk. Alright, there we go.
And I'm just going to make sure it's a good
size there, fill in. And this is the point
where we can now go in, open up our scene and run it. And you will see
if we click on it. We kind of get this
tiny little pop up here, but there's
nothing inside. Now, the easiest way
to add things into it would be inside
of our menu button. We have this section
called items. We can say Add element, right? Then we can say like new file, add element open, add new. Maybe we have save, and let's add one
more for quick. And it's all right
there in the inspector. So if that's all you need for
each of your menu buttons, boom, there you
go. You've got it. Now you can click on
it, and you just got to provide a little bit
of code to make these. Of course, that also means we could just duplicate our button, slide it over, of course, change whatever options
you want in there and we have a
second menu button. Now, I'm only going to
have one of them set up here just to show you. But if you just need simple menus like that,
that's all you have to do. Now, if you want to have
a menu that sticks out a bit in terms of if
you hover over it, right, and then it
opens up another menu, if you want to do
something like that, then we're going to have to go into the code to access that. Now, I've got my script just
sitting on my menu bar. You could set them on your
menu buttons if you want. That way, each button
can control itself, which would probably be
the better and smarter way to go about it if you're
creating an actual product. So for me, since I only have
the one menu button here, it's not that big of a deal. But again, if you had, maybe five different
buttons there, maybe some of them had
multiple different menus, then you're probably
going to want to at least break it down
into each button that way. Alright. So the first thing
I'm going to do is well, I'm going to show you how we
can add these buttons in. With this my menu button, I'm going to delete new file, open, save, and quit. So I have no items
here in the inspector, and I'm going to show
you how we can add those in through Code. All right, so I'm going
to create a variable. We'll make it on ready. Bar, let's call it, Bile button. And that'll be, of
course, our file button. The class we can cast
it as is a menu button. All right. So we
have ahold of that. Now we can go flebuton dot. And we just say add item, I believe it is for us here. Oh, no, my mistake. We
actually have to get ahold of the pop up because it's a pop
up menu that shows itself. So we want to get pop up. Now we can create a
variable here, for example, we can say file we can
call it the File menu, which is, of course, a pop up menu. There we go. Now we
can set it equal to file button dot Get pop up. And all we have to do
now is bilemnu dot, and we can go add IM. And we can see ad icon item, which means we can have an
image displayed on there. So if you want to have,
like, a small floppy disk shown next to your Save
button, you can do that. We've also got check items. So if you want to be something that you can just tick on and off, you can do it that way. The radio check, which is
just the circle button. And then we have the again, check item and radio check and all that without the icons, and sub menu we'll
get into in a moment. And what is this
multi state item? Well, let's take a look at it. I'm going to hold
Control click on. And he adds a new multi
state item with text label. The label is a string,
then maxmun of state, the default state,
ND, Excel, let's see. Contrarily to normal
binary items, multistatoms can have
more than two states as defined by Max state. Each press activate the item, but increase the state by one. Default value is defined
by default states. So it looks like
we get an increase or we can have multiple states. So every time we
click on the button, it maybe changes mode.
Let's take a look at that. Let's change to set
the state to mode, and we'll set the maximum
of states to three. All right, so let's go
ahead and run that. Let's take a look at
this multi state. We click it? Well,
we can click on it, and we don't see
anything happening. But if we were to take a look, if we were to
take a look at this, we could have the states getting the state's affecting what's going on in
our project now, as you see from us
here, it doesn't really it's not going to do
anything by itself, right? It's something that's
going to require additional additional
things to help us. Whereas something like
a check item, right? Calls check me. And if we were to run
that, even though we don't have anything here, we can go at that
and click on it, and you can see we have
this little checkbox, and we would have to set
up getting that item and setting the check ability on it or the check property. Alright, so how can we go about? Let's take a look at how we
can add our items back in. Can we just say add item, and this way we can put it
in a string and we can do our new file, I think,
is what we called it. And at this point, we
can go ahead and we could just copy, paste these in. So we can say new file open. I believe we had save here, and then we had quit. All right. So if we were to run this
and take a look at our menu, you would see all of these
options are now in here, just like we did when we did
it through the inspector. So if you prefer doing
it in code, you could. But if you just need a
simple menu like that, going through the
inspector would be the easiest or quickest way to add new items into your menu. Now, I did say
that we could have new or files that would
open up into other menus. And to do those, it's a
little more complicated. In that case, we
actually need to create ourselves a new pop
up menu for this. So I'm going to save New pop. And that's going to be a pop
up menu that'll be equal to a new pop up menu
pop up menu dot new. And I'll just go ahead
and turn this down a bit. Pop up menu dot new.
So then we have to go to we can add a new item into it just so
we can actually see it. So we'll say newpop
dot add item. We'll say this is my new item. Alright. And now, in order to
create this or add this into its own little menu that's inside of our
original pop up, we just go ahead and get
our we get that file menu. And we add sub menu item. Now, the first thing
is going to be a string. So let's go
ahead and take a look. We'll call this
my sub menu item. And what's next? Next is going
to be the actual sub menu. This is going to be the new
pop up menu that we created, which I call new Pop. And that's all we
have to put in. We don't have to put we
don't have to put an ID in. It's going to automatically
just be added onto the bottom of our list
just like these go. So if I wanted to, we
could go ahead and set that. Oh, that's right. This is supposed to be a string, which should be
called pop up menu, but I'm going to go ahead
and just make sure we don't run into any issues
in the future with this. We would go ahead and
do pop up dot name, and give it a name, right? Change this property. So
we'll call this new pop name. Oops that should be a string. There we go. And we changed
this to the string variant. There we go. That's what it's
going to be looking for. So now if we were to run
it When did we get here? As index name on type string. What are you referring to here? Let's see. All right,
see the issue. That's right. And GB Script name
has a lowercase. I was working with
C Sharp recently, so got that little
mixed up there. And the other issue is we
actually need to put this in as a child of our menu. So we go to the file menu, add Child, and we would
add our new pop up menu. There we go. So now when we run
it, you can see, we have our file,
we open that up. And now we have this item
called submenu item, and it's got an arrow
pointing to the right, indicating that it opens up, and there's our new item
there. This is my new item. Go ahead and let's call
all of that our setup. And let's go into our
It's our final menu, I do believe, right? And we can connect. And we can connect a
signal. What signal? Well, that's unclear. So let's take a look
at the pop up menu. Methods. We're not looking
at those theme properties, constants, fonts, font sizes,
icons, styles, signals. Here we go. ID focus, ID press, index press,
and menu change. These are all the signals
that we can take a look at, and just by immediately
thinking of it, I would imagine we're
going to either look at ID press or index press. Emit when an item
of some index is pressed or its
accelerator is activated. The accelerator has to do with the multi, the multi state. And let's take a
look at ID press, emitted when an item of some ID is pressed or
it's acceleratorsted. No, I ID is negative, either explicitly
or due to overflow, this will return to
corresponding index instead. So the question is, which
one do we want to look at? Well, I think I'm going to
go with the index for this. So I'm going to connect
my index press. Come in, connect index press. It's going to be a pllable
connected on Self. And we'll say, we'll
call this item. I'll call it item selected, and I'll create a
new function for it. Well, I'm assuming
this is index press, we're going to get
an index in here. This is my assumption, so
I'm going to find out. I'm going to go ahead
and print the index, and we'll see if that works. If not, then we'll
have to go back, take a look at the signal again. File. If I click, quit, I got Index three,
new file, index zero. Okay, so this is working
exactly as I would think. And of course, if I
go into the new menu, this is my new item
here, click on that. I'm not going to get
anything because that's going to
have its own signal that you would have
to connect up. We got the index working. Awesome. What can we do now? Well, we can take a look at our bio menu and see
what our options are. Oh, I hope that wasn't
showing the whole time. So items selected index, and our item is just going to be file menu dot get item
text, pass in the index. And then we're just going to
do a match statement here. So match item, and
we're going to match this text if it's
equal to new file, open, save quit, and we're going to do the
corresponding block of code. Now for quit, we're just going
to do Get tree dot quit. So if we were to run that and
select quit from our menu, our program should close. And it does. So that's how you
would set that up to do whatever it is
that you need to do. Obviously, your options are
going to be different and it's going to vary based
off of your application. But there's how you go
ahead and set those items up in order to get
those to work. So you've got to
connect a signal. In my case, I'm using the index press signal
instead of an ID. And then I'm just
passing in the index so I can get the items text. And then I just match
the text and perform the appropriate section of code. Alright. Hopefully that was clear. Hopefully, I didn't
block anything that was too important
as we went through that. But that's how you go ahead
and create some menus for your applications if you do go down the
software route. Of course, not all programs
need the menu bars, but the ones that do, it'll
be nice to know how to do it.
77. Whast are Particles: All right, everyone, welcome
back. And we're going to go ahead and talk
about particles today. Now, particles are it's a
whole fascinating world surrounding the particles and particle systems and their crucial role
in game development. Particle systems
are a powerful tool that allows us to create mesmerizing visual effects by adding a touch of magic
and realism to our games. What exactly are
particle systems? Well, imagine tiny dynamic
entities that could be spawn, move, and interact with the world in chaotic
yet controlled manner. Particle systems
are a collection of these small entities
known as particles, and they all come together to form stunning effects
like smoke, fire, sparks, magic spells, and even things that you
wouldn't think of such as maybe bats quickly flying out of a cave
as you enter it. Those could be
particles. The magic of particle systems lies in their ability to
create the illusion of complex phenomena using
simple individual elements, whether it's creating
a starry night sky or a powerful explosion. Particle systems give
us the flexibility to craft visually healing and immersed experiments
for our players. Now, you can do this
in either two D or three D. And the systems, for the most part, are
going to work the same. There might be some
small differences. One of these, of course, being that extra dimension that
we have to worry about, which is just natural when
moving from two D to red. And it's just how
easy it is to create particles in the
Gatto engine here. As you see here, I just added some GPU particles
into my scene. I'm just using the
icon as my texture. All I'm going to do is
go to process material, and I'm going to select
particle process material. And just like that, you
can see we already have particles working in the engine. Now it's just all about
tweaking and changing a bunch of different values to
make things happen. Eale would just increase
the lifetime of this. And look at that.
That's increase these maybe 50 on the amount. And there you have it.
We have this simple, but technically, it is a particle system
of just the icon. And when you get into
things like three D, you can use these
particle system to create additional things such
as weather effects like rain and snow. All right. Hopefully this got you to know exactly
what particles are, different ways that
they can be used, and hopefully got you
a little excited to start playing around the
particle system yourself.
78. Creating a 2D fire: All right. All I have here is my GPU particles two
D added into a scene. And from here, we're going to
go ahead and we're going to create a two D fire effect. Now, you can go
ahead and of course, experiment further,
increase your fire, make it something a little
more unique for yourself. If you wanted, um, let's
go ahead and jump in. Now, I'm going to be using
a smoke. What is it? Smoke texture. And you can find these all
over the Internet. This one is
specifically comes from Kenny Particle Pack or
Kenny's Particle Pack. And you can find I believe
it's on Kenny dot NL. It's got a lot of free assets there for
you to play around with. And so I'm just going to take that
smoke and bring it into my texture. For my
particles here. And now I'm going to go
to process material here, and I'm going to click
on the arrow here, and I'm just going to select new particle process material. All right. And
that's what I got. Now, this is pretty large. So the first thing I want to do is I want to
adjust this scale. And I'm going to come down to the scale section here
inside of my material. Go to the scale curve and
select a new curve texture, open that up, open my curve. And just because I already know what I'm
going to put here, I'm going to go
down to about 0.34 for the left hand side and the right hand side is going to come spot all the way down. And that's what I'm
going to work with. Now, I might come back and tweak this later, but that's
what I'm starting. All right, so let's
start at the top, time randomness, that's fine. Date. We can do a point. In certain situations, use a sphere and you
could play around that, but I'm just going to
use just one point. Particle flags. We don't
need any of those. Direction. Well, we don't
want to go anywhere on the X, but we do want to go
somewhere on the Y. Now we want to go negative one, direction on the Y
because we want to go up. Gravity, we can just
remove if we want. And the initial velocity, I'm going to go
ahead and say 32. I want to take a look. That's
not really going anywhere. We increasing that
playing with that a bit, so we can see it's moving up. And what if I just increase
my lifetime to 2 seconds? So we can see it's
starting to take shape. So I'm just going to go
ahead and play around with some of these here. I'm going to lower my
spread maybe down to 16. Now, we don't have a
whole lot of particles. We're only working
with eight, so that's why it's looking the way it is. But what if we come up to the
amount at the top here and maybe go to 50 even? Okay, so that's looking a
little closer towards a fire. And if I change my lifetime back to one, how does that look? That looks okay. I
think I'm going to tweak inside of my scale
here a bit in the beginning. Right now, I'm sitting on 0.19 for the beginning. We'll
see how that goes. And of course, with a fire, we're going to need some color. Do inside of the color section, I'm going to go
to my color ramp. And from the drop down, it's
like a new gradient texture. Where did that go? There it is. So I'll click on
my color ramp now, click on my gradient texture. And now I'll click on
the black section. I'll turn that to a yellow. I'll click on my white section, pull it in maybe about halfway, and I'm going to turn that
to a red or an orange. I'm just going to click
into my texture at a random position to
add another slot. And with that, I'm
just going to turn the opacity all the
way down on it. Now we kind of have that fade off that you're
seeing here at the top. And I'm just gonna
pull that in bit. Now, let's see. Can you tell a difference
if we go like that? We cannot. Okay, so I'll show you that little trick later. Alright. So we have our
yellow, our orange, and a transparent section
inside of my color ramp. Now, to make this look more like fire and not this
cloud that we're looking at, I'm going to scroll
all the way down to material under Canvas item. I'm going to click
the drop down. It's like Canvas item material. And for the blend mode,
I'm just going to set that to add. All right. So now with that
one opson change, we already have something that looks a lot more like a fire. Now, if you want to have that
white center on your fire, Then all you have to do is
just take your color and see how I've got Oh, you
cannot see on there. All right. One
moment. All right. I'll pull that display
capture open for you there. Would you see how I have my
color right here on the edge? Well, if you want
that white center, the white hot center, all you have to do is just pull away from the edge a little bit, and you see the close
more you pull it, the larger that white
hot area is going to be so there's a little tip for you that you can do for
your original color there. I'm just gonna pull it
away just a little bit, maybe go a little more
closer to the orange. We don't want to go all
the way to orange, right, 'cause we don't want
orange going into orange. I'm going to go a
nice yellow orange, a golden orange
and pull away from the center of bit so I get
that nice white hot center. All right. And with that, we basically have ourselves a fire
all set up here. Now, depending on what
you're looking for, the amount, right, can vary. So if we go to 12, we can
get something like that, which we lose that
white hot center, but this may be something closer to what
you're looking for. Eight was the default.
So depending on the artistic visual that
you're looking for, you can tweak the
amount here to whatever it is that's going to fit you and what it
is that you want. And this is why
when you're looking at a fire, for example, in a game, if you have
a lower spec machine, you might lose a bunch of frames when looking at the fire. And then when you look away, your frames shoot
back up because a fire can have a ton
of particles to it. Especially if we're talking
more in three D. I suppose, but that would be why
cause particles can have, say, 1,000 parts to them, and then each of those parts is going to have
their own texture. So it's almost like adding 1,000 sprites to your screen, right? All of a sudden.
Well, with that, we have ourselves a fire. I'm going to turn
mine back down to 50 because I really don't
feel like we need 100. And we could come in and play with something like
hue variation here, which is going to tweak the hue, which is going to
look like the color. So if we were to say, turn
the minimum up to maybe 0.2 and then change the max
up to 0.6, or, you know what? Let's just turn the max all
the way up. And look at that. Now we have like this
magical fire instead. That we have coming
up. Now, we could use this since it's
in a vertical form, we could use this for
something like a campfire. Now, if this was
to D, obviously, we'd probably tweet the
scale and make things even smaller, even smaller than this. But of course, that's
going to depend on the texture size that
you're using to begin with. So you can see with
that, we can have these two variations and have
more of this magic look. And just like other sections, we can add a curve if we want to do that
for our variation. And we can play
around with those, and it would affect base off of Although, mine is not changing. That's a little interesting. Minimum value is zero
that we had there. Quite interesting.
It's not affecting. Maybe it's a little bit of a bug with that curve or something
at the moment. I don't know. But you can see how hue
variation can instantly just add that magical feel to
it with all those colors. If you want, you could maybe tweak angular or velocity
if you wanted to, that's going to have to
do with turning, right? Your Texas turning in that, so you see if we turn
that all the way up, that's really spinning
in more of a ball. I'm just going to
lower that back down. Orbital is going
to be as you see, the whole thing is
going to be going in an orbit around your
point here in the middle. Now with it up there, obviously, that's not going
to make a difference, but here you go so you
can see some shooting. Now, so you can get dif these
different kinds of effects, and it's all these little
effects that we kind of take and piece together to create these awesome visual
effects inside of games. But I think that's all
we need to cover here, give you a good a good
base to go off of? Lifetime obviously goes with how long that fire
is going to last. You see the reason why we
get one little puff there. And there is because the other
fires is still existing. And we told it that so many, 50 can exist at one time. They're lasting for 200 seconds, so they're going to
live for quite a while. But you see 1 second, obviously, they die quick, so they're going to
keep respawning. One shot means it's
going to go just once, just one quick poof. So that's something
that you would use for something
like an explosion. Current emitting back
on up here at the top. And we can easily adapt this. So if we say zero
on the direction there and you can see one on the X there and you can see if we made it longer on the
lifetime or something, you can see immediately how
we can go from a campfire. And then with some
slight tweaks, we can now modify that into
maybe a flame thrower attack or consistent fire breath
for a dragon or something. And all we have to do is just make maybe three
very tiny tweaks. But right, I'm going to prevent
myself from rambling on. I'm going to go ahead and leave
that there. There you go. We've gone ahead
and we've created a two D fire for our world. So if you wanted to add
something like smoke, you would just add that as a
secondary particle, right? So as a quick show, we just
have another particle. We want the particle
to be behind our fire. I'm going to pull my smoke
texture back in again. At a particle process material, change my scale
with a new curve. And all we're doing
is just going over those same steps that
we did previously. Like we did before. But
we went with there. I'm going to go with
color instead of a ramp. Just going to go with a
dark gray on my color here. Let's set our direction. Negative one on the Y. Give us some initial velocity. Gravity set to zero. My spread to be
similar to smoke. I'm going to add a
material to this, as well. A Canvas item just so I can
add set it to additive. We get something a little more smoke like like you see there. And as you see, just by
making these few tweaks, we've almost got got the
look that we're going for. The amount here and eight maybe we'll
add a couple for 12, and all we have is it's
not lasting as long. I'll just go ahead and
the velocity up a bit. There we go. I'll just
move that right back over. You can see now we got this
smoke coming off of our fire. Right. So there you go. I'll pull that back down, increase my smoke a little more. But they have just that simple and those few
twits going from a start. And you see we've added
a smoke onto our fire. Alright. So with that, we've got a fire. We've got smoke with it.
That'll do it for this one. And next, we'll go ahead and
take a look at how to create a fire using particles
in three D. This way, you can get a sense of how similar and
different two D and three D is when
creating particles and how much of your knowledge will transfer from one to the other.
79. Creating a 3D fire: Alright, everyone, we're
going to go ahead and create a fire effect again, but this time in three D. So I just have a
three D scene here, and I'm going to go ahead
and just add a whoops. Just add GP particles three
D into our three D scene. Now, at first, you may
be a little confused because you don't see a
texture anyway anywhere. Well, in order to create this
fire, what we need to do, since we're using two D sprites we're going to go to our
drop passes. Go to pass one. And from your drop down menu, just go ahead and select a
plain mesh. Open that up. Now, you see it's pointed up. Obviously, that's not going to work because we're going
to be looking at it, you know, from the
side like this, right? So we need it to face us
instead of facing the sky. So inside of our pass one, inside of our plane
mesh, we look down. We see orientation, and we can go and change that to these
different directions. And if you see set it to face X, we can see it's going to be
facing us, which is great. Now, the other issue
that we have is, obviously, if we turn around, the fire, right, the plane disappears because the
back isn't rendered. We look from the side,
we can't really see it, so we can only see
it from one side. That is not great. We need to do what's called a billboard. But I add add this billboard to us so that we can always
be looking at it. We're going to go ahead and
add material here right under our orientation and just
add a standard material. And inside of there, if we
go in and we scroll down, we'll see a section
called Billboard. Now if we open that up and
set the mold to enabled. Well, it looks like it
just disappeared from us. So let's try why billboard. Well, that's not working either. How about particle billboard. Now you might be
wondering why none of these options work
under billboard. And for us, because we're
using particles that here, we actually have to set
this a different way. So none of these
billboard options are actually going
to work for us. So in order to billboard
this properly, we actually have to come up
to our process material and, of course, add that
particle process. And then under drawing, you see, it's still the same
way, nothing's changed. We go to the transformer
line and send it to Z or Z, billboard, and Okay,
nothing works there. Let's move to the next one, wide to velocity. Take a look. Okay. Okay, it looks like
nothing is really working here. Well, that's
interesting. Now, you might be a little confused. Why is nothing going on? How
come nothing's happening? And this is why it's important
that I wanted to go over this three D section
as well instead of just calling it
particles and saying, Hey, your two D knowledge
transfer is over, because three D might be
a little confusing like this when you haven't
worked in it. So with transformer lines
set to Z or Z billboard, we need to also come on
down to our orientation, and we change that
to face Z or face Z. And now we can see it. And as we spin around, we
can always see it. It's always going
to face the camera. Alright, so that's awesome. So now we can actually
start working on creating this buyer for us. Well, we're going
to go inside of our material on
our plane, right? So drop passes pass
one, our plane, inside of there, material
read under orientation. And inside of Albedo, just like in regular three D,
everything looks the same. We're going to go
in texture, and I'm just going to
bring my smoke in. And you'll see that it's
got a black background. Well, that's not nice. That's not really
what we had planned. I thought, well,
what we expected. So what we do for that is
we actually come up to the transparency section and
we'll set that to Alpha. And you have other options
here Alpha scissor, Alpha hash, and depth pre pass. Now, depending on what
you're doing, that may have different effects. But for us, the only what we want
specifically is Alpha here. And for the blend mode, we're
going to set it to add, just like we did in
two D, when we added that canvas item, material. Okay, so now we're
getting something closer to what we're used to. Call doesn't really matter. We can leave it on back
just so it doesn't render the other side since we never
see the other side anyway. And that's what call means. So if we set front, it's still there, but it's
not rendering out the front. It's rendering out the back, but since the front
is always facing us, we're never going to see it. So we're going to set
it or leave it on the default of back because we never see the back. We
only ever see the front. And this is something
that'll help out in performance for
your games as well, if you're making something
in three D. That way, you're basically not
rendering what you can't see. Now, for shaded,
if we spin around, you'll see that it
gets dark here. And obviously, if it's a
fire, it has its own light, so that doesn't
really make sense for the fire to be dark on one
side and bright on the other. So we're going to
go into the shading section of our material, and from per pixel, we're going to set
that to unshaded. Now, the last thing we
need to do inside of this material is
under vertex shader, turn on use as albedo. And if we don't use that, we won't be able to
use the color in our particle or the hue
variation or the color ramp. We won't be able to
use any of that. It'll just stay plain white
with that turned off. We have to use the color here
in Albedo, and that's it. Now, obviously, we
don't want that. We want to actually use
the color ramp in that, so that's why we're
going to use this albedo and turn that on
under vertex color. Alright, so draw pass. We can completely minimize
that section, and we're done. We can just go specifically into the process material
or our particles. Now, just like before,
we have our time, our emission shape,
and everything. Now, since we're in three
D, I'm actually going to change our emission
shape into a sphere, and I'm going to
set my rtus to 0.4. Now, basically, this
is going to give us a little bit of depth ifier
so it doesn't look as flat. Article flags, we don't need to worry about
that direction. Well, we want to go in the
other direction, right? So we have our Y set, is it negative Y here? Well, we have gravity
pulling us down. And if down is negative,
then we want to go positive. So I'll just say
gravity to zero and set our Y to positive
one with a direction. Initial velocity,
I'll set it to four. And the reason why
I'm going so low, as you can see that four is actually a
really high number, whereas in two D, when
we're looking at pixels, it's a very, very small number. Now, we can see it going out in this huge directional area, and that's because
our spread is 45, so let's turn that down
to something like 12. Now we can have
something that's a little more reasonable
for a fire. We go. And even then, you might want to lower it
even further than that. 12 looks like it would be pretty good for a smoke, though. And I'm going to go in and
just like we did before, add a new curve
texture to my scale. And I'm going to
shrink that down for starters and then shrink it down towards the end
and just kind of find something here
that works for me. And yeah, I think just
going from one down to zero like that over time,
I think that'll be fine. My color, I'm going
to use a color ramp, a new gradient texture. And just like before,
I'm going to go with some kind of yellow
here at the start. I'm going to throw orange
somewhere in there. Towards the end,
we'll be transparent. If I just move that over,
get something like that, and I think I'm going
to throw some more orange cue on the other side. Just to really, really affect a whole lot there. I don't throw black in the bean. Just to get more of
a fire gradient, although, as you see,
it's perfectly fine here. I'll just throw another
black on this side. All right. So just like that, we're getting a nice
fire going on here. And of course,
depending on the amount of particles that you
want to put in here, maybe 200, as you see, that's going to make
a huge difference to the visual look of it. So eight obviously isn't the number we want
to go with this. 50 that we were using in
two D is pretty decent. So you could probably
get away with 50 for performance instead
of something like 200, but you could always go
with 200 if you wanted to. But for the most part, we've gone ahead and we have our two D fire re
created here in red. And, of course, we can come
in and we can play with the Q so we can have a
magical fire, get created, our Que variation Now, let's go ahead and we could look at angular
velocity linear radio. You can play with all
that stuff if you wanted. Angle is the angle that the texture is going
to spawn in at. So if you wanted to play
around with that, could. So if I come up, say
up to 45 degrees, so that's going to give it
a little more variation and hopefully make it
look less copy paste, make it look a little nicer. But overall, that's it. Everything else is
going to be exactly the same as two D here. Safe little setup that we
had to do in the beginning. And you'll see that sphere, if you change that spear radius. The bigger we make
that basically, the bigger the fire
is going to be. I'm just going to set
that back. D 0.4, just purely for looking.
Yep, there you go. We have that. So
something I'm going to mention here is since
you're in three D, you're going to have a world
environment, of course, and if you want to add a smoke, it's going to be exactly
the same like we did in two D, right
out of smoke, do the setup like we
did in three D here and just kind of stick
it inside of the fire. But you're going to have a world environment in
three D at some point. If you're making a just
about any three D game, especially if you want to have some kind of post processing. So with world environment here, I just added one into the scene. And I'm going to go
to a new environment, and this is where, of course, you come in, and I think I went over
this at one point. We're going to come in
and create a skies. That's come in sky,
create a new sky. I say seeural sky like that. And we can have our skies
set up for a three D game. But what you can also do in this world environment is if we come on down to
glow, turn that on. Look at our fire has
this little orange glow around and what's nice for
especially with fire here, blend mode, if we set it to additive, take a look at that. Now we have that fiery look coming off of it,
like bloom, right? And we can tweak bloom here. If we wanted to, I can get
real insane real quick. That's where your bloom option would be if you
wanted to have that. And your HDR threshold, you can really come in and
tweak all of these things, and you can see exactly how it would affect something
like our fire here. You see, we even got that
flickering going around. I just wanted to show you
how your three D particles can be affected by the
world environment, by options like your bloom, your blend mode, having glow enabled and
things like that. But right now I'll do it
here for three D particles.
80. How to Code any Mechanic: Alright, so let's take
a look at how we can code virtually any mechanic
that we can think of. So for this example, we're
going to go ahead and create a double jump for our little
guess platform or character. And if we think about it,
we have to know we're going to jump off the ground
and jump once in the air. Now, to keep track of that
just those two times, we need to know how
many times we have jumped so we know
whether or not we can. So for this, I'm going to crink on the variables here
to keep track of that, right? Jump count by default
is zero. All right. And when we jump off
the floor, obviously, our jump count has to go
up by one plus equals one. Cool. Now, what about when
we're not on the floor? But when we're not on the floor, we can do the same thing that
we're doing here where we check if we press
our jump button, and this where we can say, and jump count is less than two. All right, so this means
we can jump when we have zero and we can jump when
we have one on our counter. That gives us two jumps, right? Zero and one. And all we're going to do here is
the same thing we do when we normally jump, right? We go up and add
to our jump count. Now, you're going to
notice an issue here. We're going to jump
once on the ground, once in the air, right? We have our double
jump. But if we try again, it doesn't work. We're back to a single jump. Now, why do you think that is? Well, it's because our count never resets at
any point, right? Starts at zero, right? Let's take a look at this. We
start at zero, and we jump. That's one, two, three,
four, five, six. So after we take that
initial double jump, we're already at two or greater. So this statement
will never be true, so we can never get that
mid air jump again. Which means we have to reset this jump count at some point. So when do we reset this count? When do we let the player
have their double jump back? Well, typically,
you let them have their double jump back after they land back on the ground. Okay? Well, how do we know
when we are on the ground? Well, we already have that
check, if we're on the floor. So if we're on the floor, jump count equals zero, right? We just reset it. And now
we have that double jump. Here we go. So all you have to
do is slow down, think about the problem and what it is
you're trying to do. Think about it
logically and break it down into each step. And if you do that, you can virtually work
your way through creating any mechanic that
you can think of All right. So there's how you can
create pretty well any mechanic that you'll be able to think
of for your games. And this can work
the same way with creating your software as well. Just, of course, not
going with jumps, but maybe implementing
a feature or implementing a tool or
an action or something.
81. Gravity and Jumping: Alright, so here we're going
to talk about how we can add gravity and create
a jump in our game. And I'm doing this here in their bonus section because it doesn't really fit in
with roger, per se. Though you could go
back in if you want, you could try and add this
into three D version. But Madness, because if you're making two D
games or three D games, you're probably going to
need to be able to jump or work with gravity
at some point. So I'm going to throw
this in here anyway. So what we got here first,
I'm going to explain is the three physics body types. The static body, which is
down here on the bottom, is working as our floor, and the static body
is something that does not move no matter
what happens to it. So you can think of this
as like the ground, a tree, a building, right? It's something that's
not going to move, and it's not going
to have any impact. The rigid body two D here, which is on the right hand side, in our picture is
already by default. Set up to have physics
applied to it. So this is something
that's going to be just interacted with, kicked around for something
like maybe a ball in soccer, right? Running around on the
field, kicking it. Or if you've played sky Rim, all the clutter, the food, the cheese wheels that go
flying all over the place when you run around or
use fuss ro Da, right? These are all rigid bodies. It's something that acts when something interacts with it
or force is applied to it. Now, if we were to run this, you're going to see the
rigid body falls straight down because of that
natural physics, and the static
body doesn't move, so that is why we
use it as a floor. And of course, other things
like buildings and that. Now, no matter what kind of
physics body we use here, you have a collision shape, and that defines the shape for that specific physics body. And all of these
have sprites just so we can visually see
what's going on here. And our character
body, as you know, from Froger is what we
use when the player is going to have control
of set character and it's going to take inputs. Now, there are rare occasions where you might
use a rigid body, but that's going
to be very niche and specialized at that point. Let's go ahead and look
at our character body. I have two variables here, one for our gravity,
one for our height. All right. And inside
of our process here. Now, again, this
should probably be under physics process
just because it is related to our physics
bodies moving around. But for this example, it's fine. Now, to use these
instead of movement, we're going to use velocity, and a character body has a velocity property already
by default as a four point X. So in order to use this
velocity property, we have to use move and
slide or move and collide. I'm going to use
move and slide here. Now, let's think about this. When do we want
gravity to apply? Well, we only want it to apply
when our character is up in the air so that they can be brought back down to earth, right, back down to the ground. Okay, well, how can we say if the character's
not on the floor, then add gravity to them. Well, we can do it just that. Goto has a function built
in called is on the floor, which performs that check for us to see if we're on the floor, which by default, the direction of up is in the
negative Y direction, so that means positive Y. When we collide with
something below us, that's going to be
considered the floor. So we can say if and we
said not is on floor. And we need to add our
gravity to it, right? So, so we take our velocity, and we're in two D and it'll
be the same in three D. We access our Y axis. And we set that
with our gravity. Now, we don't set that equal to our gravity because we want our gravity to pull
us down, right? And as you fall down, you build momentum and you move
faster and faster. That's how things work, and
if positive is coming down, we need to add plus
equals gravity. All right? So if we go ahead and play this, we will see now that
our character body falls just like our rigid
body. Play that again. Right? So our
character body might fall just a little faster
than our iced body, but you see they work the same. So that's how you would apply gravity to a character to a
physics body of some sort. Alright. So now,
what about jumping? Well, I have a variable uptop
there for my jump height, and this is going to represent the velocity that we have
going up in the air. Well when can we jump?
Well, we can only jump when we're on
the ground, right? So instead of checking when
we're not on the floor, we want to check that
we are on the floor. I is on floor. And we can add this as a
second argument and just say, and we press our jump button, or we can have it as a
separate indentation here, if that makes sense for you, whichever one is easier
for you to follow. It would be cleaner just to have the two statements
in one line here. But again, it's up to you. You just want to
try avoiding having too many nested statements
whenever you can. So we'll say if input is action and we don't want to say pressed
because we're going to be sitting there
bouncing like a bunny. So you want to say just
pressed or just released. So whenever our finger goes down or when our
finger comes up, that's when we're
going to get a jump. And that's personal preference. I prefer pressed myself, and I'm going to set
this to my upkey my jo and how do we go up? Well, we do the opposite
of gravity, right? If gravity is pulling us down, we do the opposite to go up. So let's get our
velocity on our Y axis. And if positive pulls us down, let's negative go up, so minus equals our jump height. You see we're on the ground and we can go ahead and we can jump. So just like that,
we've already created a simple jump mechanic for us. And you'll notice that we can't jump when
we're in the air. If I spa the button, we can only jump once
we hit the ground. And if you wanted
to have movement, you're left and right at
work with your velocity as in most games, you will. It's going to work the
same way as our jump here. So if we go ahead and check, so I'm going to
back out of my if, so I'm going to make sure that
we're still on the floor. I'm going to say I
input is action. And this where I'm
going to say rest as long as we're
holding left or right, we want to move. I'm
going to say right. Then we're going to
check our velocity, and we're going to
go on the X axis this time because we're
moving left and right. Now, if you're in three D, you're going to be
working with the X axis and the Z axis, and this is going to be
obviously have more dependency. But for us, I'm just
going to go here. We just need velocity
dot X for this example. And if we're going to the right, that's going to be a positive. And we can go ahead and just set this to something like ten, and I'll copy this for
the other side or left, and if we're left, that
means it's minus equals. I'm going to make this else if. So if we press up, we jump, and then we have a separate second if chain here. If we press right,
we go positive X, else if press left,
we go negative X. If we take a look, there we go. Oh, there we go.
Sliding back and forth. So if you don't want to
gain that speed there, you can just set it to
velocity of X equals, and that'll just have you
going that fast immediately. Now, as you can see, we're
going a little slow here. So let's see what happens
if we move it up to 100. Alright, so there you go. And we can still jump this whole time. Now, we have an issue
here, in this case, see if I stop pressing
left or right, M E is going to keep going in that direction because
this never gets set. And this is why this if chain
has to be a separate block. So we got if we press right, se if we press left, and we can finish
this chain with an s of Velocity X equals zero. And that's all we have to do. And now it'll stop moving when we stop
pressing our button. And there's our
jump. Here we go. Alright, so there you go.
There's how we can work with creating a jump, as well as working
gravity into your games. And I suppose a quick showcase of how you would use velocity instead of position or
something like this. All right. So that'll do it for this quick showcase for again, just show you how to use gravity and creating a jump because it's something that you're
probably going to need to know when you're creating
some gigs for yourself.
82. Saving and Loading Files: All right let's talk
about how we can save files and the
different types of files. So we're going to start
with the text file, classic text file here. So let's go ahead and we can create our save function here. I have a random scene here. That script on it. No big deal. Doesn't really matter it's
saved just so I can run it. And I'm going to
create my function, save text. All right. So what is that we need to do? Well, think about
this logically. We need to open up
a file somewhere. We need to have the writing
permissions, right? Because we want to write
a file, saving it. And we want to be able to modify the contents
of that file. So line Goto four with
D descript two here, we can actually do most
of that in one line. So I'm going to save var
F to be my file here. And we can do this cleanly just because it's only going to be used here
in this one function. It's not something that's
going to be used everywhere. So it's only going to have a use of maybe one
or two line, right? So we're going to get
the file access class, and this is what we call open. Now, even if the
file doesn't exist, we still have to open
it at that location. As a string, I'm
gonna pass in Rs. Pooling slosh, we
should put it in our side of our
project folder here. And I'm going to go ahead
and give it a name and say I'm going to call it text test dot TXT. Then the second argument is going to be the
mode that we give it. Which depends on
what we're doing. Now, we're saving
a piece of text. So like I said, we want
to write to that file. So we're going to
use file access dot. And at this point,
we have a file. We have a file that's been opened or my specific directory with permissions to
write for that file. All right. So what is it we
need to do next? Well, we have we need to actually store
a piece of information. Well, to do that, we got to have a piece of
information to store. So I've got a handing
on the A MIPsum downp with text that we
use as placeholders. So I'm just going to create
my variable here at the top and call it not text. I don't want to confusing. Let's call this maybe
a story, right? Maybe we have story
application or writing application we have all this all this text here
that we're going to store. Now, it doesn't
really matter what it is, but we're
going to do that, so we can go F dot Store. And what we can do is we
can say store string, store R, store line. All these different
options here. Right now, I'm just going to
go ahead and say store line, and I'm going to store story. All the text that's in story. But my ready function, I'm going to go
ahead and just call this save Pet function. And when I run this, see, initial, it looks like
nothing happened. We're going to close and
take a look at our files. We see text tests, TXT right here, and there's
all the contents within. Okay. So how can we actually
load that information? I'm going to go ahead and
delete everything in there. So we can see that story is a D. When we start this off? And let's take a look at
how we would load a piece of text or load information
from this text file. Load text. Now, starting off the same, we have to open up our file. Only this time, we want to have the read permissions because we want to read the
contents that's in it. So read instead of write. And if we used store string, we can now get as text is
what we can call on our file. Now, in our case, we can go
ahead and we would assign a story to equal whatever this
text is in this situation. So if we load text, we can then hook auto filled
in there, print story. I we take a look at the output. We can see our story
did get printed out, but our story started as empty. Obviously, it was
loaded in just fine, and we got all of
our data out of it. So that part is fantastic. Alright, so I'm going
to go ahead and show you the store VR, if you want to choose that
instead of store line. You have to store your variables individually one
by one, like so. And if we were to take a
look at the file afterwards, we see we can't
really see anything. We can't really see the
information that's in here. And there may be a good or bad thing depending
on yourself, I suppose. But then in order to load
this information up, we have to use Get Navar, and we have to do
this continuously for as many variables
as we stored in there, and they're going to come back in the same order
that they were saved in. So you would have to make
sure that you're loading them in the exact same
order to save them. So whenever you save the file, you're going to have to go into your load function as well, and edit that every single time. So you could do it this way, and there are some people that do personally. I
don't like this. If I want to store multiple
pieces of code like this, or multiple pieces of
data, I should say. There are better
ways, in my opinion. And one of those would
just be a JSON file. And, of course, with that,
we just save it and load it. It doesn't matter if we
add data to it later on in the future or not. So let's go ahead and
take a look at this. I'm just going to go ahead
and push all that down there. And we're going to create
a function here, right? So we're going to say
funk, save Jason. And how would we
save the JCN file? Well, much like we
did previously. We need to have a file
with writing permissions. Obviously, it's not
going to be a text. It's going to be a JSON. And all we have to do all we can do is we can store
line here as well. So we can say r not
Var FDA store line. And the way that we
store this would be json dot springify and pass in the
dictionary of information. So I'm going to go ahead and
create that dictionary with the same three piece
of information here. All right, so we've gone
ahead and we start that. We have that save set up, right? Store line, stringify,
and buy data, which of course is our
dictionary that we have here. And we call our function Save
Jason, so let's run this. Okay. That should be long
enough, close it, and we take a look in our files, and we have JCNFle here. There you go. So this is what our JSON
five would now look like. And now we can go
through and we can assign individual
pieces of information, so we can say experience equals, and then just grab
the experience out of this, for example, or we can just go for the
whole thing and just say that my data equals our
temporary data once we've actually loaded it. So you can see how this
would work a lot nicer, and there's even, of course, the store bar, right? But Even if we store VR, we would have multiple
dictionary sets, right? So we have multiple JC Bile
or JSON Lies in there. But let's take a look at how we would load this information. So I'm going to go ahead and erase everything out of my data. For the time being. Actually, no embrace it. I'm just going to comment it out so that it doesn't exist. So it's the same
thing as if it was an empty dictionary
at this point. And let's take a look at
how to load a JSN file. We create a function, load Jason and just like
everything prior, we need to have a file opened with the
correct permissions. So we're going to read
instead of write. So what do we do
that's different? Well, for this, we're
actually going to need a JSON object because we can't call the function that we need without creating an
actual instance of it. So I'm going to say
var J equals JSON. New. All right. And we want to parse it or check for any
errors while parsing it, so we're going to say,
parse error equals. It's going to be J dot pars where we pass in our
text Val, right? F dot as text. And now we can check. So we're going to
say I pars error. Is equal to zero, right? So double equals here. And if it's zero, that just means that
we had no issues when it came to parsing
out our information. Which means it's safe
for us to use that data. As such, we can go
ahead and sign my data. Is equal to J because remember, we parsed out so
that the information is stored inside
this JSON object. JG data. And if we were to come up here, we can go ahead and we can even do everything
before, right? So we print, by data,
see that it's empty. Go ahead and load our JCN file, print your data
again afterwards. See that run. See we had an empty dictionary, and then we had everything
loaded in afterwards. So there you have it. And it doesn't matter what order these things are in since
they are key value pairs. It could be an
alphabetical order, it could be a random order. As long as the key and
value still match, it wouldn't make any difference. But there you go.
That's how you would do something for JSON files. And personally, I used to absolutely hate them and
avoid them at all costs. I was being stubborn
at the time, and I would much
rather at the time, I would have rather used like ten random text files instead
of just one JSON file. It was a very bad
habit at the time, but now I use JSON Files, and that's one that's my
preferred way to store all my variables
personally, at least. So if you have
multiple variables that you want to
store, there you go. You can go ahead and set that. And even if you wanted to even if you just create a
temporary dictionary, just to store everything. But that's not the only
data that we can do. There are more pieces of data. And importantly, the one
that's really going to be important for software
developers here, especially for game developers where you want to
organize things like your audio options
and display options, we're going to use what's
called a config file. Now, a config file is very
professional looking. And if you've moded sky room, touch the INI file, you'll know exactly what this is going
to look like. Look like. These config files or I&I
files are configuration files. And they allow us to keep
all of our information even cleaner and even more organized than something like
a JSON file, for example. All right, so I'm just going to push those off to the side, and we're going to say
funk, save config. And unlike JSNFles, this is going to be saved
quite differently. And we're going to need a
dictionary for this, as well. Only this one, I'm going
to call this my settings. So we come in, and
we would have, say display display
settings here, right? And that would be set
as its own dictionary. I'll go ahead and delete those. Inside this display,
I don't know, maybe we have like graphic. Well, obviously, it's going
to be grabbed we have preset. Maybe the user has
medium by default. And again, maybe that's
option index two, you know, whatever
you're going to store the Alright, we come down. We can do another option, we'll say there's a lucian
and I'm going to go ahead and just completely
fill the soap for us with some example
information. Right? So I just have an example of some settings here
of some display, some audio, and of course, you can keep going, add as many pieces of information
there as you want, add as many what these are going to be a categories,
we would say. So this is the dictionary
that we're going to use when saving and
loading for config. The first thing we need to
do in our save function is we need to have a config, so I'm going to create a
new config file object. Config file. New. And now we use some four loops. I'll say four
section in settings, keys settings dot keys. Okay. So for all
of our sections, so it's going to be
display and audio. So we have two sections in here. So for each of
those, and then for P in settings section, we're going to go say inside display and we're going to say, for each of these
preset resolution HDR, do this next block of code. Then inside of audio, we're going to do this
same block of code to this next collection of
keys inside that section. And thing we're going to do here is we're going
to set some values. C dot set value, and set value takes
a few arguments. It's going to take our
section, follow our key. And then settings
section and key. I have a typo
somewhere, don't I? Yes, I'm using all lowercase. They should be
uppercase. Here we go. All right, so we set some values inside of this conflict file. And you note, we haven't opened up our file or anything yet. So outside of this
double four loop, we just now call C dot save And the location that
we want to save. So in our case, res,
collash for this. So I do want to note here that
the saves location across all devices is going to
be the user location, and that's going to
be different based on each platform, right? So Mac is going to be
different than Windows, which is different than Linux, it's going to be
different from Android. But every location is going
to have a user user location. So I'm just using bred just
so we can see it easily in the file system
without having to have a bunch of captures and
trying to figure that out. And I'm just going
to save this as my setting dot INI file. So if I save this config now and we run it,
that's enough time. We take a look at
our file systems, and you can see here, I
have a settings INI file. If I open that up, you can
see how everything is nicely organized into categories
for everything. So you can see how
confit files can look both very professional, as well as very organization. And still just
using a dictionary. Technically, we're
using dictionaries and side of dictionaries
to achieve this. And configs would be
my biggest preference, as I stated there,
anything related to settings or preferences
in a game or application. All right. So how would we save not save. How would we load the CIfO? Well, let's take a look
at loading a config. Load config. And of course, we're going to need a new
config object to use. And we're going to check for any errors as the first thing we do. So we're going to save
error c dot load, and we're going to look
for that setting s file. It's probably going to be
down near the bottom, folks. I'm just going to hit
up on my keyboard. There's T and there's
my settings I and I. All right. So now we'll know if we have
any errors loading that. So we can say, if Oops. Error, not equal. Okay. So if we have an error loading for whatever reason,
we can go ahead and, we can just print something
else failed load, and we actually have an
error code, this as well. So we can say error code
and do our percents. We can just go that
in with the error. Now if I were to hold
control and click on Okay, you can see this brings us to this section here. Okay is zero. But if I were to scroll down, we can see all of the
different error codes here. Can't write, can't
open, already in use, no permission, bad
path, not found, corrupt, can't create,
timeout can't connect, method not found, link
not found, parse error. So you can see all of
our error codes here. So if you were to ever
be given an error code, all you have to do is just
come in here and look it up and you'll be able to see
exactly what the issue was. Alright, so now assuming that
we did not have an error, we can go ahead and start
running our four loops, and I'm just going to copy
the same two from above. So we have a four section
in settings keys, four key and settings section. And inside of the
loop this time, we just go ahead and we see it. We set our settings section Kos I can write that proper. We set this equal to the
information we get out of the conf C dot t value. And it's literally going to be the same thing here,
setting section. It's going to be written
a little differently. We just pass in the section E. And then
our last argument, we just put it in null, which should be the default. But just put that in anyway. And now you notice
if we come up. Notice how our master
is pen here, right? For audio. And we're
going to know this works. So I'm going to pert this up. I'm going to go into my
settings on INI and change Master 10-100, save it. Now we'll run the load config. I will see a set of ten
printed out here for Master. We're going to get the
hundred after we load. Take a look, and
Audiosecon Master 100, so we know it loaded
successfully. There you go. There's how we can save
and load config files, JSON files, and text files. Now, it's up to you to determine which file type is going to be best for your situation. But there's how you can
do all three of those.
83. Triggers and Pedals: Alright, so let's talk
about having support for the triggers
on a controller, such as, you know, left trigger, right trigger, L two,
R two, what is it? ZL or ZL, and Z Z, ZR. I don't really take a look
at the Nintendo buttons, but I think those are it. Now, unfortunately
the switch switch controller for that they're just clicky so they're
not really triggers. They don't have that travel
time, that travel path. They're either pressed
or they're not. So unfortunately, for me, I can't use those to
show you that here. So what I'm going to use is my analog stick to kind
of simulate that for you. But you can use this
for those triggers. You can use this for
an analog stick, for example, when you
move forward, you walk, and when you press
it all the way, your character's
running, that would be another use for what I'm
going to show you here. And another use,
which I think is cool is you can use
this concept to support steering
wheels and pedals if you're going to if you're creating a racing
game, for example. Because you got that travel
time that's going to work for the steering
wheel being turned, how far it's turned to the
left and to the right, how much your accelerator
pedal is pressed down, how much the clutch is pressed, how much your brake is pressed. So you can use this
for a wide variety of controllers, as you can see. And you can think of so many
different uses for this. One of the old uses is you press the shoot button
down part of the way, they aim, you press it all
the way, and they shoot. So what I've done
is I've created a shoot button in my
project settings. And like I said, I'm
just going to use my analog stick to simulate this because my triggers are clicky. They don't work like that. This is a I have a super
Nintendo controller that's been modernized, so I don't have the right kind of triggers
to show you that. So again, I'm just going to
use my analog stick to kind of emulate what you can expect. So here in the process function, I'm going to go ahead
and print it out for us. Just so you can see, and
this will be input dot. And we're going to say
get action strength. Now, you see raw
strength and strength, and you might wonder
what the difference is. Raw strength is going to ignore your
controller's dead zone. Get action strength
is going to take the dead zone into
consideration, right? So I'm just going
to use strength, and I'm going to use
shoot to show you this. So if we go ahead and run this, you can ignore that.
None of that matters. And we can just look
down here in the output, and you'll see as I start
moving I stick to the right, which you can imagine again, is moving for blocking
around or it's triggers. As you see I'm in my dead zone. And as I leave the dead
zone, there you go. So you can see just how far
my stick is being pressed here all the way up until
we get all the way, which in my case is about 0.98. And you can use this as I was situating or suggesting or your
different situations. So now I can go
ahead and show this. And sometimes using
my analog stick, I'm going to use this
as walk and run. So we would say, if input Dot get
Ax and strength, it says shoot, which
you can imagine just walk or forward
or whatever. If the action strength is
greater than, say, 0.9, we're going to print
out running or shooting and then we can have another if or else
if either one will work here. And we're going to
have almost the same situation here if input, get action strength, shoot. It's greater than, and
we're going to say 0.01. So this way, basically,
we're out at the dead zone and we
know we're moving. All we're going to do is
we're going to print out, and we're going to say
walking or aiming All right. So now you'll see
right down here. As we go, if we have
our sprigger pressed partway or our analog
stack only move partway, we're walking or aiming
with our weapon. And once we go all the
way and hold it there, we'll be running or our
triggers pressed all the way, we're gonna be taking the shot. Bam. There you go. So you can
see how useful this is. So you can take this
into a series with in terms of an
accelerator pedal, right? How quick or what your speed
is going to be at, right? So you're going to
have, maybe your speed multiplied by
your action strength, and that'll show how fast you're going and same thing
with stopping, right? If you're hitting
the brake pedal, you have how quick you're
going to reduce speed. You're going to take that
and multiply that by the strength of the brake pedal. And now, the harder you press it, the quicker
you're going to stop. All right. So that's how you can use something
like action strength, which is something that's kind of exclusive
to controllers. You can use it on PC as well. The problem is with things like keyboards and that usually a button is going to
be pressed or a snot, so it's either going
to be zero or one, which is why on PC games, we usually have an
alternate button, right? You have a walk button or a walk toggle that
you would use, whereas in controller,
you just move the analog stick partway
versus all the way.
84. Controller Vibration: All right. So here, I'm
going to show you how you can add vibration to your game. And we're talking about
things like your controllers. Now, I don't have a controller
that supports vibration, so I can't the controller on the microphone or on the desk or anything and let you hear go. So kind of going to have to
take my word for it on that. And if you don't believe it,
you can go ahead and read documentation, look it up, search for, and you'll find you're just going to get the same answer of what I'm going to tell you here. So whenever you want
to create vibration, now, for example, I could
put this here, right? I can put it in here or up here, you know, wherever I want
this vibration to occur. And typically
you'll have this on a strong attack or when
the player gets hit, for example, whenever it is that you want this
vibration to occur. So in order to make this happen, we just go we get
our input class, so input dot start
Joy vibration. And this takes four arguments. First is the device, and
this is the device ID here. And for first player,
your first controller, this is usually going to
be device zero. All right. Next up, we're going
to have the magnitude of our weak motors. Now, the weak motors is usually located towards the
top of the controller, and they're obviously not as strong as the
bottom because they just want to get shaking,
some rattling up there. And the reason why they're
weaker up top is because you have a firmer grip on the bottom of the controller than you have at the top, right? They just want to shake it. They don't want to
make it hard to hit the buttons
or make you miss. So we can say 0.5 string. Third argument is going
to be the same thing, but our strong motors. The strong motors is located at the bottom of the controller. You can usually find this pretty much where the
palms of your hands are. So it's going to be nice and
tightly wrapped in there. And note these magnitudes go
on a scale of zero to one. So we can say 0.5 here as well. So at this point, the
whole controller is shaking at half its strength, both top upper half
and bottom half. And the last thing
here is the duration, and this is the amount of
time in seconds of how long it is going to
vibrate if we put five, it's going to vibrate
for 5 seconds. So if you have this
plane with an animation or an attack and you know
how long it's going to be, you can go ahead and
put that in there. And since I have this
in the ready function, if I were to play this and I had a controller that
supported vibration, then my controller would start
vibrating immediately for 5 seconds as soon
as my game Alright, it's as simple as that to add
vibration into your game. You take that one line
of code and place it wherever you want
to have vibration.