The new ultimate introduction to Godot — Transcript

Learn game development with Godot by creating 7 games, from 2D platformers to 3D shooters, with no prior coding experience required.

Key Takeaways

  • Godot is a powerful, free, and beginner-friendly game engine for 2D and 3D game development.
  • No prior coding knowledge is required to start learning game development with this course.
  • Understanding how games render frames and respond to input is crucial for game programming.
  • Customizing the editor and managing projects efficiently improves development workflow.
  • The course provides practical, hands-on experience by building a variety of game types.

Summary

  • Introduction to coding by making seven games in Godot game engine, including 2D and 3D genres.
  • Godot is free, open source, and easy to use, suitable for beginners and experienced coders.
  • Course covers basics of game engines, frame rendering, user input, and game logic.
  • Step-by-step setup of Godot engine, project creation, and editor customization.
  • Detailed explanation of Godot UI elements: viewport, 2D/3D modes, script editor, and asset library.
  • Instructions on adding assets, managing scenes, and basic game object manipulation.
  • Emphasis on practical coding skills transferable to other fields like AI and app development.
  • Options to access full course via Patreon subscription or Udemy purchase, with free introductory content on YouTube.
  • Tips on optimizing editor display for different devices and customizing themes.
  • Introduction to scripting in Godot, including animation, input handling, and game mechanics.

Full Transcript — Download SRT & Markdown

00:00
Speaker A
Heat. Heat. [Music] Hello. In this course, you're going to learn how to code by making games in GDU. We will create seven games in total. A runner game, a platformer, a farming game, a monster battle game, a 3D space shooter, a 3D platformer, and a 3D shooter. All the games will be made in the popular game engine GDU, which is entirely free and super easy to use. By the end of this course, you will be able to create games and you should feel comfortable coding, meaning you can branch out into other areas like data analysis, AI, or app development. For this course, there are no requirements.
00:47
Speaker A
I will assume that you have no coding knowledge at all. Although, if you can code already and you just want to learn GDU, you can skip the first part and jump straight into game development. You can get this course on Patreon for £5 a month. On there, you also get all of my other courses and you see future courses early. And if you don't like subscriptions, you can buy this course on Udemy for about $10. Just wait for the super regular discounts. And if you don't want to buy anything, this video contains the introduction to coding and three of the games, the runner, the platformer, and the basic 3D shooter.
00:59
Speaker A
This will teach you all the basics of coding and GDU. So, I hope you enjoy.
01:08
Speaker A
Before we start coding, we need to talk about how video games work to understand what a game engine like GDU does.
01:21
Speaker A
Fundamentally, any video game is just an interactive movie. Like in a movie, we are playing individual images in sequence. And for some reason, these images are called frames. If that happens fast enough, it looks like movement. For a movie, that is usually 24 frames per second, or for a video game, you want to have at least 30. Now, the difference between a movie and a video game is that video games dynamically create each frame depending on player input, enemy movement, timers, and a range of other options. So, what a video game engine like GDU does is it first calculates where stuff needs to be or it checks player input, the movement of every object, if an enemy was defeated, and loads of other things, whatever you specify. And once all of that was calculated, we are drawing one frame. This we do at least 30 times per second until the game is over. This is how any video game works. So GDU basically is giving you tools to capture user input. It lets you draw images and 3D objects. It can play sounds and you can use it for lots of other more advanced things like physics calculations, light simulation, and even online communication. GDU is a really powerful tool and it is entirely free and open source.
01:33
Speaker A
To get it, all you have to do is go to gduengine.org and click on download latest. The website should then give you the right download link. If you want something specific, just scroll down.
01:42
Speaker A
GDU works on basically any platform. Just choose what works for you. Once the download is done, unzip and open the folder and then click on the icon that doesn't say console. You should be seeing a dialogue like this.
01:47
Speaker A
And yes, GDU does not need to be installed. Just keep the downloaded folder somewhere safe so you don't accidentally delete it. With this dialogue, you can manage all of your GDU projects. At the moment, we don't have any. To fix that, you can either create a new one or import an existing project. I want to create a new one.
01:54
Speaker A
Then you get a create new project dialogue where you can give the project a name. Let's just call it test project or whatever you want to call it. It doesn't really matter. After that, you get a project path where you can select where you want to store it. Just choose a good spot. Ideally, create a folder specifically for your GDU projects.
02:10
Speaker A
Also, keep in mind GDU is going to create a folder by default inside of this path. If you don't want that, just disable this toggle. After that, we have three options for the renderer: Forward Plus, Mobile, and Compatibility. On the right side, you can see a bit of information about them. Forward Plus is going to give you the most options and the best look. I'm going to use this one throughout this entire tutorial.
02:26
Speaker A
However, if you want to make, for example, mobile games, then you have to account for less powerful hardware and more limitations. Compatibility is mostly for browser games where you have very limited amounts of hardware power.
02:40
Speaker A
Now, in our case, we only care about Plus. That's the most straightforward one. You can also use version control, but that we don't really care about.
02:56
Speaker A
Once you have all of that, click on create. And here we are. This is what you see when you start up GDU for the first time. Now, I will be talking about the different elements in just a second.
03:12
Speaker A
First of all, though, you can customize this thing quite a bit. For that, you want to go to Editor and then Editor Settings. In there, you have Interface and Editor, which allows you to customize a lot of different things. For example, if all of this is too small for you, you can set the display scale. The default is auto at 150%, but this you can increase, which you can even push further with a custom display scale.
03:24
Speaker A
In my case, to make sure all of this is visible, I'm going to set it to 2.5 and then the display scale to custom. That way, we're getting this scale. If you now go to save and restart, it will ask if you want to save the current scene, which I do want to do, and then we get the same editor with all of the elements quite a bit larger. Now, in your case, you probably don't have to do that. Just choose something that fits your needs. Most people leave it as it is, which is totally fine. But in my case, lots of people watch these videos on a phone. For those purposes, this thing has to be larger. Besides that, you can go to Theme and choose a custom theme. Under Preset, Default is this bluish color, which I wouldn't recommend because blue is just a bit distracting.
03:38
Speaker A
My default is gray. If you have the phone selected, after a second, GDU is going to change the look. And there we go. We have something much more neutral.
03:53
Speaker A
Finally, if you want to hide the top bar, you can press Shift and F11. And then you are in full screen, which is what I'm going to go with. But in your case, just choose whatever you prefer.
03:58
Speaker A
Cool. With that, we can start working inside of GDU. Let's talk about the different UI elements. The really big thing right in the middle of the screen is the viewport. At the moment it's 3D.
04:15
Speaker A
If you hold the middle mouse button, you can rotate in here. Later on, we are going to explore this quite a bit more, but for now it's not too important.
04:22
Speaker A
Instead, if you look at the top, we have 2D, 3D, Script, Game, and Asset Library.
04:36
Speaker A
We are mostly going to work in 2D for now. And in there, we have a 2D space.
04:46
Speaker A
Besides that, we have Script in which we are later going to have all of our scripts. Then we have Game and finally we have the Asset Library which allows you to download different kinds of plugins. We are going to have a deeper look at this later on but in the most basic sense it allows you to expand GDU by adding specific tools. And by the way, you can switch between these different modes using the F keys. F1 is 2D, F2 is 3D, and F3 is Script. Those are the ones you're going to use all the time. For now, I want to work inside of 2D. Inside of this scene, you can place a whole bunch of elements. Those you usually get from the file system that you can find in the bottom left. By default, GDU has one folder with one image file, icon.svg. This is the GDU logo. To add this to your game in the most basic sense, all you have to do is drag and drop it into the viewport and then you have one image that you can move around and, well, you can also scale it and do quite a few things. I'll talk about this in a bit more detail later on, but for now I want to undo it with Ctrl Z. While you could simply add a graphic into this viewport, this is not usually how you're supposed to approach it. Instead, you want to look at the scene panel. This allows you
04:58
Speaker A
Now, in our case, we only care about Plus. That's the most straightforward one. You can also use version control, but that we don't really care about.
05:08
Speaker A
Once you have all of that, click on create. And here we are. This is what you see when you start up GDO for the first time. Now, I will be talking about the different elements in just a second.
05:22
Speaker A
First of all, though, you can customize this thing quite a bit. For that, you want to go to editor and then editor settings. In there, you have interface and editor, which allows you to customize a lot of different things. For
05:38
Speaker A
example, if all of this is too small for you, you can set the display scale. The default is auto at 150%, but this you can increase, which you can even push further with a custom display scale.
05:53
Speaker A
In my case, to make sure all of this is visible, I'm going to set it to 2.5 and then the display scale to custom. That way, we're getting this scale. If you now go to save and restart, but those
06:06
Speaker A
asking if you want to save the current scene, which I do want to do, and then we get the same editor with all of the elements quite a bit larger. Now, in your case, you probably don't have to do
06:17
Speaker A
that. Just choose something that fits your needs. Most people leave it as it is, which is totally fine. But in my case, lots of people watch these videos on a phone. For those purposes, this thing has to be larger. Besides that,
06:31
Speaker A
you can go to theme and choose a custom theme. Under preset, default is this bluish color, which I wouldn't recommend because blue is just a bit distracting.
06:44
Speaker A
My default is gray. If you have the phone selected, after a second, GDO is going to change the look. And there we go. We have something much more neutral.
06:53
Speaker A
Finally, if you want to hide the top bar, you can press shift and F11. And then you are in full screen, which is what I'm going to go with. But in your case, just choose whatever you prefer.
07:04
Speaker A
Cool. With that, we can start working inside of GDO. Let's talk about the different UI elements. The really big thing right in the middle of the screen is the view port. At the moment it's 3D.
07:17
Speaker A
If you hold the middle mouse button, you can rotate in here. Later on, we are going to explore this quite a bit more, but for now it's not too important.
07:26
Speaker A
Instead, if you look at the top, we have 2D, 3D, script, game, and asset library.
07:33
Speaker A
We are mostly going to work in 2D for now. And in there, we have a 2D space.
07:38
Speaker A
Besides that we have script in which we are later going to have all of our scripts. Then we have game and finally we have the asset library which allows you to download different kind of plugins. We are going to have a deeper
07:51
Speaker A
look at this later on but in the most basic sense it allows you to expand GDO by adding specific tools. And by the way you can switch between these different modes using the F keys. F1 is 2D, F2 is
08:04
Speaker A
3D and F3 is script. Those are the ones you're going to use all the time. For now, I want to work inside of 2D. Inside of this scene, you can place a whole bunch of elements. Those you usually get
08:17
Speaker A
from the file system that you can find in the bottom left. By default, GDAU has one folder with one image file, icon.svg. This is the GDAU logo. To add this to your game in the most basic sense, all you have to do is drag and
08:32
Speaker A
drop it into the viewport and then you have one image that you can move around and well you can also scale it and do quite a few things. I'll talk about this in a bit more detail later on, but for
08:47
Speaker A
now I want to undo it with Ctrl Z. While you could simply add a graphic into this viewport, this is not usually how you're supposed to approach it. Instead, you want to look at the scene panel. This allows you to create a scene tree where
09:02
Speaker A
we can create a 2D scene, a 3D scene, a user interface, or create another node.
09:08
Speaker A
If you click on other node, you can see all of the nodes in GDO. And nodes in GDO are incredibly important. I'll talk about those in just a second. But basically, in here, we have a whole bunch of nodes that can do different
09:22
Speaker A
things. The easiest one is a timer which is just a basic countdown timer. I think this one is self-explanatory.
09:30
Speaker A
Besides that, we have an animation player or if you look under node 2D, we have an animated sprite 2D which is just an animated picture. We have GPU particles, we have a camera, we have a collision shape, and if you look under
09:45
Speaker A
collision object 2D, we have for example an area 2D that lets you check if something entered an area. For now, don't worry too much about these nodes.
09:54
Speaker A
I'll talk about them in a lot more detail in just a second. I guess what we can do for now is drag the image back into the viewport. And then we can see inside of the scene tree, we have one
10:04
Speaker A
node called icon. That's because this file name is called icon. The actual note is a sprite 2D. If you hover over it, you can see type sprite 2D. Once you have that, you can look on the right side there, you have the inspector. This
10:20
Speaker A
gives you all of the properties of this node. For example, under transform, we have the position, rotation, scale, and skew of this one node. If you change these values, you can see they update inside of the viewport in real time.
10:36
Speaker A
And in there, you can do a ton of different things and manipulate this node to your heart's content. Although, not something I want to do. Let's undo all of this. That way we are ending up right here. Every node has a ton of
10:52
Speaker A
properties that you could be changing. And being able to change them is pretty much what gives you a game. And all right, with that we have the basics of GDO. So let's talk about how we combine all of these different elements. To
11:06
Speaker A
understand how GDO works, you have to understand scenes and notes. They are the fundamental part of literally any game made in GDO. Let's start with notes. Those are the fundamental building blocks of literally any project in GDO. They could, for example, be
11:22
Speaker A
images, timers, sounds, 3D objects, animation players, and really a lot more. GDAU has hundreds of nodes. Back inside of GDAU, if you click on this plus icon, you can see all of the notes.
11:37
Speaker A
There are lots of drop-own menus in here. If you click on them, you can see everything that's available. Now the way this is supposed to work is that you're combining different nodes inside of a scene. Scenes actually have two
11:50
Speaker A
purposes. Number one, they are a container for nodes. Or in other words, you're combining different nodes inside of a scene. Besides that, scenes also manage what is displayed inside of the game. For example, a scene could be a
12:05
Speaker A
level. Imagine a Mario level where you have a fire world, a forest world, a water world, and so on. Each of these levels would be one scene and you can tell good which one to display. Now this is a concept we really have to practice.
12:20
Speaker A
So let's have a look at all of this in practice right away. Back inside of the editor I want to get rid of this sprite 2D by simply deleting it. Going to double check. I do want to delete it.
12:34
Speaker A
After we have that I want to create a root node for now a 2D scene. This note we can rename to let's say first scene.
12:46
Speaker A
Usually in GDO you are going with this naming style where you start with a capital letter and then you don't add spaces and instead you are adding for the second word another capital letter.
12:58
Speaker A
You could add spaces but when it comes to coding those can be really confusing.
13:02
Speaker A
So I would recommend to not do that. This would be our first scene which I want to save. This you can do either by pressing Ctrl S or inside of scene you can save the scene. Dangod is asking you
13:16
Speaker A
for the location. I want to keep the default one here. So click on save. And then in the file system you can see first scene. Also if you look at the viewport we have our first scene. And inside of this scene we have one note at
13:30
Speaker A
the moment a very basic node 2D. This is our root node. To this we can add other nodes. This you do by either clicking on the plus icon or pressingt controll and a. In either case you get to create new
13:45
Speaker A
node. In there you can select any of these nodes. There is kind of a color scheme going on. 2D nodes are blue and they are inside of node 2D. If you click on the dropown menu you can see all of
13:58
Speaker A
the 2D nodes. Green ones are for user interfaces. In there for example we have text and text input.
14:07
Speaker A
There's quite a bit more in here, but for now that doesn't really matter. Then we have red nodes. Those are for 3D games. These tend to be a bit more advanced, but for now it's not too much of an issue.
14:21
Speaker A
Finally, we have other nodes and those tend to be whiteish. For example, in there you have a timer or you have an animation player that can be used for both 2D and 3D games. I think at the beginning this can be quite
14:37
Speaker A
overwhelming. So don't worry too much about any of this for now. You primarily want to work inside of node 2Ds. And one of the easiest nodes that you're always going to start with is a sprite 2D.
14:50
Speaker A
And at the moment I can't find it. Oh, there it is. Sprite 2D. Now most of the time you don't actually go through this menu manually. Instead you search at the top. I want to have a sprite and then
15:05
Speaker A
Godo is already going to a sprite 2D. This I want to use. So click on create.
15:11
Speaker A
Then we have our first scene and a sprite 2D. This sprite 2D at the moment is not visible.
15:20
Speaker A
If you zoom out then you can see that well we can't see anything. That is because this sprite 2D needs to have a texture which you can see inside of the inspector. At the moment the texture is empty. Now if you click on the drop-own
15:36
Speaker A
menu is giving you a ton of options. For example, you could create a simple gradient 2D and then you are getting something that you do want to customize.
15:46
Speaker A
So in there you want to drag and drop the points around and then you get a proper result. Although not something I want to do. So let's undo it. Instead, you are supposed to drag a texture in there that you're getting from the file
15:59
Speaker A
system. In my case, at the moment, we only have a single file, icon.svg. Drag this one inside of texture. And then finally, you can see the actual image. And once again, inside of the inspector, you can transform this thing
16:15
Speaker A
to your heart's content. Like you have seen a few minutes ago, via this system.
16:20
Speaker A
You can add more and more nodes to your scene. For example, we could be adding another sprite 2D with another Godo logo and then move the second Godo logo somewhere over here. To make those two distinct, I could go to visibility and
16:36
Speaker A
then modulate. This one lets you add a color tint. If you click on it, you can change the color quite a bit. Let's make the GDO logo quite red. Or really whatever you want. It doesn't really matter. With that, we have two good
16:49
Speaker A
logos inside of the scene. or in other words we are building a scene tree. This is effectively what we are creating in here. Now a really important thing that you do have to understand is that these nodes are related. For example, this
17:06
Speaker A
sprite 2D is a child of the first scene node which means when we are changing this first scene the changes also apply to both of the children. If I go to first scene and then to transform, there we have rotation. If I rotate this note,
17:23
Speaker A
the children rotate as well. However, if I rotate the child on its own like this, sprite 2D, then the other nodes are not affected. In other words, a parent affects the child, but the child does not affect the parent. On top
17:40
Speaker A
of that, these two nodes right now are siblings. They both are first seen as the parent, but otherwise they're not really related. Which means if you move one, you don't affect the other.
17:52
Speaker A
However, what you could be doing is attach this sprite 2D2 by simply dragging it on the sprite 2D and then sprite 2D2 would be the child of sprite 2D, which itself is the child of the first scene. Because of that, when we
18:07
Speaker A
are changing sprite 2D, we are also changing its children. And if we change the first scene, then we are changing all of them as well. I hope this system makes sense. Basically, once a node is a child of another node, it is affected by
18:22
Speaker A
all of the changes to the parent. A super important thing to understand. Now, besides that, if you want to create a new scene, all you have to do is click on this plus icon. The door already tells you add a new scene. And then you
18:36
Speaker A
can create another scene. Inside of this scene, I want you to do an exercise.
18:42
Speaker A
Create a good stick figure by using sprite 2Ds. The end result should look something like this. This should happen via notes and scenes. Pause the video now and see how far you get.
18:57
Speaker A
Inside of GDO, I want to create a 2D scene that I want to rename right away to stick bigger to this node. Then I want to add a sprite 2D. You can do this either via what you had selected before or inside
19:15
Speaker A
of recent nodes. Click on create. And then once again, we can't see anything. For that, you want to drag icon. SVG into texture.
19:26
Speaker A
Then we can see good. And let's say this part could for example be the tors. So to make that look a bit more realistic, we want to scale it up by using these points or by going to transform and then
19:40
Speaker A
increasing the scale on the yaxis. By default, those two scale together. If you want to scale one individually, click on this chain icon and then you can change these individually.
19:51
Speaker A
Alternatively, you can also drag these points and then change all of this dynamically. This gives us the torso attached to that. I want to have another sprite 2D, which should be the head. For this head, once again, we want to add icon.svg to
20:09
Speaker A
texture. Once we have that, we can't really see a difference. But if you move the head to the side, you can see that well the head because it's the child of the torso is going to get the same
20:22
Speaker A
scaling behavior. In other words, if I change the scaling of the torso, we are also affecting the head, which is usually not ideal. But for now, what we can do is simply scale this thing quite a bit down to something like so. and so
20:42
Speaker A
and then move it on top of the node. That way we're getting some kind of a hat. Besides that, once again, I want to add another sprite 2D, which you can also do by simply dragging icon. SVG into the viewport. That way, GDO is
20:57
Speaker A
automatically creating another sprite 2D with the name of the file you just added, which is not what I want. This should be let's call it the right arm which at the moment is not a child of torso. So it doesn't get the scaling
21:10
Speaker A
behavior applied to it. That's totally fine. This thing I just want to scale down a bit to something like so. And then inside of transform I want to rotate it to something like this. Next up I want to press Ctrl and D. That way
21:28
Speaker A
we are duplicating the note. And this gives us the other part of the arm which we want to rotate as well. Let's say something like this. And I guess right arm two should be a child of the right
21:42
Speaker A
arm. That way if we're changing the upper arm, we are changing this note as well. Next up, I want to add another node. This is going to be the left arm, which at the moment is a child of the right arm, which I don't
21:57
Speaker A
want. I simply want to drag it onto stick figure and then left arm is not a child anymore. Because of that, if you go to transform, we can undo all of these changes. And then we get the default GDO logo. And this I want to
22:13
Speaker A
once again scale down a bit and rotate so it looks a bit more like an arm. Then we can duplicate this thing again. Move it here and transform it just a bit more.
22:26
Speaker A
Let's say something like this. And then left arm two should be a child of left arm. Two more things I want to add. And for that I simply want to add the abodo logo. And once again this should be a
22:37
Speaker A
child of stick figure. Then I can undo all of these changes. And for this part I simply want to add a leg. So let's make this a bit thinner and a lot longer. And move it down here.
22:52
Speaker A
This should be the right leg which we can duplicate and then move it to the side. This would be the left leg. And with that we have a very basic GDO stick figure. All of this I want to save as
23:08
Speaker A
stick figure.tsseen. Click on save. And now inside of the file system we have stick figure.tsseen.
23:16
Speaker A
Looks pretty horrendous to be honest but I think you get the idea. Now once we have that, what is super important to understand is that this scene can be added to another scene.
23:29
Speaker A
For example, to our first scene, we can click on this icon where we can instantiate a child scene. If you click on it, you can see all of the scenes inside of the project. At the moment, we only have two. First scene, that's our
23:44
Speaker A
current scene, and then the stick figure, which is what I want to add. If we are doing that, we are getting the stick figure at the moment. It's rotated because first scene itself is rotated by a certain amount which I don't want to
23:58
Speaker A
have. If I undo that, then we have the stick figure inside of our first scene.
24:04
Speaker A
And I hope you understand how this system comes together because it's really important to understand. For example, later on the stick figure would be replaced by a proper player which has all of the parts that the player actually needs. And then the first scene
24:19
Speaker A
would be a level that itself is a scene with all of the parts of a level. And one part of this level is the player itself. So effectively the scene is going to be what you display inside of
24:30
Speaker A
the game. And the scene is something that organizes different nodes. It does two things. If you then combine different scenes together, you can create pretty complex projects that are still maintainable because you only ever touch small parts of it. We are going to
24:44
Speaker A
practice this sort of system a lot more throughout this course. I just hope for now you understand the absolute basics of it. Two more things that I absolutely want to cover. Number one, let me move this thing a bit down here. This thing
24:58
Speaker A
here and this sprite down here. All of this should be inside of this blue frame. This is what you actually see when you are running the game, which by the way you are doing via these buttons up here. The most important button is
25:12
Speaker A
run project or F5 if you click on it. Budo is asking you what the main scene is going to be. You can select one manually or you can select the current one which in our case is first scene
25:24
Speaker A
which is what I want to do. If you click on it then the game is going to run and we can see the stuff that we have just created. On top of that on the top of this window we get a
25:36
Speaker A
lot more things that aren't too important. So don't worry about them. Although the one thing you do want to worry about is the resolution which at the moment is 1152x 648. Now if you resize this window this can change. You
25:50
Speaker A
can also go to project project settings and then under display and window set a custom window resolution although that's not too important at the moment. Besides that what can be really confusing is the positioning inside of this window. If
26:06
Speaker A
you click on first scene, we have a position of zero and zero. This is in the top left. You can see it via this red cross dot thing. If you click on the first sprite 2D, this one here, it
26:18
Speaker A
currently has a position of 151 and 168 for X and Y, all the horizontal and vertical axis. What do these numbers actually mean? To understand them, you have to understand how the window works.
26:32
Speaker A
The origin point is in the top left. This is position 0 for X and zero for Y.
26:39
Speaker A
If you go further to the right, then X is going to become larger and larger until you reach the right side. This at the moment would be position 1152.
26:49
Speaker A
Or in other words, this for example could be 100, this could be 200 and so on until we reach the right side of the window. I think this part makes sense.
27:00
Speaker A
The further right you get, the greater X becomes. On the Y-axis, this gets a bit more confusing. I think to go down, you want to increase the number. For example, this would be 100 pixels. If you go down a bit further, you'll be at
27:17
Speaker A
200 pixels. And if you keep on going down, at some point you reach the end of the window, which I think was 648.
27:25
Speaker A
This can be sometimes counterintuitive. you want to increase a number to go down. Most game engines work like that where the origin point is in the top left and if you want to go up then you have to go with negative numbers. So
27:38
Speaker A
this part here for example would be 100 especially in the beginning this can be confusing but once you work with it for a bit it does become fairly intuitive and just to play around with it for a bit if you have this note selected I can
27:53
Speaker A
set the value to zero and zero. That way we are right in the center. If I then increase this value for X to let's say 50, we are going further to the right. And if I set the Y value to
28:07
Speaker A
100, we're going quite a bit down. If I set Y to negative 100, then we are going up. And via that system, you can place different nodes inside of this window.
28:20
Speaker A
And well, with that, we have the foundation of GDU. At this point, you just have to learn about more nodes that do more things and you have to learn about GD script to make all of this interactive. To add a script to a scene,
28:32
Speaker A
you want to have a note selected and then click on this icon. Via that you can attach a script. Let's stick with our first scene. And then you can select the language. The default here is GDScript. That's totally fine. Then we
28:46
Speaker A
have inherit. This has to match the type of node that we are working with. And usually you want to stick with the default. The next important field is the path where we want to save the script that we are creating. Most of the time
28:59
Speaker A
you can stick with the defaults and simply click on create. Once you have that inside of the file system we have first scene.gd and we can write some code in here. That way we can create the logic for our
29:12
Speaker A
game. From this point on you can continue in two ways. If you don't know any coding, simply keep on watching from here. I will talk about the basics of coding. If however you already know some coding, even just a little bit,
29:29
Speaker A
I would recommend that you skip ahead and start with the first game. If you have done any kind of coding before, you should be good to go already. And of course, you can always go back and look at the coding part. I guess if you're
29:41
Speaker A
not sure, here are a couple of code snippets that we going to use inside of the first game. If this doesn't look overwhelming, you can safely skip ahead.
29:49
Speaker A
Let's get started with coding. And for this part, I will assume that you have never touched a programming language before. Don't worry, it's actually not that hard. In the most basic sense, all that we are doing is create some kind of
30:03
Speaker A
logic. For example, if you want to move an object to the right, if its position is less than 800 pixels, it would look something like this. We start by creating an if statement by writing if.
30:16
Speaker A
Then we are checking a value that can change. So this position X could be part of an object that is moving to the right. This we are comparing against a static value. In this case, 800. This condition can either be true or false.
30:32
Speaker A
If it is true, then we are doing the stuff that is indented on the next line.
30:37
Speaker A
And if that is the case, we're getting the current position x and we're assigning it a new value, which is going to be the current value plus five. So we are moving it further in a certain direction. And that's really all we are
30:51
Speaker A
doing most of the time. The majority of the logic isn't going to get that much more complicated. In practice, this kind of logic can be created in multiple different ways. Gudau is actually supporting multiple coding languages.
31:06
Speaker A
The default one is called GDScript, which is really, really easy to learn. It is actually very similar to Python, which is one of the most common programming languages. If you know GDScript, you basically know Python. And Python can be used for a ton of other
31:21
Speaker A
things like data science, databases, AI, and so on. Besides that, GDO does support other languages, but I'm going to focus on the basics. So, we're going to work with GDScript. Once we have that, to actually write code in GDO, you
31:36
Speaker A
want to attach a script to a note and via that you can change the property of that note like the position, size, rotation, and anything that you can find inside of the inspector. Or in other words, back inside of the scene that we
31:50
Speaker A
have seen earlier, if you click on this sprite 2D, you can change any of these properties like position, rotation, scale, and skew. You could also change the visibility, modulate, and really anything that you see in here can be
32:05
Speaker A
changed via GDScript. All you have to do is hover over the property and then Godo is telling you how you can change it.
32:12
Speaker A
And there can be a ton of information in here. You can also change other nodes, create new nodes, target other scenes, and even get data from the internet. There's basically no limit to what you can do.
32:25
Speaker A
GDO is incredibly flexible and lets you do a ton of things. We are nearly ready to start. There's just one more thing that we have to cover and that is that Gudau organizes the code via functions.
32:37
Speaker A
Functions in the most basic sense are just blocks of code. Via those you are grouping different lines of code together to do a certain thing. For now we are going to work inside of two functions that are inbuilt into GDO. The
32:52
Speaker A
ready function which is executed when a scene is ready. You see in a second what that means. Besides that we have the process function which is run on every single frame of the game. And before I start throwing too much theory at you
33:06
Speaker A
let's have a look at all of this in practice. Back inside of GDO, this is getting a bit too complex. So, I want to create a new scene, which is supposed to be a plain 2D scene.
33:21
Speaker A
Let's rename this one to coding one. This I want to save right away. You could create another folder in here if you click on this icon, but in my case, I'm going to leave it as it is. Click on
33:33
Speaker A
save. And now we have a scene with one node coding one which is totally fine for now. To this scene I want to add a script like we have done before. So attach a new script and leave all of the
33:47
Speaker A
defaults here in place. Then create. And now to actually do something we have to work inside of a function because remember all of the logic in good has to be inside of a function. To create a function, you want
34:03
Speaker A
to write the keyword funk and then the name of the function. You can basically choose any name in here, but there are some special names. They usually start with an underscore.
34:16
Speaker A
If you simply type an underscore, then GDO is suggesting you all of the inbuilt GDO functions. The one that I want to work with is ready. If you click on that, you get ready. then to parenthesis an arrow and then void. This last part
34:33
Speaker A
we actually don't need. So you can get rid of it to keep things easier. This would be the most basic way to create a function. You have the keyword funk.
34:42
Speaker A
This always has to be there. Then the name of the function and then two parenthesis. We will see later why these are important. If we only type this, GDO is going to complain which you can see at the bottom that GDO is expecting an
34:57
Speaker A
indented block after the function declaration which means we have declared a function here and after that if you press enter GDO is creating an indented line which basically means that we are pressing tap and whatever we are writing
35:12
Speaker A
next is going to be indented. Having this line being indented means it is part of this function. That way if we later on create another function let's call it something then anything that is indented afterwards is part of this
35:29
Speaker A
function or in other words via indentation you can group things together. So what can we actually do inside of this ready function? And well the most basic thing that you want to do is to print data for now. For that you
35:45
Speaker A
simply want to write print and then use parenthesis again. After that whatever you write inside of this print statement is going to be printed out once we are running the game. For now let's simply write a number 1 2 3. Could be any
36:01
Speaker A
number for now. It doesn't really matter. Once we have that we want to run this one scene coding one. If you simply click on this icon run project or F5 then nothing is going to happen because earlier we have set this first scene as
36:19
Speaker A
the main scene which means no matter where you are if you're clicking on this icon you always run the first scene. If you don't want that instead of coding one you can click on this icon here where you are running the current scene
36:32
Speaker A
or simply press F6. If you are doing that then the game is going to run and if you look at the bottom there we have the output tab and this at the moment says 1 2 3 that we are
36:46
Speaker A
getting because inside of script we are printing 1 2 and three once the scene is ready. Alternatively, what you can also do inside of project project settings, you can go to run and then set the main scene. I guess for now we can set the
37:03
Speaker A
main scene to coding one. Then I can close this dialogue and simply run the project.
37:11
Speaker A
And now we are running coding one via F5 or this button. At the moment we are using two inbuilt functions of GDO.
37:21
Speaker A
print is a function and ready is a function. But this might be a little bit confusing because for the first ready function we had to use funk whereas for the second function we don't do that. So what's happening here? To understand
37:36
Speaker A
that let's talk a bit more about functions. There are two things that we are doing at the moment. Number one is we are creating a function. For that we are using the funk keyword then the function name and then we have
37:49
Speaker A
parentheses that can accept parameters which we don't have at the moment that's going to come later but via those we could add information to the function.
37:58
Speaker A
After that we have indented code with the actual logic. Now the important thing is that this is only creating a function. It doesn't actually use that function at least by default. To actually use this function, you have to
38:12
Speaker A
call it, which is another way of saying that you want to execute the code that you have created. For that, you want to use the function name and then add in arguments depending on how many parameters you have. Now, in our case,
38:24
Speaker A
we are creating the ready function. And this function is special because GDO is calling it internally. Whenever we are executing the project, this function is being called by GDO once the scene is ready. So we only have to create it. GDO
38:40
Speaker A
is calling it for us. But for the print function, it's the other way around.
38:45
Speaker A
It's an inbuilt function into GDO. So we don't have to create it. We just have to call it. And when we are calling it, we have to add an argument into it. At the moment, this is 1, two, and three. And
38:58
Speaker A
the result of this is that GDO inside of output is printing one, two, and three.
39:05
Speaker A
If you want to display some text in here, you couldn't simply write something. That wouldn't work. Instead, I will talk about later why this doesn't work. But what you have to do is put this inside of quotation marks. Single
39:20
Speaker A
or double ones would both work. You just have to be consistent. I will use double ones because that's what GDAU uses internally, but it's really up to you. If I now run the project again, we get something inside
39:33
Speaker A
of the output. And that way you can print anything inside of the output. To practice all of this, I want you to create a new function and call it as well. So now we're doing both things.
39:46
Speaker A
The new function should print something and one to three. Or in other words, you want to call the print statement twice inside of that new function. And the new function itself you want to call inside of the ready function. Pause the video
40:01
Speaker A
now and try to figure this one out and see how far you get. First of all, we want to create a new function. For that, once again, we will need the funk keyword and then the name of our function. I guess I should have
40:17
Speaker A
mentioned this earlier, but this has to be inside of one string of characters. This could for example be something.
40:24
Speaker A
After that, you need the parenthesis, opening and closing ones, and then colons. Then inside of the function we need one level of indentation like so.
40:36
Speaker A
Kudo should be doing this automatically. And then we want to call the print function and write something.
40:44
Speaker A
And on the next line we also want to print 1 2 and three. Via that we have a new function that does two things. We are printing something and we are printing one two and three. But this function by default doesn't do anything.
40:58
Speaker A
If I run the code, the output is only something which we getting from this print statement. To actually use this function, you have to call it which you do by writing the function name in my case something and then add the
41:13
Speaker A
parentheses afterwards opening and closing once. If you're doing that, then we're getting something twice and then one two three. The first something comes from this print statement. The second one from this one. And then we get one, two, and three. I guess the
41:30
Speaker A
first print statement should say something else. Let's say test. Then this becomes a bit easier to see. We have test something and 1 2 3. And via that I think you can already see a couple of basic things. The most
41:43
Speaker A
important one is that GDO is executing code line by line. We are starting inside of the ready function which is called once the scene is ready. In there first of all we are calling print and test. After that we are calling the
41:59
Speaker A
something function which is down here. Inside of this function we are printing two more things something and 1 2 and three. Because of that we can see test first then we have something and then we have 1 2 and three. So with that already
42:18
Speaker A
we can create a new function and we can call functions as well either in built ones or ones that we have created ourselves. In a little bit we are going to talk a lot more about functions.
42:30
Speaker A
They tend to be slightly more advanced and usually you cover other things first but since GDO executes all of the code inside of functions I had to cover it right away. So I hope this part isn't too confusing. The only thing that you
42:43
Speaker A
have to really understand is that you are creating functions via funk, the name of the function and then parenthesis. Also, don't forget about the colon. You want to indent some lines so you know that this line belongs to
42:56
Speaker A
this function. After which you can write any kind of logic. In the next part, we're going to talk about that a lot more. To call a function, you want to write the name of the function and then parenthesis. Inside of the parenthesis
43:09
Speaker A
you can add arguments which we don't have for the something function the one that we created but for the print statement we can add one argument and this one prints a certain thing. So with that we have functions.
43:22
Speaker A
Next up then we can work on actual logic. Now that we can create basic functions we can work on logic and variables. And let's start with logic right away inside of GDO. Here we are again and I want to keep on working
43:37
Speaker A
inside of coding one specifically this script. At the moment we are only printing test which doesn't really do very much. So instead let's do something a bit more interesting and I guess while we are here we can get rid of all of this stuff
43:54
Speaker A
as well because it's going to be a bit confusing. I only want to have the ready function where we are printing something.
44:03
Speaker A
And that something is not going to be a word. It's going to be a math equation.
44:10
Speaker A
And for that you can simply type something like 2 + 2. Run the project.
44:16
Speaker A
Then you get the result four. Other operations would be 2 minus 2. Then we get zero. You can also do two multiplied with two or let's say two multiplied with three. That way we are going to get six. And finally you can do
44:34
Speaker A
two / 3. Although then we would be getting zero because GDO is rounding this value that we can change later. For now not too important. Let's do 9 / 3.
44:45
Speaker A
That way we're getting three as the result. These would be very basic things that you can do via math inside of GDO.
44:52
Speaker A
And Gudo supports a huge range of math operations. The best way to learn about them is to use the documentation.
45:02
Speaker A
GDO actually has multiple kinds of documentation. There's one inside of the GDO engine right away. If you click on help, there's search help and then you basically get an overview of all of the parts of the engine.
45:18
Speaker A
This isn't really a tutorial. It's more of a manual. If you go to Google, you can look for GDScript reference.
45:27
Speaker A
That way, the first result should be the Godo documentation. If you click on that, you get a page that tells you all about GDScript. It is quite a long page, but in there, you have a ton of information. I would recommend to have
45:44
Speaker A
this page open all the time. It's super super useful. Right at the beginning, we have an example of GDScript. And there are some things that we have already seen like for example a function with a couple of parameters that we're going to
45:56
Speaker A
cover later. Besides that, there are loads of things that you haven't seen yet. So don't worry too much about it.
46:02
Speaker A
Instead, go down a bit further to the operator part. In there, you can see all of the math operations like x + y, x - y, and then you get all of the other operations as well. The only
46:19
Speaker A
things that you need for now are these operations. Everything else is going to be a bit confusing, but it is still super useful to at least have a look at this page and see what you can be doing.
46:30
Speaker A
By the end of this course, all of this is going to make sense. Now, using this information is really important. So, I want you to do an exercise right away. I want you to calculate Pythagoras theorem where site A is 10 and site B is 20.
46:44
Speaker A
calculate the output using GDScript. Just in case you don't know what Pythagoras theorem is, you can go to Google and then look for Pythagoras theorem calculator.
46:59
Speaker A
Then Google is giving you the formula that you have to write inside of GDScript.
47:05
Speaker A
You're taking the square root of the square of A plus the square of B. Via that formula you can calculate a side C inside of a triangle simply from knowing side A and side B. So in our case we
47:20
Speaker A
know side A is 10 and side B is 20. The result should be around 22. This is what you should be getting. So effectively what I want you to do is to put this formula into GDScript.
47:35
Speaker A
For all of that, you want to look at these couple of lines inside of the documentation and figure out how to combine them. Pause the video now and see how far you get.
47:49
Speaker A
Back inside of good do I want to print the result like we have seen before.
47:56
Speaker A
Although before that I want to add a hashtag and then add exercise. If you add a hashtag, then good knows this is going to be a comment, meaning the code is going to entirely ignore whatever you write in here, which makes it much
48:11
Speaker A
easier to document your code. Not something you have to do, but I think in this case it does make things a bit easier to read. Once we have that, we have to write the actual formula. You can see it in the bottom right at the
48:23
Speaker A
moment. First of all, we want to get a squared which in our case is 10 and then squared which you do by adding two asterisks and then two. That way you are squaring the number 10. Then we want to
48:37
Speaker A
add something which is the value for B which in our case is 20 which we also want to square. So two asterisks and then a two. If we run the project now we are getting 500.
48:51
Speaker A
That is because the square of 10 is 100 and the square of 20 is 400. If you add both of them together, you're getting 500. But now we have to take the square root of all of this. Now getting the
49:06
Speaker A
square root might have been one part that is a bit more complicated because there's no square root in any of this.
49:14
Speaker A
However, what you can do is use the power once again. If you take half the power of any value, you are taking the square root. Or in other words, let me demonstrate it really quickly. We can print 9 asterisk asterisk. So the power
49:32
Speaker A
of 0.5. That way we are taking the square root of 9. The result is going to be three or at least I hope it is. And it is 3.0.
49:42
Speaker A
However, now there's another thing that we do have to worry about. If I simply add asterisk asterisk and 0.5, we are not going to get 22. If I run the entire thing, we are getting 120. And we only focus on the value. Let me get rid
50:01
Speaker A
of this one. This value should return 22. Whatever we have seen down here with 22. The reason why we don't see it is because this square root only applies to this value, but we want to apply it to the entire
50:19
Speaker A
thing. To do that, you want to wrap them inside of parentheses like so. And let me add a bit more spacing to this. That way, it's going to be a bit more visible. We first of all want to do
50:33
Speaker A
this operation and then take the square root of the entire thing. via these parenthesis, we can control the order of operation. If I now run the entire thing, we should be getting 22 something. And we do. This looks really
50:47
Speaker A
good. So, I hope this part wasn't too overwhelming, but effectively we have used different kind of equations and put them together to create a bit more advanced logic. And this logic you can control via parentheses. And that way,
51:02
Speaker A
with a bit of practice, this should become fairly straightforward. But now what if we want to make all of this more dynamic where the numbers aren't always going to be 10 or 20. For that we have to learn about variables. Variables are
51:17
Speaker A
basically buckets that store data. You can either read them or you can change the value.
51:24
Speaker A
This is super useful to keep things organized. And once again, if you look at the GDScript reference at the top, we have a whole bunch of variables. Let's create some of those. Those you can create outside of a function. And they
51:41
Speaker A
are just about the only thing that you can create outside of a function. To create a variable, you always start with var. That way, Godo knows you want to create a variable. Then you need a variable name. This could, for example,
51:54
Speaker A
just be a. After that you want to assign a value to this variable which you do via equal and then the value you want to assign like for example E 10. Next up we can create another variable B and this
52:09
Speaker A
one can be 20. And now you have two variables which you can use inside of this equation. All you have to do is replace the 10 with A and the 20 with B.
52:22
Speaker A
If you run the code now, we are still getting 22 something. But if I change these variables to let's say 20 and 30, then we're getting something else.
52:35
Speaker A
Whatever the output is, via that system, you can be much more descriptive in terms of what your code can do. So I think just looking at this, it makes quite a bit more sense instead of just having random numbers in here. Although
52:49
Speaker A
when you're naming variables, you do want to be careful. There are a couple of things that you have to do.
52:56
Speaker A
Number one, variable names cannot start with a number, have a space in them, or use special symbols like the dollar and the amperand symbol. Those are reserved by GDU. Other than that, you are basically good to go. And by the way,
53:11
Speaker A
these rules also apply to functions. They basically have the same kind of naming scheme. Besides that, variable names are usually written in the snake case convention, meaning you only use lowercase letters and if there's a space, you use an underscore. That's
53:28
Speaker A
what most people use, but it's just a convention. You don't have to follow it.
53:32
Speaker A
That being said, it is recommended that you do. For example, instead of simply using A, you might want to go with site A. And for B, you want to have site underscoreb.
53:49
Speaker A
Once you're doing that, GDO is complaining because now variable A and variable B don't exist anymore. Instead, they have been renamed to side A and side B. Once you're doing that, GDAU is happy again and we are good to go. That
54:07
Speaker A
way, the variable naming is also a lot more descriptive. Most of the time you do want to be quite careful how you name variables.
54:16
Speaker A
If you mess this up and your code becomes more complex, this can be incredibly confusing. Other than that though, this is basically how you create variables. You create them in the first few lines of the code and then inside of
54:28
Speaker A
any function you can use them as a standin for any other number. So at the moment we are simply reading a variable. Besides that, what you can also do is overwrite the value. So for example, site A can be instead of 20 a 100. After the
54:48
Speaker A
line, I can print site A again. Run the code. And now as an output, we are getting 100. And I think now it's important to understand how GDO is executing the code.
55:02
Speaker A
It goes through it line by line. It first does this line, then it does this line and then it does this line. Because of that for this formula, the value of site A is 20. But on the next line, we
55:16
Speaker A
are changing that value to 100. And just to demonstrate, let me run the project.
55:21
Speaker A
The current output of the formula is 36 something. This is what we're getting from this statement. But if we move site A being 100 one line before that and run the thing again then we getting a different number 104. That is because now site A
55:40
Speaker A
is 100. So inside of this formula site A is 100. But if we update value A afterwards then this site A is what we're getting up here 20 in my case. So it's really important to understand how this code is executed. Udo goes through
55:57
Speaker A
it line by line and then simply goes through all of these operations. Really important to understand sometimes this can give you some weird results.
56:08
Speaker A
Besides that, along with variables, we have to learn about data types. Now, inside of GDO, there are a ton of different kinds of data types. So, for now, I am only going to focus on the most common ones. First of all, we have
56:23
Speaker A
text. These inside of GDO and really any kind of programming language are called strings. You are creating them via double or single quotation marks and then whatever kind of text you want to have inside of them. Besides that, we
56:36
Speaker A
have numbers and those are actually two data types. We have integers and floatingoint values or simply floats.
56:45
Speaker A
The difference between them is that integers are full numbers meaning 1 2 3 20 and so on. could also be negative like negative 100.
56:54
Speaker A
Loing point values have decimal points like 1.0 would be a floatingoint value. Could also be 1.5 or -2.4.
57:03
Speaker A
Then we have true and false values. Those are called booleans. They can only be true or false. Once we get to if statements, those are becoming incredibly useful. Finally, we have different kinds of lists. Those can store multiple values inside of a single
57:20
Speaker A
variable. Now those I am not really going to touch yet. There's going to be a separate part on them. But there you have arrays, dictionaries, and vectors.
57:30
Speaker A
I do want to mention them now because they are incredibly important, really, really common. Variables and data types.
57:38
Speaker A
You can force a variable to only accept a certain data type. For example, you can tell a variable to only hold integers or floatingoint values. That way, it would be impossible to assign text to it, which is generally a good
57:53
Speaker A
idea. It's a good safeguard to make sure a variable doesn't get the wrong kind of data. Although, if you don't do that, variables by default can hold any kind of data. But let's play around with all of that. Back inside of GDU, let's say I
58:08
Speaker A
want to create a new variable. And this can just be called test. Test should only hold strings. Like for example, sum test string. This value I want to print.
58:23
Speaker A
And this we can do all the way at the end inside of the ready function. I want to print test.
58:30
Speaker A
If I now run the project, we're getting some test string that works pretty well.
58:36
Speaker A
We are printing this piece of text or this string. However, before this final line, we can assign a different value to test like for example 1 2 and three. If I now run the code as an output, we're
58:52
Speaker A
getting 1 2 and three, which would be an integer because now we have a full number. If we want to avoid this kind of behavior, what you can do after naming this variable test, you can add a colon
59:07
Speaker A
and then tell it to always be a certain kind of data type. For example, a string.
59:14
Speaker A
If we have that set up, then good on this line is going to throw an error that we cannot assign a value of type integer as a string. We are telling GDO that this variable always has to be a
59:27
Speaker A
string. Meaning we cannot assign an integer to it. If we change this to some other string, GDO would be perfectly happy because we still have a string. Besides string, we also have integer.
59:45
Speaker A
And if I do that, Gdor is going to complain on these two lines that we are trying to assign a string to a variable that can only hold integers. Which means now this has to be numbers. So 1 2 3 or
60:00
Speaker A
really any other number. Via that you can be very explicit in terms of what kind of value you are working with, which usually is a good idea, especially once projects become more complex. You want to be very very explicit in terms
60:14
Speaker A
of what values you have. Without that you can very easily get some random errors that you don't understand and always having the right data type is a good way to avoid that. Now this can be sped up quite a bit. If you simply add
60:29
Speaker A
colon and equal to a certain kind of value then you're forcing this variable to only hold the data type that is first assigned to it. In this case an integer.
60:40
Speaker A
Meaning now if I try to add a different kind of value to test like for example a string then good is going to complain because this variable can only hold a type integer because that's what we first assigned to it
60:58
Speaker A
or in other words this has to be a string. So with that we have different kinds of data types. We have integers and we have strings. Besides that, you can also add floatingoint values like 30.0 or let's say 30.2. Now, both of
61:17
Speaker A
those are numbers and if you use them inside of an equation, they would still work. So, if I run the code, good is still going to execute all of this and we are good to go. But sometimes this
61:28
Speaker A
difference between an integer and a floatingoint value does become apparent. We have actually seen this earlier. If we have two divided by three. So the first operation we did in the beginning we have gotten is zero because we are
61:46
Speaker A
dividing an integer by another integer and the result is also going to be an integer which has to be a full number.
61:54
Speaker A
Is actually giving us a warning about that. If you look at the debugger down here we are getting errors although in there we have errors and warnings.
62:02
Speaker A
Yellow ones are warnings. we have an integer division where the decimal part will be discarded. That happens on this line. To avoid that, to get an actual value, you want to have 2.0 divided by 3.0.
62:18
Speaker A
That way, if I run the thing again, we are getting an actual value 0.666 and so on. So sometimes using different data types is incredibly important even for basic math equations and without knowing the different data types. This kind of
62:35
Speaker A
behavior would be very confusing. So always make sure when you want to have very precise results you want to use floatingoint values. Anything with a decimal. The next important part are properties and methods. And those you kind of actually already understand but
62:53
Speaker A
let's go through it step by step. So far we have covered variables and functions.
62:59
Speaker A
Variables store values and functions are blocks of code that you can execute. I hope at this point this is reasonably straightforward. But besides that we have properties and methods. These are also basically variables and functions but they belong to an object like a
63:16
Speaker A
sprite 2D for example. Or in other words, inside of a sprite 2D, we have a position which is just storing the position of that sprite 2D. Besides that, the sprite 2D has functions that are part of it. Like for example, look
63:31
Speaker A
at and that way you are rotating the sprite 2D to look at a certain point. In practice, position and look at are just a variable and a function. But to emphasize that they are part of an object. We are calling them a property
63:47
Speaker A
and a method. There isn't really that much of a difference. The only thing that you really have to be careful about is that you adding a dot after the object and then you can use the property or the method. Once you understand that
64:02
Speaker A
system, you can actually dynamically change nodes inside of GDScript which gets you a lot closer to an actual game.
64:10
Speaker A
So let's have a look back inside of GDU. I want to create a new scene where once again we have a 2D scene as a root node which I want to rename to coding 2.
64:22
Speaker A
Maybe not the best name, but it's good enough for now. This I want to save right away as coding 2.
64:28
Speaker A
After that I want to assign a script to it called coding two. That way once again we have another script and we still have coding one and the first scene. Now in here I want to work with a
64:43
Speaker A
sprite 2D which at the moment is difficult because inside of this scene we don't have a sprite 2D that however we can change by simply clicking on plus and then adding a sprite 2D which once again needs to have the texture. So
64:59
Speaker A
let's drag it in there. And then we have the GDO logo. As a reminder, inside of the inspector, we can see all of the properties of this object. For example, there we have position, we have rotation, we have scale, and so on. And
65:14
Speaker A
to be a bit more explicit, this sprite ID is an object, or to be fully precise, it's an instance of an object, which is a fancy way of saying it's one object that we can use inside our game. That
65:28
Speaker A
means inside of GDScript we can access all of the properties and methods of the sprite 2D. This once again has to happen inside of a function. So let's work with function ready.
65:42
Speaker A
Once again we don't need this void part to avoid confusion. Let me remove it.
65:47
Speaker A
I'll talk about later what it actually means. To actually work with this sprite 2D you can simply drag it into the code like so. And then you can see what GDO actually does. It adds a dollar sign and
66:00
Speaker A
then the name of the node that you want to work with. That way you're getting the object and on this object you can add a dot and then get all of the properties. For example, somewhere we should be having a position. This should
66:15
Speaker A
give us the same position that we can see inside of the inspector which at the moment is 251 and 169. This value we want to print. So we want to put it inside of the print statement and then
66:30
Speaker A
run the current scene. Really important. Coding one is the main scene at the moment. But we want to run coding two.
66:38
Speaker A
So you don't want to click on this button. You want to click on this run current scene button. If you're doing that, you can see the good logo. That looks good. And you can see the position inside of output. We're getting 251 and
66:53
Speaker A
169. Exactly what we can see inside of the inspector. Besides that, we can also get the rotation of the sprite 2D. Let me run the current scene again. We should be getting 0.0.
67:09
Speaker A
And we do. That looks really good. So, fundamentally, this rotation is a variable. It stores a certain kind of value. whatever we are getting inside of rotation but it is called a property because it is part of a sprite 2D. That
67:25
Speaker A
being said, it behaves just like a variable which means we can assign a value to it. For example, the rotation could be 20.
67:36
Speaker A
If I now run the current scene again, then we're getting an output of 20. And on top of that, the GDO logo is rotated by 20° via that system. You can update all of the nodes inside of GDO in real
67:50
Speaker A
time which is how you get an actually dynamic game. This would be properties. Besides that, we have methods which are basically functions that are part of an object. So once again I want to have the sprite 2D. For that you can either write
68:07
Speaker A
the dollar sign and then sprite 2D or you can simply drag and drop the note in there like so. whatever you prefer.
68:18
Speaker A
If you now add a dot, GDO is giving you all of the properties and methods of this object. And if you scroll around, you can see there are well a lot. The most important ones are usually at the
68:31
Speaker A
top. If the left thing says P, you're getting a property. If it says F, you're getting a method. There are a few more.
68:40
Speaker A
I'll talk about those later. They aren't too important for now. Most of those are properties and functions. One method that is very easy to use is rotate.
68:50
Speaker A
This is a method that kind of does the same thing that we have done up here. It rotates the node by a certain amount.
68:58
Speaker A
Let's say 90°. And I want to comment out this line by adding a hashtag in front of it. If I now run the current scene then you can see the good logo is rotated by a certain amount 90° and on
69:13
Speaker A
top of that we are printing 90° because we are using this print statement. Once you have all of that you can actually start moving this node 2D inside of the scene. For that though, first of all, I want to get rid of all of the stuff that
69:29
Speaker A
we have done so far and instead introduce another function that GDO calls automatically. It is called underscore process. This one is slightly more advanced. Now we have one parameter that we can actually entirely ignore. So don't worry about this part. On top of
69:47
Speaker A
that, we can get rid of this void. But don't forget the colon. This process is called constantly. Every time GDO generates a frame, it is calling process. Or in other words, if I now print something, this something is going to be
70:05
Speaker A
printed multiple times per second. So if I run this current scene, we get something a lot. So there you can see the outputs we have, they are increasing very very fast, which is totally fine.
70:17
Speaker A
In fact, this is what we want because now I can grab the sprite 2D and then rotate it by a certain amount. Let's say something very slow, 0.5.
70:30
Speaker A
If I now run the current scene, then the goodo logo is going to rotate. It is going to rotate quite fast. But that we can control. Let's say 0.1 in here. That way, this feels a bit better. Besides
70:45
Speaker A
that, we can also move this sprite to D in any direction. Although for that, we have to target the position, which if you hover over it inside of the inspector has a data type of a vector 2.
71:01
Speaker A
This value here, I'll cover this kind of value in the next part. But basically, via a vector 2, we get a list that has two values for X and Y. Those we can target via dox and doy. Let's say for
71:15
Speaker A
now I only want to have dox. And this value should get the current position of the note.
71:25
Speaker A
Let me add a bit more space so we can see this properly. I want to assign a new x position to the note that is the current value plus some kind of addition. Let's say plus one.
71:40
Speaker A
And then if I run the script again, the good logo is going to be very slowly moving to the right.
71:50
Speaker A
If I increase this value to let's say 10 and try this again, it's going to be more visible. Now GDAU is moving to the right. So with very few lines of code, we can move stuff around inside of the
72:03
Speaker A
game. By the way, this kind of operation is really common and there's a shortand to make it easier to write. Instead of writing all of this, we can simply write plus equal 10. That way, we're getting the current value and adding something
72:20
Speaker A
to it. In other words, these two statements are doing the same thing except that the second one is much easier to read. As a consequence, let me comment out the first one. If I now run the game again, we are getting the same
72:36
Speaker A
result. Most of the time you are going to use this kind of line. It's just much easier to write. All of this we should be practicing. So I want you guys to create another moving sprite 2D. This one should move from the top left to the
72:51
Speaker A
bottom right. And while it is doing that, it should also scale up. Pause the video now and try to implement this kind of logic.
73:03
Speaker A
I want to add another sprite 2D to the scene and make sure this sprite 2D2 is not a child of the first sprite 2D. In fact, let me rename it to exercise sprite. That way, it's a bit easier to
73:19
Speaker A
read. This exercise sprite once again will need a texture inside of the inspector. Otherwise, we can't see it.
73:27
Speaker A
Drag the GDO icon into it. And there we go. In the top left, we have the GDO icon. After that, inside of the script in the process function, I want to add another comment for the exercise.
73:43
Speaker A
Now, in here, I want to get the exercise sprite and do a couple of things. First of all, I want to get the position dox plus equal, let's say, five. That way, this sprite is going to move to the
74:00
Speaker A
right. And to make them a bit easier to distinguish, this exercise sprite under visibility and modulate is going to get a different color. Let's make it really blue. Something like so.
74:13
Speaker A
Doesn't really matter, but it makes it a bit easier to understand. Now, we have both of the good logos moving to the right. Good start. Besides that, I want to duplicate this line.
74:27
Speaker A
which I can do by pressing control or command shift and D. Besides X of the position, I also want to update position.y and increase this value. Remember, if you want to go down, you have to increase the Y value. If I now run the
74:47
Speaker A
project again, the Gau logo is moving to the bottom right. We could reduce the speed here just a bit to let's say three. That way we are going a bit more towards the actual bottom right of the window. Also in just a bit we're going
75:03
Speaker A
to find a better way to update the position. So you don't always have to target X and Y separately.
75:09
Speaker A
But for now I want to press control shift and D again because besides the position I also want to get the scale.
75:17
Speaker A
Now for this one you do want to be careful. If you add plus three in here and run the thing, then you get some weird behavior. We are scaling this thing up very very fast.
75:30
Speaker A
A better way would be to multiply the current value with something like 1.1 like we have seen with plus equal.
75:39
Speaker A
Multiply equal takes the current value and multiplies it with whatever you write in here. That way, this scaling becomes well, still quite fast, but a lot slower than before. Let's set this to 1.001.
75:54
Speaker A
That way, it doesn't grow that fast. I guess you can still kind of see it. Once again, control or command shift and D and then scale.x.
76:07
Speaker A
And now we are scaling the GDO logo in all directions. A bit hard to see. Let's do this with 1.005.
76:19
Speaker A
That way it should be more visible. And there we go. This is definitely scaling up. With that, we have learned about properties and methods, which are basically variables and functions, but they are part of an object. Like for
76:34
Speaker A
example, a sprite 2D. Once we have that, we can actually do dynamic things inside of the game, which is a massive upgrade. And to get really good at GDO, you want to be able to use as many properties and functions of an
76:50
Speaker A
object as you can. The best way to learn about them is to go to help and then to search help. That gives you once again to go documentation.
77:02
Speaker A
In there, for example, you can look for sprite 2D. double click on it and then inside of the script view you are getting the documentation for sprite 2D.
77:13
Speaker A
There you can see all of the properties and all of the methods or at least some of them. If you go a bit further down, you're getting a lot of descriptions in terms of what you can do. Being able to
77:25
Speaker A
read through here and understand what's going on is incredibly helpful to really get good at.
77:32
Speaker A
With that, really quickly before we finish, back inside of coding 2. At the moment, we have a script attached to the parent note coding 2 of type node 2D.
77:44
Speaker A
And from there, we are influencing a sprite 2D or the exercise sprite here and here. But what if you want to influence the note itself with the script? In our case, this note 2D. Let's say for example once the scene is ready
78:02
Speaker A
bunk ready then we want to move this node or in other words the entire scene to the right.
78:13
Speaker A
Well for that all you have to do is grab the property of this current node and you can do that right away. For example if you want to update the position you just have to type position without any
78:25
Speaker A
of the dollar sign stuff before it. Once again, you just want to look at the inspector and then find a property that you want to change like position at the moment. This once again is a vector 2.
78:36
Speaker A
So in there we have position dox. And this we could set for example to a value of 200.
78:45
Speaker A
If I now run the script, everything is going to be 200 pixels further to the right. A bit hard to see. I guess if I change this to 600, it's going to be much more visible. Here you can see now everything starts much
79:00
Speaker A
further to the right. And that's basically the system. If you have the note itself with the script, you simply target the property or you can call a method. And if you have a child, you target that child with the dollar sign
79:12
Speaker A
and then the name of the node. After that, you can call any kind of method or use any property that you want. The next important topic is going to be booleans and logic flow.
79:26
Speaker A
Via that we are going to learn about if and while statements. These allow you to control what code gets run and how often it gets run. Using an if statement, you can run a code once if a certain
79:39
Speaker A
condition is true. With the while statement, you can run code forever as long as a condition is true. Both of these are really easy to implement, but we have to figure out what is true inside of code. And for
79:55
Speaker A
that we have to look at the data types again. Up to this point we basically only worked with text and numbers. Those at this point I hope are at least reasonably straightforward. Next up we are going to look at booleans which can
80:11
Speaker A
only be true or false. That's the only two options that you have. So let's talk about how to create these kind of values. And most of the time you are creating them by a logical operators. We have smaller than, greater than, is
80:27
Speaker A
equal to, is smaller than or is equal to, and is greater than or is equal to.
80:33
Speaker A
All of these operations are either true or false, which is a boolean value. Now, there are other ways to create boolean values in GDO, but those aren't that important yet. Although what is important to mention that you can also combine
80:48
Speaker A
multiple conditions like for example a is greater than 5 and b is equal to two.
80:54
Speaker A
And by the way if you're wondering why we using two equal signs for the comparison here that happens because when you are creating a variable and you assign a value to it for that we are using the equal sign already and we
81:08
Speaker A
can't use it here and here at the same time. For all of this, I want to work in GDO once again. Create a new scene where the root node is a 2D node. Let's call this coding three boolean to add a bit
81:26
Speaker A
more detail. Then I can zoom in a bit and add a sprite to the scene like so. After that, I want to attach a script to the scene like we have done before. All the defaults here are totally fine. and then
81:42
Speaker A
create. Just for testing purposes, I want to create a funk ready. In there for a really really basic if statement, you first of all want to type the if keyword and then the condition that you want to check. For example, 10
82:02
Speaker A
is greater than five, which is going to be true. If that is the case, add a colon and press enter. Then once again we have an indented line. By that you know that any code that comes afterwards is part of this if statement. Just like
82:21
Speaker A
for the if statement we have one level of indentation. And that way we know that the if statement belongs to the ready function.
82:29
Speaker A
Same system really. Now if this statement is true I want to print let's say 10 is greater than five. Now I want to save the entire scene. Coding free boolean.tsn is totally fine. Click on save and then run all of this.
82:49
Speaker A
In the output we're getting 10 is greater than five which is perfect. If however I change this condition to four is greater than five and run this again then we are not getting any kind of output.
83:03
Speaker A
This line only gets run if this condition is true. If it is not, then GDO is going to ignore all of this. And to go into a bit more detail, let me get rid of all of this and then print the
83:18
Speaker A
comparison operator right away. Let's say four is greater than five, which we know is not true. But if I run the script, then Gudo is telling me that this is false and this is a boolean data type.
83:34
Speaker A
If I make this a true statement, let's say 7 is greater than five and run this again, then we're getting true. Other comparison operators would be an equal comparison for which you need two equal signs.
83:48
Speaker A
And for this, let's check if five is equal to five, which it should be. And it is perfect. If I change this number to a true, then this is going to be false. And besides that, we have smaller
84:03
Speaker A
or equal to and greater or equal to. Besides that, one more that I forgot to mention is this one which checks if two values are different from each other. So at the moment we're checking if two is different from five which it is. So if I
84:21
Speaker A
run this then we're getting true. However, if I check five is different from five then we're getting false because well five is five. So with that we have basic boolean values and we can use them inside of an if statement. Once
84:38
Speaker A
again as a reminder all you need is if and then let's say four is equal to four a colon and after that you can run any kind of logic. Let's say print four.
84:52
Speaker A
Besides that what you can also do is via and expand the if statement. So for example, we only want to run this if statement if four is equal to 4 and if 10 is greater than three. Both of these
85:10
Speaker A
statements are true. That way we're getting four. However, if one of them is wrong, then this if statement is not going to run. So if I change the three to an 11, then this if statement is not going to run. Both of
85:27
Speaker A
these statements need to be correct. If you only care about one of them, you can use the or keyword. That way, only one of those has to be true. So, if I run it now, since 4 is equal 4, that part is
85:42
Speaker A
true, the entire thing is still going to be run even though 10 is not greater than 11. And that's pretty much it for basic if statements. Although, there's one more thing that you can do. Two more things actually.
85:57
Speaker A
For a basic if statement, let's say if and I want to have a false statement or is greater than 10.
86:08
Speaker A
If that is the case, I want to print a. This condition obviously is not going to run. However, if it is not running, I want to do something else instead that I can do via the else statement.
86:23
Speaker A
in which case I want to print E. What is going to happen now is that GDO checks this if statement first. If it is correct, it's going to run this line.
86:34
Speaker A
However, if this doesn't run, so it's false, then GDO is going to run the else statement and we'll print B. Or in other words, if I run this now, we should be seeing B. And we do.
86:46
Speaker A
However, if this statement was to be true, then it would only run the first line, in which case we would get a. You only ever get one of these. They can't run at the same time. And you can be
87:00
Speaker A
even more detailed in here via the l if statement. This is going to run if this one is false and you want to attach another condition to it. Let's say one is equal to one. If that is the case, I want to
87:16
Speaker A
print C. And let's make sure the first condition is going to be false. So 8 is greater than 10. They can run the thing again. And now we should be seeing C.
87:26
Speaker A
And we do. So at the moment, GDO starts on this line and checks if it's true, which at the moment it's not. Because of that, it's going to the L if condition and then checks the boolean value. In
87:39
Speaker A
this case, this one is true. So it runs C and then discards anything that comes afterwards.
87:46
Speaker A
However, if this condition wasn't true, let's say two is equal to one. Then GDO is going to print B. So it checks this condition. It's false. It goes to the next one. It's still false. So it goes to else and we're getting B. Obviously,
88:02
Speaker A
these conditions aren't really that useful yet. But once we start using properties and things like note positions or health values, this becomes incredibly powerful. If statements are being used all the time, you see them constantly.
88:17
Speaker A
So something we are definitely going to practice in just a bit. First of all though, there's one more way to execute code that you don't see that often, and that is a while loop.
88:30
Speaker A
This while loop runs code as long as a condition is true, which means you do have to be really really careful. If you do something like while one is equal to 1 and then you run any kind of code in
88:44
Speaker A
here, let's say print a, this while loop is never going to stop. Meaning any code that comes afterwards is not going to be executed. The code would simply stop working. In fact, if I run this now, we would get a ton of output. So, if you
89:03
Speaker A
look at the console, you can see a ton of stuff, but well, good doesn't run well anymore simply because this line destroys everything.
89:13
Speaker A
And now, good has crashed. So, when you're using while loops, you do want to be careful. Here we are again. And let's create a while loop that doesn't crash good. For that you want to create a condition that doesn't stay true
89:26
Speaker A
forever. I think the best way to approach that is by first of all creating a variable.
89:32
Speaker A
Let's say var a and this has to be an integer with a default value of zero.
89:38
Speaker A
This we can make a bit shorter by simply doing this. That way we have a variable with the name a and we're assigning an integer to it. And because of this colon, this variable can only have integers.
89:53
Speaker A
this we want to use inside of this while loop. Let's say I want to check while a is smaller than 10.
90:02
Speaker A
While that is the case, I want to print the value of a and then also print while loop is running.
90:13
Speaker A
This would still crash good because a doesn't change. It will always be below 10 because the current value is zero.
90:21
Speaker A
However, what we can do is a plus equal 1. That way, this condition is going to be false eventually. Let's try to run the scene.
90:34
Speaker A
We are getting the scene running perfectly fine. GDO doesn't crash. That's a good start. And inside of the output, we are getting zero. Y loop is running one 2 three and so on. We're getting up to nine. and then the while loop has
90:52
Speaker A
stopped. That way we could run code multiple times which occasionally can be super useful. Although in practice you don't really see while loops simply because if anything goes wrong you are crashing the entire game and there are better ways to
91:08
Speaker A
run code multiple times. But once in a while it does come up and you do want to know what it's doing.
91:15
Speaker A
That being said, what you really want to practice is the if statement. So let's do that. I want you guys to bounce the sprite that we have created left and right. Or in other words, make the sprite move left and right. And whenever
91:27
Speaker A
it hits the window border, make it bounce in the other direction. There are a couple of ways of doing that. I guess just get started and see how far you get.
91:40
Speaker A
First of all, we want to move this icon. I guess we can start by moving it to the right. For that we will need the funk underscore process.
91:52
Speaker A
I want to grab the icon update the position.x and let's say plus equal. If I run the scene the icon should move to the right. That's a bit slow. I guess we can go with 10.
92:11
Speaker A
And that looks reasonably all right. Although this number has to change. So if we hit the right side of the window, this 10 should become a - 10. I think the best way to approach that is to create a var direction which once again
92:27
Speaker A
is going to be an integer and the default value should be one. After that I want to multiply this 10 with the direction. That way by default with this value being one, this value keeps on being a 10. In other words, we are still
92:43
Speaker A
moving to the right. That looks good. But if we change this one to a negative one and run the whole thing again, then we are going left. And we do perfect. In fact, what we can do is replace this 10
92:56
Speaker A
with a proper variable like for example speed. This once again could just be an integer with a default value of let's say 15.
93:05
Speaker A
This 10 was still a bit slow. And instead of this 10, I want to have speed.
93:12
Speaker A
That way we can control the speed and the direction of this sprite 2D. And this kind of logic you see a lot where you have a speed and the direction and this you apply to some kind of node. We
93:25
Speaker A
are getting really close to having actual games. But anyway, for now the start direction should be one. So we are going to the right. However, on every single frame of the game, I want to check if the icon.position position.x
93:44
Speaker A
is smaller than or equal to the right side of the window which in this project is under display and window 1152.
93:54
Speaker A
If you change this number, go with whatever is in here. In my case, I want to check if the icon position.x is greater than 1152.
94:04
Speaker A
If that is the case, direction should be -1. That way if I run the scene we are going to the left and I realized this should be greater than or equal to 1152. That way this should actually work. And now
94:25
Speaker A
we are going to the right by default. And then we are bouncing and going to the left. Although we never go back.
94:32
Speaker A
That we can address via another if statement where we want to check. Let me copy all of this. If the current position dox is smaller or equal to zero. If that is the case, direction should be one again. And if I now run
94:53
Speaker A
out of this again, the sprite 2D should bounce left and right. And it does. That looks pretty good. And all right with that we have if statements and while loops but most importantly if statements. Next up we're going to work with data. Once again here
95:15
Speaker A
are the most common data types I have talked about earlier. At this point we have covered the first three. So we should be good on those. So finally we can work on arrays, dictionaries and vectors. Vectors is what we're going to
95:30
Speaker A
start with because those you are going to use the most. Vectors are basically a better way to store numbers. We have vector twos and vector threes. Now technically there also vector fours 5 6 and so on but we only really use vector
95:46
Speaker A
twos and vector threes or a vector 2. It just stores two numbers vector 2.x and vector 2 doy. If you have a vector 3 then you have x y and z. Other than that they work in exactly the same way. By that system,
96:03
Speaker A
you can store, for example, positions incredibly easily. On top of that, vectors are really useful because of vector math. The most common example is when you multiply a vector 2 with a integer or a float, doesn't really matter. In that case, you are
96:20
Speaker A
multiplying both values. So, the five becomes a 10 and the two becomes a four. Both were multiplied with two. Besides that, you can add two vectors to each other. That way you are adding the x part. So in this case, the
96:36
Speaker A
10 and the one together and the y part, the three and the two. The end result would be 11 and five. There are a few more examples of vector math, but we get to those when we make the actual game.
96:49
Speaker A
Finally, vectors have a ton of methods that are incredibly useful. And I guess let's have a look at all of those in practice. Once again, back inside of GDO, I want to create a new scene with a 2D root node coding for
97:06
Speaker A
data. This I want to save right away in the usual folder and also attach a sprite to this scene so we can work with something. Finally, I want to attach a script to the entire thing. Create. All the defaults here are
97:24
Speaker A
fine. And then I want to work inside of the ready function and for now print the position of this icon. Drag it in there and then look for the position. If I now run this script as an output, we are getting
97:49
Speaker A
values 327 and 310. This is a vector 2. Or in other words, if you look at this icon, the sprite 2D under transform, you can find the position. And if you hover over it, GDO is telling you the data type. It is a
98:05
Speaker A
vector 2. Which means on this vector 2, we have two values that we can access via X and Y.
98:15
Speaker A
If we go with X, then we are going to get the first value, 327. Let's just try that. And there we go. 327. And of course you can also create new vector 2 via a variable. For that you want to
98:30
Speaker A
create a new variable. Let's call it pause for position. And then you simply assign it a vector 2. And inside of GDO we have vector 2 and vector 2 I. The i means that you're only getting integers as a value. By
98:46
Speaker A
default you're getting floating point values. Most of the time you are simply going to go with vector 2, three, or four depending on how many values you need.
98:57
Speaker A
The integer version isn't really that common. It's very specific and we're not going to use it. You want to have parenthesis and then you can set the x and the y value. Let's say 200 and 300.
99:11
Speaker A
This would be a very simple vector 2 that we can use to for example update the position of the icon. Icon.position position is going to be the pause variable. If I now run all of this again, then we have moved this logo
99:26
Speaker A
around. So if I change the number from 200 to 500, run all of this again. Then the good logo should be roughly here. And it is perfect. And that's pretty much all you have to know for the absolute basics
99:40
Speaker A
of it. You can create a vector 2 by simply writing vector 2 and then you assign the values to. Besides assigning values, you can also add dot and then you have for example down, left, one, right, up or zero.
99:56
Speaker A
Those are simply pointing in different directions. If you for example have right, you would get a vector 2 with one and zero. Meaning in a 2D space, you'll be going to the right by one unit. And remember in the last part when we try to
100:11
Speaker A
move the icon around, we could do that on the x-axis quite easily. But now via vector 2 we can do it in any direction.
100:20
Speaker A
For that and this is something you see all the time you want to use the process function get icon.position and then add the position although a better name for that would be the direction because this is what this
100:38
Speaker A
thing is effectively. Then we can get rid of the ready function. We don't need it anymore. And instead of position, this is going to be direction. This at the moment would move the GDO logo, but it's also going to be very very slow.
100:53
Speaker A
But let's try. There we have the GDO logo moving to the right. If I change this vector 2 to let's say one and one, we're going to the right and we're going down. Remember to go down you have to
101:08
Speaker A
increase the Y values. And there we go. We are going down and right. On top of that, what we can do because of vector math, we can create another variable.
101:19
Speaker A
Let's call it speed. And this can be a basic number like 20. This I can multiply with the direction.
101:28
Speaker A
And then we are still going in this direction, but now at a much higher speed inside of the game.
101:36
Speaker A
That is looking pretty good. And just to demonstrate how this would be working, if I print another vector 2, so vector 2 right away with the values of two and three, I can multiply the entire vector with let's say three. Then we're going
101:54
Speaker A
to multiply this two and this three both by three. As a result, we will get six and 9. Let's try.
102:03
Speaker A
There we go. We are getting six and 9 both of which are floatingoint values because a vector 2 always stores floatingoint values unless you add vector 2 doi. Then you would get integers which you usually don't want. And well that's pretty much
102:21
Speaker A
it for the basics of vector 2's especially for positioning. They are incredibly common. We have two more data types and the easier one is arrays. This is just a list that stores values. It would look something like this. You can
102:36
Speaker A
have any kind of data type in here. Any kind of number, strings, booleans. You can even have an array inside of another array. By that you can store any number of data points. And if you want to get
102:47
Speaker A
one value, you are doing an indexing operation, which simply means that you are adding square brackets afterwards and then you define the index that you want to grab. The index always starts at zero and then goes up. The first value
103:02
Speaker A
would be index zero. Then you have 1, two, and so on. Which means if you have square bracket zero, you're getting the first value. If this was a one, you'll be getting this value. And that's pretty much it. You can also loop over all of
103:19
Speaker A
the values inside of an array. For that, you would need a for loop. You start with the keyword for, and then you define a variable. Very often this is called I but you can call it whatever you want as long as it's a valid
103:31
Speaker A
variable name. And then you need some kind of array. Now inside of the code that has to be indented, we are running the code for every single value inside of the array and we are storing that value inside of the variable while we
103:47
Speaker A
are running it. That way you can grab every value and work with it. But let's do all of this in practice. And for that I want to create a funk ready. Once again to create an array you simply want
104:02
Speaker A
to let's say for now print then square brackets and then any kind of value.
104:06
Speaker A
Let's say 1 2 and three. We can have a string. We can have a boolean value that you can create directly. All you have to type is true or false. And finally you can add another array into an array with
104:22
Speaker A
values inside of it. one, two, and three. If I now run the script, we are getting inside of output all the way in the beginning the array. And that's really all we need. And I guess while we are doing this, let me comment
104:40
Speaker A
out this line. So we only see one output. I hope the system here makes sense. You simply have square brackets and then values separated by a comma.
104:50
Speaker A
There's no limitation on data types or number of items in here. It's a really flexible system. And if you want to grab one item after the array, you adding square brackets and then the index. For example, zero would give you the first
105:05
Speaker A
item. You always start counting from zero, which sometimes can be a bit confusing, but you get used to it.
105:12
Speaker A
Pretty much all programming languages work like this. But now if I run out of this again, we are getting one, which is this integer here. If I set this to three, we're getting 0 1 2 and 3. Meaning we
105:30
Speaker A
will get the string. At least if I can count right. And we do. That looks good. Once again, I think this operation is pretty straightforward. I guess one thing that you can do here is count from the back
105:45
Speaker A
via negative numbers. Negative -1 would be this last item. -2 would be false.g -3 would be the string and so on. You basically go backwards.
105:58
Speaker A
We're getting the array as an output or to be a bit more specific the array inside of the larger array. That works pretty well. Besides that, what you can do is a for loop with for i in and then
106:12
Speaker A
I want to grab this array. Let's actually store it inside of a variable bar. Let's call it test array and then this value or any kind of array. It doesn't really matter. This we can replace here test array makes all of this a lot more
106:33
Speaker A
readable. And also for i in test array, don't forget the colon. And now budau is going to go through every single value inside of this array.
106:45
Speaker A
And it's going to store it inside of this i variable, which means inside of the for loop, we can print i. And we would be getting every single one of these values. Let me run it again.
106:58
Speaker A
Inside of the output, we're getting this one, two, and three because of this print statement. But after that, we're getting one, two, three string false and the array 1, two, and three.
107:11
Speaker A
We went through every single value inside of this array. By that system, you can loop over the array and do pretty much anything you want in here, which is a fairly common operation. And besides arrays, we have dictionaries,
107:27
Speaker A
which are pretty much arrays except now we have key value pairs. This system looks like this. We have curly brackets and then we always have a key, a colon, and a value with the key value pairs being separated by commas. On top of
107:42
Speaker A
that, both the keys and the values can have any data type. Our first key value pair is this one where the key is the string A and the value is the integer one. The same system applies to the
107:55
Speaker A
second key value pair. But for the third key value pair, the key is the string C and the value is another string called test. Finally, for the last one, the key is the integer four and the value is an
108:08
Speaker A
array. All of which would be totally fine. Like for the array, you can still do indexing.
108:14
Speaker A
Although this starts to get a bit messy to observe but effectively we have the dictionary here and then we have square brackets with the key that you are looking for which currently is this key here. The output is then going to be the
108:29
Speaker A
associated value to it the one here and this is what we're getting. Also like for an array, you can use a for loop with four, then the variable name in and then the dictionary. Then you cycle over the dictionary. Although for that you do
108:45
Speaker A
have to be a bit careful. But let's do all of this in practice. I am inside of the code and I want to create another variable. Test dictionary. To create a dictionary, you want curly brackets and then the key value pairs. Let's say a
109:02
Speaker A
could get a value of one. Then I can have a key called one, two, and three with the associated value being an array with one, two, and three. And finally, you can even have a key like true, the
109:15
Speaker A
boolean value where the associated key is, I know, a string. Let's just call it string. For keys and values inside of a dictionary, any data type is fine.
109:28
Speaker A
Although I guess what I haven't mentioned is that these keys need to be unique.
109:34
Speaker A
You cannot have duplicates in there, which means using something like a boolean value is usually a pretty bad idea, but you could do it.
109:44
Speaker A
Once you have that, and let me comment out the stuff that we have done for the array. Oh, and by the way, if you select multiple lines of code, you can press control or command and then the forward
109:55
Speaker A
slash. That way, you're commenting out multiple lines of code. Super handy. I want to print the test dictionary.
110:04
Speaker A
If I now run the current scene, we are getting the dictionary that we have just created. And this stuff should have been commented out. You get the idea. We have a dictionary where we have key value pairs. And these keys you can access via
110:18
Speaker A
indexing. For example, if I add square brackets and then the key 1 2 and 3, that's this key here. And the associated value is the array 1 2 and three. So if I now run all of this, the value that we are getting is 1, two,
110:37
Speaker A
and three. With that system, you can store data and be much more explicit what it's about. Having too many values inside of an array can be a bit confusing. So sometimes using a dictionary is much more elegant and much
110:50
Speaker A
easier to understand. Besides that, like for a dictionary, you can use a for loop with for i in test dictionary. And then for now, I just want to print I and let's see what we get. And to not make
111:05
Speaker A
this confusing, I want to comment out the earlier print statement as well. So the only output that we are getting is from this for loop. Let's run it.
111:15
Speaker A
There we go. As an output, we're getting a 1, two, and three and true. If you compare this to the actual dictionary that we have created, you can see that we are only getting the keys. We're getting a 1 2 and 3 and the boolean
111:31
Speaker A
value true. If you use a for loop with a dictionary, you are only getting the keys returned, which sometimes can be what you want, but very often not really ideal.
111:44
Speaker A
to customize that. Every dictionary has a couple of methods that let you customize how the for loop is going to work. By default, you're getting the keys. If you don't want that, you can use values. That way, this for loop is
111:57
Speaker A
going to cycle over the values inside of this dictionary. Let's try. And there we go. Now as an output we are getting one the array 1 2 and three and string which is the values inside of this dictionary. So that is something
112:16
Speaker A
you do want to be careful about. Using a for loop with a dictionary can either get you the keys or the values. Now most of the time we are not going to work that much with data. So arrays and
112:29
Speaker A
dictionaries aren't going to be a common thing that we will work with, but once in a while they are very handy. The most important thing that you want to practice though are vectors. Those come up all the time. For that, I want you
112:42
Speaker A
guys to make a sprite bounce in all directions. The sprite should move via a vector 2 and it should bounce on every single window border. Pause the video now and try to implement this one. You will need a vector 2 and if statements for all of
112:57
Speaker A
this. Back inside of GDU, I think just to keep things organized, I want to add another sprite 2D to the scene and rename it to exercise sprite. After that, inside of the process function, I want to create another variable. And all of this is for
113:23
Speaker A
the exercise. I want to have an exercise direction which is going to be a vector two that let's say by default is pointing to the right. So x is going to be one and is going to point up. Y is going to be -1.
113:41
Speaker A
This variable should only hold vector 2's which you can do by defining the vector 2 as the data type or simply do this operation. That way the first value assigned to this variable is a vector 2 and afterwards it cannot change the data
113:57
Speaker A
type. Besides that I want to have an exercise speed which is going to be an integer with let's say 30. After that, inside of the process function, I want to get the exercise sprite and update the position.
114:18
Speaker A
To this value, I want to add the exercise direction multiplied with the exercise speed. And now this line is getting quite long, which makes it a bit hard to read. If that's an issue for you, you can click
114:33
Speaker A
on this button. That way you are expanding the code window. Quite handy sometimes. Let me try to run the code. The GDO logo should move to the top and to the right.
114:46
Speaker A
And there we go. We are moving in the right direction. Although we are not bouncing, which is the whole point of the exercise. We can check if and I want to get the exercise sprite position doy is smaller or equal to zero. If that is the
115:05
Speaker A
case, I want to get the exercise direction and update the y value. This one should now be one that way. And let me reduce the speed just a bit to 20. We should be bouncing.
115:22
Speaker A
There we go. We are bouncing once at the top of the window. And effectively now we have to duplicate this thing once and check if the logo is exceeding the value 648 or whatever you have set as the window
115:39
Speaker A
height. The default is 648. If you haven't touched this value, if that is the case, exercise direction.y should be negative one. Then we can duplicate all of this and then change position Y to position.x.
115:56
Speaker A
If position X is smaller than zero, we are on the left side of the window, which means exercise direction.x should be one. If the position is greater than 1152, then we are on the right side of the window. So the direction X should be
116:13
Speaker A
negative, meaning we are going left again. And with that, we should be done. There we go. This looks like a pretty good bouncing. It is time to talk about functions in a bit more detail. Along the way, we are also going to talk about
116:30
Speaker A
scope and return. Really important concepts that you have to understand to actually understand functions. But let's go through it step by step. We have already seen that you can create and call function. Creating functions looks like this. You start with the funk
116:46
Speaker A
keyword. Then you add the name of the function. Afterwards, you add parentheses with the parameters that we haven't done yet. Then you have to add a colon after which you have the indented code with all of the logic. That way you
117:03
Speaker A
are creating a function. To actually use the function, you have to call it, which basically means you want to write the function name along with parenthesis.
117:15
Speaker A
And inside of the parenthesis, you can add all of the arguments. That way, the function actually does something. We haven't actually created any parameters.
117:24
Speaker A
So, let's have a look at that. As always, here we are back in GDO. And I want to create a new scene. Just as before, this is going to be a 2D scene that I want to rename to coding five
117:37
Speaker A
functions. Let me expand this just a bit like so. and then save the entire thing. The location doesn't really matter. So, click on save. And then we have a scene that we can work in. All I want is some
117:53
Speaker A
code. So, I want to attach a script to the node. Click on create with all of the defaults. And then we can write some code. For now, I want to create a function that we can just call test
118:07
Speaker A
funk. That would be the name of the function. And afterwards, you need parentheses and a colon. Then inside the function you have to write the logic that you want to execute. Let's do something simple. I want to print test
118:21
Speaker A
function. And that's all that this function does. With that we have created a function. And this we have done a couple of times by now. However, if I execute this one scene, nothing is going to happen. We don't get any output. That
118:36
Speaker A
is because this function does not get executed. Or in other words, it's not being called.
118:43
Speaker A
The functions that do get called automatically are functions that start with an underscore. Like for example, funk ready. This function gets called by good once the scene is ready. Which means what we can do inside of this function. We want to call this function.
119:00
Speaker A
We simply have to do test funk then parentheses opening and closing once and then we are calling all of this code.
119:08
Speaker A
Which means if I run this one scene inside of the output, we're getting test function.
119:16
Speaker A
This part should still be super straightforward. We have done this a couple of times already. But all of this we can expand.
119:24
Speaker A
Most importantly by adding parameters. That means inside of the parenthesis you can add parameters. For example, parameter_1.
119:35
Speaker A
Simply by doing that, GDO is already going to complain that let me expand this. There are too few arguments for the test function call. GDO expected at least one but received zero. Or in other words, there's now one slot that we have
119:51
Speaker A
to fill when we are calling this function. This at the moment could be any kind of data type. I could for example write 1 2 and three and GDO would be happy. Once again, also let me fix my typo. This
120:04
Speaker A
should be parameter one. This parameter one becomes a variable inside of the test function. The value assigned to this variable is what we have added as an argument when we are calling the function. In other words, I can print
120:20
Speaker A
parameter one. Run the scene once again. And as an output, we're getting 1 2 3 the value that we have added when we called the function. With that system, you can make your functions much more flexible. And you can also force a
120:35
Speaker A
certain kind of data type. All you have to do is add a colon after the parameter and then define the data type. For example, right now I only want to allow integers for this data type. That way, if I change this to let's say a string
120:51
Speaker A
that says something doesn't really matter, then GDO is going to complain. You cannot pass a value of type string as an integer. This function only accepts a single parameter that has to be an integer. Let's change this back to
121:05
Speaker A
one, two, and three. Although you can also add multiple parameters. Let's call this one parameter two which can be a string.
121:17
Speaker A
And then GDO is going to complain once again. So now we have to add a second argument which now has to be a string.
121:24
Speaker A
And once again good is happy. And to actually use parameter 2, what I haven't covered yet is that when you're calling the print statement, you can add multiple arguments as well. For example, we can add parameter 1 and parameter 2.
121:41
Speaker A
Then if I run out of this again, we're getting 1 2 3 and string all combined.
121:47
Speaker A
If you want to have a space between the two, simply add one more argument with a string that has one space inside of it.
121:55
Speaker A
That way this looks just a bit cleaner. And effectively those are parameters and arguments.
122:04
Speaker A
Parameters are slots inside of a function that you can fill with arguments. And that way you are giving them a value that you can use inside of the function. Super handy. Finally, you can give a parameter a default value.
122:20
Speaker A
Let's say for parameter 2, we want to have a default value. And that you do right after a default value of test.
122:28
Speaker A
That way if we don't give an argument here then good is going to use this value.
122:36
Speaker A
Or in other words I can run the entire thing again. We're getting 1 2 3 and test. GDO used this value for parameter one and this value for parameter 2. The one thing that you always want to be
122:50
Speaker A
careful about is that these parameters are organized via their position. This is the first parameter. So the first argument is going to go to this parameter. Then you have the second parameter and the second value would be for that one. So second would be here.
123:06
Speaker A
Always be careful about that one. The position of these parameters and their arguments are really important. It's the only way to really link them. But other than that, this is basically as complicated as it gets. If you understand it, you understand functions
123:22
Speaker A
reasonably well. That being said, there are two concepts that are really important that can be quite confusing. The first concept is scope or more specifically, you have a global and a local scope. What that means is inside of a function, you can
123:39
Speaker A
create variables. But if you create a variable inside of a function, it only exists in that function. Or to be a bit more technical, the variable exists in the local scope of the function.
123:52
Speaker A
Variables created in the beginning of the script are in the global scope, meaning they are accessible everywhere.
123:59
Speaker A
Inside of this test function, you can create variables. This happens in a normal way. You type var and then the name of the variable.
124:08
Speaker A
Let's call this one the local variable. This could be any kind of data type. For now, let's go with local var. Once you have that, you can use this local variable like any other variable. You can print it, you can change it. Let me
124:26
Speaker A
just print it and run the script. We're getting local var. So, that looks good.
124:34
Speaker A
We have a variable like any other. However, inside of the ready function, this variable does not exist.
124:42
Speaker A
If I try to print it here, print local variable, GDO is already going to complain that the identifier local variable is not declared in the current scope.
124:57
Speaker A
What that means is that this function has a scope and this function has a scope and local variable only exists inside of this test function. It does not exist inside of the ready function.
125:09
Speaker A
I guess an easier way to think about it is that every single function is its own box. Inside of this box, you have a ton of logic and you can create variables.
125:21
Speaker A
But these variables only exist inside of this box. If you create another function, this function would be another box with its own content. That's really all that local scope means. Variables created inside of a function are only available in that function. However,
125:39
Speaker A
what you can do in the beginning of the script is create a variable and this is what you have already seen. Let's call this one global variable with the value global var. And this global variable is available everywhere.
125:56
Speaker A
We can print it inside of the ready function and we can print it inside of the test function.
126:04
Speaker A
It would work in both of them. So we're getting global var twice. First from this print statement and then from this print statement. The reason why the system exists is that functions should be self-contained. All of the logic in here shouldn't connect too much
126:20
Speaker A
to stuff outside of the function. It really helps to have modular logic where a function does its own thing and simply gets its data via the parameters.
126:31
Speaker A
If you get too much data from other sources, things can get really complicated and confusing. So be careful here. And with that we have covered scope. Next up we have to talk about return values.
126:44
Speaker A
This is how data is moved around. And also you can specify what kind of data a function returns.
126:52
Speaker A
Something that I haven't talked about yet is this arrow and then void. This defines what kind of data this function returns. And void means it returns nothing. This part actually is necessary. If you get rid of it, nothing
127:07
Speaker A
would happen. But you can make it useful. For that, I want to create another function. Let's call it function return something.
127:19
Speaker A
No need for any parameters, but I do want to return an integer once we're calling this return something function. After that, you need the colon and then we can print return something function was run. However, now GDO is
127:38
Speaker A
still complaining that not all code paths return a value. effectively now who do expects when this function is run it returns a value specifically an integer to get that we need the return keyword and then some kind of value that
127:55
Speaker A
we want to return for now let's go with 100 and then good is happy again if I print return something really importantly with the parenthesis so we are calling the function I and run this script and we're getting 100 and I think it's
128:18
Speaker A
important to understand what happened here. Let's go through it step by step. Inside of this print statement we have called return something which means GDO is looking at this function. First of all it is going to print some kind of
128:34
Speaker A
string. Doesn't really matter what it is. After that we are returning the integer 100 or in other words this function is replaced with 100 or whatever was returned in here. This 100 is then being picked up by the print statement and GDO
128:53
Speaker A
prints out the value. Effectively this return something function after it is called gets the value of this 100. We could even change the value. For example, you could multiply it with two, rerun the script, and now we're getting
129:10
Speaker A
200. Programming languages when it comes to this kind of system are super flexible. And generally, understanding how return works is really, really important. It pretty much defines how data is sent across your code. For example, here is a slightly longer line of code.
129:31
Speaker A
First of all, we are creating a vector 2 that has an x value of three and a y value of four. This would be the first value that gets returned. After that, we are calling a method on this vector
129:47
Speaker A
where we're getting the length of the vector, which means the returned value from the vector gets changed to something else. After that we are multiplying the entire value by a factor of two or in other words the thing that
130:04
Speaker A
was just returned this value here gets changed once again and we're getting something else after that all of this gets passed into the str function which turns any value into a string which means this becomes once again another kind of value. Finally, via the
130:25
Speaker A
print function, we are printing this final value. This does look a bit complicated, but once you play around with it, it becomes really straightforward. You always have to go from the innermost part to the outermost part and then work through it step by
130:40
Speaker A
step. Getting used to all of this will take you some time, but not that much time. You'll be fine. For now, the one thing that you really have to understand is that when we have this arrow at the
130:52
Speaker A
end of the function, we are defining some kind of return value. If that is the case, inside of the function, you have to return some kind of value at the end of it. And all of this should be practiced. So, let's do
131:06
Speaker A
an exercise. I want you to create a calculate function. It should look something like this where you can add two numbers and then the operation as a string. There should be plus, minus, divide and multiply. The correct answer
131:21
Speaker A
should be returned. Which means inside of calculate, you shouldn't use any kind of print statement. You simply want to return the final value and then print that return value. Pause the video now and see how far you get.
131:38
Speaker A
I want to create a funk calculate where we have three parameters. Let's call it number one, number two, and the operator.
131:54
Speaker A
All of those should only accept a certain kind of data. For number one and number two, let's say to keep it simple, this should only be integers.
132:05
Speaker A
Whereas for the operator, this should always be a string. The return value once again to keep things simple should also be an integer. And just to test if things are working, I want to check if the operator is equal to plus. If that
132:24
Speaker A
is the case, I want to return number one plus number two. And if that is not the case, else I want to return let's say zero.
132:40
Speaker A
That way inside of the ready function and let's comment out all the other stuff so this doesn't get confusing. I only want to print the return value from the calculate function where for now we're doing 1 + 2
132:57
Speaker A
like so. And then we should be getting as an output the number three. And we do. That looks good. Although this logic here doesn't work terribly well yet.
133:09
Speaker A
That we have to work on. First of all, I want to create a local variable called result.
133:18
Speaker A
This is going to be an integer with a default value of zero. And this is the only thing that we are going to return at the end of the function.
133:29
Speaker A
In between that via if statements we are going to do the actual math. So let me copy and paste this in there. First of all I want to check if the operator is plus then the value of result
133:43
Speaker A
should be number one plus number two. L if operator is equal to minus then result should be number one minus number two and I think you get the pattern. If operator is equal to multiply then result should be number one times
134:16
Speaker A
number two. And finally else this has to be divide. So result is going to be number one divided by number two. And that is pretty much all we need.
134:35
Speaker A
We have a couple of parameters inside of the function. Then we create a local variable and we're adding a whole bunch of logic that assigns a value to the result. At the end of the function, we are returning one value and that one
134:49
Speaker A
value is being printed out. This should still give us a three. Let's try. That looks good. We're getting a three.
134:57
Speaker A
And if I do 10 minus 3 then we should be getting seven. And we do. That looks really good. I suppose one thing that you can do is give the operator a default value of plus. That way if we only give it two numbers like
135:17
Speaker A
so, then we're going to add them together by default. Let's try. We should be getting 13. And that looks good. All right. Perfect. With that, we have basically all you need to know about functions. And by the way, inside
135:32
Speaker A
of GDO, the default style guide tells you that there should be two spaces between functions. Not something you have to do, but something that you usually see. It's just to keep your code a bit more readable. Anyway, with that,
135:45
Speaker A
we have another super important concept. All righty, let's get started with the first project where we are going to create a progress style game. Obviously, this isn't going to be the most sophisticated game. However, it is going to teach you all of the important parts
136:01
Speaker A
of GDO, like using scenes and notes, using GDScript, and using all of this to create logic. By the end of it, you should already have a pretty decent idea how good works on a basic level. Now, to get started for the first part in this
136:14
Speaker A
project, we are going to create a very basic outline where we have a player and the background. Or to go into a bit more detail, we want to create a basic game scene and then place the player inside
136:26
Speaker A
of it. On top of that, we want to move the player by just a bit.
136:31
Speaker A
Although for now, this is going to happen without input. That's going to be the next part. Here we are in GDO and at the moment we don't have any kind of scene inside of the engine. That being said, if you look at the file system, we
136:44
Speaker A
have a couple of folders. Most importantly, we have graphics in there. We have, for example, the player, a simple version, and the tile set. We're going to come to that later. Then we have a whole bunch of objects and so on.
136:58
Speaker A
We also have fonts and audio, but those aren't too important. Now, to get this project, you want to look at the video description. In there, you can find a link to Google Drive folder, which is going to look like this. In there, you
137:11
Speaker A
have the project files for every single game. For example, right now we are working in the Frogger game and in there you have the Frogger project setup and the Frogger start files. The second one you want to download. So download and
137:26
Speaker A
then your computer should be downloading the entire thing inside of the project stages. You're going to find this by the way the finished code for every single part of the game. If you get stuck somewhere, you can use that to figure
137:39
Speaker A
out what went wrong. Should be quite helpful. But much more importantly, the file you just downloaded, it's going to look like this. And you want to extract it in the usual way. Then you're getting the GDO starting files. Right now, this
137:55
Speaker A
is just a folder. To import the entire thing into GDO, you want to open the editor. And then you can simply drag and drop the files from the folder, the one you have just downloaded with all of the stuff inside.
138:10
Speaker A
Just drag it in there and then you're good to go. Open this one and you should be seeing the project. Alternatively, you can go to import and then navigate to where you have to be, which in my case is going to be the downloads
138:24
Speaker A
folder. In there you have Frogger start files. Open this one and then you want to open this project file inside of the folder. You're going to get the same result that you are seeing in here.
138:35
Speaker A
Double click on that and then you get exactly what I have started with. Other than that this project does not contain any kind of script. All of this we have to create ourself and well for that first of all I want to create a 2D scene
138:51
Speaker A
which I want to rename right away to game. Then save the entire thing with Ctrl S or scene and save scene. And I want to save it inside of the scenes folder. Game.tsn is totally fine.
139:07
Speaker A
And now we have our first scene for the game. And this is going to contain all of the logic. So for example, attached to this is going to be the player, the background, all of the cars and so on.
139:18
Speaker A
Speaking of which, first of all, I want to add the background to it. And for that, we can look at graphics. In there somewhere, we have map.png.
139:29
Speaker A
This I want to import or in other words I want to create a sprite 2D which can hold a texture. So in other words I want to drag map.png into this texture slot and then we have the background that is actually already
139:46
Speaker A
pretty solid. That way we have at least something to look at. Next up I want to create the player. For that I want to create a new scene and then create another 2D scene.
139:59
Speaker A
This is going to be for the player. And to that I want to add another sprite 2D.
140:06
Speaker A
This sprite 2D is going to display the player graphic. So let me zoom in a bit and then go to the folder graphics player and player symbol. Drag it inside of the texture and then we have the player. Although if you look closely,
140:21
Speaker A
this is looking horrible. Also, while I'm talking about it, if you look at game and you zoom in into this map, this is also not looking great. So, what's the problem here? When you have graphics like for example the player, GDO has to
140:36
Speaker A
scale it. This original player graphic for the player is 12x4 pixels. A really, really small graphic. And GDO to make it this big has to scale it up by a lot, which is totally fine. The issue is that
140:49
Speaker A
there are different ways to scale a graphic. and the one that we are currently using is really really not working. To fix that, all we have to do is go to texture and there we have filter. At the moment, it's set to
141:02
Speaker A
inherit. But if we set this to nearest, then this is looking significantly better. That being said, this isn't what I actually want to do. So, let me undo it simply because I want to do this operation for every single graphic
141:16
Speaker A
inside of my graphics folder. Doing it one by one would be kind of a pain. You can simply go to project project settings and then look for texture and then look at textures. In there you have a default texture filter which is set to
141:31
Speaker A
linear by default but we want to set it to nearest. That way by default we are scaling all of the graphics in this filter style and that is going to look a lot better. Nice improvement. Then I want to save the scene. Player.tsseen is
141:46
Speaker A
totally fine. And then we have the player. And this player we want to add to the game scene. So with game selected, I want to either instantiate a child scene or press control shift and A. And then we can add the player scene
142:02
Speaker A
to the game scene. If I now zoom in a bit, we can see the player.
142:08
Speaker A
Let's move the player roughly here so it's a bit easier to see. And then we can try to run the game. For that, click on this button here or press F5 on the keyboard. And then you want to
142:21
Speaker A
select the current scene to start the game. Select current. Then we're getting a graphic. And it does work, but it's really small at the moment. That we're going to fix later. For now, this is totally fine. I am happy with that. I
142:34
Speaker A
suppose to see the player a bit better, we can scale the sprite 2D, which we do under transform and then scale it by a factor of six.
142:45
Speaker A
If I now go back to game, the player should be much more visible and that is definitely better. All right, with that we have two scenes that work together. Next up, we want to move the player in a certain direction. For
143:01
Speaker A
that, the player scene needs to have a script. So, click on attach a new script.
143:07
Speaker A
We want to have inherit node 2D and save it inside of scenes and player.gd. All of this is fine. Click on create.
143:17
Speaker A
And now we can write a couple of lines of code. Now for the player, first of all, I want to have a couple of basic variables. I want to have a variable for the direction. And this needs to be a
143:30
Speaker A
vector 2. If we set this data type, the default value that we are getting is going to be a vector 2 with x and y both being zero, which is exactly what I want. Although if you wanted to be a bit
143:43
Speaker A
more specific here, you could do vector 2.0. Same thing really. Choose whatever you like. Besides that, for the player, I want to have a speed, which should be an integer. And for the default value, I want to go with let's say 200. Once we
144:01
Speaker A
have that, I want to call a function that runs on every single frame. This could either be funk_process or it could be funk physics process.
144:15
Speaker A
I am going to use physics process because later on for collisions we want to have just a bit of physics. Although at this point it wouldn't really matter.
144:26
Speaker A
And in here we want to move the player position or in other words we want to grab the position of the current node.
144:33
Speaker A
Remember when we are attaching a script to a note like for the player at the moment we get access to all of the stuff inside of the inspector. So at the moment we are targeting the position via this position value. If you hover over
144:48
Speaker A
position you can see that this value wants to have a vector 2. And the way I am going to approach it is I'm going to add a value to it which is going to be our direction multiplied with the speed.
145:02
Speaker A
And that's actually all we have to do. Although at the moment this isn't going to do anything. So if I run the main scene, the player is not going to move. But that happens because our vector 2 for
145:14
Speaker A
the direction is zero. We have a vector 2 with zero and zero. And this we are multiplying with 200. The end result is going to be a vector with zero and zero.
145:28
Speaker A
So the position doesn't change whatsoever. However, what we can do is change this vector 2 to a value that's not zero. I want to have a vector 2 where x is 1 and y is zero. And now if I
145:43
Speaker A
run this thing again, our player is moving to the right, although it is quite fast. Let's change this to a five.
145:53
Speaker A
And there we go. Now the player is moving to the right. If I set this to one and one, then the player is moving right and down. And that is working pretty well.
146:05
Speaker A
Perfect. With that, we have a really basic setup. Obviously, it doesn't do very much, but at the very least, we can move things around. Let's do an exercise. I want you to create a new scene with a few objects like trees,
146:20
Speaker A
boxes, whatever you like inside of the graphics folder. Add all of that to the scene and then add the scene to the game scene. So you are decorating the entire thing a bit effectively. On top of that, use GDScript to scale up the scene over
146:33
Speaker A
time. How fast this is going to happen is entirely up to you. Pause the video now and see how far you get.
146:43
Speaker A
I want to add another scene, which once again is going to be a 2D scene. Let's call this one exercise object. The name really doesn't matter. And then save it.
146:55
Speaker A
The scenes folder is totally fine. Save in here. And then we want to attach a couple of objects from the graphics folder. Let's say I want to start with a basic tree. You can actually just drag and drop it into the scene.
147:10
Speaker A
Is automatically going to give you a sprite 2D. Although by default the position is going to be a bit weird. So let's reset that one. And then the tree is right in the center point of the scene. I guess besides that, we can add
147:24
Speaker A
another tree. And let's say we could add a box like so. Yes, I want to save. And then inside of the game, I can add via this button or control shift A the exercise object.
147:41
Speaker A
This we can place somewhere, let's say here. Then run the game. And we have another scene inside of the game. doesn't look amazing yet, but at the very least, we have something. Besides that, I want to add a script to the scene. All of the
147:58
Speaker A
defaults here are totally fine. Then create. And like for the player, I want to run a function on every single frame of the game, which I'm doing via physics process once again.
148:10
Speaker A
Now, for this thing, I want to target the scale property, which we can target via scale. So hover over the property inside of the inspector and then you're getting some bits of information that are super useful. Once again, GDO wants
148:25
Speaker A
to have a vector 2 with X and Y and that determines the scale. So to target it, I want to type scale and then assign a new value to it where we want to get scale and multiply it with a value of let's
148:41
Speaker A
say 1.1. Let's try the entire thing. And that might be quite fast. And yeah, it definitely is, but you get the idea.
148:50
Speaker A
Let's change this to 1.001. Then it's not so strong anymore. Now we can see that the scene that we have just created is growing very very slowly. Not something we can use for the actual game, but for an exercise, this
149:05
Speaker A
is pretty all right. And with that, we are pretty much good to go for this part. Although there's one thing that is a bit annoying. If you look at the bottom, Gudo is complaining with the debugger where we have not two errors
149:18
Speaker A
but two warnings that we are not using the delta parameter. To fix that, I want to add an underscore to both of them. That way, GDO stops complaining. If I run the scene again now, the debugger doesn't complain,
149:34
Speaker A
which feels a lot better. Next up, we are going to move the player around using player input, which is bringing us a lot closer to an actual game. For that, we have to capture user input, which in GDO is quite easy. We can
149:49
Speaker A
simply create an input map. Via that we can capture keyboard, controller, joystick, and mouse input, which is really all that we need. So back in GDO you want to go to project project settings and at the top we have an input
150:05
Speaker A
map. The way this thing is working is you define an action and associated with this action you have some kind of input like a key press on the keyboard for example. For example I can type left and press enter. Then we're getting one
150:21
Speaker A
action for left. And to this action, we can assign events, which is a fancy way of saying a button on the keyboard, a mouse button, a joypad button, or whatever you have available in here. Gudo is also listening for input, meaning if you
150:38
Speaker A
press a button on the keyboard, for example, the left arrow key, then it gives you the right option right away, which is super handy. So in my case, I'm going to click on okay. And now to the left action, we have the left physical
150:52
Speaker A
button on the keyboard. Besides that, another action I want to add to it is the A button on the keyboard. Click on okay. And now we have two key bindings for this action. You could also add a controller, although for now I am not
151:06
Speaker A
too worried about it. What I rather care about is to add other keyboard bindings for up, right, and down.
151:18
Speaker A
For all of these, I want to add the keyboard bindings. So for up, it's the up arrow on the keyboard or the W key.
151:26
Speaker A
For right, I want to have D on the keyboard or the right arrow. And finally, for down, I want to have the S key or the down arrow.
151:40
Speaker A
And that is all we need for now. We can close this dialogue and then work inside of GDScript. Specifically, I want to work inside of the player. Now, there are a couple of ways to work with the keyboard bindings. The easiest one, I
151:55
Speaker A
think, is to use input and then is action pressed. This is looking for an action that is being pressed. Let's start with the right action and then print the result. If I now run the code, by default we're getting false because
152:12
Speaker A
the button is not pressed. But if I press right on the keyboard, we are getting true. If I release it, we're going back to false. The way we could use that, for example, is to only move the player if this value is true. Let me
152:28
Speaker A
cut it out and add it to an if statement. Only if you're pressing the right button, then we want to move the player. If I run the thing now, the player is not moving. But if I press to
152:38
Speaker A
the right, then the player is moving, which is already quite a bit better. Although this still isn't exactly what we want to actually move the player in a certain direction. I want to keep position is equal to direction time
152:54
Speaker A
speed. And then when we are pressing the right button, I want to change the direction to a vector 2.
153:05
Speaker A
which is the same as a vector with one and zero. Besides that, I want to duplicate all of this and then get the action pressed for left. If that is the case, direction should be vector 2.
153:23
Speaker A
If I now run the code, I can press to the right, the player's going to the right. And if I press left, we are going left. And this kind of works although the player never stops which isn't ideal. Meaning we have to figure out
153:37
Speaker A
some kind of system to organize the input and then get the right direction. There are a couple of ways of doing it.
153:45
Speaker A
And the best way to get started is to look at input. For that hold control and then click on input. Then you get the documentation for input. If you go down a bit, you can see all of the methods
153:59
Speaker A
associated with it. There are quite a few. The one that we care about the most is called get vector.
154:07
Speaker A
Click on that and then we are going to do an exercise. I want you to read the documentation and figure out what input.get vector actually does and how you can use it. Pause the video now and see how far you get.
154:26
Speaker A
I hope you read this entry. I think overall it's fairly straightforward. Basically, get vector wants to have four inputs negativex, positive x, negative y, and positive y. Or in other words, for normal people, left, right, up and down. These are the directions that we
154:48
Speaker A
can add to this method. And as a result, we are getting a vector 2 that organizes all of them super easily. Or in other words, back inside of the player, I want to get rid of all of this and instead
155:04
Speaker A
update direction via input and get vector. Now we need the four different directions. negativex is left, positive x is right, negative y is up, and positive y is down. Once we have that, I can run the game and now move
155:28
Speaker A
the player around. It's like magic. If I stop pressing any of the buttons, then the player stops as well, which works really, really well. Get vector you see all the time. It's incredibly useful and fundamentally it's not that complicated.
155:44
Speaker A
All it does is it takes four inputs and then returns a vector that we can use right away inside of the direction. And to finish all of this up, I want you to do another exercise. Create another input this time for the space key. And
155:58
Speaker A
then inside of GDScript, when this one is being pressed, print something. And as an extra challenge, make sure that when the button is pressed, you're only printing it once, not multiple times.
156:11
Speaker A
You will definitely have to read the documentation for all of that one again. Pause the video now and see how far you get.
156:22
Speaker A
Once again, back inside of GDO, I want to go to project project settings, input map, and then create a new action. I call this action confirm because later on from the title screen, this one goes back to the actual game.
156:38
Speaker A
Confirm might not be the best name, but it's going to work for our purposes. The actually important part is I want to add a key binding to this action with the space button. Click on okay. And now we
156:48
Speaker A
have space physical. That's all we need. Next up, inside of the player script, I want to check if input is action pressed with confirm. If that is the case, I want to print something.
157:06
Speaker A
And you might think that this is all we needed. However, if I now run the game and I press space, even if I press it once, we're getting something multiple times.
157:17
Speaker A
Not ideal. So, what's the problem here? is action pressed checks if this key is pressed on every single frame of the game and physics process always runs at 60 frames per second. Meaning this function checks every 60 milliseconds if
157:33
Speaker A
this key was pressed or not. Even if you only press it for a tenth of a second for good. This is quite a few inputs.
157:40
Speaker A
Now there are a couple of ways to fix it but the easiest one is to not use is action pressed but rather is action just pressed. That way, GDAU is only checking if the button is pressed, but not if it
157:52
Speaker A
is held down. If I now run the thing again, I can press space and we only get one output every single time. Much better. With that, we have user input.
158:04
Speaker A
At the moment, we do have some basic input, but the game just doesn't look very good. Most importantly, everything is tiny and we can only see part of the background. All of this is going to be fixed in this part where we are going to
158:17
Speaker A
add the camera. That way we can zoom in and actually follow the player on the map. And fortunately, cameras in GDO are really, really easy.
158:29
Speaker A
You simply create a camera and then tell the camera to follow the player. That's all we need. The camera could also follow any other object. Really, whatever you need. On top of that, you can also set limits and speeds for the
158:42
Speaker A
camera. That way you have a ton of control over how this thing is moving.
158:47
Speaker A
First of all, the player shouldn't be scaled up anymore. So the scale should go back to one and one.
158:54
Speaker A
On top of that, inside of the exercise object, I want to get rid of this code.
159:01
Speaker A
So we're not scaling it up anymore. That way I can run the whole thing and everything is super super tiny.
159:09
Speaker A
To fix that, we want to add a camera and zoom in. On top of that, the camera should follow the player. Now, for that to the player scene, I want to add a camera 2D.
159:23
Speaker A
If I now go out a tiny bit, you can see this pink purpleish frame. That is the frame of the camera. And simply by having it attached to the player, it is already going to follow the player. Or
159:37
Speaker A
in other words, if I now run the game and I run around, the camera is following the player, which is already a lot better. Besides that, if you look at the inspector, we can modify a couple of things. Most importantly, the zoom
159:52
Speaker A
level. If I set this to a factor of four for X and Y, then the frame has gotten a lot smaller. If I now run the game, we can see the player quite a bit better.
160:06
Speaker A
And that is actually already making a pretty big difference. You can also set the offset and for example move the camera down by quite a bit or up by quite a bit because the player might want to look a bit more ahead. But I
160:22
Speaker A
guess for our purposes we can leave it at zero and zero. Besides that, if you look a bit further down, we have a few more options. We can set a limit for the camera. By default, these are basically
160:34
Speaker A
infinite. Then we have position smoothing. And this you always want to enable. That way the camera follows the player a bit more smoothly. You can actually see it right away. If I run the game and I move around, the camera takes a little
160:50
Speaker A
bit of time to catch up with the player, which right now looks a bit silly because the player is too fast. But if we increase the speed of the camera to something like 20, then this is going quite a bit better.
161:08
Speaker A
Usually you do want to have position smoothing enabled. It just looks and feels better, but once again, whatever you think is best. Finally, we can set a limit. For example, for the left side, we never want to go further than zero
161:21
Speaker A
pixels. If I now run the game again, I can go to the right, but the camera stops at position zero and that is pretty okay. Obviously, you want to measure this value. For that, inside of the game, you want to look at where this
161:43
Speaker A
map starts and ends. The best way I find for that is to drag the ruler and then you get a pixel measurement. So if you hold it there, this is going to be negative 192.
161:57
Speaker A
Since this thing is symmetrical, the right side is going to be 192 as well.
162:03
Speaker A
Then for the top we have negative I think this is going to be 320 and positive 320 because once again this map is symmetrical. Now to get rid of the rulers, you simply want to drag them outside of the screen. After that inside
162:20
Speaker A
of the player for the camera the left side should be negative 192 the right side should be 192 the top should be -320 and the bottom should be 320 top and bottom can be very easily confused but remember going up means you are
162:41
Speaker A
decreasing the values but let's try all of this now and I can move in the different actions and we cannot go outside of the window and that is working pretty well and makes the game feel quite a bit nicer. I
163:00
Speaker A
guess while we are here what you could also do inside of project and project settings in general you can look at display and window in there you can set the viewport width and height. Usually I set them to 1280 by
163:17
Speaker A
720, which is a much more standard resolution. Besides that, you can set the mode. You can stretch the thing in different ways. You can work with landscape or portrait and do lots of different things in here. Although I'm
163:30
Speaker A
not going to touch them too much. If I run the thing again now, you can see our resolution is 1280 by 720. And obviously, you can also resize the entire thing. That works totally fine.
163:42
Speaker A
And with that, we have cameras. Our game is coming together quite nicely, but there's one really important thing missing right now. Physics or in other words collisions that we're going to fix in this part.
163:55
Speaker A
And for that, we have to talk about physics in good. We want collisions. And for that, GDO has dedicated nodes. There are three that basically do all of the work. The first one is a static body 2D. This is a
164:11
Speaker A
well static physics object. it doesn't move and it's basically for objects like houses, trees, spins, really whatever doesn't move and needs to be collided with. Next up, we have a character body 2D. This is a physics object that can be
164:26
Speaker A
moved via code. Pretty much any kind of character is going to be a character body 2D. This could be the main player.
164:33
Speaker A
This could be enemies. This could also be a car. Really, anything that moves and doesn't have to be physically accurate while moving. More or less anything that moves and needs to collide with something is going to be a
164:44
Speaker A
character body 2D with some minor exception. The most important one is for rigid body 2Ds. These are physics objects that can be moved via physics.
164:54
Speaker A
These are going to be used for arrows, cannonballs, and things like that. And just to be explicit, the difference between a rigid body 2D and a character body 2D is that a rigid body 2D gets some code in the beginning to determine
165:08
Speaker A
the direction of the movement and then everything else is covered by physics. Whereas a character body 2D is going to continuously get directions from the code. Meaning these objects can be updated constantly. Besides these three nodes, there's one more node that you
165:24
Speaker A
see very often and that is an area 2D. This one simply checks if a body is in an area and that's all it does on its own. It doesn't do any kind of physics, but it works very similar compared to
165:36
Speaker A
the others. As a consequence, they are usually grouped together. And before we get started, there's one more super important thing, and that is that physics objects are not moved via their position. Instead, we're giving them a velocity, and then GDO calculates the
165:53
Speaker A
position via that system. GDO can account for physics right away. First of all, I want to create a static physics object. We can actually use the exercise object for that. Now, at the moment, we have a node 2D at the root node. This I
166:10
Speaker A
want to change. For that, I want to right click on it and then change the type.
166:17
Speaker A
If you now look at all of the nodes, we can go to node 2D. And in there, we have a collision object 2D. If you expand that, we have an area 2D and we have physics body 2Ds, but we have a static
166:30
Speaker A
body 2D, a character body 2D, and a rigid body 2D. The nodes I just talked about, these are the main physics objects, although they're not the only ones. If you expand static body 2D, you also have an animatable body 2D, which is
166:46
Speaker A
basically a static body 2D that can be moved a bit. And if you expand rigid body, we have a physical bone 2D, which is going to be useful for skeleton animation, but not something we need at the moment. So instead, I want to work
167:00
Speaker A
with a static body 2D. Click on change. And now GDO is going to complain that this node has no shape. As a consequence, it cannot collide or interact with anything. To fix that, we have to add another node, either
167:15
Speaker A
collision shape 2D or collision polygon 2D. To get started, I want to add a collision shape 2D. If we add that, GDO is going to give us another warning that a shape must be provided. With the note selected, you
167:31
Speaker A
want to look at the inspector and there we can add a shape. Loads of options in here. Choose what you think is best.
167:39
Speaker A
Usually, a rectangular shape 2D is working the best. And I guess just to keep things simple, we can get rid of the box and of the second tree.
167:53
Speaker A
And then change the shape of this thing so it fits the tree reasonably well. And by the way, if you hold command or alt, then you can scale this thing while mirroring it around the axis. This works on X and Y.
168:09
Speaker A
And let's create the box like so. Cool. With that, we have one physics object. If you now look inside of the game, we have a tree. Basically, that being said, at the moment, we are still not getting collisions. And if I run the
168:26
Speaker A
game, the tree just doesn't do anything. For actual collisions, both the player and the tree need to be physics objects. At the moment, the player is simply a graphic that can move around. No collision yet.
168:43
Speaker A
Now before we start working on the player inside of the tree in the script you want to make sure that you are extending the right node. At the moment node 2D is incorrect because this is a static body 2D meaning this should be
168:59
Speaker A
static body 2D as well. Without that the code would start doing weird things. Now that being said this exercise object doesn't need to do anything anymore. We can remove the script entirely and close the script. We can simply discard it.
169:18
Speaker A
That way we simply have a tree. And I guess while we are here we can rename it to tree. And just to be consistent inside of the scenes folder this shouldn't be exercise object. This should be tree.
169:35
Speaker A
And the script. So exercise object.gd GD we can delete remove it and then the game is going to be a bit cleaner. Now that we have that we can start working on the player. First of all the player
169:50
Speaker A
root node needs to change the type. We want to have a character body 2D.
169:57
Speaker A
Once again is going to complain that we have no collision shape. This we can change by adding a collision shape to B and then giving it a shape for the player. I want to go with a rectangular shape and then scale it so we are
170:15
Speaker A
hitting most of the player. You want to leave a bit of space at the top and at the bottom because these parts should overlap with other objects. That way you get a fake kind of 3D effect. Looks really nice. You see later what I mean.
170:29
Speaker A
Besides that, what's really important to do inside of the script, we want to extend the character body 2D. And now that we have that inside of the game, I can move the player around and we still don't have collisions.
170:47
Speaker A
That is because at the moment we are changing the position of the player via the position property, which you can do.
170:55
Speaker A
You wouldn't get an error, but you also wouldn't get collisions. The way you are supposed to approach it is you are supposed to overwrite the velocity which is a property of a character body 2D.
171:08
Speaker A
This needs to be moved in a certain direction which we are getting via direction multiplied with the speed.
171:16
Speaker A
Once we have that you want to call move and slide. That way it applies this velocity and actually moves the character body 2D. As an outcome, the player is going to move a lot slower. That we can fix by
171:34
Speaker A
changing the speed back to 200. Might actually be a bit too fast. But now the important bit is we have a collision with the tree.
171:46
Speaker A
So I cannot go further than this tree. And that is working really really well.
171:52
Speaker A
That is all we needed for collisions. For the player, we have a character body 2D which we are moving via the velocity and move and slide. Besides that, we have a tree which is simply going to be a static object with a collision shape.
172:10
Speaker A
We also have an image, but that isn't actually necessary, at least for the collision. For the actual game, this is important. So, with that, we have a pretty good system. To finish up this part, let's do an exercise. I want you
172:23
Speaker A
guys to restrict the player to the map. Or in other words, use static bodies that ensure that the player is not able to leave the screen. Pause the video now and see how far you get.
172:38
Speaker A
Back inside of the game, in the main game scene, I want to add a new child note, which is going to be a node 2D.
172:48
Speaker A
Let's call this one borders. To this note, I want to add a static body 2D along with a collision shape 2D.
172:59
Speaker A
For the shape, I want to add a rectangular shape. That way, once again, we're getting the shape and the player is not able to move past that. So, here we cannot go further up.
173:11
Speaker A
And this shape I want to move to the right. So we are here on the right border of the map. And then I want to scale this thing up by a lot. So the player cannot go further to the left and leave the
173:26
Speaker A
screen. Let's try this one now. And the player is not able to leave. This we have to do for all of the four sides.
173:34
Speaker A
Although you do have to be careful. If I simply duplicated this static body 2D by clicking on duplicate or Ctrl D, then we would get another static body 2D that we can move to this point here. And that
173:47
Speaker A
would work. I can now run the game and the player cannot go further to the right than this border. The issue is if I wanted to change this collision shape, I would also change the other one.
174:02
Speaker A
If you duplicate a static body 2D with the collision shape, these collision shapes are going to be linked, which sometimes can be useful, like in this case where we do want to have the same shape. And this one should be a bit
174:16
Speaker A
further here. But for the top and bottom bit, this would not work. So do be careful here.
174:25
Speaker A
Instead, I want to add another static body to B with another collision shape. And for this collision shape, I want to create a new rectangular shape that is going to be all the way at the top here.
174:41
Speaker A
And let me move it to the right position here and here is fine. Finally, I want to duplicate this shape. And then move it all the way down. So we are covering the final part of the map.
174:57
Speaker A
And now the player is not able to leave the screen in any direction. Perfect. Next up, we are going to animate the player, which is going to make the entire thing feel much more dynamic. In GDO, there are a lot of ways
175:14
Speaker A
to animate things. The easiest one is to use an animated sprite 2D, which is a sprite 2D that's well animated. Inside of this node, you can create animations and then select them. That's pretty much it. Let's have a look. Back in GDO, I
175:30
Speaker A
want to work inside of the player and then get rid of the sprite 2D.
175:38
Speaker A
Instead, I want to add an animated sprite 2D, which at the moment is going to give us a warning that we have to add sprite frames to it. For that you want to look at animation and then inside of sprite
175:54
Speaker A
frames create new sprite frames. This right now doesn't really do anything. But if you click on it again then you're getting a sprite frames editor. In there on the left side you can see the animation that you want to play. Let's
176:08
Speaker A
say for now I simply want to play the left walking animation for the player.
176:13
Speaker A
Then inside of this main field you can play the actual animation. This you can create in basically two ways. Number one is you could simply direct graphics in here. For example, if I grab a couple of these random objects
176:28
Speaker A
and drag them in there, I can play the animation and then God is going to play one frame after another, which would work, but for our purposes, this isn't ideal. Let's undo all of this. Instead, for the player, we have a
176:45
Speaker A
player tile set. If I drag it in there, you can see that we have all of the player frames in this kind of setup. And from this, we want to select specific frames, like for example, this graphic here. To work with that, inside of the
177:00
Speaker A
sprite frames, you want to click on this symbol where you can add frames from a sprite sheet. We want to go to graphics player and then select the tile set or the sprite sheet. And then we can zoom
177:13
Speaker A
in by holding control and using the mouse wheel. GDU wants to separate this graphic into specific cells.
177:21
Speaker A
We have four horizontal cells, but only three vertical ones. The size lines up pretty well. So, this looks pretty good.
177:30
Speaker A
And now, we have to select the right kind of frames for the animation. At the moment, we want to get the left animation, which is the left one. And if you click on it, you're getting a number. This would be frame zero. Then,
177:43
Speaker A
we have frame one. and then frame two. These are the three frames that I want to add to it. And now we can play this animation. Although at the moment it doesn't look great. This animation is actually supposed to have this frame,
178:01
Speaker A
then this frame, then this frame again, and then the final frame. To get that, you can simply have the first frame selected, then press Ctrl + C and Ctrl +V. And now we have duplicated the frame. And to move this frame, you can
178:15
Speaker A
either move it in the right position or use these arrow keys. That way, we can move frames around quite easily. We are getting a much nicer walking animation.
178:25
Speaker A
You can also set the frame rate if this thing is looping and if it's autoplay.
178:30
Speaker A
You can also set the frame duration, but I don't really care about any of those values. Just make sure that you are looping the animation. Otherwise, it would simply stop on this frame. Also for now I want to auto play this
178:42
Speaker A
animation and that way if I run the game we are getting a very basic animation that is looking pretty all right. And now to work with this we want to use GDScript and to keep things organized I want to create another function for the
179:02
Speaker A
animation. No need for parameters. I basically want to check if we have a direction then we want to actually play the animation. If we don't have a direction then the player should be static or in other words we only want to
179:18
Speaker A
get the first frame. That way it looks like the player is idling. If we have a direction I want to play the animation which for now means we are simply not doing anything because we already have an animation. It's just not doing the
179:31
Speaker A
right thing. However, if we don't have a direction, so we're not moving, then I want to get the animated sprite and update the frame property. This one should always be zero. Now, by default, this value increases. So, we are
179:49
Speaker A
selecting different frames, but if you set it to zero, we're always sticking on the first frame. So, this one here. That way, at the very least, we can play the animation or not play the animation.
180:01
Speaker A
really important don't forget to actually call this animation function which I want to do before we are doing move and slide animation although the actual position of animation doesn't matter anyway let's try this now if I am not moving the
180:17
Speaker A
player is also not animating but if I start moving then we are getting the walking animation and that is working pretty well next up I want to get the right walking animation for that you could add another animation in here. So, simply add
180:35
Speaker A
another animation with right and then select the player and the right movement. So, these frames here.
180:44
Speaker A
However, we don't actually have to do that. We can approach this much more elegantly.
180:50
Speaker A
So, let's get rid of the right animation. Instead, all that we have to do if the player is moving to the right, we want to flip this animated sprite on the horizontal axis, which we can actually do super easily. With the animated
181:05
Speaker A
sprite selected, we have offset. And there we can flip H. And if you hover over it, the property is called flip_h.
181:15
Speaker A
Inside of GDScript, what we can do, if direction.x is greater than zero, then the animated sprite 2D dot lip h property should be true. Let's try that. If I go left, we're looking left. And if I go right,
181:35
Speaker A
we are looking to the right. Now, if I look left again, we're not going back to the left side. So, that's not great. But at the very least, we are making progress.
181:46
Speaker A
To fix this part, all we have to do is add an else statement and then copy all of this with the difference that flip age should be false.
182:01
Speaker A
Let's try this again. And now we're getting the left animation and the right animation. And that is working really well.
182:10
Speaker A
Cool. definitely progress. Although we are trying to do something very simple and we are using four lines of code for it. This could be more elegant. The way to approach that is to first get the animated sprite 2D and then flip h. The
182:28
Speaker A
value we want to assign to it is going to be direction.x being greater than zero.
182:36
Speaker A
And then we are done. This line is doing the same thing as these four lines. And I think it's much easier to read as well. So let me get rid of these four lines. Try this again.
182:49
Speaker A
And we are getting the same result. Doing this kind of stuff comes with experience. If you work inside of an engine for long enough, then at some point you find ways to make your code more efficient. So for now, if you work
183:01
Speaker A
with more if statements, that's totally fine, but this would be more elegant and much easier to read. With that covered, let's do another exercise. I want you to finish the animated sprite, which means you should be adding the logic for going
183:16
Speaker A
up and down. So, in other words, select the right animation depending on the player movement. Pause the video now and see how far you get.
183:28
Speaker A
Back inside of GDU, I want to work with the sprite frames and then add two more animations for up and down. These unfortunately we cannot mirror I guess. Let's start with up. I want to click on this button again.
183:46
Speaker A
Select the player tile set. Zoom in. And at the moment we are looking at up which is this animation. Add the three frames.
183:58
Speaker A
And then once again I want to duplicate the first frame and place it between these two walking frames. All I have to do is press Ctrl + C and Ctrl +V and then drag this frame in the right
184:10
Speaker A
position. Just to double check, let's play the animation. And that looks pretty all right. Cool.
184:18
Speaker A
Besides that, for down, we want to do the same thing. So, grit player, get the down walking animation, add the three frames, duplicate the first one, and drag the frame in the right position.
184:32
Speaker A
Then we are getting the down walking animation. Perfect. With that we have the right animations that we can work with.
184:41
Speaker A
We just have to figure out when to play which using GDScript. I first checked if direction.x is different from zero.
184:55
Speaker A
If that is the case, I want to play animated sprite 2D and update the animation.
185:02
Speaker A
This one should be left. We are still flipping the sprite on the horizontal axis. So if the player's going to the right, then left is automatically going to become right. Besides that, else if we are only going up and down, then I
185:17
Speaker A
want to get the animated sprite to be and update the animation again. Let's say for now this one could be up.
185:28
Speaker A
Let's try this one. I can go left. I can go right. And I can go up. Although I cannot go down, at least not with the right animation. But we are making progress. Now at this point, you could
185:42
Speaker A
approach this in two ways. You could either check if direction is smaller than zero. And if that is the case, we want to do all of this. If that is not the case, let me duplicate all of this. Direction.y is greater than zero.
186:04
Speaker A
Then the animation should be down. Let's try this one. Now I can go left, right, up, and down. This once again is working. But we are also doing something very simple over four lines of code.
186:21
Speaker A
A better way of approaching this would be to get the animated sprite, then the animation and assign it up if direction is smaller than zero. And if it is not the case, else we want to assign the down animation.
186:43
Speaker A
That way we can get rid of all of this and we would have the same result. Much more elegant. Let's try all of that. And now I can go in all of the four directions. And the player is animating
186:56
Speaker A
or static when we are not moving. At this point, we have basically finished the player, which means we can start working on the cars. For those, we have to do a couple of things.
187:08
Speaker A
Number one, cars should spawn automatically in a specific interval. For that, we're going to create a timer in just a second.
187:17
Speaker A
On top of that, they should start in a set position and move in a certain direction. There are a couple of things that we have to go through. So, let's go through it step by step. Number one, we
187:30
Speaker A
have to learn about signals. These are a vital component of GDO. And basically, any node can emit a signal. For example, a node can trigger when there's a collision or when a timer triggers.
187:45
Speaker A
Every node has its own signals depending on what they're supposed to be doing. This is a super important concept. Let's have a look at it. Back inside of GDU, let's say I want to look at the player, specifically the root node. So, the
188:00
Speaker A
character body 2D. On the right, we have the inspector. And there we can also see the node. This one contains signals and groups. The thing that matters for us are the signals. In here, you can check all of the signals that this node can
188:15
Speaker A
emit. For a character body 2D, there aren't many because this node in general is just supposed to collide with things and not do that much more. So, we can check some general things, but they're not really that useful. Instead, a much
188:30
Speaker A
more interesting node that's added to the main game is going to be a timer.
188:35
Speaker A
This is, well, a timer. If you look at the inspector, you can get a wait time.
188:40
Speaker A
if this is supposed to trigger once or multiple times. If it's auto starting and that's kind of all you need. Let's say I want this timer to auto start and then run for four seconds. This right now is not going to do anything. If I
188:54
Speaker A
run the scene, at some point the timer is going to trigger, but it doesn't really do anything once it triggers. So, this is no good. But what we can do inside of note, we have the timeout signal. This one is going to be
189:07
Speaker A
triggered when this timers out. The way you are going to use it is you double click on it and then you have to connect it to a script. At the moment, the only note that we have with a script inside
189:20
Speaker A
of the scene is the player. So, what I want to do is to add a script to the game scene. Add script. The defaults here are fine. Create. And now with the timer selected again, double click on timeout again. and then add the
189:36
Speaker A
signal to the game script connect. And then inside of this script, we can run a function. Let's say I want to print timer has triggered.
189:50
Speaker A
If I now run the entire thing again, every 4 seconds, we should be getting timer has triggered. There we go. This should happen multiple times. There we go. This looks pretty good. If we enabled one shot, this would only happen
190:06
Speaker A
once. This system, I want you to practice right away as well. So, I want you to create an area 2D node.
190:15
Speaker A
This should be at the top of the map. And when the player enters, it should print player entered. An area 2D node works like the other physics objects.
190:26
Speaker A
Meaning, you have the note and then you need a collision shape. After that, look at the signals and see what you can work with. Pause the video now and see how far you get.
190:40
Speaker A
I want to add an area 2D note. Once again, good is giving us a warning that this has no shape. This we can fix by adding a collision shape 2D or collision polygon 2D. In your case, you could just add a collision shape 2D with
190:58
Speaker A
a rectangle. it would be totally fine. But just to illustrate what you can do with a collision polygon, let me add this one. So create and now nothing has happened. But if you look at the top, we can create a bunch of points with this
191:14
Speaker A
thing here selected. Once you have that, you can simply draw a couple of points vaguely at the top of the screen like so. And to close the shape, you want to click on the origin point again. Now we
191:25
Speaker A
have another shape for this area 2D. For the area 2D, the inspector doesn't matter that much. But if you look at the signals, we getting a ton of stuff to work with. Most importantly, we have body entered. This one checks if a
191:41
Speaker A
physical body has entered this area, which is what we're looking for. So, double click on it and connect it to the game script. On area 2, the body entered would be a decent name.
191:55
Speaker A
Although what you could also do is rename this area 2D to finish area 2D and then the name here would also change. It's usually a good idea to have descriptive names in here.
192:08
Speaker A
Since our game is going to be quite small, this doesn't matter so much, but for a more complex game, you really, really want to have precise names.
192:16
Speaker A
Anyway, click on connect. And now we have another function that is going to be called whenever a physical body enters this area 2D.
192:26
Speaker A
Once it happens, we can print the body that we are getting. And we can print as entered. Let's run the entire thing.
192:38
Speaker A
And if I move up at some point, we are getting inside of output the player character and has entered. So this function here did trigger. So with that we have signals. Those are incredibly useful inside of GDO. They make any kind
192:55
Speaker A
of note much more interactive and give you a ton of options. Before we finish, there's one more thing that I want to do and that is to organize the game scene a bit better. Instead of game, I want to
193:07
Speaker A
add another child node which is going to be a plain node which I want to rename to timer and then add the timer that we have just created to it. And that way I can also remove timer 2. But don't add
193:21
Speaker A
the two because you cannot have the same name for two nodes. The timer that we have created should be called the car timer. And for now, I want to disconnect this signal, which you can do by right clicking on it and then disconnect.
193:37
Speaker A
Also, inside of the script, this timer function should disappear. We're going to replace it in just a second. For now, I just want to have a clean start. On top of that, the finish area 2D can go inside of borders. I think they kind of
193:53
Speaker A
work together. And finally, this exercise object should just be a three. That's the better name for it.
194:03
Speaker A
On top of that, the sprite 2D is simply going to be the BG or the background.
194:09
Speaker A
That way, all of this feels much more organized. This is something you are going to learn really, really fast. The scene tree can become cluttered incredibly fast, and you want to keep it as organized as possible. Now that we
194:22
Speaker A
can create a working timer, we can start working on spawning the cars. For that, we have to go through a couple of steps.
194:29
Speaker A
And along the way, we are going to learn how to spawn scenes via code. In other words, we want to create instances of a car whenever a timer triggers. For that, number one, we have to create a basic
194:42
Speaker A
car scene. This is going to happen in the normal way. We are just going to create a new scene with a sprite and an area 2D. After that, we're going to store the car scene in the main game.
194:54
Speaker A
Next up, when the timer triggers, we're going to create one instance of that car scene. And finally, we can attach the car scene to the current game scene.
195:06
Speaker A
That way, we can actually see it. First of all, inside of GDO, I want to create a car scene. Add a new scene. And the root node is going to be an area 2D.
195:18
Speaker A
This area 2D, by the way, I have used because there are no actual collisions between the player and the car. Whenever there's any kind of collision between the two, the game is ending right away.
195:29
Speaker A
So, an area 2D here is totally fine. To this area 2D, I want to add a sprite 2D so we can see something. The graphics for that are going to come from cars.
195:40
Speaker A
Select one of them and then assign it to the texture of the sprite 2D. Then we are getting one car. After that for the area 2D I want to add a collision shape 2D which for this one can simply be a
195:56
Speaker A
rectangle shape. Make sure you cover the whole car like so. And so I guess kind of like this.
196:07
Speaker A
Doesn't have to be too precise for our purposes but obviously for a real game do spend some time on it. All of this I want to save as car.tsseen. Click on save. And now we have one car.
196:21
Speaker A
That actually should be renamed to car. And then inside of scenes, I should have done that before. This shouldn't be area 2D.TSCN.
196:31
Speaker A
This should be renamed to R.tsseen. Much better. Now we have a car scene. This I want to spawn inside of GDO whenever this card timer triggers.
196:46
Speaker A
Speaking of which, for this one, wait time should be 1 second for now and it should auto start. After that, for node, I want to go to timeout once again and then connect on car timeout timer to the
196:59
Speaker A
game script. And now we get on car timer timeout. Whenever this thing triggers, we want to create one instance of the car scene. and attach it to the game.
197:10
Speaker A
For that, we already have a car scene. So, next up, we have to store the car scene inside of the game scene, which we do all the way at the top. I want to create a variable car scene. The data
197:26
Speaker A
type for this one is always going to be a packed scene. You are getting it by preloading the car scene. Budo is now giving you all of the options of data that you could preload. In my case, I want to get
197:43
Speaker A
scenes and car.tsn. That way, let me add just a bit more space. We have the car scene ready inside of the game scene, which means we have covered the second part. Next up, we have to create one instance of this car
197:59
Speaker A
scene, which is going to happen every time the timer triggers. To create one instance of the car scene, we have to call instantiate. That way we are creating an instance of it which we want to store in another variable. Let's call
198:15
Speaker A
it car. That way we have one instance. So we have covered the third step.
198:21
Speaker A
Finally to actually see the car we have to attach it to the current scene. This happens via add child. I want to add the car and then I can run the game.
198:34
Speaker A
And we should be seeing the car somewhere around the origin point. So there we are getting the car on top of that with the game still running. You can look at the scene tree and there we have remote where you can see the nodes
198:49
Speaker A
in real time as the game is running. And there you can see GDO keeps on adding area to these to it every time the timer triggers. Besides that you can see the notes that we have added ourselves. So,
199:03
Speaker A
this is a real-time view of the game. And well, you can see quite well that we are adding more and more cars inside of the game. You can't see them because they're all in the same position, but that we can work on. Inside of the car
199:16
Speaker A
scene, I want to add a script to it. The defaults here are fine as they are.
199:22
Speaker A
And then for the car, I want to add v direction, which is going to be a vector 2 that at the moment points to the left.
199:33
Speaker A
Besides that I want to have v speed which is going to be 100. After that I want to call funk_process in which we are updating the position of this area 2D node.
199:50
Speaker A
So once again inside of transform we can update the position of this node like we have done in the beginning of this project. I want to get the direction multiplied with the speed.
200:04
Speaker A
And you might be wondering now why do I use process for the car? Well, for the player, I used physics process. And well, for the player, we have collisions. So, we want to include physics. Whereas for the car, we don't
200:19
Speaker A
actually have collisions. Once again, as soon as there's a collision between the player and the car, the game ends right away. So we don't actually have collisions. We are simply checking for an overlap. In practice, you could also
200:32
Speaker A
use physics process. It doesn't really matter for our purposes. But anyway, with that, we should have the car movement. Although I think 100 is a bit too much. Let's go with two. Let's try out all of this now. And there should be
200:45
Speaker A
a car going to the left. And that is looking pretty good. Perfect. Once again, if you look at remote in the game, you can see we are adding more and more car scenes to the game. That being said, there is a bit of a problem.
201:04
Speaker A
Number one, adding the cars to the game scene is going to clutter the scene tree a lot, which is going to make it difficult to work with. So, what we can do at this point is add another node 2D
201:16
Speaker A
that we can call objects. All of the objects in the game are going to be inside of this node 2D, including the player and the tree. Add them in there. And then inside of the script, I want to add the cars to this objects as
201:33
Speaker A
well. You can simply drag and drop objects in the right position. Don't forget the dot. And now we're adding the car to the objects node.
201:43
Speaker A
If I run the game inside of remote, all of the cars are going to be inside of objects. If you minimize it, this looks a lot cleaner. Once again, not something you have to do, but it's going to make
201:56
Speaker A
your life quite a bit easier. Besides that, it's actually not a great idea to spawn cars indefinitely. So, at the moment, we keep on adding more and more cars, and this goes on forever. It never stops, which isn't great for performance
202:14
Speaker A
because once a car leaves the screen, it shouldn't be there anymore. You can't see it. You can't interact with it. It should just disappear. And think of a more complex game. The more objects you have, the slower the game is going to
202:28
Speaker A
run. So, you want to keep the amount of objects as low as possible, which is generally a good idea.
202:35
Speaker A
In other words, for the car, as soon as the car leaves the screen, we want to destroy it. That you can do by adding another node which is called a visibility screen notifier 2D. This can check if notice entering or exiting the screen.
202:53
Speaker A
It should roughly fit the texture that looks all right. It doesn't have to be too precise. And then inside of the signals, you can check if the screen was entered or exited. We care about exited.
203:05
Speaker A
If I connect this to the car scene, we want to destroy the instance of the car scene as soon as it leaves the screen or when this function is triggered. This in good you are doing via Q3.
203:19
Speaker A
This destroys the current instance of the node. Or in other words, if I run the game again and go to remote inside of objects, we only ever have maybe two cars.
203:33
Speaker A
As soon as the car leaves the screen, we are destroying it. So, we only ever have that many cars. And inside of the game, you can see we only have two cars on the screen, maybe three cars sometimes. That
203:45
Speaker A
way, we are making sure that we only ever have so many cars on the screen, which is going to be really good for performance. Now, obviously, for our game, since it's really simple, it doesn't really matter, but it's
203:56
Speaker A
generally good practice. Besides that, I want to set start positions for the cars. At the moment, the car always starts in the origin point, which obviously isn't great. To fix that, I want to add another note 2D to the scene
204:13
Speaker A
tree that I called car start positions. In here, we want to store a couple of nodes that have the start position for the car.
204:25
Speaker A
For that you could use a node 2D. It would work, but GDO also has a marker 2D that works a little bit better. So with this marker 2D, if you move it, you can see that we have the origin point
204:41
Speaker A
along with this cross around it. So it's a little bit easier to see. But outside of that, we only really care about the position of this node. And this we are getting via transform and position.
204:52
Speaker A
these marker 2Ds. I want to move all of the car lane start positions. Left or right doesn't matter so much.
205:01
Speaker A
You can alternate or you can stay on one side, whatever you think is best.
205:08
Speaker A
So, let's do this again like so. And like so. And then we have a start position for every lane. Once we have that, as soon as we have a new car, we want to update the position of that car.
205:21
Speaker A
For that, first of all, I want to get a random marker from the car start positions. Let's store that in a new variable position marker. The way you're getting that is first of all, you want to get the car start.
205:39
Speaker A
And then get children. This is going to return an array with all of the child nodes.
205:48
Speaker A
On an array, you can call the method pick random. That way, you're picking one random child of car.positions.
205:57
Speaker A
And once we have that, we can get the current car and update the position of that car. Now, right now, you don't get position as a suggestion. That is because GDO doesn't know what kind of note this car is that you have just
206:14
Speaker A
instantiated. If you want all of that, you can add s and then the type of node that you want to create. So in my case, an area 2D.
206:24
Speaker A
That way if you have car, you can get all of the suggestions again, which can be super helpful. And generally being really picky about the right data type is a good idea. It can make your life much easier. Anyway, for the car
206:38
Speaker A
position, I want to have the position marker. And don't forget, position marker is just a note on this. We want to have the position as well. If you want to be super precise here, this could be S marker 2D. If I now run all
206:55
Speaker A
of this, we should be seeing a car coming from the right. And that is working pretty well. If we go further down, there also some cars that can also disappear. And that looks pretty good.
207:08
Speaker A
The issue now is on the left side. We can't see any of the cars simply because if a car starts here, for example, it only goes left. Not great for our purposes.
207:21
Speaker A
But that we can work on inside of the script for the car. Once the car is ready, or in other words, funk ready, we can simply check if position.x is smaller than zero. If that is the case, we know we are on the left side.
207:40
Speaker A
If that is the case, direction X should be one. That way, we're turning the vector left to a vector right.
207:49
Speaker A
Although, if I run the game now, this is not going to work. We are still getting the cars on the right side, but we have no cars coming from the left side.
208:00
Speaker A
The issue is that this ready function only runs before we are updating the position. Or in other words, the ready function, this one here, is called when you're adding a note to a scene, which currently happens on this line when we
208:17
Speaker A
are calling add child, which at the moment is a bit of a problem because we are adding the car here and the current position of the car is zero and zero.
208:27
Speaker A
And then we are running this line here which is never going to trigger because the position is zero and zero.
208:34
Speaker A
Only after we are doing all of that we are setting the position of the car. As a consequence this if statement is never going to trigger. I can actually demonstrate I want to print car direction.
208:48
Speaker A
Let's run it. And this function is never going to run. So this doesn't do anything.
208:55
Speaker A
Fixing that, fortunately, is very simple. We want to update the position of the car before we adding it as a child to the scene, which is totally fine to do. When we are calling this ready function, the car already has the
209:10
Speaker A
right position. And that way, we should be getting cars coming from the left as well. So there we get car direction. I just have to find it. There we have the car.
209:22
Speaker A
This can be kind of annoying in GDO. Understanding when these inbuilt functions are being called sometimes can be a little bit tricky. Always remember ready is called when you're adding the note to the scene tree. And while we are
209:36
Speaker A
here, I don't want to print something when that happens. Instead, I want to get the sprite 2D and flip H should be activated.
209:48
Speaker A
That way, the car is pointing in the right direction. And with that, we should be having cars that go reasonably well in both directions.
209:58
Speaker A
At some point, there should be one coming from the right as well. Let's look up here. That definitely works.
210:04
Speaker A
This we can refine, but I think for now, this is working reasonably well. Now, before we continue, there's one important topic that we do have to cover that does get a bit more technical.
210:14
Speaker A
Frame rates and delta time. So far, we did not care about the frame rate at all. the game simply worked and that's totally fine. However, in some instances this can be an issue. That is because the frame rate is affecting the movement
210:29
Speaker A
of objects. Not always but in some circumstances and that we have to talk about. And while we are here inside of GDAU for the car when we are calling process we are getting delta. Same for the player inside of physics process.
210:46
Speaker A
There we also have a delta and so far I just didn't talk about it but it's a really important parameter but let's go for it step by step. Now the main issue is that a frame rate determined movement
211:00
Speaker A
can be inconsistent. Here's a table with the same movement but different frame rates. The actual speed is the first column where we always want to move at 10 pixels per frame. Or in other words, inside of our game or the car for
211:17
Speaker A
example, we are moving the car by a certain direction multiplied with a speed. In our case, for example, this would be a speed of two on the horizontal axis.
211:30
Speaker A
This change in position is applied on every single frame. So effectively we are moving at pixels per frame. Besides that we have the amount of frames per second. This number is going to vary on the computer. If you have a really slow
211:45
Speaker A
one, you might only get 10 frames per second. If you have a really good computer, you might get 500 or more frames per second. This also depends on what happens inside of the game. If you have a lot of objects, the game is going
211:57
Speaker A
to be more difficult to run. Generally, you want to have 30 or more frames. That way your game is going to feel smooth.
212:04
Speaker A
But for this example, it doesn't really matter what the number is. What does matter is the final column where we get the pixel movement per second.
212:13
Speaker A
This is simply the multiplication of these two numbers. For example, if we are moving at 10 pixels per frame and we have 10 frames per second, we are moving at 100 pixels per second, which on its own would be totally fine. But the issue
212:32
Speaker A
is depending on different frame rates, we're getting a different speed because we are applying a change of position multiple times per second. And this number varies. If we apply the change in position 10 times a second or 500 times
212:46
Speaker A
a second, it's obviously going to be different, which for our game is going to be a problem because, well, you can see it here. If our pixel movement is 100 pixels per second or 5,000 pixels per second, the game is going to feel
213:02
Speaker A
significantly different. Or in other words, the movement speed of your game will change depending on the computer.
213:10
Speaker A
And this is really, really not good. Just imagine any game where the movement speed could either be 100 or 5,000. No game would work like that.
213:21
Speaker A
And as a consequence, we have to account for it, which we are doing via delta time. All that this concept describes is the difference between the current frame and the previous frame. Or in other words, it tells you how long it took
213:34
Speaker A
your computer to render the current frame. Doesn't sound that important, but it's actually super useful because imagine you have a game that runs at 30 frames per second. Then delta time is simply 1 / 30 or 33 milliseconds.
213:51
Speaker A
If you have different frame rates, then you get different numbers. Obviously, the specific number here doesn't actually matter. What matters is that the higher the frame rate becomes, the smaller delta time will be, which is incredibly useful because let's do the
214:07
Speaker A
table again with delta time. The first three columns are what you have seen before. The only addition now is that we have delta time. For example, if our frames per second are 10, then delta time is 1 / 10 or 0.1. If our frame rate
214:24
Speaker A
is 30, then delta time is going to be 1 over 30 or 33 milliseconds. All of that is useful because delta time and the frames per second effectively cancel each other out. Imagine this formula here written in a slightly different way
214:40
Speaker A
where we have 10 pixels per frame from here multiplied with the frame rate. In this case that's 30 frames per second.
214:49
Speaker A
This number and this we are multiplying with delta time. This number here 1 / 30 or 1 over 30. The end result has to be 10 for the simple reason that 30 and 1 / 30 are simply going to be one. The only
215:08
Speaker A
thing that's left is the 10 that we are getting at the end. And this works with all of these numbers. So if we have 60, we would have 60 multiplied with 1 over 60, 500 multiplied with 1 over 500, and
215:22
Speaker A
so on. Frames per second and delta time cancel each other out. The only thing left are the pixels per frame. And that is really all we want. That way, it doesn't matter what the frame rate is, you're always getting constant movement.
215:37
Speaker A
And this you should use whenever you change the position or rotation of any node. The one place where you don't have to use it is with physics bodies because for those GDO automatically applies delta time. And finally, let's do all of
215:50
Speaker A
this in GDO. That way, all of this can also be a lot more practical.
215:55
Speaker A
We want to work inside of the car where at the moment we updating the position by getting the direction and multiplying it with the speed which on its own works totally fine. If I run the game, the cars are going to move. Let me find one.
216:11
Speaker A
There we go. We have movement. However, this movement depends on the frame rate. Or in other words, if I go to project project settings and then toggle advanced settings, then under run, we have a maximum frame rate, which right now is set to zero, which
216:31
Speaker A
means we have no maximum frame rate. Udo will try to run the game as fast as possible. Let's say I want to limit the frame rate to 12. That way, we get at least a little bit of movement.
216:43
Speaker A
If I now run the game, it's going to feel really rough, but the important thing is the cars are moving very, very slowly.
216:53
Speaker A
If we increase the number to 30, then they should be moving a lot faster.
217:02
Speaker A
And there we go. Now the taxis are quite a bit faster. And this is a problem.
217:09
Speaker A
The frame rate shouldn't affect the movement inside of the game. Let's set it to zero for now. That way God is trying to run the game as fast as possible.
217:19
Speaker A
Now to actually fix this, all you have to do is multiply this value with delta time and then you are done. That's all you have to do. So if I run the game now, the cars are going to move quite a
217:31
Speaker A
bit slower because delta time is a very low number. So there you can see the cars are not fast at all. Simply change the speed to a larger number. Let's say 200.
217:43
Speaker A
And now the cars are a good bit too fast. Let's go with 100 here.
217:54
Speaker A
And then we have a car that is moving at a much nicer pace. Really importantly now if I go back to limit the frame rate to 12, the game is going to be much choppier, but the speed of the car itself is not going to
218:09
Speaker A
change. And that's the important part. That is the point of delta time. It makes sure that you can change the position independent of the frame rate.
218:19
Speaker A
A super important concept that you have to use whenever you're changing the position or the rotation or any of these basic properties of a sprite 2D, for example, to make sure that the frame rate doesn't affect the speed of it.
218:32
Speaker A
However, if you have a physics object that you move via the velocity and move and slide, you don't have to do that.
218:39
Speaker A
your door applies delta time here automatically. Next up, we're going to work on the player car collisions.
218:46
Speaker A
Or in other words, we have to add a signal to the car that is going to be emitted whenever there's a collision between the two. However, this has to happen inside of the game scene because there is all of the logic for the actual
218:58
Speaker A
game. Or in other words, we have to connect the signal once the car is spawned via GDScript. Here we are back in the game and the issue we have at the moment is that we want to check if the
219:11
Speaker A
player overlaps with this car and for that we can use a signal for the entered would be best. The problem is we can connect this to the car but then we have a script inside of the car. So in here I
219:27
Speaker A
guess that would do something but it wouldn't really be that helpful. All of the logic for the actual game is inside of game.gd. GD. So in here I want to run the script for the collisions.
219:39
Speaker A
Fortunately what we can do once a car has spawned we can connect a signal via GD script. All you need is the car that we have created. Really important. We want the car instance not the car scene.
219:54
Speaker A
On that thing we can run a method called connect. Then we need the name of the signal which in our case is called body entered. Simply type this string of it body underscore entered.
220:08
Speaker A
The second argument is then the function that you want to call which in my case is going to be go to idle because that's what we later on want to do once there is a collision. Also really important I
220:23
Speaker A
want to pass this function as an argument in here but I do not want to call it meaning there shouldn't be parenthesis afterwards. We only want to have the word go to title without anything else.
220:36
Speaker A
After that I want to create this function. So funk go to title. No need for parameters. And now once it is the case I want to print player car collision. And that should be it. Let's try inside of the game.
220:58
Speaker A
I am getting a lot of errors. You can see in the bottom GDO is really really unhappy with us. Under errors, we are getting an issue and let's read it out.
221:13
Speaker A
Gudo has an error calling from signal body entered to callable go to title the one that we have just created here. And the issue is the method expected zero arguments but was called with one.
221:27
Speaker A
Understanding these error messages is incredibly important. So let's go through it. Go to title expected zero arguments because there's no parameter.
221:37
Speaker A
However, because of connect and body entered, we are calling this function with one argument. This number here at the end. Effectively, when good is calling this function, it passes an argument into it. But inside of the function, we don't have a parameter. And
221:52
Speaker A
as a consequence, we're getting an error message. This happened because when you look at the signal body entered, we are getting the body as an argument passed into it. And this is what Gdole wants to do. To fix that, all you have to do is
222:08
Speaker A
add one parameter, which would be the body. Although in our case, we don't really care about it. But just to demonstrate what is happening, let's print the body that we are getting. And if I now rerun the entire thing, we are
222:22
Speaker A
getting a whole bunch of collisions actually. Let's have a look at the output. The first collision that we are getting is a static body 2D collision.
222:33
Speaker A
Then we have another static body collision, another one. And then we have the actual player collision. We are going to work on that in just a second.
222:41
Speaker A
But for now, the important thing that you have to understand is if you want to connect a signal via GDScript, you get the node or the scene you want to connect. Then you call connect with the signal name and then the function you
222:53
Speaker A
want to call. And always make sure that you are accounting for all of the arguments that GDAU is passing into this function. And once you have that, you can connect signals via GDScript. Now besides that we were expecting the player body and
223:10
Speaker A
player car collision simply the string. However, besides that we got a whole bunch of additional collisions. What happened here? When we are looking at body entered for the area 2D it looks at any body.
223:26
Speaker A
This would include these borders around the screen. Static bodies are still bodies. So whenever a car is being spawned, it will collide with this border. A car could also collide with the tree that we have created. And it
223:40
Speaker A
could also collide with any other object that we might create, which at the moment isn't really the desired behavior. So how can we fix that? For that, we have collision layers.
223:51
Speaker A
Effectively, every physics body has a layer and a mask. A mask is determining what physics object a node can see. and a layer determines what other physics objects can see the node. That way, for every single physics object, you can
224:08
Speaker A
determine which objects can see each other. So, with that, back in good, if you look at any physics object, like for example, the player in the inspector under collision, we have layer and mask.
224:22
Speaker A
All of these are just numbers, and this determines what layer and what mask the player is on. If you have over these numbers at the moment, you only get layer one. But what you can do under project settings and if you scroll down
224:36
Speaker A
a bit somewhere, we have 2D physics. And let me disable advanced settings. We don't need it anymore.
224:44
Speaker A
In here, you can name all of the various layers. For example, we could have layer one being the terrain, layer two being the player, layer three could be the cars, and layer four could be the walls. And by walls, I
225:02
Speaker A
mean these walls around the screen. And to get started with the player, the player should be on layer two, which is only for the player. So this determines what other objects can see the player.
225:16
Speaker A
And on the flip side, for the mast, the player should be able to see the terrain. He should not be able to see itself. The player should be able to see the cars. And the player should see the
225:26
Speaker A
walls. Then for the tree, for collision, the tree should be on a terrain layer.
225:33
Speaker A
And for mask, we can disable everything simply because the tree doesn't have to see anything else. And just to demonstrate, if I now run the game and go to the tree, we are still getting a collision. And that is working pretty
225:46
Speaker A
well. However, once I put the tree on a different layer, let's say layer five that we are not using, then the player can walk right through it. There's no collision anymore. The only layers that the player can see are determined by the
226:02
Speaker A
mask one, three, and four. If the tree is not on any of them, the player's going to ignore it entirely. All of this you should really practice. For that, set up the layers and the masks for the cars and the walls. Really important,
226:18
Speaker A
the cars should not see the walls or each other, but they should see the player. Pause the video now and see how far you get.
226:29
Speaker A
I want to start working with the car, specifically the area 2D node. For collision, the layer should not be on terrain. It should be on cars. That way, the player can see it. Next up, for the mast, the car should only be able to see
226:45
Speaker A
the player itself and nothing else. That way, a car should already not see the walls around the screen anymore.
226:52
Speaker A
Let's try this. And now, we should only get a collision between the car and the player. And that looks pretty good.
227:00
Speaker A
Finally, then for these static bodies around the screen, you could leave them on the terrain layer. It would kind of be possible, but I would rather have this organized. So, they should be on walls and they should not see anything else. This I want to do
227:17
Speaker A
for all of them. So, this should be only four. Same for this one. And same for the final wall only on layer four. That way, the player should still see them. There we go. This works, but the cars are going to ignore it
227:37
Speaker A
entirely in two different ways. Actually, with that system, we can control a lot better what is colliding with each other. Finally, all the way at the top, we have the finish area 2D.
227:50
Speaker A
This one should not be on any layer. In other words, no other physics node should be able to see it. However, it itself should be able to see the player.
228:01
Speaker A
That way, if I run the game again, the player should still be getting up here, and that works, but no other physics object can interact with it. At this point, we have covered all of the basic concepts to create a level. If you added
228:15
Speaker A
lots more stuff to it, you would have a pretty decent basic game. And this is what we are going to do in this part.
228:22
Speaker A
However, before we get to it, there's one important concept that I still have to cover. At the moment, the player can either be behind an object or in front of it. But this system is static. The player couldn't dynamically change the
228:36
Speaker A
position. Back inside of GDU, the position of the player relative to the tree. These two objects is determined by the node tree. So, at the moment, the player comes first and then we have the tree. And as a consequence, if I move
228:52
Speaker A
the player around, the player is always behind the tree inside of the game, you can see that the player right now is in the right position behind the tree. But if we go around now, the player is well
229:07
Speaker A
still behind the tree, but the player should be in front of the tree. That we have to fix. The system for that is called Y sorting. All that it does is it decides which object is going to be
229:20
Speaker A
on top depending on the y position. Just imagine that this line up here is y being zero.
229:29
Speaker A
The player position in this case is let's say 10 pixels and for this player it's going to be 20 pixels while the car is always going to be on pixel position 15. Same for this one. If all that y sorting is doing is it
229:46
Speaker A
compares these two numbers. Whichever has the higher y number is going to be drawn on top.
229:54
Speaker A
That way if the car is further down it's going to be on top of the player. If the player is further down it's going to be on top of the car. And that's literally it. It's a really simple concept and you
230:05
Speaker A
can apply it to GDO super easily. All you have to do is grab the parent node objects in this case and then go to ordering inside of the inspector.
230:15
Speaker A
There we have Y sort enabled. This should be enabled. And then all of this is going to work. So the player can be behind the tree like so. And the player can be in front of the tree like so. And
230:28
Speaker A
that is feeling a lot more realistic. And by the way, it's really important for this system that the collision shapes for the player and the tree don't cover the entire height of the object.
230:42
Speaker A
For the tree, we have a bit of space at the top and the bottom. And same for the player. We have a bit of stuff below and above the player. That way, these two can overlap a bit, which makes the game
230:54
Speaker A
feel much more three-dimensional. And well, with that, we have the basic system in place. Now we can add lots of objects to place all of these elements. You want to organize your project so the entire thing is reasonably streamlined.
231:12
Speaker A
Let's do some examples. We already have one object, the tree, where we have a static body 2D, a sprite, and a collision shape. We could, for example, copy this tree and then place it here and here and here. Run the game.
231:30
Speaker A
we would have more trees. Pretty straightforward. If you wanted other objects, all you would need to do is create another static body 2D node. Let's say for this one, I want to create a box for which I want to go to graphics and
231:52
Speaker A
then inside of objects, we have a couple of boxes. I want to choose one of those to add it to the scene. I want to add a sprite 2D and then box.png is going to be the texture.
232:05
Speaker A
After that, zoom in quite a bit. Add the collision shape to the for this one. We definitely want to have a rectangle that we then want to scale down quite a bit to something like this.
232:21
Speaker A
Afterwards, save the entire thing inside of scenes box.tsseen and then we have a box that once again we want to attach to objects which means in there box.tsseen and then in the origin point we have a box and by the way if you try to move it
232:41
Speaker A
and you move something else like for example right now the cars start. You can avoid that by having the box selected inside of the scene tree and then hold command or alt. That way you are only moving the note that you have
232:54
Speaker A
selected inside of the scene tree can sometimes be super handy. But anyway, once we have that, we have a box and then inside of the game we can collide with it. That being said though, for something as simple as a box, this is
233:09
Speaker A
kind of overkill because a box is well really really simple. We don't need a separate scene for that. What we could also do inside of objects is simply create another static body 2D that we could rename to let's say bench.
233:27
Speaker A
To this bench we can add a sprite 2D right away. And for that I want to use bench.png for the texture. Then we have a bench. And after that we can add a collision shape 2D with a rectangular shape that we then
233:46
Speaker A
want to scale like so. And so and then we have another object that we can work with and we didn't have to create another scene. Although you do want to be careful moving this bench around right now can be kind of
234:01
Speaker A
annoying. there's a good chance that you accidentally only direct the collision shape or only the sprite 2D which would well cause a ton of problems. So this I don't want to do. To avoid that you want to click on this symbol. If you activate
234:17
Speaker A
it, you're getting this symbol next to the note. That means you can only move the parent note. So now we always moving the entire bench as one object.
234:28
Speaker A
Super handy. That way we can move it. Let's say here. And once again, inside of the game, we are getting another object that we can collide with. There are loads of useful icons at the top. The other one
234:44
Speaker A
that's super useful is locking it. That way, this node cannot be worked with anymore, which for example, we really want to do for the background because this one really isn't supposed to move.
234:57
Speaker A
Same with the borders actually and with the car start positions. None of those should ever really move. Although the bench shouldn't be locked, but it should be grouped. This would be another way to create an object inside of the scene.
235:12
Speaker A
Once you have that, you can simply duplicate this bench, and then you can create as many benches as you like, which is also a way to approach it.
235:22
Speaker A
Although if you want to create a lot of objects, this might still not be ideal.
235:28
Speaker A
For that, we can approach these kind of objects in a different way. Let me add another node 2D where I want to have a whole bunch of let's just call it stuff. Doesn't really matter what you call it. To this note, I
235:47
Speaker A
want to add lots of random sprites. I can simply drag them in there like so.
235:53
Speaker A
There we have a bin. We can put a box here, a box there, a third box here. Let's say we can put a car in this position and a light hereish.
236:07
Speaker A
The specific shape does not matter. I just want to have a whole bunch of sprites inside of the stuff node. and make sure that for this stuff node you have ordering y sort enabled. Now we have a whole bunch of objects. The
236:22
Speaker A
problem is inside of the game we have no collisions whatsoever. For that we will need a static body 2D.
236:32
Speaker A
Now what you can do to a static body 2D is add multiple collision shapes. Which means I can add a collision shape 2D with a rectangle for now. And let's say this one is just for the car. So I can
236:48
Speaker A
resize it to something like this. And then to the same static body 2D I can add another collision shape or collision polygon. Let's say collision polygon. And then I can draw a rough shape for these objects.
237:04
Speaker A
So something vaguely here, here, here, here, here, here, and nearly done. Like so. And to refine this a bit, you can have this symbol selected and then move these points. There we go. Now we have a collision shape. And inside of
237:26
Speaker A
the game, if I go to this position, we have a collision with the car. That works. and with these boxes as well. And that is working pretty well. The same thing we can then do for these objects and for this object. And you simply go
237:42
Speaker A
through it step by step. That way you can very easily add lots of objects with one collision shape, which I think is the best way to approach it when you have a lot of stuff to add to a scene.
237:52
Speaker A
With that part covered, we can do an exercise. I want you to place a lot of elements so that by the end of it, you have a proper looking level. Place a whole bunch of static bodies and sprite
238:03
Speaker A
to these. How you're doing this is entirely up to you. You can create separate scenes or a few notes inside of the game scene. It really doesn't matter for our game. Just choose what you think is best. Pause the
238:16
Speaker A
video now and see how far you get. I went ahead and created a whole bunch of objects. Most of those I placed inside of the stuff node where we now have a ton of sprites and on top of that
238:32
Speaker A
somewhere in there is a static body 2D which holds a whole bunch of collision shapes inside of the game.
238:44
Speaker A
All we see though is that we have a ton of collisions with different objects.
238:49
Speaker A
Let's go here. Here we always have collisions and that is working pretty well. Now obviously to create a level you have to have some patience and place a ton of elements which sometimes can simply take a bit of time especially
239:05
Speaker A
doing all of the collision shapes manually can be quite annoying and later on we are going to learn ways to make this more efficient. But for now this is the easiest way to create a level. on top of that or this bit up here. We
239:19
Speaker A
don't actually need collision shapes because once the player gets to this bit, the game should be over. I guess one thing that we can do to finish up this part is at the moment we don't really get that many cars, which does
239:33
Speaker A
look a bit weird. To make that work much better, let me minimize borders and objects and then look at the car timer.
239:41
Speaker A
At the moment, we are creating one car every 1 second. If I change this to 0.1, then we're getting a lot more cars already. So now this feels a lot more like a game. This number you can tweak.
239:58
Speaker A
I think I went with 0.15 for the actual project. But obviously just test this and see what feels good for your purposes.
240:08
Speaker A
Also, while looking at this, I think we should vary the cars just a bit more. At the moment, our car is always going to be a taxi. That being said, inside of cars, we have three different kinds of
240:22
Speaker A
cars. And those we want to select randomly. For that, we have to work inside of car.gd.
240:30
Speaker A
First of all, we have to load these three cars into memory. That we do first of all by creating a variable. Let's call it colors.
240:42
Speaker A
Inside of this variable, I want to store an array that stores the green, red, and yellow car. To load them, we want to preload. And then the name of the file that we want to preload, which in my
240:56
Speaker A
case is graphics, cars, and green.png. First of all, besides that, and let me write this over multiple lines so it's more readable. I want to duplicate this line by pressing control shift and D.
241:09
Speaker A
Besides the green car, I want to have the red car and I want to have the yellow car. That way, we can use these graphics inside of the game right away.
241:20
Speaker A
And effectively, what we want to do once this scene is ready. I want to get this sprite 2D, this sprite 2D here, and then update the texture, which I can simply grab via the texture and then assign one of the images that
241:40
Speaker A
we are storing inside of this colors array. Now, to pick a random value from it, all we need is pick random. That way, we are picking one item at random. If I now run the game, we are getting
241:56
Speaker A
very unlucky. But now this looks much better. We have three different cars and that makes the game feel significantly more interesting. All right, at this point we have a basic game where a player can move around. We have static obstacles,
242:13
Speaker A
we have moving cars, and we can accept player input. However, what we don't have is a way to communicate with the player directly via text that we're going to work on now where we are creating a timer on top of the window
242:26
Speaker A
while the game is running and we're going to create a title screen. So, let's talk about creating layouts. Up to this point, we have placed nodes using absolute positioning, which is a fancy way of saying that every node get an XY
242:42
Speaker A
position that is independent from the window. That means back inside of GDU, let me create a new scene which is just going to be a 2D scene. Inside of this 2D scene, we have the origin point up here. This is position zero and zero. If
242:59
Speaker A
I now place any kind of object via a sprite 2D, then this object is going to get a position that we can see inside of transform. We can have some cleaner numbers. Let's say 100 pixels and 120 pixels. This number tells us the XY
243:16
Speaker A
distance from the origin point. This number does not care about the window size, the blue frame we have right here.
243:25
Speaker A
In other words, if I save this scene, let's say inside of the main folder right now, and run it, we have the car here. And if I resize the window, the car doesn't really care. It's always in the same position relative to this top
243:40
Speaker A
left point, which is fine for 2D nodes. They are supposed to work like that. But layouts work differently. They are placed using relative positions, which in effect means that instead of giving them an XY position, we are placing them
243:57
Speaker A
10% from the left side of the window or 20% from the top of the window. Things like that. That is really important. For example, if this is the game window, a UI should always be in the same top left
244:11
Speaker A
position. For example, for health bar up here or for some indicator in the bottom left. Even if the window becomes smaller, let's say the new window is something like this because it's resized, then the UI should still be down here
244:29
Speaker A
and maybe scale down a bit, but it shouldn't fundamentally change the position. Let me close the scene that I have just created and delete it entirely. So, note 2D.tsn we can delete.
244:42
Speaker A
Instead, I want to create another new scene, which this time is going to be a user interface. Once we have that, we are getting something that looks a little bit different. We are getting a red frame and we're getting green
244:57
Speaker A
needles around it. I'll talk about those in just a second. If I add a new node to the scene. So far, we basically only work with node 2Ds, the blue ones. Now, we're going to work with the green ones.
245:11
Speaker A
Those are control nodes which you're using entirely for UIs. In there, for example, you have a label that gives you text. You have a panel that is a basic panel that you can style. There's also a texture rectangle. That way you can
245:27
Speaker A
display an image. We are going to work with these nodes in just a second.
245:31
Speaker A
Although for now, the note that I actually want to work with is called a color rectangle.
245:37
Speaker A
This one is well a rectangle that displays a color. If you look at the inspector, we can select any kind of color in here. Let's go with a reddish value for now so we can see what's going on.
245:50
Speaker A
And then we can resize this thing like any node 2D. That part is fairly straightforward I think. That being said though, that's not the system you are supposed to be using. Instead, if you look on the right in the inspector, we
246:06
Speaker A
have layout and in there we get a whole bunch of options. The most important one is the layout mode. There we have position and anchors.
246:16
Speaker A
If you have position selected, then you can treat this thing basically like a node 2D where we can work with transform and give it an XY size, a position, a rotation, and a scale. all of the basic things. This can be useful if you want
246:34
Speaker A
to display text inside of a game. So for example, later on inside of the game, we want to display some text and for that we do want to use the position. So we can integrate a layout node in a 2D
246:45
Speaker A
scene. However, purely for the layouts, we want to work with anchors. And for those, we don't really need transform. Instead, we are getting anchor presets. Loads of options here, but I want to work with custom. We're getting three options. Anchor points,
247:02
Speaker A
anchor offsets, and grow direction. A really important part for now is anchor points. In there, we have left, top, right, and bottom. Via those points, we define the distance from the node to the side of the screen that we are talking
247:17
Speaker A
about here. Just for an example, let's leave left and top at zero and zero, but right we can set to 0.4. 4 and bottom to 0.2.
247:30
Speaker A
If I then zoom out just a bit there, we can see things better. And now let's talk about it. At the moment, we have this blue rectangle. That is our screen.
247:44
Speaker A
At the moment, in my case, the screen dimension is 1280x 720. You might have different numbers. It really doesn't matter because GDO for layout nodes changes these numbers to a scale from zero to one. So only for the
248:03
Speaker A
x-axis from here we are going from zero to one. Same for the y-axis we are starting up here with zero and then we are going all the way down to one. That's the bottom border. Because of that for example for
248:21
Speaker A
the right side when we are defining 0.4 we are talking about 40% of the screen width at the moment for the left side we have defined a value of 0.0 that means the left side of the note is
248:36
Speaker A
on the left side of the screen however for the right side we have set a value of 0.4 four. That means the right side of the note gets 40% of the width of the screen. In other words, we have another 60%
248:54
Speaker A
that the node is not using. Afterwards, we get to the end of the screen. The same system we are using for top where we start on the top of the window or in other words, the top of the node has a
249:07
Speaker A
distance of zero from the top of the screen. But the bottom side is 20% of the screen height from the top of the window. That is how you have to think about layouts. You don't define an XY position. Instead, you define a distance
249:24
Speaker A
to the screen borders. Anchor points for that are the most important part. Besides that, the one that I do want to talk about in this bit is anchor offsets. Those are in pixels and they give you an offset. For
249:37
Speaker A
example, for left, we can add, let's say, 20 pixels. And that way, besides the anchors, we're getting 20 pixels from the left side. Via that you can also see what degree needles are for.
249:52
Speaker A
They tell you the anchor points. Besides that, right now for the top, I also want to have 20 pixels.
249:59
Speaker A
And then I can save the entire scene inside of scenes. And let's call it title.tsn which should also be the name of the root note title.tsn.
250:14
Speaker A
If I now run the scene in the top left we are getting the note that we have just created and this thing grows or shrinks with this screen which can be really handy. That way if your game runs
250:30
Speaker A
on a really small screen and if you have a really large screen then it still works. Even more importantly what you can do is place this thing in the bottom right down here where for example the left side can have a value of 0.7
250:47
Speaker A
the top can be 0.6 the right can be one and the bottom can be one. Then we don't need any offsets.
250:55
Speaker A
And now if I run the current scene again, I can resize the window and the note is always going to be in the bottom right regardless of the window size. And that can be incredibly useful. So I hope the
251:10
Speaker A
system makes sense. You basically, at least for now, want to work with layout mode anchors and then for the anchor preset you want to have custom. That way you get the anchor points and the anchor offsets. Besides that, if you look at the top, you have
251:25
Speaker A
this button. Via that you can set anchor presets. For example, you can place a note right in the middle, in the top left, in the bottom right, or you can make it cover the entire available space. This is usually just a starting
251:38
Speaker A
position. Once you have clicked on any of those buttons, you can still go to anchor preset and go from the one you have selected to custom and then change whatever you like. With that covered, let's create the actual title screen
251:52
Speaker A
that I want to use for the game. For that, first of all, this color rectangle is going to be the background.
251:59
Speaker A
I have a custom color 633 C65, which is a purpleish color. After that, I want to add another note, which is going to be a label.
252:13
Speaker A
If you now look at the inspector for label, we basically have text where we can write let's call this one the car game.
252:24
Speaker A
Then in the top left you can see car game although the font is really really not ideal. It should also be quite a bit larger. The way we can change that is inside of the inspector we have theme
252:38
Speaker A
and theme overwrite. Basically, you can apply a theme to multiple layout nodes, which we are going to do later. But for this project, we only want to apply custom styling to this particular note, which we can do via theme overwrites. We can change, for
252:55
Speaker A
example, the color and give it a different font color, which I don't want to do. We can also give it a custom font and a custom font size.
253:06
Speaker A
For the font size, I want to have 140. That way, at the very least, this thing is quite a bit larger. For the font, we will need a font file that I have inside of the folder fonts. In there, we have
253:22
Speaker A
better VCR and Crackman. F. Crackman.f is what I want to use. So, simply drag and drop it in there. Then, we have a much nicer looking font.
253:32
Speaker A
this I want to center which I can do by going to this symbol up here and then placing it in the center that way it's right in the center which is a decent start but not perfectly yet so to
253:46
Speaker A
customize that and move this text up in just a bit I want to go to layout and then change the anchor preset to custom that way I can use anchor points and anchor offsets once again the only thing that I really want to do
254:01
Speaker A
is inside of anchor offsets. I want to change the bottom and then move the entire thing up by some amount.
254:10
Speaker A
Let's say negative 250. If I now test this one scene, then we have a bit of text that is slightly on top of the center. This looks good.
254:26
Speaker A
Besides that, I want to add another layout node which is a texture rectangle. Via that we can add a picture. I want to go to graphics, then to player and use player simple.png.
254:40
Speaker A
Simply drag it in the texture. And then we have the player. This player should be right in the center of the window, which means anchor presets center.
254:51
Speaker A
And then we have the player. That looks good. We can also scale the entire thing.
254:58
Speaker A
Go to layout transform and then for the size we can change this to let's say 100 and 100.
255:10
Speaker A
And then once again you want to apply the center preset so it is right in the center. Finally I want to add another label. This is going to be for the score. For now, let's simply write high score with some kind of number 1 2 3.
255:29
Speaker A
This once again I want to have right in the center of the window and then move it down a bit which we can do by going to layout anchor presets custom and then anchor points. We want to move the top
255:42
Speaker A
down by a bit. Let's say something like so. After that I want to go to theme override fonts and font sizes.
255:52
Speaker A
For the font, I want to use fonts and better VCR. Simply drag it in there.
255:58
Speaker A
Then we have a nicer looking font. And for the font size, let's go with 50.
256:05
Speaker A
Maybe a bit large. 30 is better, I think. Once again, play around and see what you like. Anyway, with that, we have the basic title screen. That looks good. This is all we need in here for now. Besides that, inside of the game,
256:22
Speaker A
let me run it. At the top of the window, I want to have a bit of text.
256:28
Speaker A
And now, you do have to be careful. You can add a layout node to a node 2D, like our game for example. I could simply add a label to it with for now let's say some text and then move it to the center top of the
256:46
Speaker A
screen like we have done before for the title. The issue is if I now try to run the game I can't see it in the top but if I move up there we have some text and this text is entirely static. So not great
257:03
Speaker A
yet. Effectively we have to tell Gudo that this label should be relative to the camera that we have selected which in our case is the camera of the player.
257:13
Speaker A
The way you are doing that is by adding another node that is called canvas layer. If we add the label to this note as a child and run the game again then we have in the top left some text.
257:30
Speaker A
A bit hard to see. We have to basically redo the anchor preset. Then you can see if I zoom out, we have it up here, which still looks a bit confusing. But if I now run the game again at the top of the
257:44
Speaker A
screen, we have some text. And that looks pretty good. With that, we can do an exercise. I want you to customize the label on top of the window, the one for the score. Number one, it should count the time since the start of the game.
257:59
Speaker A
For that, you can use a timer. Besides that, give it a custom font and an offset from the top of the window so it looks a bit nicer. If you want to experiment, you can also give it a
258:12
Speaker A
custom size and a custom color and just see what you can change. Pause the video now and see how far you get.
258:22
Speaker A
The most important thing is that this text displays some actually useful information. Or in other words, it should display the elapse time since the start of the game. The way I approach that is first of all, I created another
258:38
Speaker A
timer that should be the score timer like so. This one should auto start and have a wait time of 1 second. After that, I want to connect the timeout signal to the game scene. Connect. Then inside of the game scene, I want to create another
259:00
Speaker A
variable for this score, which has to be an integer with a default value of zero, which is what we're getting by default.
259:08
Speaker A
So score int is totally fine here. Every time the score timer times out, I want to increase the score by one. When that happens, I want to get the label and change the text of that label. Once again, if you look at the inspector for
259:27
Speaker A
the label and you hover over the text or the property you want to change, then you can see how you approach it inside of GDScript. For label, if you want to change the actual text, you simply want to get label.ext
259:41
Speaker A
and assign a new value, which has to be a string. Let's say for now, I want to change it to something.
259:50
Speaker A
If I run the game after 1 second, some text should become something and it does. That is working well. That unfortunately means we couldn't assign the score right away because the score is an integer while the label wants to
260:05
Speaker A
have a string. If I run the game now is going to crash. So this is no good.
260:12
Speaker A
Luckily, this we can change very easily. You want to wrap this score, so the integer into the str function. That way, GDAU is turning the number into a string after which the entire thing should work just fine. We get 1 2 3 4 and so on.
260:32
Speaker A
This is working pretty well. If you want to be fancy here, you could also do something like this string time elapsed and then plus the string that we are getting from the score like so. Make sure you have a space in there. And then
260:52
Speaker A
if you run the whole thing, you're getting time elapsed with the current time. You could do that, although I don't really care about that. I simply want to display the number. I think that's enough. Now, besides that to
261:08
Speaker A
style this text, I want to go to first of all theme override and then fonts and font sizes.
261:17
Speaker A
The font should be better VCR. And the font size, let's go with 40. Inside of the game, this should also look okay.
261:28
Speaker A
And yeah, this works reasonably well. Besides that, for the offset at the top, I want to go to layout, anchor presets, change it to custom, and then anchor offsets for top should be let's go with 20. After that, inside of the game,
261:47
Speaker A
we are getting I think that looks all right. Finally, the default text should be zero. And to make sure that this zero is actually centered, we want to set the horizontal alignment to center. That way we are actually in the center. If I now
262:04
Speaker A
run this thing again, we get zero, 1, 2, 3. And this is working pretty well.
262:12
Speaker A
Perfect. The last major part of the game that we have to work on is the transition between the game and the title screen.
262:20
Speaker A
Once we have that, we have an actually functioning game. So, let's talk about it. We want to transition.
262:28
Speaker A
Or in other words, we want to change the scene from the game scene to the title screen. This should happen when the player reaches the finish area or when the player gets hit by a car. We also want to be able to go back. If we're on
262:42
Speaker A
a title screen and the player presses a button, then we're going back to the game. On top of that, we want to keep the score information, which means that the score inside of the game should also be displayed inside of the title screen.
262:56
Speaker A
For that, we have to talk about global data. But let's go through it step by step. Back inside of GDU, when the player reaches this finish area 2D, we want to load the title screen. And you can see for this area we already have a
263:12
Speaker A
function via signal which is this one here. To load another scene inside of GDScript you only need a single line of code. First of all you want to get tree.
263:26
Speaker A
This is a really common operation inside of GDO. The tree is basically the scene tree. This one gives you a ton of options. And to change a scene you have two methods. either I change scene to file or change scene to packed. Scene to
263:41
Speaker A
file is easier. Let's work with that for now. Then as an argument, you need the file path to the scene that you want to load, which in our case is going to be scenes and title.tsn.
263:55
Speaker A
If you have that, I can run the game and go to the top part. And then we have the title screen.
264:03
Speaker A
Although on top of that the debugger is not happy. First of all the parameter body is never used inside of this method. That we can fix easily simply by adding an underscore to body. Then we have an actual red message that GDO does not
264:21
Speaker A
like. We are removing a collision object node during a physics call back and this is not allowed and might cause undesired behavior. Effectively what that means is inside of the game we have lots of physics objects and if you change a
264:37
Speaker A
scene while the physics are updating you might get an error. Now all that really means is that when we are changing the scene GDO might get stuck on a physics operation and this we want to avoid. The way you are doing that is and GDAU
264:52
Speaker A
actually tells you that you are supposed to use call the third which is just another function call the third. This one calls a function. So we have to add a name here of a function.
265:07
Speaker A
Let's create a new function called change scene. This one doesn't exist yet. So funk change scene.
265:18
Speaker A
No need for parameters. All that we want to do in here is get tree and change scene to file title.tsseen.
265:26
Speaker A
Simply by having that I can run the game. Go to the top. We have the title screen and goodo doesn't throw an error anymore. This setup can be a bit annoying but it's really important to get physics right. Most of the time when
265:41
Speaker A
you are changing a scene you want to call the third then create another function and inside of that function you are changing the scene. That way you make sure the physics objects don't cause problems. Besides that when the
265:55
Speaker A
player gets hit by a car then we also want to go to the title screen. At the moment we are for the cars connecting the body and that signal to the function go to title. meaning instead of this
266:09
Speaker A
function we want to do something and well fundamentally we simply want to call the third once again and then change the scene to the title scene. So now if I run the game and I get hit by a
266:23
Speaker A
car we are once again getting back to the title screen and once again good is complaining that the parameter body is never used. There should be an underscore before body. Let's try this one again. And now we can get hit by a
266:37
Speaker A
car. We get the title screen and Godo is not complaining anymore. Perfect. This system we should practice right away. I want you to go from the title screen back to the game. This should happen when the player presses the space button
266:52
Speaker A
while the title screen is active. Pause the video now and try to implement this one.
267:01
Speaker A
On the title screen, we want to do something for which we're going to need GDScript. Create a new GDScript. All the defaults here are fine. I want to constantly check for some keyboard input that we can do inside of physics process
267:18
Speaker A
or simply inside of process. It doesn't really matter. Let's go with process. And for this, we also don't need delta.
267:25
Speaker A
So there we can add an underscore. I simply want to check if input is action just pressed. And then inside of project settings for the input map earlier we created an action called confirm which is for the space button
267:43
Speaker A
which means for this one we can look for confirm. If that is the case I want to get the tree and then change scene to file game.tsseen. tsn and that is actually all we need. Since there are no physics objects inside of
268:02
Speaker A
the title screen, we don't need call the third. In other words, if I run this current scene and press space, we getting to the game scene and the game runs just as before and we can go back. This is
268:17
Speaker A
looking pretty good. Finally, then we have to get the score from the game to the title screen. There are a couple of ways of doing that. The way I want to cover is by creating a global node.
268:31
Speaker A
Effectively, what that means, I want to create a new scene. And this scene is going to be a plain node. It's not going to hold any complex logic. I simply want to change the name first of all to
268:44
Speaker A
global. Then save it inside of scenes. That's totally fine. And add a script to it.
268:52
Speaker A
Global.gd. The defaults here once again are totally fine. The only line of code that I actually want to have in here is var score an integer with a default value of zero.
269:06
Speaker A
This scene really doesn't do very much. It simply stores a score. But the important thing is that this global scene should be available in every single scene. So game, player, tree, and most importantly title.
269:21
Speaker A
The way we are doing that is you want to go to project project settings and in there you have globals. In my case I want to click on this symbol go to scenes and then get global.tsseen and make sure you don't get GD by
269:37
Speaker A
accident. You want global.tsn the scene. Open this one. Then you can give it a name. Global is totally fine. And then add. That way we have a global scene called global. Make sure it's enabled.
269:50
Speaker A
It should be by default. And then you can close this dialogue. And really important now if I run the game and I go inside of GDO to remote while the game is running. There we get global. Even though we didn't add this global scene
270:06
Speaker A
to the scene tree inside of the game and on top of that if I finish the game, we're going to the title screen, but we still have global available. So effectively if you add anything to this globals the note will be available in
270:23
Speaker A
every single scene bar none. This can be quite nice. For example inside of the game when the player has reached this final area I want to get the global score. So globalcore and then update the score to the current
270:41
Speaker A
score from inside of the scene. global.score score refers to this variable and this score refers to the score inside of the current game scene.
270:53
Speaker A
Meanwhile, inside of title.gd when this scene is ready, which means funk underscore ready, I want to update, let me show the scene three. I want to update this score which we get via label two.
271:12
Speaker A
This thing should get text. And for now, I simply want to create a string of global.
271:22
Speaker A
And that should be it. If I now run the game and I can run up. Let's hope I don't get hit by a car. We're getting two inside of the title screen. If I try this again, and let's wait a few
271:33
Speaker A
seconds. Make sure I don't get hit by a car. And then we're getting eight because it took me 8 seconds to finish the game.
271:43
Speaker A
With that, we are moving data around the different scenes. Or to be a bit more specific, we have one global file that stores the score.
271:54
Speaker A
And this thing we are referencing all the time. Although I only want to do this operation if the score is greater than global dot score only. Only then do we want to update the global score. This we don't
272:11
Speaker A
want to do when the player gets hit by a car because then it's basically game over. Let's try that. And let me go really fast to the top of the screen. So we have 3 seconds. If I try this again
272:23
Speaker A
and I need longer than 3 seconds and let's hope I don't die along the way.
272:28
Speaker A
Now we have 5 seconds. And I just realized the time should be smaller than global.score score because the lower the number, the better the score. I think you get the idea. Besides that, what I also want to do inside of the title
272:46
Speaker A
screen, this label two should have the horizontal alignment, not left, but center. That's going to look a lot better. On top of that, what you can do if you really want to inside of title, you can add another string for
273:04
Speaker A
high score and then simply add the string to it. That way I can run all of this again.
273:13
Speaker A
Try to get to the top of the screen. And now we're getting zero. Okay, not great because the score right now by default is going to be zero.
273:25
Speaker A
and the score that we can achieve in the game is never going to be below that. I guess a really easy way to fix that is to set a default value of 10 for the score.
273:37
Speaker A
Then I can run this again, right? To finish the game. Now we get a high score of two. That feels a bit better. And well, with that, we can move data between different scenes, which is giving us the basic game. All
273:53
Speaker A
we have to do now is add sounds and then we are done. To finish up the first game, we have to add sounds for that.
274:00
Speaker A
GDU has three nodes. An audio stream player, an audio stream player 2D and an audio stream player 3D. The only difference between them is that a 2D and 3D version care about the position.
274:13
Speaker A
Meaning the further away you are, the quieter it will become. And then obviously the 2D node only cares about the 2D space. The 3D one cares about the 3D space.
274:22
Speaker A
Other than that, adding audio is pretty straightforward. Let's jump right in. Back inside of GDU, if you look at the file system, we have a folder for audio in which we have the file for the car and for the background music. For now, I
274:38
Speaker A
just want to play the background music for which I don't care about the position, which means I can simply add an audio stream player. This one here.
274:48
Speaker A
And then besides that, we have the 2D version and the 3D version. You can also listen to audio, although I never found a good purpose for that. Anyway, I want to create an audio stream player. Click on create. And then on the right side,
275:04
Speaker A
you get a ton of options. The one that really matters is the stream. This wants to have the actual audio file, which means in my case, I want to drag happy.mpp3 in there. And then we have the sound. If you click on playing,
275:23
Speaker A
you should be hearing a preview of it. If you're setting it to autoplay and start the game, then it's going to work right away, I guess. Besides that, you can also set the volume and a few more specialized
275:37
Speaker A
things, but they are not that important. I guess the one thing that you do want to care about is looping. This one should be enabled, especially for background music. This one is actually quite important. That being said, if I
275:49
Speaker A
try the game and I go to the title screen, then we don't get music anymore. That is because the audio stream player only exists inside of the game scene. In the title scene, it does not. And if you edit it
276:06
Speaker A
in here like we have done inside of game, then it would start again which I don't think would be a good experience.
276:13
Speaker A
I want this music to play continuously that we can achieve by attaching it to the global scene where at the moment we are only storing the score.
276:25
Speaker A
All we have to do is add the audio stream player. And by the way, for any kind of node, you can have a right click and then cut and copy or simply press Ctrl X or Ctrl + C. Works like in any
276:36
Speaker A
other program. Now, inside of the global script, we are still doing the very same thing with the same stream. If I run it, we're getting music continuously, which I think is much better. Although I do want to lower the volume just a bit. For
276:57
Speaker A
volume, the default is zero. And if you want to make it quieter, you need negative values. Let's say -10, which you can fine-tune. Just play around and see what you like. Besides that, we have audio and car.mpp3.
277:13
Speaker A
To test this one, I don't want to autoplay happy. Mp3 so we can actually hear what's going on. To the car scene, I want to attach an audio stream player 2D. Make sure you're getting this one.
277:26
Speaker A
To that, I want to attach car.mpp3, which sounds like this. We do want to loop. So, looping should be enabled. And then we want to make sure that the player only hits this part if we are close to the car, which
277:43
Speaker A
happens with the 2D version of this node right away. Although, we do have to make sure that this is set to play.
277:50
Speaker A
The difference between them, by the way, is if you have playing enabled, it is going to play inside of the editor. If you set it to autoplay, then it's going to start inside of the game, but not in
278:00
Speaker A
the editor. You usually want to go with auto play. Anyway, now inside of the game, we are getting a whole bunch of sound, which at the moment is way too loud.
278:16
Speaker A
Let's lower the volume to -20. That way it's not going to be so overwhelming.
278:25
Speaker A
That works. Once again, play around if you want to customize this. The one value that really matters is max distance. If we exceeding that distance, we cannot hear the audio file anymore.
278:37
Speaker A
At the moment, it is setting to 2,000 pixels, which is a lot. If you look at the map, the distance from the top to the bottom is 600 pixels, a lot less than those 2,000.
278:52
Speaker A
I guess we can set it to 100 pixels and just see how this works. If I now try this again inside of the game, right now I can't hear anything, but if I get close to the cars, then you can tell the audio is getting
279:06
Speaker A
louder and quieter depending on my position. You can customize this even more with attenuation, which is a curve that determines the volume given the distance. For example, you could make this thing fall off a lot faster.
279:23
Speaker A
That way, after this amount, we can't hear anything anymore. Although, this I don't want to do. But after that, we are basically done.
279:36
Speaker A
Still works pretty well. And I do want to make sure that the background music is enabled. So auto play should be true.
279:42
Speaker A
And now [Music] cool, this works. Now I guess before we finish, there are a couple of minor things that we can work on. For example, inside of the player, the move speed is quite fast. I think 100 here is fine.
280:04
Speaker A
That way the player feels more controllable. We also don't need this part. That was just for practice earlier. So we can just remove it. It's not going to make a difference. Finally, what we should also do, the default direction
280:19
Speaker A
should be vector 2.0. Now, this isn't going to make much of a difference since we are changing direction right away using the input function. This isn't going to matter, but sometimes it might. It's just a bit cleaner. In fact, we don't need this
280:35
Speaker A
vector 2.0 at all. This is totally fine. The default value is vector 2.0. You don't have to specify it. So now we have created our very first game. Well done.
280:47
Speaker A
Let's get started with the second game, a Metroid style platform. While making this game, we will learn about a few more advanced concepts in GDO. Most importantly, number one, animations. GDO has a ton of systems to animate things
281:02
Speaker A
and we are going to learn about two. the animation player. That's a node and twins. Via that with GDScript, you can animate any property. Next up, we have the tile map layer. This is an amazing tool to build levels. Finally, we will
281:18
Speaker A
look at lights and shaders, which are essential for a good-looking game. Now, to get all of this started, here we are in good, and I already have a couple of things. no scenes or code. But in the file system, we have a whole bunch of
281:34
Speaker A
graphics that we are going to use. For example, there is the player. Looks a bit weird right now, but we'll work on it. We have a couple of audio files. Those are very simple. And then inside of project, project project
281:49
Speaker A
settings, we have an input map with left, right, jump, and shoot. The one thing that's new here is that we are capturing mouse input. the left mouse button which you can get by clicking on plus and then mouse buttons. That's all
282:04
Speaker A
I've done here. I got left mouse button. Besides that, inside of general for the window, I'm going with 1280 x 720. That one is very simple. And finally, under textures, I have set the default texture filter to nearest because once again, we are
282:23
Speaker A
working with pixel art and we want to get the right filtering behavior. This would be the starting project. And to set up the basics, I want to create a 2D scene. Rename it to, let's call this one level. Save this one inside of a new
282:41
Speaker A
folder called scenes. I suppose inside of this folder, we can create another folder for levels and then save it in there. That way, inside of the file system, we have scenes levels with the main level. The only thing that I want
282:57
Speaker A
to have in here is a static body 2D with a collision shape. For this collision shape, I want to have a rectangle shape that we can expand quite a bit.
283:09
Speaker A
Something like so. This is going to be our floor for testing purposes. It's not going to be visible by default inside of the game. If I run the scene and select the current level scene to run at the moment, we do have a scene, but
283:26
Speaker A
we can't see the collision shape. For that, under debug, you can enable visible collision shapes. If I now run this again, we can't see the floor. Can be very nice to get things started.
283:40
Speaker A
Next up, I want to create a new scene where the root node is going to be a character body 2D, which will be our layer. Once again, this I want to save inside of scenes. In there, I want to
283:56
Speaker A
have a folder for let's call it entities. We're going to put the player and the enemy drones in there. For now, player.tsseen, that's fine. And to this body, I want to add a collision shape, which is going to be some kind of
284:12
Speaker A
capsule shapy thing. We can refine this later on. For now, I want to save, go back to level, add a node 2D, alt entities.
284:25
Speaker A
As a child of that node, I want to have the player.tsseen file. And then we are getting the player collision shape. If I run the scene again, you can see we have the floor and the player. Looks very
284:40
Speaker A
plain at the moment, but it's a good way to get things started. Nearly done with the first setup part. The last thing that I want to do is to move this player to the right. That's going to be your
284:52
Speaker A
exercise. This should be reasonably straightforward if you paid attention to things in game one. Pause the video now and see if you can remember.
285:05
Speaker A
First of all, we have to give the player a script. Click on this button. The defaults here are totally fine. And then we need funk physics process.
285:19
Speaker A
In there to move a character body 2D, you want to always call move and slide.
285:25
Speaker A
This by default though is not going to do anything. So right now we have no movement whatsoever because we have to set a velocity for the player. This can be something like vector 2 dot right multiplied with let's say 50.
285:44
Speaker A
If I now run this again, we have the player moving to the right. Looks pretty good. Although all of this should be a bit cleaner.
285:54
Speaker A
I want to have a variable for the direction of the player. This is going to be a vector 2. And I want to have var speed which is going to be an integer with a default value of 50. That way for
286:13
Speaker A
velocity we can multiply direction with the speed. The end result is going to be the same. Actually right now it's not because direction doesn't have a default value. This we can set vector 2. Right.
286:29
Speaker A
And now we can try this again. We are moving to the right. This system we are going to refine quite a bit for proper movement. For now I simply want to add an underscore to delta so good stops
286:41
Speaker A
complaining inside of the debugger. Then we are done with the setup. For the first proper part of the platformer game I want to have proper movement so we can go left, right, and jump. Here we are back in GDO and I want to move the
286:55
Speaker A
player for that. At the moment we have a vector 2 that defines the velocity.
287:03
Speaker A
That does work, but that's not the system that we want because I don't really care to move in all four directions at the same time. I only want to move left and right from the keyboard and then be able to jump. The down
287:16
Speaker A
movement is covered entirely by gravity. That means to get started I want to only move left or right for which we will only need a direction underscore x which is going to be a floating point value for which we don't need a default value
287:35
Speaker A
meaning this value at the moment is going to be 0.0 zero which we are then going to use to update velocity dox.
287:45
Speaker A
It's going to be direction dox multiplied by the speed. That part is still fine. Once again, we don't have any movement and that is expected. Cool.
287:56
Speaker A
To change that, I want to get funk and something like get input. Instead of this function, we're going to overwrite direction.x. X via input and the function I want to use is called get axis. This works very much like get
288:15
Speaker A
vector except now we are only looking at one axis or in other words we have a negative and a positive action. The negative action in my case is going to be left. The positive one is right.
288:29
Speaker A
After that let's print direction.x X. And don't forget to call get input, which I want to do inside of physics process before we're doing anything else. Get input.
288:41
Speaker A
If I now run the game, I can press right, we get 1.0. If I press left, we get 1.0.
288:50
Speaker A
And that works really well. Also, you can see inside of the game, we are actually moving the player. Really good start.
288:59
Speaker A
That means we don't have to print the direction anymore. Next up, I want to work on the jumping mechanic which will consist of two parts. We have jumping and we have falling. Let's start with jumping. I want to check if input dot is
289:15
Speaker A
action just pressed and we have a jump action that is space on the keyboard. If that is the case, I want to update velocity.y Y and this needs to have some kind of negative value because we want to go up.
289:32
Speaker A
Let's say for now -10. If I run the game, I can press space and the player moves up. That looks good. We will refine this in just a second. First of all though, I want to have the second
289:46
Speaker A
part of the equation which is gravity that I have covered in a separate function. Let's call this one apply_gravity.
289:58
Speaker A
And all that this really does is velocity doy plus equal and then some kind of value.
290:08
Speaker A
Let's say for now plus equal 10. That way we're going down and we are accelerating.
290:16
Speaker A
This we have to call. I want to apply gravity. Let's try now. And the player falls down. Although if I press space, we're not jumping because the gravity is too strong. But if I set this value to 200,
290:36
Speaker A
then this should be enough. I can now do basic jumps. Obviously not amazing yet, but a really, really good start. And I think what we should also do is add a camera to the player so we're not so
290:52
Speaker A
zoomed out. I want to have a camera 2D with a zoom level of three.
291:00
Speaker A
That way that feels quite a bit nicer. So, we do have a basic jumping mechanic, but we do have to make it a bit stronger so the player can jump higher. I want to have two more variables.
291:16
Speaker A
One is going to be jump strength which is going to get a default value of let's say for now 10 and this always needs to be an integer. Besides that I want to have gravity which is also going to get a default
291:37
Speaker A
value of 10. When we are getting input I want to have the negative value of jump strength. Now this might look a tiny bit weird. We are defining a variable and then we are getting the negative value.
291:51
Speaker A
The reason why I'm doing it is that when we are defining the variable I only want to care about the distance that we want to jump. The actual logic in which way we are going can be covered right here.
292:03
Speaker A
A negative jump strength would just look weird, but that is subjective. You could add a negative value in here just fine.
292:11
Speaker A
For the gravity, I want to use velocity.y and add gravity to it. This right now would give us very low numbers, so not much is going to happen.
292:24
Speaker A
To test this a bit better, we can add export in front of both of them.
292:33
Speaker A
That way, with the player selected, we are exposing these variables to the inspector and then can set a custom value. This even works when the game is running. So, let me run the game. We are getting basically no jumping because
292:49
Speaker A
jump strength is too low. But if I simply click on the inspector and you can see at the top the game is still running. We can pause the game or we can restart the game. If I now set jump
293:01
Speaker A
strength to let's say 200. I can return to the game. And now we are getting a very basic jump.
293:12
Speaker A
Once again if I increase this number to let's say 600. Return to the game. And we are jumping quite a bit more. Maybe something like 400 would be better.
293:27
Speaker A
And that is looking not too terrible. The next change that I want to work on is gravity. But before we can get to that, there's one more change that we have to make. This should be plus equal gravity time delta,
293:44
Speaker A
which we are getting from the parameter. So in there I want to have delta. After that when we are calling gravity I want to add delta as an argument which we are in turn getting from the parameter of
293:58
Speaker A
physics process. That way inside of apply gravity we're getting delta which at the moment is going to be a really really low value. If I run the game again and I jump, we are well not really falling because we are multiplying 10
294:16
Speaker A
with something like 0.001. You can even see it if I restart the game. Gravity is incredibly low. But inside of the inspector, while the game is still running, I can set this to let's say 200.
294:31
Speaker A
And then we're getting something more reasonable. Let's try a th00and instead. Then we're getting slightly better jumps and this is now frame rate independent.
294:46
Speaker A
We can get back to this later on to refine numbers. But I think for now this is all right. That means to finish up this part I want to add an exercise where you are getting the input for
294:57
Speaker A
shooting. For now simply print shooting if the player presses the shooting action. On top of that, add a half a second reload time to it so that we have an interval to control the player shooting speed. Pause the video now and
295:11
Speaker A
see how far you get. To get started inside of get input, I want to if input is action just pressed as always and then I want to get shoot. If that is the case for now, I simply want to print
295:32
Speaker A
shoot. If I run the game and I press the left mouse button, we are getting shoot. That looks pretty all right.
295:42
Speaker A
The issue is I can press really fast and then we're getting shoot very very quickly. There should be some kind of reload mechanic. So, we can't shoot too fast. I want to add a timer.
295:56
Speaker A
Rename this to reload timer and then set a waiting time of 0.5. This timer also should one shot. After that, you could go to note and work with timeout, but you don't have to.
296:14
Speaker A
Instead, what you can do when the player has triggered this shooting action, we want to start the timer. So, reload timer dot start. Then this timer is going to run for half a second. And while this timer is running, we don't
296:30
Speaker A
want to allow this if statement. Or in other words, I want to check for two conditions. If the player is pressing the button and the remaining time on this timer has to be zero. That way we know it doesn't run anymore.
296:47
Speaker A
All we need for that is the reload timer left. And this value should be zero.
296:55
Speaker A
I can now shoot really fast and we only get shoot every half a second.
297:03
Speaker A
If I change the value of the reload timer to 2 seconds. Try this again and click as fast as I can.
297:12
Speaker A
We are only getting shoot every two seconds. Cool. This works. Next up, I want to work on the bullets. That way we can do at least some very basic shooting. We are also going to learn about custom signals, meaning you can
297:28
Speaker A
create your own signals and emit them. But let's go through it step by step.
297:33
Speaker A
Number one, inside of the player, when the player presses the shoot action, we want to shoot a bullet.
297:42
Speaker A
But for that, we have a problem. The bullets need to be inside of the level.
297:47
Speaker A
That way, they can interact with other entities. But we get the player input inside of the player. Which means we have to connect this line here to the actual level.
297:59
Speaker A
For that, first of all, the level is going to need a script. Attach a script.
298:03
Speaker A
The defaults here are fine. Then we can do something in there. The thing that we want to do is from the player we want to capture is signal. Now, the player does have if you have the player selected
298:18
Speaker A
inside of level, we have all of the signals for the character body 2D, which can be useful, but for our purposes, they're basically useless.
298:28
Speaker A
So, instead, I want to create a custom signal, which you can do by simply typing signal and then add the name of the signal. In my case, shoot.
298:40
Speaker A
Simply by adding that in the inspector for the player we are getting shoot. On top of that you can define parameters.
298:48
Speaker A
In my case I want to have a position which needs to be a vector 2. This will be the starting position of the bullet and I want to have a direction which is also going to be a vector two.
299:02
Speaker A
Once you have that, inside of the inspector, you get the two parameters you have just defined along with the data type. Back inside of the level with the player selected, you can click on the signal and connect it to the level script. I
299:18
Speaker A
guess for now, we can simply print the position and the direction inside of the player script. when this if statement is being triggered. I want to get the shoot signal and emitted. For that we will need two arguments the
299:36
Speaker A
position and the direction. For position we can simply go with the position of the node. That's all we need. For the direction at least for now I want to have a vector 2 dot right.
299:51
Speaker A
And that should be it. If I now inside of the game use the left mouse button, we are getting different outputs.
300:00
Speaker A
We are emitting the signal here and inside of the level we are capturing these two bits of information and printing them. Via that you can create custom signals. It's a really easy system and incredibly useful to connect two scenes to each other. And in our
300:18
Speaker A
case, the position is already the right bit of information. The one thing we have to change though is the direction.
300:25
Speaker A
The bullet should go in the mouse direction relative to the player center. In other words, if the mouse is vaguely here, then the bullet should go this way. If the mouse is on top of the player, then the bullet should go up.
300:40
Speaker A
For which GDO actually has a function. It is called get local mouse position and that way we are getting the local mouse position. This is the mouse position relative to this origin point or to be a bit more specific the origin
300:57
Speaker A
point of the scene that has this script attached to it. Let me actually demonstrate inside of the game. If I press the left mouse button and the mouse is vely here we are getting 197 and -7. If I'm up here,
301:14
Speaker A
we're getting 2.3 and -100. If I'm on the left side, we're getting 170 and5.
301:23
Speaker A
If I am right in the center, so basically here, we're getting pretty much zero and zero. I am always looking at the bottom numbers. The first one is for the position, and this one doesn't change because the player isn't moving.
301:37
Speaker A
Now, this works, but this is not a good direction. in just a bit. We want to use this direction to move the bullet.
301:47
Speaker A
But for that to work properly, the direction should always have the same length, which at the moment it does not.
301:54
Speaker A
Imagine if this is the player scene with the center point here. If I click here and here, we're getting this direction and this direction. This vector could have a length of one, and this could have a length of three.
302:11
Speaker A
This difference is really really bad because for bullet movement we want to multiply both of those with some kind of speed for the actual bullet speed. But if the length of the vector is three then this bullet is going to move three
302:27
Speaker A
times as fast. Obviously not ideal. And the way around that is to normalize the vector for which you simply need normalized.
302:38
Speaker A
That way any kind of vector is going to get a standard length of one or in other words if I restart the game now and I press somewhere here the vector we're getting has a value of vaguely one and
302:52
Speaker A
then basically zero or to draw all of this I have clicked vaguely here. So the original vector that we're getting is this and by normalizing it we are setting a length of this vector to one.
303:08
Speaker A
And it is always going to be one. I could have clicked here. I could have clicked here. I could have clicked let's say here. And we would have gotten very different lengths. But from normalizing the vector, we are always getting a
303:21
Speaker A
length of one. So it be here, here, or it be here. That way we're getting a constant direction. And this we can multiply with a speed to always have the same speed.
303:33
Speaker A
This, by the way, we didn't have to do in the first game for the player movement because when you do input.get vector, the vector that's being returned is already normalized. If you look at the documentation for it, GDO tells you
303:48
Speaker A
the vector has its length limited to one. That means it's normalized. Although this we don't want to do at the moment. With that, we get the bullet start position and the proper bullet direction. That means inside of the
304:03
Speaker A
level, we have to spawn a bullet that starts on this position and moves in this direction. For which inside of graphics and fire, we have a default bullet. Looks fairly basic, but it's good enough. This part is going to be
304:22
Speaker A
your exercise. I want you to create a bullet scene, spawn it when the player shoots, and then move the bullet in the right direction. Pause the video now and see how far you get.
304:36
Speaker A
I want to create a new scene and the node I want to create has to be an area 2D. I can rename this to bullet and then add two nodes to it. I want to have a sprite 2D and I want to have a collision
304:53
Speaker A
shape 2D. Also, all of this I want to save inside of scenes and a new folder called bullets.
305:02
Speaker A
Bullet.tsn is totally fine in here. And then for the sprite 2D, I want to have default.png.
305:11
Speaker A
That way we can see the bullet. And next up for the collision shape, I want to have a rectangle shape 2D that I want to scale down quite a bit to something like this. Next up, inside of the level, I
305:28
Speaker A
first of want to add another node 2D with the bullets. After that, in the level script, I want to preload the bullet scene. So var bullet scene which we getting from preload and bullet.tsn when the player shoots. So when we're
305:52
Speaker A
getting on player shoot I want to create one instance of this bullet that we do via bullet scene dot instantiate.
306:03
Speaker A
And this we then want to add as a child to the bullets node that we have just created. dollar sign bullets add child and bullet.
306:14
Speaker A
That way if I run the game I can press the left mouse button and in the top left you can barely see it up there. We are getting a bullet. To refine this I want to get the bullet itself and update
306:29
Speaker A
the position. And by the way to be a bit cleaner here when we are instantiating the bullet this should be as an area 2D. That way we always get the right kind of note and we get the predictions. So now position
306:46
Speaker A
does show up. Position is going to be the position we're getting from the parameters. So position in here. If I now run this again, I can press the left mouse button and we are creating a bullet in the center of the player. That
307:01
Speaker A
does work. Although I feel like this could be organized a bit better. Instead of setting the position in here, I instead want to call a setup function on the bullet itself where we are going to add the position
307:16
Speaker A
and the direction. That way we can keep all of the logic inside of the bullet which is just a tiny bit cleaner. To the bullet add a script. The defaults here as always are fine. And we will need
307:29
Speaker A
funk setup with a position vector 2 and the direction also a vector 2. First of all I want to get the position and set it to the position that we're getting from the parameter. Just to test if this is working. If I press the left
307:47
Speaker A
mouse button, we are getting a bullet. That looks good. Although, if you look closely, the bullet shouldn't start in the center of the player. It should be to the right. We want to get the position and then add the direction
308:04
Speaker A
multiplied with some kind of offset. Let's try 12 for now. inside of the game. If I create a bullet, it is just a bit outside of the player. I guess 16 here might be a bit better. But once again, once we have
308:20
Speaker A
graphics, we can refine all of this a good bit. Let's leave it like this for now. Besides that, I want to update a direction for the bullet, which doesn't exist yet. For that, I need var direction. This has to be a vector 2.
308:38
Speaker A
And then the direction is going to be the direction we're getting from the parameter. And this we can use now with funk physics process. I want to update the position and add direction times let's say 30. Don't forget we also need
309:00
Speaker A
delta. If I run this, I can shoot a bullet in a direction. And that is working pretty well. With the basic setup covered, we can work on the animations for which we have to learn an incredibly important note, which is the animation
309:19
Speaker A
player. Via that at least for now, we're going to animate the legs. The top part of the player is going to come later. Also, for now, inside of the game, I think these collision shapes are going to become a bit distracting.
309:36
Speaker A
So, instead to the static body 2D, I want to add a sprite, which is going to get icon. SVG, the GDO logo. And then I'm going to move the GDO logo in the same position safely here. Then we can expand this
309:56
Speaker A
thing. So we are covering roughly the collision area. Then we can go to debug visible collision shapes disabled. Run the game.
310:08
Speaker A
And now we do have the player, but the player itself isn't visible. We do can see the floor because of the good logo.
310:18
Speaker A
That's good enough. With that, I want to work on the player legs, which we are still going to store inside of a sprite 2D. To those I want to add inside of characters, we have player.png.
310:34
Speaker A
If I drag this in there, then you can see we have the player, but cut up in various parts. The top part we're going to cover later. For now, I want to look only at the legs. First of all, we have
310:47
Speaker A
to cut this tile sheet into individual parts. For that, inside of animation, we can set the H frames and the V frames.
310:56
Speaker A
We have 1 2 3 4 5 6 7 8 H frames. And we have three V frames.
311:05
Speaker A
That way we can select one of the frames and we get one part of the animation.
311:13
Speaker A
Looks pretty all right. We want to animate this frame property. If I just do it with the mouse, let's say from this point forward, if you play these frames fast enough in sequence, you get a running animation. This can be done in
311:28
Speaker A
a couple of different ways. You could write some code to loop over these frames and then play them continuously.
311:34
Speaker A
Would be possible, but also quite a bit of work. Alternatively, you could use the animation layer in there. You can if you click on animation create a new animation. You can give it a name. Let's call it the
311:50
Speaker A
run animation. After that you get a timeline to which you can add tracks and you can animate different properties. The easiest and most common one is the property track.
312:03
Speaker A
If you click on that GDO is asking you what kind of node you want to animate.
312:08
Speaker A
We want to go with the sprite 2D. If you click on okay, then good is asking you what property of the sprite 2D you want to animate. In our case, that is going to be the frame.
312:21
Speaker A
And now if I click on open, we can work inside of this timeline. If you hold control or command and use the mouse wheel, you can zoom in. This bright gray area is the timeline at the moment. And
312:34
Speaker A
by default, we're going from zero to 1 second. Although you could change this here to whatever number you want.
312:42
Speaker A
In fact, the walking animation should be 1.4 seconds. The button right next to it determines if this animation is looping or ping pongs. Ping pongs means we start from zero, go to the end, and then go from the end back to zero and do this
312:58
Speaker A
over and over. In our case, we want to loop the animation. This button should be blue. That's the basic setup. Now we have to add values to this timeline.
313:09
Speaker A
This you can do in two ways. You can either rightclick and insert a key. If you're doing that you can see a small preview. And most importantly on the right you can give the property that we have defined here the frame a value.
313:23
Speaker A
So effectively if you're looking at this sprite 2D under frame we are changing this value with whatever we have set in here. Also, once we have the animation player, you can see next to the property this key. If you click on it, you can
313:40
Speaker A
add the property straight to the animation timeline, which I don't want to do right now. Let me get rid of all of this. Just to get started, I want to add a key. And the first value is nine. You can already
313:56
Speaker A
see a preview there, although might be quite small. Then after 0.2 2 seconds. I want to add another key which is going to get a value of 10. Next up, another key. This is going to be 11.
314:12
Speaker A
0.2 seconds later, I want to go to 12. Then at 0.8, and I think you can see where this is going. I want to go to value 13. After that, another key. This is going to be value 14.
314:26
Speaker A
And we have one more insert key. value 15. That way we are getting the walking animation. And if you drag the indicator left and right, you can play the animation or just click on this button.
314:41
Speaker A
Then you can see that we have a running animation. Although fundamentally we are still working with a sprite for the visuals and that's really important to understand. All that the animation player is doing is it's changing this property which means at the moment we
314:58
Speaker A
have to move the legs up to align with the collision shape. I guess here is broadly fine with that. Inside of the game we have the legs although right now they don't animate. That is because inside of the
315:14
Speaker A
animation player, we have to give it a default animation, which means you want to click on this button, then you're autoplaying it, and inside of the animation, you get this autoplay icon.
315:25
Speaker A
With that, we have the running animation. Besides that animation, I also want to add a new animation called idle. For this idle animation, I want to add a track property track with the sprite 2D. And once again, I want to
315:45
Speaker A
target the frame. The animation length is going to be 1 second. And this is what I actually want to autoplay. You can only play one animation automatically. For this animation, I want to insert a key starting right at the beginning. The
315:59
Speaker A
value should be 16. And also, this should be looping. From that we are getting the legs being entirely static which is fine. Now we have to figure out how to move between idle and run. This we can do in GDScript.
316:16
Speaker A
And for that I want to create another function called funk animation. If the player is moving we want to play the walk animation. If the player is not moving we want to play the idle animation.
316:32
Speaker A
To get that first of all, we need the animation player node. The property we want to target is called current animation. In fact, if you have the animation player selected and you look at the inspector, there we have the
316:45
Speaker A
current animation. At the moment, we have run and idle and reset. This one you can ignore this. You have to give a value which has to be a string. Let's say for now I want to go to walk. But
316:58
Speaker A
this I only want to do if the player is moving, which we know is happening if we have direction X. If that is not the case, else we want to idle. Make sure you are calling this function.
317:11
Speaker A
We want to call the animation. And now inside of the game, by default, nothing is happening. But if I start walking around, then we are making the debugger really unhappy.
317:24
Speaker A
Let's see what happened. We have animation not found. Walk. That's a good way to indicate what went wrong. So check inside of the animation player.
317:36
Speaker A
We have idle and run. So in other words, this shouldn't be walk. This should be run. Once we have that, this is looking much much better. So I can idle and I can run. Wrong direction, but generally this works. And while we
317:54
Speaker A
are here, what we can also do with this sprite to des selected and in fact I should rename this to let's call it legs. These legs by default always point to the right. But if the player's moving to the left, they should be
318:09
Speaker A
facing left, which we can get fairly easily. I want to get the legs and then flip H. If the player is moving to the left, I want to flip the legs on the horizontal axis.
318:23
Speaker A
This value has to be true or false. And we can set it by direction X being smaller than zero. This operation is going to return a boolean. It's going to be true if we are moving left and it's
318:36
Speaker A
going to be false if we are moving right. So with that, I can go to the right. I can go to the left. And that is working pretty well. We don't have jumping yet, but that we can work on
318:48
Speaker A
next. That part is actually going to be your exercise. I want you to add the jumping animation.
318:55
Speaker A
This should also be played inside of the game when the player jumps. A tip for this one, via is on floor, that is just a function inside of a character body 2D, you can check if the player's on the
319:06
Speaker A
floor or not. That's going to be really important. Pause the video now and see how far you get.
319:12
Speaker A
Number one, inside of the animation player, we have to add one more animation called jump.
319:24
Speaker A
For that, we want to add a track property track. We want to target the legs, the sprite 2D. In there, we have the frame on the timeline. We want to insert a key and then find the jumping animation. If you toggle these values,
319:40
Speaker A
you can see a preview what we need. There's only one frame for the jumping animation and it's frame 17.
319:48
Speaker A
This we do want to loop and we don't want to autoplay it. That covers the animation player.
319:55
Speaker A
Good start. Next up inside of the code, we have to figure out when the player is jumping. So technically what you could be doing when we are getting input and the player is jumping, you could change the animation to jump.
320:11
Speaker A
Although what would be easier inside of animation we can first of all check if the player is on the floor.
320:21
Speaker A
Only if that is the case do we want to play the run or the idle animation. If that is not the case, else then we basically only have one option, the jump animation, which basically means I want to get the
320:36
Speaker A
animation player. Set the current animation to jump. And then we are done inside of the game. I can now jump. And we have some legs that are well animated.
320:52
Speaker A
That is looking pretty good. That means next up we can work on the upper body. For that we have another sprite 2D which I can rename to to soul. Once again we want to get player.png. Drag it into the texture. And then for the
321:14
Speaker A
animation frames I think we had eight H frames and three V frames. Then we want to move this sprite 2D up by a couple of pixels. If you use the keyboard with the arrow keys, this is going to work much better. Let's try it
321:30
Speaker A
inside of the game. And that is working pretty well. Obviously, we have to actually animate the upper body. And for that, let's think about the problem. If you look at the player frames for the upper body, we essentially have eight
321:49
Speaker A
directions that the player can face. This is to the right, bottom right, down, down left, and so on. We have to pick one of those depending on where the mouse is pointing. If the mouse is here, so to the right of the player, then we
322:03
Speaker A
want to get this first frame. If the mouse is on the left here, then we want to get this one. This unfortunately cannot be done in the animation player, at least not efficiently. This could actually be a pretty good exercise. Try
322:20
Speaker A
to get the right upper body frame. And just be creative. See how far you get.
322:27
Speaker A
If you can't do this one, don't worry about it. It is a tiny bit more advanced.
322:35
Speaker A
Let's go through it step by step. First of all, we need to get the mouse position relative to the center of the player. This we have already done.
322:46
Speaker A
Inside of get input, we have used get local mouse position and normalized it. That we can reuse. Let me copy it. And inside of animation, I want to get a new variable. Let's call it the raw direction. As a reminder, if
323:05
Speaker A
I print this value, I can see where the mouse is relative to the player. Down there, I have very close to one and zero. We are to the right of the player.
323:18
Speaker A
If I go up, then we are at zero and negative one. These values we need to clean up so they are more easily accessible. Let's create another variable adjusted direction.
323:32
Speaker A
This should be a vector 2 with x and y where x is going to be the rounded value of the raw direction dox.
323:43
Speaker A
The same thing I want to do for y except now we have the rounded value of raw direction.
323:50
Speaker A
Let's print this one. That should be a bit easier to see. Now if the mouse cursor is to the right of the player, we get one and zero. If I'm to the left, we get -1 and zero. If
324:04
Speaker A
I am above the player with the mouse cursor, it's 0 and negative 1 and so on.
324:09
Speaker A
This works for all eight possible directions. What you can also do is set this vector 2 to vector 2 integer. That way, instead of floating point values, you're getting integers, which I think for this purpose is a little bit
324:24
Speaker A
cleaner. Both would work though. In this case, it doesn't really matter. So at this point we have eight possible values. These we have to convert to the frames that we're getting for the player. This would be frame zero, frame
324:39
Speaker A
one, frame two. And I can actually show it inside of the torso. At the moment we are on frame zero. The player facing to the right. If I set this to a one, we're going down right. Frame two is down.
324:51
Speaker A
Frame three is bottom left. I think the easiest way to connect this vector 2 to the frame is by creating a dictionary.
324:59
Speaker A
This can be a constant value where we have gun directions which is a dictionary where for example we have a vector 2 integer with one and zero. The associated value or the frame is going to be zero.
325:18
Speaker A
For the next value we're going to the right and down. The frame is one. Then we are only going down. So x is zero. Y is one. The frame would be two. And this is going to continue for a bit. Let me
325:31
Speaker A
actually copy it all in so you don't have to watch me type for too long.
325:35
Speaker A
These would be all of the eight values that we can work with. And if I add a bit more space, then this looks a lot cleaner. I hope the system here makes sense. We have a dictionary where we
325:45
Speaker A
have a vector 2 with a frame. The vector 2 we are getting from the mouse direction.
325:53
Speaker A
And then the frame is going to be what we need inside of the player for the right animation frame.
326:02
Speaker A
Once we have all of that, all we need to do is get the torso sprite 2D and adjust the frame.
326:10
Speaker A
The value is going to be the gun directions with the adjusted direction. And that should be it. Also, I realized this should all be vector 2 integers.
326:26
Speaker A
That way, we are keeping constant values. Now, let's try the entire thing. And the player is following the mouse cursor. The other animation is also working pretty well.
326:40
Speaker A
So, that is looking really nice. We can also still shoot, although the shooting speed is a bit low, but that's a problem for later. Next up, I want to add a marker so the player knows the shooting direction. This is also going
326:55
Speaker A
to be animated. But for this animation, using an animation player would be overkill. It's just too simple of an animation. So, we're going to learn a simpler system to create animations called twins. via those you can animate any property with just a couple of lines
327:12
Speaker A
of code. First of all, inside of the player, I want to add a crosshair so we know the direction that we are pointing at. I want to add another sprite 2D that I want to rename right away to marker.
327:26
Speaker A
For this marker, you can find a texture under UI. There we have crosshair. Drag it in and we are getting a crosshair.
327:35
Speaker A
This crosshair we want to place in the right position using GDScript, which I guess could be another animation. You could also place it inside of animation, I guess, but let's keep things organized. I want to have a function
327:51
Speaker A
update marker. All I want to do in here is get the marker and change the position to the position that the player is pointing at, which once again we have done this a couple of times by now. We
328:06
Speaker A
want to get the mouse position relative to the center like so. And then multiply this with some kind of value. Let's say 40. That's basically all we have to do for the position of the marker. Although we do have to call the function
328:21
Speaker A
update marker. Then we can run the game. And inside of the game, I now have a marker which is quite a bit too large.
328:33
Speaker A
To fix that really quick, with the marker selected inside of the inspector, you can go to transform and change the scale to 0.5.
328:42
Speaker A
For both X and Y, they should be linked. Next attempts. And that feels much more reasonable.
328:52
Speaker A
Now we come to the interesting bit. When the player is shooting, I want this marker to scale down and then scale up again. We could use an animation player.
329:01
Speaker A
Let's actually do that. I want to use an animation player in which I want to add a new animation.
329:10
Speaker A
I guess we can call this one this scale. I want to add a track property track.
329:15
Speaker A
get the marker. Okay. And then the property I want to animate is going to be scale. A vector 2. You could also target X and Y separately, but I want to get vector 2 scale. In there, I can
329:30
Speaker A
insert a key at the beginning. I want to start with 0.5. Let's say around 0.2 seconds. Scale to 0.1 for both X and Y. And then let's say by 0.6 seconds I want to go back to a scale
329:48
Speaker A
of 0.5. If I play this we getting a short animation. This we want to play when the player is shooting the gun.
330:00
Speaker A
All we have to do inside of get input when the player is shooting. I want to get animation player 2 and then play the animation. We need a name for that scale. That is basically it. If I now shoot, we're getting a short
330:20
Speaker A
animation on the crosshair. This would work, but it's kind of overkill. The animation player does a ton of stuff and we only want to have a super super basic animation for which we can use a simpler system.
330:37
Speaker A
Let me first get rid of the animation player two and then of this line so we don't get an error. That way we are back to the crosshair not doing anything besides the position. I want to create what is called a tween short for in
330:54
Speaker A
between. All that it is doing is it takes a property and moves it from one state to another state over a set duration of time.
331:03
Speaker A
To create it, you want to get tree and create tween. Then on this tween, you have lots of different ways to change a value. The easiest one is tween a property for which first of all, we need an object
331:22
Speaker A
that we want to target. This effectively is a node in most cases. In our case, we want to get the marker. On this marker, we need a string with the property that we want to change. That is scale or the
331:38
Speaker A
name. If you look at the inspector, when you hover over it, this property is called scale. This is what you want to target. If you wanted to change the position, it would be all in lower case position. After that, you
331:52
Speaker A
need the value that you want to go to, which in our case is a vector 2 with 0.1 and 0.1 or X and Y. Finally, we need a duration. Let's say 0.2 seconds. And that is it. With two lines of code, we
332:11
Speaker A
can animate the crosshair. If I now run the script and shoot, the crosshair becomes really, really small.
332:20
Speaker A
To make it large again, all we have to do is do another tween property line where we want to have the marker node target the scale. And now our target scale is going to be 0.5 and 0.5 with a
332:34
Speaker A
duration of let's say 0.4 seconds. The tween is going to play these animations one after another. It first plays this one and then this one, which means inside of the game, we're getting a nice animation. And this is working really
332:51
Speaker A
well. This you can also customize a lot. For example, you can make it play forever. You can make it play in parallel if you want to. There's a ton of stuff you can do. To learn more about it, you want to go to help and then look
333:04
Speaker A
for twins. There's a really good documentation for all of it. And this thing is incredibly powerful. Most importantly, you want to work with the different methods. All of this here is pretty much what you need.
333:19
Speaker A
For example, via tween interval, you can create a pause. Via stop, you can stop an animation. Via set loops, you can set the loops. By set parallel, you can make the animations play in parallel. And that's kind of it for basic tween. For a
333:34
Speaker A
very basic animation, this is what you want to use most of the time. It's a very simple system. It's super reliable and very easy to implement. Let's practice this one. I want you to scale the bullets when they are being
333:47
Speaker A
launched. They should start from zero and go to one. And this is for both X and Y. Pause the video now and see how far you get the work inside of the bullet. We can simply target funk underscore. Ready? So
334:08
Speaker A
once the bullet is being spawned, we want to create var tween once again via get free and create tween.
334:19
Speaker A
Then we want to have tween and tween property on that. We want to target the sprite 2D. Drag this one in there. And then we want to get once again the scale. The final value is going to be a vector 2.1
334:42
Speaker A
with a duration of at least for now 0.5 seconds. So we can see what's happening.
334:49
Speaker A
This right now is not going to do anything because the default scale of the sprite 2D is already one and one.
334:58
Speaker A
So, what we would have to do is when we're getting started, get the sprite 2D, update the scale to vector 2.0.
335:10
Speaker A
That should already be enough. If I now launch the game, shoot a bullet, the bullet is growing when we are shooting it. And that is working. Alternatively, what you can also do instead of running this line to scale the bullet down, you
335:26
Speaker A
can add after tween property dot rom. That way you can set a start value which in this case is going to be vector 2.0.
335:39
Speaker A
And now we're getting the same result with one line less. And I think this is also a good bit more readable. Although I guess that can be slightly subjective, but it's still a really, really useful system. At the moment, we only have the
335:55
Speaker A
player and pretty much nothing else. Let's change that by creating the level. For that purpose, we are going to learn about a new node called a tile map layer. Via that you can create really complex levels inside of a single node.
336:11
Speaker A
You can also add animations, collisions, and even autotiling. Although for now we going to keep it simple. Back inside of GDAU, first of all, this static body 2D for the floor really doesn't work anymore. Let's get rid of it entirely.
336:30
Speaker A
Instead, I want to add a tile map layer note. Notice here we have a tile map and a tile map layer with the tile map being depreciated.
336:42
Speaker A
It still works, but you are not supposed to use it. It's just there for backwards compatibility.
336:48
Speaker A
So use tile map layer create and then first of all nothing happens. Although we did get a tile map button at the bottom of the editor in which at the moment we can't really do anything for that. First of all you want to look
337:07
Speaker A
at the inspector. There we have tile set and we have to create a new one. Click on that and then we get two buttons at the bottom. Tile set and tile map to understand what's happening here.
337:20
Speaker A
First of all, inside of the inspector, when you click on tile set, you get a whole bunch of options. A tile shape and a tile size.
337:31
Speaker A
Those are the really important ones. I want to keep all of the defaults here.
337:35
Speaker A
and then go to tile set and look at graphics and tile sets as well. There we have subway and walls.png.
337:45
Speaker A
For now, I want to direct subway.png into this area. If you drop it, then good is asking you if you want to create an atlas texture, which we do want to do.
337:57
Speaker A
Once we have that, I can actually explain what's going on. So we start with all of this. This is one PNG file. And via this tile map layer node, we are separating it into little chunks of 16x 16 pixels or whatever you
338:15
Speaker A
have specified in. You can also get a different shape and a different size. But in my case, the defaults work perfectly. And the fundamental idea is that you can use the tile map via this tile map button.
338:32
Speaker A
Pick one of these parts and then place it inside of the level like so. For that, make sure you have this pencil button selected. Then you can draw. And if you have this rectangle tool selected, you can create entire areas
338:47
Speaker A
quite easily. Although that's not what I want to do. If you leftclick and you have the rectangle tool selected, you can delete entire areas. And if you have the pencil selected, you can place stuff with the left mouse button and remove it
339:01
Speaker A
with the right mouse button. The basic way you are supposed to use it is to place tiles deliberately. So this could be one floor. Then I want to place this tile, place it here. Then I want to have this tile, place it there. And
339:14
Speaker A
maybe this middle bit for a bit of variety. Something like this. then we would have one part of the level.
339:24
Speaker A
That being said, if I run the game, this is not going to do very much. Well, it is inside of the game, but the player doesn't collide with it.
339:34
Speaker A
Also, there should be this one here. We're going to fix that in just a second. But for now, the main thing that you have to understand is that fundamentally, when you're working with a tile set, there are basically three
339:47
Speaker A
steps. Inside of the inspector, you can create a tile set where you set a tile shape and a tile size. After that, inside of tile set, you can look at what you have created and modify it. That we're going to work on in just
340:05
Speaker A
a second. Under the paint tab, you can do a couple of things. Finally, with tile map selected, you can grab different parts. This can even be multiple bits and place them inside of the level to make them visible. If you
340:20
Speaker A
spend enough time on it, then you can create really nice levels. Although it is going to take a while, creating levels is just going to take some work.
340:29
Speaker A
What you can also do if you have the tile set open, you get a whole bunch of extra stuff. The most important one for our purposes at the moment is the physics layer. Via that you can add collisions. First of all, we have to add
340:43
Speaker A
a physics layer. Then you get the usual stuff where we have a collision layer and a collision mask for which first of all I want to go to project project settings then find 2D physics and I want to name a couple of layers. The first
341:00
Speaker A
one is going to be terrain. Then I want to have layer. Besides that I want to have the drones and the bullets. That's all we need. Once we have that inside of the tile set, the tile set should be on
341:14
Speaker A
the first layer terrain and it doesn't have a mask. It doesn't need to see anything. Just to keep things consistent, the player should be for the character body 2D collision. We are going to be on layer two. We can see
341:29
Speaker A
layer 1, layer three, and we cannot see the bullets. Only the player can shoot bullets, and the player shouldn't be able to shoot himself. Then finally for the bullets the area 2D for the collisions it should be on layer 4. It can see the terrain
341:47
Speaker A
and it can see the drones. That way we have collisions covered. Although if I run the game, this still isn't doing anything. The reason for that is to actually get collisions.
342:01
Speaker A
These tiles need to have an actual shape for the collision that you can find inside of tile set under paint. Once you have to find a physics layer inside of select property you will find physics layer zero in there. Once you have it selected you
342:20
Speaker A
get this shape and this you can place on different tiles. If I place it for now on all of these tiles, the one that I have used inside of the game, then I can run the game. And now we have
342:34
Speaker A
collisions. You can also change them. The basic idea is that you are modifying this shape which you can also add snapping which I would generally recommend. Grid snap is pretty good. I usually go with a separation of eight. And then you can
342:52
Speaker A
drag these points to a specific part. For example, something like this. And then use them like so. If you click on one, you get preview. And let's say for this one, I want to be roughly here.
343:06
Speaker A
This doesn't have to be too precise, but you do want to spend some time on it.
343:11
Speaker A
Also, by these three dots, you get a couple of shortcuts to rotate or flip it. For example, if I press H, then this is being flipped and I can use it here.
343:22
Speaker A
Although I probably want to expand it just a bit. Something like that. This I also want to do for this tile. But we do want to cover the entire bottom bit. Like so.
343:32
Speaker A
Like so. And like so. That looks pretty all right. I guess we can do the same thing here and here.
343:40
Speaker A
And then inside of debug, I do want to have visible collision shapes. Run the game. And now you can see that we have collision shapes that work pretty well.
343:53
Speaker A
On top of that, if you put this time map layer before the player inside of the scene tree, I can run the whole thing again. And now the player is on top of them, which looks a lot better. If I now disable the
344:10
Speaker A
visible collision shapes, try all of this again. This is looking pretty all right, at least for the basics. Now, in my case, I want to have multiple layers, which effectively means I want to have multiple tile map layers. The one we
344:28
Speaker A
have created so far is the let's call it the collision layer. Besides that, and let me organize all of this inside of a note 2D called layers.
344:40
Speaker A
This should come right at the beginning of the scene tree. and contain all of the layers. I want to add another tile map layer. This one is going to be the background layer. And then I want to have a background detail layer.
345:00
Speaker A
Finally, I want to have a foreground layer called FG layer just to demonstrate how this system is going to work. and the BG layer and BG detail layer should come first. So we have background, background detail, collision and foreground. For the
345:19
Speaker A
background, I want to create a new tile set. Once again, the defaults here are totally fine. Then inside of tile set, I want to use subway. Create an atlas texture. This one doesn't have any collisions. I basically want to grab
345:33
Speaker A
this black tile. Then inside of tile map, grab the rectangle tool and draw some kind of black area for the background. You can also drag another PNG file into the tile set like so.
345:49
Speaker A
Click on yes. And then you get a lot more options. For example, for this one, I can select all of this.
346:01
Speaker A
And then with the pen selected, I can place something like this. For BG detail layer, I want to have a new tile set.
346:13
Speaker A
Once again, details here are fine. Then inside of tile set, subway.png is the main thing I want to use. And there, for example, we could use a bin.
346:25
Speaker A
For that, you want to go to tile map, select the bin, and then place it. I don't know, let's say here. Once we have that, I can run the game. And now we are getting something that is looking a lot
346:40
Speaker A
more like a real game. Still not perfect, but this is definitely progress. The last thing that I want to do inside of FG layer, the usual stuff, new tile set. Inside of the tile set, I want to add subway.png.
346:56
Speaker A
I do want to have an atlas texture. And then I want to place let's say this light source here by tile map.
347:05
Speaker A
Select it and then place it let's say here. Now this should be in front of the player. But inside of the game this doesn't work. Let me demonstrate so I can get there. And the player is in front of the light. That is because
347:24
Speaker A
we have the layers first in the scene tree and then we go to entities in which we have the player.
347:30
Speaker A
So the player is drawn after the lights. To change that with FG layer selected you can go to ordering and there you have the Z index. This determines when stuff is being drawn and by default you always get zero. If you set this to a
347:47
Speaker A
one then it's going to be drawn after everything else. The basic logic is that GDO goes through all of the Z indexes in order and then draws them. By default, everything is zero. So if this value gets a one, then this layer is always
348:06
Speaker A
going to be on top, no matter what you do. By that system, you can keep all of the layers inside of one node. And don't worry so much about the order. keeps the scene tree a bit more organized, which I
348:17
Speaker A
think is a good idea. Let's do an exercise. I want you to create a proper level. Make sure that you adding lots of stuff to it and that the player cannot see the gray background. There should be a proper surrounding area so the player
348:29
Speaker A
can never leave the level. Pause the video now and see how far you get.
348:37
Speaker A
Righty, back inside of the level. I'm going to create a level and speed up the video so it doesn't get too boring.
349:15
Speaker A
Okay, I think that was definitely enough for a reasonable level. I think just by watching the video, you can tell that creating levels does take a while.
349:27
Speaker A
Simply drawing the border around the level took me 5 minutes just on its own.
349:32
Speaker A
Now later on we are going to learn ways about automating this process where you are placing one tile and then good selects the right one for you. Makes the whole thing so much easier. But for now I think it's a good idea to appreciate
349:48
Speaker A
how difficult level creation really is. That being said there's one thing I forgot to tell you. Let's say with the collision layer selected via this selection button you can select elements and then copy paste them. Super handy.
350:04
Speaker A
We are nearly done. There's one last thing that I want to do. Let me run the game again. And we definitely have to speed up the player but also we can look outside of the level for that. First of all, with BG layer
350:22
Speaker A
selected, I want to draw a vague rectangle around the level. So, we have a clear border on one side.
350:33
Speaker A
Something like this. Looks all right. Don't need this part, I think. But do need those bits and those bits up to here. We need this part, this part and this part. Then I guess we can cover this area. Nearly done
350:57
Speaker A
here and here. Then we need this area and we have to cover the entire bottom like so. Once we have that, you can look at the top. There is telling you the pixel coordinates. For example, this line here is at around -100.
351:22
Speaker A
I'm pretty sure it's going to be 96. So, what we can do inside of the player camera 2D, we can go to limit and then go to left 96.
351:34
Speaker A
Now, I can go to the left and we cannot see the background. This gray bit here is because of the window. If I rescale it then you can see this is just part of the background. If you click on
351:48
Speaker A
this button that disappears and then good scales properly and we can see nothing of the background in the actual game.
351:58
Speaker A
The same thing I want to do for basically all of the sides. So at the top we are at let's say -32.
352:06
Speaker A
On the right side we should have a much larger number. let's say 2,780 and at the bottom we are at around 900.
352:21
Speaker A
So on the player this is going to be top -32 right was let me go to the bottom right then I can see both numbers and if you zoom in a lot you can tell much better where you are.
352:37
Speaker A
So 2780 should be right here. Right. 2780. For the bottom I want to have 960 exactly.
352:50
Speaker A
960. And then we shouldn't be able to see the background. Let's try. So I'm going to zoom out a lot.
353:00
Speaker A
Place the player. I guess we can start in the default position. So, we can check the top and that definitely works.
353:09
Speaker A
Then we can place the player somewhere. Let's say here, we cannot see the bottom and we can't see the right. Also, if you move the player around, the purple rectangle around it is the camera. And you can see that at some
353:28
Speaker A
point the camera stops, which is a really good indicator. And with that, we have a level. It is time to create an enemy, which is going to be a drone. This thing is just going to move towards the player and explodes
353:43
Speaker A
once there's contact. But the player can also shoot at it, and after three hits, the drone explodes.
353:50
Speaker A
All of this is going to be an exercise right away. I want you to create a drone yourself. For that, it should activate when the player gets in range. That's going to be an area 2D.
354:02
Speaker A
When activated, it should move towards the player. Once again, the drone is going to be a character body 2D that you move via move and slide with the velocity.
354:11
Speaker A
Once it gets close to the player, it should stop and explode. So, you stop the movement and use the animation player to play the explosion animation.
354:19
Speaker A
Finally, when the player hits the drone three times, the drone should also stop and explode. That is going to be quite a bit, but I think at this point you can manage this. So, pause the video now and
354:31
Speaker A
see how far you get. To get started, I want to create a new scene with a character body 2D root node that we can rename right away to drone.
354:47
Speaker A
I want to save the whole thing inside of scenes and entities drone.tsseen. Then, let me move to the center. There we go. To find the drone image, you want to go to characters and there we have drone. A very basic animation. You can
355:04
Speaker A
barely tell that it's even animated. We could play all of this via a sprite and for example an animation player.
355:12
Speaker A
Alternatively, we can also get an animated sprite 2D for which we can set a sprite frame with a default animation.
355:23
Speaker A
And in there if you click on this button you can select from graphics, characters and drone. We want to have four horizontal images and only one vertical one like so. Then we can select the different images. Add four frames. And
355:40
Speaker A
now we can autoplay the animation. That way you get some basic effect. Alternatively, you could have also used a sprite 2D with some GDScript or you could have used an animation player.
355:54
Speaker A
There are loads of different ways to get a basic task done in GDU. And I really want you to think about the different approaches you could be taking. I think this is the easiest one, but there are alternatives. Besides that, I want to
356:06
Speaker A
have a collision shape 2D, which I think for this thing can be a circle shape.
356:13
Speaker A
Let's resize it to something like this. That looks okay. And then just to test things inside of the level in entities, I want to add the drone. Oh, and by the way, at this point, once your levels become a little bit larger, it's really,
356:29
Speaker A
really easy to drag the wrong node from the origin point. So, instead of the drone, I drag the bullets, which shouldn't be the case. The easiest way to get around that is with the drone selected inside of the scene tree. you
356:42
Speaker A
want to hold command or alt and then you are only moving the node that is selected inside of the scene tree can be incredibly helpful. Besides that with the bullet selected you can also lock them via this button. That way you can't
356:58
Speaker A
move them anymore. The same thing I want to do to layers and two entities. They shouldn't be draggable inside of the game. There are a couple of useful buttons at the top. I would recommend to go through them when you have time. Yes.
357:11
Speaker A
for example, a ruler in there or there's grid snap and be quite helpful, but I want to focus on the basics, which is the drone. Let's run the game and see how it looks.
357:24
Speaker A
That looks pretty respectable. Now that we have that, I want to create an area 2D node, which I want to rename to detection area. To that I want to add a collision shape 2D which is going to be a circle
357:44
Speaker A
shape that needs to be reasonably large. Something like this. Let's see how it looks in the game. And I think that's a good detection area.
357:55
Speaker A
If the player gets into this range, the drone is going to activate for which we want to add a script. The defaults here as always are totally fine. And for the detection area, I want to go to note and
358:07
Speaker A
then body entered. Although first of all, I forgot one thing. With the character body drone selected, I want to go to collision. And this should be on layer three. It can see the terrain. It can see the player
358:22
Speaker A
and it can see the bullets. Besides that, for the detection area collisions, it shouldn't be on any layer and it can only see the player. And for now, let's simply print the body that we are getting. It should only be the
358:39
Speaker A
player. We can actually rename it to player. And this has to be a character body 2D. And the player is being spawned right next to the drone. But if I go outside and come back, this should be enough. We are going to see player
358:57
Speaker A
again. So that is definitely working. Once we have that, I can create a var direction. As always, this is going to be a vector 2 without the default value. I want to have a var speed.
359:14
Speaker A
This can be an integer with a value of for now let's say 50. And I want to store the layer, a character body 2D.
359:24
Speaker A
Now inside of this function when we are getting the player I want to assign the player to player. So I want to get the variable and assign the parameter.
359:36
Speaker A
Although you can see this logic is going to be quite confusing and GDO really doesn't like it. This causes a ton of errors. I guess inside of the parameters we can call it the player body. Now once we have a player body, I want to run
359:52
Speaker A
funk physics process and check if this value exists. So there's anything inside of this variable, then this if statement is going to trigger. If there isn't, it is not. All I want to do if we have a player is first of all get the direction
360:10
Speaker A
to the player. Let's call it var deer. This we can get from vector math. We need the player dot position and from that subtract the current position of the note. This we also want to normalize like we have done for the bullets. Super
360:28
Speaker A
important. So that when we are multiplying the direction with the speed, we are getting a constant speed.
360:34
Speaker A
Speaking of which, all we have to do is get velocity and assign it direction multiplied with speed. And also we want to call move and slide. To test all of that, I want to move the drone and the player a
360:50
Speaker A
bit further apart. So I can actually walk into this area. Let me try. And now if I get close enough, the drone starts moving towards the player. And we really should increase the player walking speed. It is really, really slow.
361:07
Speaker A
I guess 120 should be quite a bit better. That feels definitely better. Now I can also run away from the drone.
361:20
Speaker A
If the player goes outside of the detection area, the drone should stop, which we can check via body exited.
361:28
Speaker A
Once again, we have the player body, which has to be a character body 2D. You don't have to rename these, but I think it's good practice. It just makes the entire thing much more understandable.
361:42
Speaker A
If that is the case, I want to remove the player body from the player variable. To do that, I want to get the player variable and assign it a value of null, which is empty. Once we have that,
361:55
Speaker A
back inside of the game, I can walk towards the drone. It follows me. And if I run away, it stops. This works multiple times. Perfect. Also, GDAU is really unhappy with us because inside of physics process, we don't use delta and
362:12
Speaker A
inside of player body, we don't actually use the player body. So, we should add an underscore before it. If I now try this again, the debugger should be happy. And that looks much better. Now, we have a drone
362:26
Speaker A
following the player. After we have that, I want to play an explosion. once the drone gets really close to the player. For that, first of all, I want to add a sprite 2D, which we can rename to explosion sprite.
362:46
Speaker A
Inside of the inspector for the texture, I want to get fire and explosion, which is an explosion with 1, 2, 3, 4, 5, 6, 7, eight frames or eight H frames to be specific. This we want to animate
363:02
Speaker A
via the frame property. For that you could use another animated sprite. Although to practice things, I want to add an animation layer which is going to get a new animation explode.
363:16
Speaker A
I want to add a track property explosion sprite and get frame. With the timeline open, I want to go to the explosion sprite and then set the animations.
363:28
Speaker A
I can select all of them. We should be going from zero to seven. So the first one is zero. And we go all the way to seven. And I think this might be a bit too fast.
363:41
Speaker A
So we want to space things out. I can just select all of them and then give each 0.1 seconds like so.
363:57
Speaker A
So, so and so. Then the entire duration of the animation should be 0.7 seconds.
364:06
Speaker A
Let's try it now. And for some reason, the first frame is always a bit longer in the preview. But inside of the game, this isn't going to be an issue. Which means next up, I want to add another area 2D node to
364:23
Speaker A
the drone. This one is called collision area. Once again, I want to have a collision shape 2D, which is going to be a circle shape. And this one should be just a bit larger than the drone.
364:37
Speaker A
Something like this. Also, for collision, you don't want to be on any layer and you can only see the player.
364:47
Speaker A
If a body enters now then we want to explode the drone for which we don't need a body. So this one can get an underscore. All I want to do is get the animation player and play explode. Let's see if that works.
365:08
Speaker A
And that is maybe not ideal. First of all, the explosion sprite should not be visible by default. It should be hidden.
365:17
Speaker A
So, click on the eye. And then once the node collides with the player, I want to get the explosion sprite and show it.
365:28
Speaker A
Next attempt. Much better start. And now we get one explosion. This happens multiple times.
365:38
Speaker A
So, we can test things. We are nearly done. The one issue that we have is that when the drone is exploding, so somewhere here, we don't actually get rid of the drone. It sticks around.
365:51
Speaker A
To fix that, first of all, when we have an explosion, the drone should stop moving, which we can do very easily. We just have to set the speed to zero.
366:02
Speaker A
That way, if the drone gets close, it stops moving. Good start. Besides that, I want to hide the animated sprite 2D so we can't see the drone anymore.
366:18
Speaker A
That part is also super easy. Animated sprite 2D and hide. Also, the explosion sprite by default shouldn't be visible.
366:30
Speaker A
Once we're doing that, the drone can move towards the player. And this almost works. Basically, what we now have to do once the explosion has finished playing, we want to delete the entire scene, which we can do in two
366:46
Speaker A
ways. Either with the animation player selected inside of node and signals, you have animation finished. You could delete the node when this function is running. Alternatively, which I think is the better approach, instead of this function, we can uh wait
367:04
Speaker A
the animation layer dot animation finished. We are waiting for the animation to be finished. And then we want to delete the note via Q3.
367:18
Speaker A
Let's try this one. And now if the drone comes to us, it explodes and disappears.
367:25
Speaker A
And I realized the bin here really doesn't work. But first of all, let me explain why this line is really important. If we didn't include it, we would play the animation but then delete the note right away, which means we
367:38
Speaker A
wouldn't see the animation. Now the drone simply disappears. Now we are still playing the animation, but we are deleting the entire thing right away, so you can't really see it. for which we have this await line and then
367:53
Speaker A
everything works just as expected. Next up, when a bullet hits the drone, the drone should lose some health. Inside of the bullet, I want to check for a body entered and connected to the script of the bullet.
368:12
Speaker A
For now, let me simply print the body that we want to target. Also, the bullet speed is incredibly slow. 30 is just not very good. And this should be speed anyway. Integer with let's say 100. And then this speed we want to use for the
368:30
Speaker A
bullet. Let's try all of that. If I now shoot at the drone, I do have to make sure I hit it. There we get drone. Also, we get collision layer. That is expected. The bullets can see the drone and the terrain. If a drone
368:49
Speaker A
hits the terrain, I simply want to delete the bullet, which we can do via Q3.
368:56
Speaker A
However, inside of the drone, I want to have a funk hit, which for now simply prints drone was hit. Once we have that, inside of the bullet, I want to check on the body that we're getting from the
369:12
Speaker A
parameter. If there is a hit function, I want to run the hit function but only then so that when we are getting the terrain we are not doing anything. And just to demonstrate before Q3 I want to run body.it
369:27
Speaker A
which is going to work for the drone but not for the terrain. Let me get to the drone. Make sure I hit it on the first try. There we go. Drone was hit. This one works. But if I hit
369:39
Speaker A
anything else then good is going to crash because there's no hit function inside of tile map layer. We first have to check if the hit function exists inside of body that luckily we can do very easily. If the string hit is in
369:58
Speaker A
body that's all we needed via that good checking if there's a hit function or property inside of this node and then it is going to execute it. So next attempt I can now shoot at the drone a couple of
370:13
Speaker A
times. Make sure I hit it. That looks good. Drone was hit and if I hit anything else the drone just disappears.
370:19
Speaker A
That means finally inside of drone I want to set var health an integer with a default value of three. This we then want to reduce. So health minus equal 1.
370:33
Speaker A
And we want to check if health is smaller or equal to zero. And then I want to play basically what we have done in here.
370:46
Speaker A
In the most basic sense, you could simply copy all of this and you should be good to go.
370:54
Speaker A
Let's try for that. I have to make sure I hit the drone. One, two, and three. We get the explosion and the drone disappears. That being said, you shouldn't copy lines of code like this. It's really bad practice. A better way of approaching
371:09
Speaker A
that would be to create another function. Let's call it explode. We want to have all of these lines. Paste them in there. Make sure the indentation is correct for all of them.
371:22
Speaker A
And then if health is below zero, we want to explode. And if the drone gets close to the player, we also want to explode.
371:32
Speaker A
That way you are referencing the same code twice. And if you want to make changes, it's really easy to do. So let's try. I can get to the drone. I can shoot at it. It explodes. That looks good. And if I just get close to it,
371:50
Speaker A
then it also explodes. Perfect. With that, we have the basic drone. There's one more mechanic that I want to add. When a drone explodes, it should damage everything around it, including other drones. To achieve that kind of effect, we have to group all of the
372:08
Speaker A
drones via which we can introduce a new mechanic back inside of GDU. If you look at note besides signals, we have groups.
372:18
Speaker A
Those can be incredibly useful. For example, inside of the drone with the root note selected, I can create a new group and call it drones. Then we have a scene group.
372:32
Speaker A
What can we do with that? Well, inside of the level, let's say when the scene is ready, bunk ready, I want to print everything inside of this drone's group. If you look at the scene tree for the drone, we now
372:50
Speaker A
have this symbol, indicating that the node is inside of a group. If you hover over it, GDAU is telling you what the group is called. To access all of these nodes, all you need is get underscore tree. Don't forget to call it and then
373:05
Speaker A
you can get nodes in group or you can get get first note in group.
373:12
Speaker A
Quite often if you want to have access to one node globally everywhere inside of the script like for example the player you might have a group dedicated to the player only. Then get first node in group usually makes sense but for our
373:27
Speaker A
purposes we want to get nodes in group. Then we need the group name which in this case is drones.
373:37
Speaker A
If I now run the game, I am going to get an array with one node inside the drone.
373:45
Speaker A
If I add multiple drones, let me duplicate it. And I don't want entities to be locked. That way we can move stuff inside of it.
373:55
Speaker A
I just want to have a couple of drones like so. So, and so if I now run the script, we get an array with four drones. And that is pretty much all you have to know about the basics of groups.
374:14
Speaker A
When you have a scene, you can assign the node to a group and then every time you create an instance of the scene, you have access to that via the group. And this, by the way, is going to work
374:25
Speaker A
everywhere. We can check inside of the game scenes for all of the drones. And we can check inside of the drone itself.
374:33
Speaker A
For example, in there, I want to have funk ready as well. And then simply copy from level this one line.
374:46
Speaker A
Then I can run the script. And now we should get the same output a couple of times. And that looks pretty good. Every single drone is going to output this print statement. via this system, you can target scenes basically anywhere
375:00
Speaker A
inside of GDO and you're not really constrained by any kind of scene setup. Now, to test all of this, I want you guys to implement the drone explosion.
375:09
Speaker A
Basically, make nearby drones explode when the drone explodes. You can set the range yourself. Just choose something that you think looks good. Pause the video now and see how far you get.
375:22
Speaker A
I want to work inside of the script for the drone and we don't need the ready statement anymore and we also don't need it inside of the level. All of this can go instead when the drone is exploding
375:37
Speaker A
this function here before we are running Q3 but after the animation I want to for drone in get underscore tree and get notes in group the group I want is drones this works because the return value of this function is an array
376:00
Speaker A
meaning we can use a for loop to get every single item inside of it. All we have to do then is drone.exlode.
376:07
Speaker A
[Music] Although this we only want to do if the drone is within a certain range. Now to test out all of this first inside of level, I want to move all of the drones really close to the player so we can see
376:22
Speaker A
them at the same time. If I now run this, we get the drones and if one of them explodes, they all explode. That being said, inside of the drone, we only want to explode nearby drones. That we can do
376:38
Speaker A
via the current position. And then we have distance 2. We want to check drone.position.
376:50
Speaker A
If this value is let's say smaller than 10 pixels, then I want to run drone.exlode.
376:57
Speaker A
Also, this should be an if statement. Let's try this one now. And we have to make sure that the drones are close to each other.
377:09
Speaker A
And well, that was quite hard to see. Let's move one drone over here so we can test things a bit better.
377:20
Speaker A
The drones explode, but this one is totally unaffected. And if I move the player just a bit further to the side like so, meaning we don't trigger the drones automatically, then I can play with this a bit better. So I want these
377:37
Speaker A
two drones right next to each other. Then inside of the game, make sure you don't move forward. And now I just have to shoot at them. Actually hit. And I guess we need to have a bit more of a
377:50
Speaker A
distance between them. Let's try 20. And that works much better. So, this would be the most basic setup.
378:01
Speaker A
However, back inside of the game, if I simply explode the top drone, you can see that we have the explosion and then this waiting time, which is kind of annoying.
378:14
Speaker A
Ideally, we want to explode the other drone while this animation is playing. Or to be a bit more specific, if I open the animation player inside of explode, we want to probably damage things somewhere here. How could we do that?
378:33
Speaker A
And well, first of all, we will need another function. Let's call it funk chain reaction.
378:43
Speaker A
This function doesn't need a parameter. All we want to do in there is effectively this for loop. Let me copy it, then paste it in there. After that, it's really important that this script is saved. There shouldn't be an asterisk
378:58
Speaker A
right next to it. But for now, let me not save it because what I want to do inside of animation player in the animation, I want to add a call method track. If I do that, then GDO wants to
379:11
Speaker A
have a note. I want to get drone. On that note, I can insert a key and this key is going to be a method that we want to call. We do have all of the inbuilt ones of character body 2D. For example,
379:25
Speaker A
move and slide or is on floor whatever you need. But besides that, we also have the functions that we created like hit and explode. But notice here we do not have chain reaction. That is because this script was not saved. if I save it.
379:44
Speaker A
So the asterisk has disappeared. Then I can add another key and now we get chain reaction. This can be a really annoying beginner mistake. But now when we get to this point in the animation, GDO is calling for you the chain reaction
379:58
Speaker A
function, which means inside of the game, I can shoot at the drone three times and we get a much better effect.
380:09
Speaker A
And with that, we have the drones completed. Next up, I want to add lights. That way, the game is going to look significantly better. For all of that, back inside of GDO, first of all, I only want to have a single drone. So,
380:24
Speaker A
let me delete all of the other ones and move this drone to the side. We are going to add lights to this one later on so we get a bit of a blinking effect, but that's going to come later. First of
380:34
Speaker A
all, to add lights. With the level node selected, I want to add a note and simply type light. For the 3D nodes, we have a ton of different lights, but those we don't care about yet. For 2D, we have two kinds of light. A
380:50
Speaker A
directional light 2D and a point light 2D. The point light 2D is basically a lamp.
380:57
Speaker A
Whereas directional light is more or less the sun. Let me add this one first.
381:02
Speaker A
If I do that then you can see the entire level is much much brighter. If I hide it then you can see the effect much better.
381:12
Speaker A
Also on the right we can change the color to whatever you need in here.
381:18
Speaker A
And you can even change the blend mode. So you are subtracting the color instead of adding it. If I change the color to something red then the level will become green because we are removing all of the red values.
381:31
Speaker A
can create interesting effects but not what I want to do right now. Besides that, we can change the energy and this one changes well the energy.
381:40
Speaker A
Something you want to use very very carefully. I guess for now what I want to do is to make the color much darker.
381:50
Speaker A
Something like this. Then for the blend mode I want to mix the color. So we are mixing basically all of the layers with this color. And this is definitely too dark. I guess something like this works a lot better. And to see the difference,
382:06
Speaker A
if you toggle this node, this is very much noticeable. For all practical purposes, we now have a sun that makes things darker. Besides that, if you look at the inspector, we also have shadow.
382:21
Speaker A
This we can enable, but at the moment it's not going to do anything, I guess.
382:26
Speaker A
to make it visible. Let me change all of this back to normal and then add another node. The note I want to add is light occludder. This is basically a collision shape for lights. If you add it, by
382:38
Speaker A
default, nothing is happening and GDO is giving you a warning that you have to add a polygon inside of the inspector in the includ polygon 2D. Do that and then still nothing happens. But now at the top you
382:52
Speaker A
get three buttons that let you draw a shape. Let me draw something random like so. And now this shape is blocking the light and anything below is casting a shadow.
383:06
Speaker A
For that you do want to make sure that shadow is enabled. If it isn't then this is just blocking out the light. You might also be wondering why do we still get a warning or this olude note? If you
383:17
Speaker A
simply go outside of the scene and come back to it is disappearing. It's just a small bug. Doesn't really matter. Now, for this scene, I don't want to do that.
383:26
Speaker A
So, let me get rid of it. And for the directional light 2D, I want to set the blend mode to mix and the color to something darker. So, we get more atmosphere inside of the game. Let's see how that looks.
383:40
Speaker A
And that is definitely a change. Just play around and see what you like. Now the second kind of light that we can work with is a point light 2D effectively a lamp. If you add that one once again by default nothing is
383:55
Speaker A
happening because for this light you will need a texture. Inside of graphics we have lights and there we have a couple of textures. The one you want to use for now is called main.png. If you are that one in the
384:10
Speaker A
origin of the game, we have a light source that is defined by this texture.
384:16
Speaker A
If we have white points, we get a lot of light. If we get more grayish points, we get much less light.
384:23
Speaker A
And this works together with the directional light. If I make everything super dark, then you can still see this outline. You can also scale it inside of the point light. You have a texture scale and you can make it smaller or
384:36
Speaker A
larger. You can also offset the entire thing. Although this is not what I want to do, but besides that, you can also mess with the color and do something weird in here.
384:48
Speaker A
You can update the energy and the blend mode. Shadow also works in exactly the same way. Now, in my case, I don't want to do any of this. And for directional light, I want to have a bit more
385:00
Speaker A
visibility. Something like this. And then I want to add the point light 2D to the player character.
385:08
Speaker A
Inside of the player character, point light 2D along with main.png. Then the player is going to be much brighter, which does look a bit weird.
385:18
Speaker A
But back inside of the level, we get a pretty nice effect. And by the way, what you can also do, if I add another point light 2D to the level scene, if you click on the drop-own arrow for
385:32
Speaker A
the texture, you can create new textures from scratch. For example, there is a gradient texture 2D. If you click on it, you are getting a texture that you can modify right inside of the engine. So, if you look closely, let me zoom in a
385:48
Speaker A
bit. And I guess if we move this thing over here, it's much more visible.
385:53
Speaker A
This gradient can be changed inside of the editor and then you are getting a realtime preview of how it's going to look. This you could for example use all the way on the right. We have a couple of doors that could do with a bit of
386:09
Speaker A
illumination. Let's move it here. And then we can move the light roughly here. And you can already see if I toggle this light, this is making a difference.
386:27
Speaker A
We can maybe move it a bit more like this. Besides that, if you change the color, you can reduce the amount of red and then make this thing a lot greener.
386:38
Speaker A
Although, you do want to play around with what looks good in here. I guess adding a bit of red to it could be a nice effect. I hope you get the idea. By this system, you can make things look much more
386:51
Speaker A
appealing. If you compare this door to this door, this one just looks better. And finally, what we can also do by adding another point light, we can illuminate this sign for which we have L3.png.
387:08
Speaker A
You can already see if I drag it around, we have the right light source. And this one is being spawned in the origin point, but I want to have it here.
387:18
Speaker A
That way, this sign is looking much more interesting inside of the game. It is now illuminated and it works along with the player.
387:32
Speaker A
If you compare this sign to the other sign, you can definitely tell the difference.
387:37
Speaker A
Also, what we can do if I have the point light selected, we can, for example, change the energy and make it flicker just a tiny bit inside of the level script.
387:52
Speaker A
When this thing is ready, funk underscore ready, I want to create, let's call it like tween for which I want to once again create a tween. And by the way, you can either get the tree and then call create tween
388:09
Speaker A
or you can simply go to create tween right away. Both would work. Choose whatever you like.
388:17
Speaker A
Then for the light tween, I want to tween a property. The node I want to target is point light 2D2. This one. And on there I want to get energy as a string energy. The final value has to be a float for now. So we can see
388:38
Speaker A
something. Let's say 10.0. The duration could be 2 seconds. If I run the game, you can see the sign is definitely getting brighter.
388:51
Speaker A
This should be much less strong. 1.1 maybe. After we have that, I want to duplicate the line and go to let's say 0.9.
389:03
Speaker A
That way you are going to get a very very minor effect. And this I want to play forever which we can do via light queen and then set loops.
389:15
Speaker A
If you don't add any value in here, let me open the documentation. If you add any kind of value in there like a two, you're going to play it twice. But if you call it without any arguments, it's going to run forever,
389:28
Speaker A
which is exactly what we want. That way, inside of the game, it's going to be quite hard to see.
389:36
Speaker A
But if I make the value stronger, let's go with 1.5 and 0.5, then you should definitely see it there. You can absolutely see that this is making a difference.
389:55
Speaker A
I think the main issue is that this 2 seconds is a bit too long. 0.3 maybe.
390:05
Speaker A
Now we have more of a flashing effect, but you get the idea. Let's stick to 2 seconds and then we get at least some kind of effect.
390:15
Speaker A
Should be something to indicate that here is an important part of the level. Anyway, this is kind of all you have to know about lights to get started.
390:24
Speaker A
You have either a directional light 2D for the sun or point light for a specific kind of light source. For those, you have to add a texture, which you can either create yourself in something like Photoshop or you can
390:35
Speaker A
create them via the drop- down menu. To practice all of this, I want you to add a drone light, which is basically going to be a red light that flickers on the drone. Animate this via the animation player. You could also use a tween, but
390:52
Speaker A
I want you to practice using the animation player. That one is super important. Pause the video now and see how far you get.
391:02
Speaker A
I want to work inside of the drone. And for now, let me hide all of the areas so we can actually see what's going on. Much better.
391:15
Speaker A
First of all, I want to add a light to this red part of the drone for which I can add a point light 2D. I still have it selected and then add a main.png file.
391:28
Speaker A
Now, we're making the entire drone much too bright. That is because this light source is quite large. To scale it down, you can set the texture scale to 0.1.
391:38
Speaker A
And then you can see a bit better what's going on. We have a light source that we want to be let's say here. Besides that, I want to change the color to something more red. For that, reduce the amount of
391:50
Speaker A
green and blue. And then we are already getting close to the effect that we want. If I simply toggle the color.
391:57
Speaker A
Alternatively, what you can also do is change the energy to something like this where we toggle between a value of 1 something and 0 let's say 0.3.
392:11
Speaker A
This we want to do via the animation player. We already have one in there. I want to create a new animation for the red light.
392:22
Speaker A
I want to add a track for property. I want to target point light 2D and then target energy.
392:31
Speaker A
Open this one. The duration for the animation can actually be 1 second. I want to start with a key. The value for the light should be 0.3.
392:42
Speaker A
You can see a preview. If I now go to let's say 0.4 seconds, I can add another key with a value of 1.2.
392:52
Speaker A
This animation I want to loop. Let me run it. And just in case you are confused, we are starting at zero. Then we go to this value. And then GDO automatically tries to go back to this original value, which is why we are
393:08
Speaker A
reducing the light already. And we can just loop the entire thing. And then we have the effect already.
393:15
Speaker A
If you ping pong this value, you are playing the animation back and forth, which could also work. If you reduce the animation length to half a second, it's going to do pretty much the same thing.
393:30
Speaker A
Just choose whatever you prefer. With that, inside of the game, we can look at the drone and it still explodes. That looks good. At this point, we have basically a game. However, I want to make this thing look a bit more
393:45
Speaker A
interesting. Specifically, once a drone gets hit, it should flash. For that effect, we have to learn a new topic that does get quite a bit more complex called shaders. Using shaders, you can do a crazy amount of special
394:00
Speaker A
effects and I am only going to cover the absolute basics. But fundamentally, all that we are going to do is that we are going to determine how elements are being displayed.
394:12
Speaker A
That means if you have the GDO logo for example and this would also work with any other graphic. When we are displaying this in the game engine, what internally happens is that the GPU separates this thing into smaller chunks
394:26
Speaker A
and draws each of them individually in parallel. And this process you can manipulate. For example, you could tell the GPU to draw this part purely in yellow or make this part white. You can also change the position. For example,
394:42
Speaker A
you could move this top part here further to the right. Via this system. You can turn a 2D graphic into basically anything else. There's actually a whole website for it to give you ideas in terms of what you can do. It's called
394:56
Speaker A
gdosshaders.com. If you click on shaders, there you can get an idea of what you can do with them. Canvas items are for 2D shaders and spatial shaders are for 3D objects.
395:09
Speaker A
If you look at canvas items, they can see that you can do a crazy amount of stuff using this system.
395:18
Speaker A
But keep in mind all of this does get a lot more complex. But I want to keep it simple. So we are only going to do the absolute basics for which back inside of GDO I want to work inside of the drone
395:31
Speaker A
and specifically inside of the animated sprite 2D. We only have to apply a shader to the visible sprite which is the animated sprite 2D. To give this thing a shader, you want to go to material and there you
395:46
Speaker A
can give it a canvas item material or a shader material. Shader material is what we want to go with. So click on that and then nothing happens but you do get a sphere. That's a preview of what the shader is doing.
395:59
Speaker A
If you click on that then you can create a new shader. There are two types of shader, a script based shader and a visual shader. I actually want to work with a visual shader.
396:11
Speaker A
Then we have the mode. You have canvas item, spatial, particles, sky, and fog. Particle sky and fog I think are self-explanatory. Canvas item is for 2D items, sprite 2D, animated sprite 2D, things like that. Spatial shaders are for 3D objects. Don't worry about those
396:28
Speaker A
yet. We do want to create a canvas item shader. And then we have to save it somewhere. In my case, I tend to prefer to save all of the shaders inside of a folder called shaders.
396:42
Speaker A
That keeps things a bit more organized, but you could save it wherever you want.
396:46
Speaker A
It doesn't really matter. After you have that, click on create. And then nothing happened. To actually do something, you have to click on this item again. And then you can see, let me expand it. We have a field where we can create a
397:04
Speaker A
shader using visual notes. The most important thing is the output and to that thing we can add different information.
397:14
Speaker A
The only two values that we care about are color and alpha although there are quite a few more. And next to them the dot determines what kind of data type we are working with.
397:25
Speaker A
Gray means GDO is looking for a floatingoint value and shades of purple means some kind of vector.
397:33
Speaker A
Hala wants to have a vector 3 for red, green, and blue. Down here we have shadow vertex. This one is a lighter shade. This is going to be a vector 2 which doesn't matter for now.
397:45
Speaker A
And fundamentally the way this system is working, let me show the drone and the output node. If you right click on this field, you can add other nodes. For example, in there, if you look at color, we have under variables a color
398:01
Speaker A
constant. If you double click on that, you get a color constant with a golden node.
398:08
Speaker A
If you click on this arrow, those telling you what the individual parts of this node are. We have red, green, blue, and alpha. Meaning this is a vector of four which is fine for our purposes.
398:21
Speaker A
Effectively what you want to do you want to drag this node into color and then we have turned this node white. Also you can see that GDO has converted a vector 4 into a vector 3 which it is doing by
398:35
Speaker A
discarding any extra information. Meaning from this vector four we have red, green, blue and alpha values. But to this color vector three we only get three values. Red, green and blue.
398:46
Speaker A
Meaning alpha was discarded. And well now inside of color constant we can change the color and this will show up inside of the game right away. If I launch the game then you can see that the drones are now colored in this
399:03
Speaker A
specific way. On top of that, what we can also do, let me give myself just a bit more space like this. Right now, we work with the color values. But besides that, if I right click again, we can add
399:17
Speaker A
other nodes. And most of the time, you are simply searching for the note you're looking for. For example, I want to add a float constant.
399:28
Speaker A
And then connect this to the alpha value, which right now makes the drone invisible. That is because we have set alpha to a value of 0.0.
399:36
Speaker A
If I set this to a one, then you can see that we have made every single pixel visible. The reason for that is if I disconnect this node, a computer graphic is always a rectangle. This red outline you see is the actual graphic. The
399:53
Speaker A
reason why we can see a drone shape is because all of these pixels are invisible. But via the shader and the alpha property, we can make all of these pixels visible. As a consequence, we would get a rectangle, which obviously
400:08
Speaker A
is not what we want to do. That being said, if you have this connected and set it to a value of 0.5, then you have 50% transparency.
400:19
Speaker A
But once again, not something that I want to do. We have to learn about just a few more nodes. One of the most important ones is called color. And you want to look for vector 4 color.
400:34
Speaker A
This is different from color constant, the one that we have just used because this is giving us the current color of every single pixel inside of this graphic. If I create it, then once again, we're getting a note with a
400:48
Speaker A
golden output, meaning this is a vector 4. But this isn't a static color like we have done here. Instead, this is the color that is inside of the original graphic. Meaning if I connect it to color, then we get the original drone.
401:05
Speaker A
If I expand it and only use the red pixels, then we get a grayscale image where the red pixels are brighter. This would work with all of them, which can give you some fairly interesting effects. You can also get
401:20
Speaker A
only the alpha values like so and that way we would get a white drone. So fundamentally what is happening now let me draw this actually the way you want to think about shaders and this can be a bit confusing is good internally via the
401:36
Speaker A
GPU separates the graphic into individual chunks something like this for each of those chunks let's say this one to get started is getting a whole bunch of information most importantly at the moment we are looking at the color meaning for This
401:56
Speaker A
chunk we're getting the red color, the green color, the blue color and the alpha value. And currently we are taking the alpha value which for this pixel is a one and set this to the value of the color since for this color it wants to
402:13
Speaker A
have a vector three which needs to have a red value, a green value and a blue value. But from alpha we only get one value which at the moment once again is a one.
402:28
Speaker A
To make this conversion happen is setting the value of all three of these to one. So one one and one for RG and B.
402:37
Speaker A
And as a consequence we're getting one as the actual color value. If you want to learn more about it, I have made a couple of shader videos on YouTube.
402:45
Speaker A
Check those out for a lot more detail. But once we have this kind of setup, what we can also do is get our float constant back.
402:56
Speaker A
And then if you want to modify the alpha value of this graphic, all we have to do is multiply this alpha value with the float constant, which we can do via a multiply node. And notice here we got
403:11
Speaker A
multiply and then a data type to the left of it. This is for float. We also have integers. And if you scroll down, we have vector 2, three, and four as well. At the moment, we only want to
403:23
Speaker A
work with the floating point values. And fundamentally, I want to multiply the float constant with the alpha of the original pixel and set this as the alpha value. Also, I don't want to use the color value for now. And right now, we
403:38
Speaker A
can't see anything because this float constant is zero. If I set it to one, we're getting the original.
403:46
Speaker A
If I set it to 0.5, then we are making the drone semi-transparent. And also at this point, we can get the color constant back. And now this is working like you would expect it to work. I can set this
404:00
Speaker A
thing back to one or to 0.1. And this works pretty well. And once again just to understand the system via this input node we're getting the original color so red green and blue along with the alpha value and this
404:16
Speaker A
alpha value for every single pixel we are multiplying with some constant via this node which we are then setting as the new alpha. Pixels that are invisible like all of these pixels around it stay invisible because they from the original
404:32
Speaker A
input node have a value of zero and anything multiplied with zero is going to be zero. So I hope that system makes sense. Once again getting used to shaders does take a while. Don't rush yourself with this one. In my case to
404:46
Speaker A
make the drone flash I actually don't want to do any of this. Instead, I want to add a color parameter.
404:58
Speaker A
And this color parameter basically gives us a color. We can set a default value.
405:03
Speaker A
And then like we've done before, set some kind of value. The default is white. And this is what I want to use, but you could change it to whatever you like. Once again, this color we could use for the color. And then we get an
405:15
Speaker A
output. So, so far this is identical to the color constant. The difference is that this color parameter can be changed inside of the inspector.
405:27
Speaker A
So, let me connect it to the output and then if it is connected to the output in the inspector under shader parameters, you can see a color parameter and you can also change it. That way, we can work with the shader from inside of
405:43
Speaker A
GDScript. And effectively what I want to do, let me expand this again. I want to mix this color with the original graphic and then control which one we see for that GDO has a mix node. And keep in mind here we
406:01
Speaker A
want to mix a vector three for the color. Create this one. And then wants to have three values. Two for the colors and then for the weight. The first color is the one we get from the color parameter. The second color is the
406:18
Speaker A
original color from the graphic. So vector for color. This we want to connect to the second one. The output is going to be the color. And right now this thing is set to 0.5 for every single one of the
406:32
Speaker A
colors. Meaning we are mixing the original color with the color parameter which currently is white. To change this value, all we care about is a float parameter.
406:45
Speaker A
This, like the color parameter, gives you a parameter that you can change inside of the inspector. And this I want to connect to the weight.
406:55
Speaker A
Once again, we are converting a float to a vector 3. The way GDO is doing that is it assigns the value of the float to all three values of the vector 3. meaning RG and B are all getting the same value,
407:11
Speaker A
which is exactly what we want. Inside of the inspector, we have a color parameter and a float parameter. And if I change the float parameter to one, you can also just type a value in here, then we only get this original color. If
407:27
Speaker A
I set it to zero, then we only get this color parameter. If I set it to 0.5, then we are mixing these two together.
407:38
Speaker A
And that is pretty much all we need. Although one thing I do want to do to have easier names, this should just be the color. And for the float parameter, let's call this one progress.
407:51
Speaker A
Once we have that, we have to figure out how to target all of this from inside of GDScript.
407:59
Speaker A
For that, inside of the drone, specifically the hit function. Besides reducing the health, we want to do animated sprite 2D, I want to get the material. And on this material, we have a shader parameter.
408:20
Speaker A
Although in this particular case, I want to set the shader parameter. You want to have the name of the node first of all, which in our case is either going to be progress or color.
408:31
Speaker A
For now, I only want to work with progress. So, pro rest and then the second argument is going to be the value we want to set to it.
408:44
Speaker A
Let's have a quick look. Once again, inside of the drone. If we set this to zero, we get the white color. If we set it to one, we get the drone. As a consequence, the default should be 1.0.
408:58
Speaker A
So, we can see the drone. But once the drone gets hit, this should be set to zero. And once the drone gets hit, we want to get a value of 0.0.
409:09
Speaker A
Let's try this one. By default, the drone should have the normal color. That looks good. And once I hit it, the drone becomes white. And that is working really well. That's a good start. But this should be a bit more animated. for
409:25
Speaker A
which I want to use a tween meaning var tween create tween like we have done before I want to tween a property where we want to get the animated sprite 2D dot material the property we want to target is called
409:46
Speaker A
shader_parameter slash progress or this progress is whatever value you set inside of this field. After that, we will need a target value 0.0.
410:01
Speaker A
And finally, it deration. Let's say 0.3 seconds. Once that's done, I want to duplicate the line and then set the value back to 1.0 over a duration of, let's say, half a second. And then we don't need this
410:18
Speaker A
last line. Let me get rid of it. I can run the script again. And now if I hit a drone, it flashes. And after three hits, it disappears.
410:32
Speaker A
And perfect. With that, we have shares along with twins. We are nearly done with the game. I just want to add some very minor parts. First of all, I want to play sounds. There are only two sounds for the explosion and the laser.
410:47
Speaker A
This part is actually going to be your exercise right away. add the sounds for the laser and the explosion. Pause the video now and see how far you get.
410:59
Speaker A
For the laser, we want to work inside of the bullet and basically play the sound whenever this thing was spawned, which means I want to add an audio stream player to be. We don't have to change the name, but I do want to add
411:16
Speaker A
laser.wav. It's going to sound like this. This want to play whenever this bullet is spawned. When the scene is ready, I want to get the audio stream player 2D and play it. Let's try.
411:38
Speaker A
That is working pretty well. Besides that, for the drone, when the drone explodes inside of the explode function, I want to play another sound.
411:52
Speaker A
I want to add another audio stream player 2D, which gets the explosion.wav sound, which we then want to play once the drone explodes.
412:05
Speaker A
Right at the beginning, I want to get audio stream player 2D dot play. Let's try this one.
412:23
Speaker A
Now, this kind of worked with a couple of issues. Let me play it again actually and pay close attention to it. If I shoot the drone three times, we get the explosion sound twice. If I just play the sound on its own,
412:47
Speaker A
you can hear it. We only have it once. And if I inside of explode print explode and try the whole thing again, you can see the issue.
413:00
Speaker A
Once again, I want to shoot it three times. We can see explode twice. That is because once the drone's health goes below zero, we are calling this function. And then we are playing the explosion animation. This one here for which
413:21
Speaker A
we are playing the animation and then we are calling chain reaction where we are checking if a drone is nearby and then we are calling explode again. As a consequence, this function can be played twice. This we obviously want to avoid
413:36
Speaker A
which we can do in a couple of different ways. I think the easiest one would be var is underscore exploding which is going to get a boolean value that by default will be false. When we are getting to health below zero, I want to
413:54
Speaker A
set is exploding to true and call explode. That way we are still doing all of this. After that though inside of chain reaction I only want to call drone explode if not is exploding. That way we're doing all of this only once. And
414:14
Speaker A
just to test things let me print explode once again. Although now we should only hear the sound once.
414:28
Speaker A
And that feels much better. Besides that, I guess, let me run the game again. The bullets at the moment are really, really slow. The player can even catch up to them.
414:42
Speaker A
That's an easy thing to fix. Inside of bullet, the speed should be something like 200.
414:50
Speaker A
Let's try that. And now this feels much more realistic. Besides that, inside of the level, this bin is really, really annoying. For that, we want to work on the FG layer and simply get rid of it. Then, inside
415:06
Speaker A
of BG detail layer, I want to find the bin again. It was here. And draw it in the same position like so. That way, the thing is actually in the background.
415:20
Speaker A
The last thing that you want to do for your game is to add a lot more drones throughout the level. So, this would just be distributing the drones all throughout the level while making sure that you have a fun game. I guess that's
415:34
Speaker A
a thing that you can do on your own. We have the second proper game. And at this point, you have a pretty good idea about the basics of GDU. So, just practice and see what games you can make.
415:53
Speaker A
It is time to get started with 3D game development. For that, we're going to create a basic spaceship shooter. Not the most complex game, but enough to cover 3D game development.
416:07
Speaker A
Fortunately, in good 3D mostly works like 2D in the sense that you are still placing notes and scenes. You use GDScript and signals. You're using layers. you're getting input, things like that. These concepts do not change.
416:22
Speaker A
On top of that, a lot of 2D nodes have a 3D equivalent. A sprite 2D becomes a sprite 3D. A static body 2D becomes a static body 3D.
416:33
Speaker A
A camera 2D becomes a camera 3D, and so on. This happens to a lot of nodes and makes it quite accessible. On top of that, there are loads of nodes that remain exactly the same. Timers, for example, don't care if you work in 2D or 3D. Same
416:51
Speaker A
for the animation player. It just plays an animation. It doesn't care about the dimensions. That being said, there are going to be some changes.
417:00
Speaker A
Most importantly, we are now working with a third dimension. We have X, Y, and Z coordinates for basically everything. Besides that, lights and cameras are becoming much more important. In fact, without using them, you pretty much don't get anything
417:17
Speaker A
useful. Finally, we're getting visuals from objects, not drawings. Meaning, we are going to start using 3D files with graphics and animations. Or we use GDO to create basic shapes. Both would be possible. And just to explain in a bit
417:32
Speaker A
more detail what that means, here is the character from our first game. For all of this, we are using pixels. This would be one pixel. This is another one. There we have another one and another one and so on. Somebody spent a ton of effort to
417:47
Speaker A
put all of these pixels in their position with the right color. After that, we are taking an image and if you want to animate it, we are cycling through different images. And that's all we really do. Fundamentally, we are just
418:03
Speaker A
showing different images. This is all we need for 2D. But for 3D, this obviously doesn't work anymore. For that to work, we need a different system. That system is going to look something like this, where we have a 3D object that we can
418:17
Speaker A
look at from different angles. The way all of that works is that this object is defined by a lot of different points.
418:25
Speaker A
For example, this would be a point. This would be a point. This would be a point.
418:29
Speaker A
And this would be a point. If you connect these four points, you are getting a surface that you can add a color to which would also be visible from every single angle. You can even change these points. So here is the edit mode and I
418:46
Speaker A
can drag any of these points and move them around and thereby change this object. Although not something I want to do but something I could very easily do.
418:55
Speaker A
Let me change this point. Then you can see it a bit better. We are basically creating a whole bunch of points and then connect them in a 3D space. Every single one of these points has an X, Y,
419:07
Speaker A
and Z coordinate. Along with that, each point is also connected to other points. And if these points are connected, you can add a color to them and that way you're getting a surface. That's the basic principle for pretty much any 3D
419:22
Speaker A
object. This is still a very simple object. These can get much more complex and they can also have animations, but that's not too important for now.
419:32
Speaker A
The only thing that you really have to keep in mind at this point is that we are not working with images anymore.
419:38
Speaker A
Instead, we have 3D objects. But enough with the theory. Let's work in GDO. And in this project, I already have a couple of files. We have a few audio files.
419:48
Speaker A
Those don't really matter. And inside of graphics, we have a lot of stuff. In there we have a ton of files that are usually called GB. This is the file format that you want to use the most for
420:03
Speaker A
3D game development. By that you can store 3D shapes and animations. Super handy. Although keep in mind there are alternatives but GB is the most common one. You can find all of these files inside of the description.
420:20
Speaker A
Make sure you have them ready. But for now, I just want to work in the 3D space. To get started, you want to have 3D selected at the top. That way, you're getting the 3D space. If you hold middle
420:32
Speaker A
mouse button, you can pan around. If you hold shift, you can go in the different directions. And if you hold control, you can zoom in and out. You can also use the mouse wheel to zoom.
420:46
Speaker A
It's pretty straightforward. And to create our first 3D scene, I want to create a well 3D scene. Click on it.
420:54
Speaker A
And then we are getting a note 3D. Inside of the viewport, we're getting this gizmo that you can move in different directions to change the position. We have the X-axis, we have the Z axis, and we have the Yaxis.
421:13
Speaker A
These little panels here let you move on two axis at the same time. If you click on the green one, you are pretty much excluding the Y-axis, meaning you only move in the X and the Z axis.
421:27
Speaker A
Might be a bit hard to see, but if I hold it like this, and then use the green panel, you can see it quite well.
421:33
Speaker A
We're only going in this axis. Besides that, you have these circles around it, and those let you rotate.
421:41
Speaker A
Although, for basic note, this doesn't really do anything. If you look at that transform there, you get all of the information. And now if I rotate it, you can at least see that we have a Zaxis rotation.
421:54
Speaker A
Since a node 3D is a single point in space, rotating it doesn't really do anything. In fact, all of this should be zero. You can also change the scale, but once again, I think this is straightforward.
422:06
Speaker A
This is giving us a really basic 3D space. This I want to save right away.
422:12
Speaker A
For that, I want to create a new folder. Let's call it scenes. And this should be a test 3D scene. We not going to use this one for the game. Although the naming scheme should be consistent. This is going to be test 3D. To this scene, I
422:30
Speaker A
want to add another note. So, press Ctrl+ A or on the plus icon. And then we can add a new note. And we want to add a 3D note. If you click on a drop-own menu, all of these red nodes are for the
422:44
Speaker A
3D space. If you look at the top there, you have collision object 3D and there you have an area 3D and physics body 3Ds with static body 3D, character body 3D, and rigid body 3D. Those should look reasonably familiar. If you use the
423:00
Speaker A
search function, you can also find a sprite 3D and an animated sprite 3D. And finally, we have a camera 3D as well.
423:10
Speaker A
Although that's going to come later. For now, I want to work with a sprite 3D, possibly the simplest 3D node to get started with because this is basically a 2D node in 3D space. We only have a texture like in a sprite 2D, which means
423:28
Speaker A
we can get the GDO logo, drag it in there, and then you want to zoom in quite a bit. At some point, you can see the GDO logo. With the middle mouse button, you can rotate around and well,
423:40
Speaker A
you have the good logo. If you now look at transform, all of these properties are going to make a lot more sense. If I rotate it around the x-axis or the y-axis or the z axis, you can see pretty
423:54
Speaker A
well what's going on. Same with position. X goes left and right. Y goes up and down, and Z goes backwards and forwards.
424:04
Speaker A
scale. I don't think I have to explain. This one works just as before. This would be our very first actual 3D object where we have a sprite in a 3D space.
424:15
Speaker A
Although this in practice is kind of useless. You want to have actual 3D objects which means sprite 3D can go. We basically never use it. Instead, the 3D object that most people start with is a simple mesh instance 3D. By that we can
424:33
Speaker A
autogenerate a mesh. By default this node is not visible because on the right in the inspector you have to create a mesh and there are loads of options.
424:43
Speaker A
Just choose whichever you like. I'm going to start with a box mesh. If you click on that we're getting a box. On this box on this box you can change quite a few things. For that you want to
424:56
Speaker A
click on the mesh. And then you get a ton of options. You can change the size in all three dimensions and then you get the different subdivisions along with a material. What does that mean? Well, for that you want
425:12
Speaker A
to click on perspective this menu button and then you get a ton of options under display. By default, we're getting normal, but you can also display a wireframe. And that way like we have seen just a second ago with the
425:29
Speaker A
spaceship we can see the different edges of this model. This is how this model is defined where effectively we have a point here, a point here, a point here and these three points are connected with the enclosing space being visible.
425:45
Speaker A
And this is working in 3D space. So we can look at it from any angle. And the subdivisions tell you how many points you get if I increase this number. We're getting more and more points on these different axes. Let me add quite a few
426:00
Speaker A
more. And now this model is defined by a lot more points which currently doesn't really help us very much. Since this is a very simple shape, it doesn't need that many points. So this is not necessary for our purposes. But later
426:15
Speaker A
on, for example, you might want to change these points using a shader. Something that we are actually going to do. And by the way, these points are called vertices. Sometimes you really want to have a lot of them, but not at
426:27
Speaker A
the moment. So once again click on perspective and then display normal. That way you can see the cube again.
426:35
Speaker A
Finally we have material. Via that we can change the color of this cube. Right now it's empty but I want to add a standard material 3D to it. If you do that the color already changes a bit.
426:48
Speaker A
And if you click on material again then we're getting a lot of options. The easiest one is albido. This defines effectively the color. If I change this to really anything else, we are changing the color of this object. You can also
427:05
Speaker A
give it a texture. Although this by default is going to look a bit weird. If I drag the GDO logo in there, then you can see we are getting the GDO logo. And let me change the default color to
427:19
Speaker A
white. But the model doesn't really know where to put the different parts of the image. And that should make sense. We have to give it a bit more information to place this image, a 2D image, in a 3D
427:31
Speaker A
space. By default, it doesn't know that. Although at the moment, that really doesn't matter that much. So, let's get rid of the GDU logo and just give this thing a color. I'm going to give it a blueish color. Let's add just a bit of
427:44
Speaker A
green. There we go. Bluish color. Good enough for our purposes. The other options you are usually going to use besides albido are metallic and roughness. By that you determine how light is reflected. If I change this number, you can see that this thing has
428:02
Speaker A
changed a bit. Although quite hard to see. Same as specular. We are changing the color just a bit, but not very much. That is because this property only really makes sense once you have a light, which we can add very easily. All I want is a
428:20
Speaker A
light 3D. And then we have three options. directional light, omni light, and spotlight. I want to add a spotlight.
428:29
Speaker A
Then we can see a light cone that I want to move this way. And via the red dots, you can change this thing. If you hold shift, you can change it more gradually.
428:42
Speaker A
Let's do something like this. And then move it a bit closer. Under spot, you can change all of these attributes as well. And under light, you can change the energy.
428:52
Speaker A
See how this looks. And now if you zoom in a bit, there you can see the light along with a bit of shading. I think if we go from an angle, this is going to be a bit more visible.
429:04
Speaker A
Something like this. There we go. This is much better. Now we have a cube with some light shining at it.
429:14
Speaker A
And if I go back to the cube under metallic, if I change this value, you can basically see how metallic this object is. Or in other words, how much light it reflects. Same with specular.
429:28
Speaker A
Although I guess still a bit hard to see or the proper effect, you want to have a proper scene with more reflections. But I think you get the idea. Metallic only really makes sense once you have light.
429:39
Speaker A
Same with roughness. If I change this value, you can kind of see how much light is reflected. Especially if you look at the preview, there you can see it a bit better, I think. So, if I have a low roughness, we're getting very
429:53
Speaker A
sharp lights. If I have a high roughness, the light becomes much more faded out. At least to get started, you mostly want to work with albido, metallic, and roughness for a decent look. But once you get further into it,
430:06
Speaker A
all of these other options give you a ton more stuff to work with, which can be quite nice, but also a bit daunting.
430:12
Speaker A
So go through it step by step. I guess in my case, I am not going to worry about it and simply delete the spotlight and only work with this mesh instance because next up, I want to change it using GDScript. I'm going to
430:27
Speaker A
add a script to the test 3D note. All the defaults here are fine and click on create. Just as before, we can use the basic inbuilt functions like for example ready.
430:40
Speaker A
Let me add just a bit more space and then get the mesh instance 3D and call one of the methods or work with one of the properties. For example, what we can do is rotate it along the let's do the
430:55
Speaker A
Xaxis. Then we need an angle. Let's go with 20. Something random. Once we have that, I want to run the current scene.
431:04
Speaker A
And we should see a rotated cube, but we don't. We don't actually see anything.
431:10
Speaker A
Why is that? Well, for 3D game development, you will need two important things to see anything, or at least anything useful. You will need a camera and lights. The first thing, a camera, is quite easy. All we need is to add a
431:27
Speaker A
camera 3D. Once you're doing that, you have a camera and you can see a preview on the right in the inspector. Let's say I want to move the camera a bit down the Z axis. And then in the preview, we're
431:41
Speaker A
getting something. So now if I run the scene, I should be seeing this cube rotated because of GDScript.
431:48
Speaker A
But in practice, we are getting something but not the right result. We do have the cube and the cube is rotated around the x-axis.
431:58
Speaker A
And I think rotating around the y-axis makes this a bit more straightforward. I guess you get the idea. The issue now though is that this doesn't look like anything in the preview. Let me run it again. This is what we are supposed to
432:12
Speaker A
see in the preview. But this is what we actually get. Why is there such a difference in the viewport? At the moment, we getting a preview for the sky and the lights from the editor. But in the game, this doesn't apply. This we
432:27
Speaker A
have to add manually and for that you have those two symbols where you can toggle the previous sunlight and you can toggle the environment. If you click on these three dots next to them you get a bit more information. Via that you can
432:43
Speaker A
change how the world looks. For example, for the sun color we can make it I don't know something random.
432:50
Speaker A
If you're doing that the cube is going to look different. Just pay attention to it when I change it again. If I change the sun color to really anything else, the cube is changing its color as well.
433:02
Speaker A
This can be a bit stronger or a bit weaker depending on what you need. Just imagine holding a red light next to any kind of object. That object, even if it isn't red, is going to look more red
433:14
Speaker A
because of the red light. And this we're doing in 3D space as well. By default, all of these lights are very very white because this is the most neutral option which is totally fine to get started with. Besides that, we have sun energy
433:31
Speaker A
which is also usually one or at least very very low. Then you can set the shadows and that is really all you need for the sun. Besides that, we have the environment and in there you can set the
433:42
Speaker A
sky color and the ground color which I think are fairly self-explanatory. We can change the color of the world.
433:50
Speaker A
Most of the time this is blue because well the sky is blue. I am going to stick with the defaults.
433:57
Speaker A
Once you have what you like, the important thing is that you want to add the sun to the scene and the environment to the scene. So click on both of them.
434:06
Speaker A
And then you get two more nodes, a world environment and the directional light 3D. Once those two are actually added to the scene tree, you can run the current scene again and you see a proper result.
434:18
Speaker A
The thing that we can see in the preview for the camera that we could also tell that GDScript still works just fine because we do get a rotation. On top of that, you can use things like funk process
434:35
Speaker A
to rotate it at a constant rate. Although this should be a very low number. Let's say 0.1 times delta. Although I guess we can rotate around another axis. Let's say Z.
434:48
Speaker A
If I now run the scene again, we are getting a very slow rotation around the Z axis.
434:56
Speaker A
Just as before, if you want to change any of the properties of the node, you want to look at the inspector and then go through it step by step.
435:08
Speaker A
Most of the time you want to work inside of transform and change something in there, but you could also work inside of the mesh and the material to change, for example, the albido color. If you hover over it, good is pretty much telling you
435:22
Speaker A
what you need to know. All of this we should practice for that. I want you to create a pink donut that moves to the right. On top of that, change the color via GDScript. Pause the video now and
435:34
Speaker A
see how far you get. I want to hide the current mesh instance and then add another one. From recent, I can get mesh instant. Double click on it. And I want to rename this to exercise donut. The name doesn't really
435:53
Speaker A
matter. Choose whatever you like. What actually matters inside of the inspector for the mesh, you want to have a Taurus mesh. That's effectively a donut.
436:05
Speaker A
This I want to rotate by 90° which you want to rotate it and hold control. That way you're rotating it in increments. Makes things much more easy to work with. Let's run the current scene to see how this looks. And that
436:21
Speaker A
definitely is a donut. Perfect. This donut should get a material. So we can get the pink color. Material. Standard material 3D. Click on it again. And then in albido we can give it a color something pinkish like so.
436:42
Speaker A
That looks all right. And with that we have a pink donut. To move it you want to use GDScript get the donut and then update the position position. And this is a vector 3. We have dox doy and doz at the
437:01
Speaker A
moment. We want to go down the xaxxis. So this way meaning we want to get position.x and then increase it by some amount.
437:15
Speaker A
Let's go five times delta and run this scene to see how this looks. That works reasonably well.
437:24
Speaker A
Possibly a bit fast. Let's go with two times delta. then you can see things just a bit better. I suppose what we can also do is change the rotation. I want to rotate around the y-axis and that way
437:41
Speaker A
we can see some spinning behavior. Once again, just get the property or the method that you want to get the desired result. Although one thing that can be a bit confusing is we have a mesh instance, then we have a mesh and then
437:56
Speaker A
we have a material. How can we change that? Well, for that I want to get the exercise donut. Once again, in there we can find a mesh. Inside of this mesh, we have a material, which by the way, you can also print to
438:17
Speaker A
see what you have available. Let me print it. Run the current scene again. And then we're getting a standard material 3D, the thing that we have assigned earlier. If you hover over it, you can see we have a standard material
438:30
Speaker A
3D. Also, all of this should be inside of the ready function. We only want to do this once.
438:37
Speaker A
Inside of this material, we have a standard material. As a consequence, inside of this standard material, we have the albido property. Albido color. If you have a value, you can see what GDO wants.
438:53
Speaker A
The data type here is called color. So just type color and in there you can create a color from a whole list of options. You could add simple integers in here. For example, one 0 0 and one gives you the full amount of red, no
439:12
Speaker A
amount of green or blue and the full amount of alpha. As a consequence, the donut should be red and it is perfect.
439:19
Speaker A
You can also simply get color dot and then you get some preview colors. Let's go with something a bit more interesting. I guess we can use deep sky blue.
439:33
Speaker A
If I now run the entire thing again, we're getting a bluish color. And well, with that, we can change the material color of the donut. And by the way, inside of the mesh, you could also change the inner and the outer radius.
439:49
Speaker A
That way, you would change the size of the donut. As always, just hover over the property that you want to change. GDO lets you change pretty much everything. And all right, with that we have the basics of 3D in GDO. Now we can start working on
440:05
Speaker A
the actual game. With the basics covered, we can work on the actual game. For now, I want to create a super basic floor and the actual player. The player can also move around from user input.
440:18
Speaker A
So, we are already getting something. For the player, we going to use a character body 3D, which works just like the 2D one. To move it, you want to change the velocity and then call move and slide.
440:32
Speaker A
The only real difference is that velocity now is a vector 3, meaning we need X, Y, and Z. But other than that, it don't really change that much. But before we get to that, we have to cover a few smaller things. So, let's work on
440:45
Speaker A
GDO right away. Here we have the scene from the last part which we don't need anymore.
440:52
Speaker A
You can just close it. You could also delete it. I guess I am going to leave it in just so you guys have it as well.
440:58
Speaker A
Now before we get to the player, I want to create a general game scene which is going to be a 3D scene that I want to rename to game and then save it inside of the scenes folder. Besides that, I
441:12
Speaker A
want to create another scene where the root note has to be a character body 3D.
441:19
Speaker A
This is going to be our player. Save this one as well. Same folder. That's totally fine. And then GDO is giving us a warning that this node has no shape. To change that, we have to give it like in 2D a collision shape 3D
441:36
Speaker A
and assign this one a shape. The only difference now is that these are 3D shapes. If I had a capsule shape, we're getting well a capsule. Good start. But we don't really see anything. And for that, you want to look at graphics.
441:53
Speaker A
If you open this one, you can see we have a ton of files to work with. To actually use them, you can simply grab one. Let me get the first one, barrel.glb, and drag them into the scene. Then if you find the right spot,
442:08
Speaker A
you can see we have a barrel. That's really all you have to do. Although if you look at the inspector, something interesting happened. We have a note 2D and this note 2D is a scene. Meaning you can open a scene. And then GDAU is
442:24
Speaker A
asking you if you want to create a new inherited scene or open anyway. I just want to open anyway for now. That way we can see what's actually happening. When GDO is importing this object, it creates a node 2D, another node 2D, and then we
442:40
Speaker A
get an actual mesh with the object. This is what is actually visible on the right side in the inspector. You could make a ton of changes to it, but these changes are going to be lost because this object
442:52
Speaker A
is going to be imported. So when you make changes, it doesn't really overwrite that. it's simply going to be discarded, which we don't want to do. Let's close the scene. Instead, what you usually want to do if you want to keep things
443:06
Speaker A
simple, you can either leave this thing as it is, or you could right click on it and then click on make logo. That way, you can edit all of this. And in our case, we only care about this barrel mesh. If
443:20
Speaker A
you now make changes to it, these are going to be permanent. That being said, I don't want a barrel for the main character. That would be slightly weird. Instead, I want to find craft speeder A, B, C, or D or Razer.
443:37
Speaker A
Really, whichever one you prefer for the look of the main character. If you drag in craft speeder A, you get the default spaceship. Besides that, we also have B, C, and B along with the racer.
443:53
Speaker A
which you could all use. It doesn't really matter which one you choose. It's just for the look. All the other code is going to work the same. So, choose which you like the most. I'm going to stick with craft speeder A2. This I want to
444:06
Speaker A
make local and then attach the mesh to the parent node. After that, we can get rid of these two notes. They're not necessary.
444:17
Speaker A
And then instead of craft speeder A, you want to go to transform and reset any kind of position. That way we are perfectly in the center of the scene.
444:27
Speaker A
And we have our player character. Although at the moment the collision shape doesn't line up. For that you want to rotate this thing by 90°. If you hold control and look at the bottom left, you want to rotate it 90 or negative 90°.
444:44
Speaker A
Both would be fine. Also the craft speeder A should be moved down just a bit so we are in the center of it and also the collision shape should be a bit smaller. You can either click on the
444:59
Speaker A
small red dots or work inside of the inspector and reduce the radius to 0.2 maybe maybe a bit larger. I'm going to stick with 0.2 and 2.2 or rather 0.25.
445:13
Speaker A
That's going to feel a bit better. And that looks pretty decent, at least for a very basic shape. Although, keep in mind for these collisions, the wings are going to be excluded, which is what I want, but might not be what you have
445:27
Speaker A
in mind. We're going to find better ways of dealing with this later on. For now, this is not too much of an issue. Once we have that, inside of the game, like as before, I want to instantiate a child
445:40
Speaker A
scene. If you just look for player, we're getting the scene right away. Player. And there, inside of the game scene, we have the player. On top of that, for a very basic floor, I want to add a mesh instance. And this mesh
445:57
Speaker A
instance is going to get a new plane mesh that I'm going to move down just a bit. That way, we're getting a floor. If you click on the mesh once again, you can set a size. I want to go with 100 by
446:12
Speaker A
100. And that way we getting a much larger area. Besides that, for the material, I want to have a standard material where we can set an albido color. The actual color isn't so important at the moment. Let's go with a
446:28
Speaker A
brownish color. It looks a bit spacey. I guess this one's all right. This game scene is what I actually want to run. So click on the run project and then select the current scene. After you're doing that, you can
446:45
Speaker A
see that you can't see anything. That is because we don't have a camera and we don't have lights. Adding all of that is going to be your exercise.
446:54
Speaker A
Most importantly, add lights and the camera so that the game is actually visible. Besides that, make the player move. The direction of the movement should come from data from the input map. Try to figure this one out and see
447:08
Speaker A
how far you get. First of all, we will need a camera 3D, which you could either add to the main game scene or to the player. For this game, I actually want the camera 3D to be static. So, I'm going to add it to
447:26
Speaker A
the game scene itself. Under recent, we have a camera 3D that I want to move vaguely here for now. and look down on the player just a bit.
447:42
Speaker A
Something like this just for testing purposes. Then let's run the game and we can at the very least see something to get the actual result from the preview.
447:53
Speaker A
You want to add the sun to the scene and you want to add the environment to the scene. That way I can run all of this again and we can see something that looks much much better. Perfect. That
448:05
Speaker A
covers the first part. Next up, this player should be moving from input. That means inside of project project settings, I want to create an input map or rather a couple of actions inside of the input map.
448:19
Speaker A
We have left, right. You could also add up and down, although those aren't actually used in the game, but we can use them for now. For left, I want to use A, or right, I want to use D.
448:34
Speaker A
Up is going to be W and down is going to be S. Choose whatever you want in here.
448:41
Speaker A
Whatever works for you is fine. Just make sure that you have these four actions available.
448:47
Speaker A
After that, give the player a script. The defaults are fine. Create. And then to move a physical object, you want to use physics process like we have seen before. The most important thing in here to move anything is to update the
449:03
Speaker A
velocity which now is going to be a vector 3. So once again we have x y and z. For now I'm going to set velocity x to 1 and then call move and slide. If I now run the game the ship is going to move to
449:22
Speaker A
the right. So we are getting very basic movement. That looks really good. So now we have basic movement but obviously we want to use the input map to make this much more interactive. For that I want to get bar direction which needs to be a
449:39
Speaker A
vector 2 with a default of 0 and zero which is what we are getting. And keep in mind now our direction is a vector 2 but the entire movement is a vector 3.
449:50
Speaker A
Other words, we have to convert a 2D input into a 3D movement. We are primarily going to do that by ignoring the Yaxis, meaning the ship can only go left, right, forward, and backward. It cannot go up or down. I also want to
450:06
Speaker A
have var speed, which is going to be an integer of four. I don't want to set velocity.x one. Instead, I want to get the direction. And then input.get Get vector with left for the negative x action right for the positive one negative y is
450:30
Speaker A
going to be up and positive y is going to be down like we have seen in the 2D space. Next up we can actually update the velocity and this is going to be direction times speed.
450:46
Speaker A
Delta is going to be applied automatically. So we can just ignore it. Although now GDO is going to give us an error that the value of type vector 2 cannot be assigned to a variable of type vector 3. And that should make sense.
451:00
Speaker A
This direction is a vector 2. Meaning we have X and Y values. But the velocity of this object is three-dimensional. It needs to have X, Y, and Z values. The easiest way to fix that is to target the
451:13
Speaker A
values individually. So velocity dox is going to be direction.x x time speed. Then duplicate this. And velocity dot z is going to be direction.
451:27
Speaker A
Velocity dox is going to be direction.x* speed. Should make sense. Direction.y is going to be us pressing up or down on the keyboard. And this we want to translate into forward and backwards movement in the game which is on the Z
451:42
Speaker A
axis. Remember, in the game, if you want to go up or down, you move along the Y axis, which we don't want to do yet.
451:52
Speaker A
Converting 2D input into 3D movement sometimes can be a bit confusing. So, I hope this makes sense. But anyway, let's run the game. I can move left and right.
452:03
Speaker A
And if I press forward and backward, we are getting all the right inputs. So, that is working pretty well. What we can also do is work just a tiny bit with physics inside of the game. I want to add a
452:21
Speaker A
static body 3D where we can add some kind of more interesting object. Let's go with rover. Attach it as a child. And then we are getting a rover that's admittedly a bit small that we can fix by making it local
452:42
Speaker A
getting the mesh and attaching this straight to the static body 3D. And also transform should be zero.
452:51
Speaker A
Most importantly after that the scale should be let's go with four. That way this thing is quite a bit larger.
453:01
Speaker A
Although I do want to move it forward just a bit so it's not on the player right away. Let's move it to the surface like so. And after that we can add the actual collision shape to it. And by the way like in 2D
453:17
Speaker A
we have a collision polygon and a collision shape. Although collision polygon 3D is very rarely used. You'll see in a second why. For now I want to add a collision shape 3D which is going to be a very basic box shape.
453:30
Speaker A
that at the moment is a bit too small. But this we can scale up to something like so. And so and like in 2D if you hold shift you get more granular values.
453:43
Speaker A
And if you hold alt then you are mirroring it along the axis. And that looks pretty all right. If I now run the game again I can move forward. And once we get a collision I cannot go any further.
454:00
Speaker A
And that is working pretty well. And I hope this makes sense. All of this is pretty much identical compared to 2D.
454:08
Speaker A
That being said, what if this rover was much, much larger? I want to set the scale to 20. That way, this rover is significantly bigger. And now I want to have a bit more control over the collision shapes. So, for example, these
454:25
Speaker A
wheels can't really be described by a simple box anymore. Although, let's not do the rotation. That way, all of this gets a bit simpler. What we could be doing right now is to create a box shape for all of this, like so. And that would
454:40
Speaker A
kind of work. But in 3D, very quickly, these shapes become too complex for that. So, this isn't something you actually want to do. As a consequence, I'm going to get rid of the collision shape 3D. Instead, you could add a
454:54
Speaker A
collision polygon 3D like so. And then you can add the polygon using the points at the top.
455:02
Speaker A
Although this is very, very difficult to use and I wouldn't recommend it. Let's actually not do it. A much better system would be with the mesh selected. Click on the mesh button at the top and then you can create a collision shape. Then
455:19
Speaker A
God is giving you a couple of options. Do you want to have a collision shape placement as a sibling or as a static body child? I want to have sibling. And then you can select the actual shape.
455:31
Speaker A
These give you different kinds of collision shapes with try mesh being the simplest one. If you now click on create, you do is going to create a shape.
455:41
Speaker A
That's going to be a bit hard to see, but if you look closely, GDO has created a shape that exactly meshes the shape of the mesh that was built on. Down there you can see the wheels. Up here you can
455:53
Speaker A
see the actual body a bit. Up there you have the antenna. And that way you have a perfect shape for this object. If I run the scene, you can well, this is slightly hard to see, but you can definitely see the
456:10
Speaker A
collisions are working. And that's pretty much all you have to worry about in terms of physics. Like in 2D, you have a character body or a static body.
456:20
Speaker A
Then you have something visual and you have the collision shape. And in 3D, most of the time from the mesh, you want to create a collision shape. That's the easiest and most reliable way. Now, before we finish, I don't want to have
456:34
Speaker A
this static body. That was just for demonstration purposes. Let's get rid of it. And the player shouldn't actually be able to move forward and backward.
456:44
Speaker A
You'll see later how the system is going to work. But the player in the actual game can only move left and right, which in our game is very easily implemented.
456:53
Speaker A
We simply want to get rid of velocity.z. If I now run the game again, we can still go left and right, but we can't go forwards or backwards anymore, which works pretty well. You keep things a bit more organized for all of that.
457:09
Speaker A
Direction doesn't need to be a vector 2. It can be a float. And then we don't need get vector. Instead, I want to have get axis with only left and right.
457:24
Speaker A
That way, we can use direction.speed speed right away for velocity.x the end result should be the same and it is perfect. Besides that, to make things just a bit more interesting, I want to rotate the model a bit when we're going
457:42
Speaker A
left and right. In other words, I want to change rotation doz. If I change this value for example to a two then you can see the ship is going to be rotated quite a bit. We are working in radians so a two is actually
457:59
Speaker A
quite a bit. Now in my case I want to use move toward that way. We're moving towards a value.
458:08
Speaker A
We are starting from a value and then going to a value over a certain duration which is called delta. Our starting point is going to be the current Z rotation of the model. So rotation.z the target is going to be the direction
458:26
Speaker A
which is simply going to be a value from 0 to 1. Finally, we need a speed which can just be delta. And for that there shouldn't be an underscore before delta.
458:38
Speaker A
If I now run this thing again, you can see that the ship is rotating along the Z axis, although in the wrong way. To fix that, all we need is negative direction.
458:51
Speaker A
Then we can try the entire thing again. And now the ship is rotating in the right way, although a bit too strong.
459:01
Speaker A
All we have to do for that is divide this by 2.0. Make sure you are using a float here so you don't accidentally get an integer.
459:10
Speaker A
Next attempt. And now the ship is rotating when we're going left and right in the right way.
459:18
Speaker A
That is working really nicely. Finally, I want to make the ship hover along the yaxis. Or in other words, it should go very slowly up and down. Something like this.
459:31
Speaker A
Makes the entire thing look much more realistic. All we need for that before move and slide is update velocity.
459:40
Speaker A
If I set this to 0.1, we will go up very very slowly. And this works.
459:47
Speaker A
Although we have to come down again as well. The best way to approach all of that is to use the sign function. The sign curve looks like this. We're going up and down with the highest value being a one and
460:03
Speaker A
the lowest value being a negative one. From this curve, we can sample. We could for example get this point or this point or this point or this point or this point and so on. We just have to figure
460:17
Speaker A
out where we are on the xaxxis which in our case can simply be the time since the start of the project. That way if time goes forward we start somewhere here we are going all the way to one and
460:33
Speaker A
then as time passes forward we are going to negative one then we go back up to one and so on that simply by using the time we can alternate between one and one to get the time all you need is time
460:51
Speaker A
do get ticks in milliseconds if I Try all of that. We should be seeing something. Although it does look a bit jittery. Good start though. To change the strength of this effect, you can either multiply the time that you
461:07
Speaker A
pass in as an argument or you can change the entire thing by multiplying it with some kind of value. For example, if you divide the entire thing by 500.0, make sure you always use a float in here. then you are going to move a lot
461:25
Speaker A
lot slower. And if you divide the entire thing by let's say 4.0 then we're not going to move as much anymore. And that looks pretty all right.
461:38
Speaker A
Although at the moment if you look at it it looks very very repetitive. If you want to make this look a bit more organic you can simply add different sign curves together. For example, I can copy all of this, add it to the first
461:54
Speaker A
one, and then simply make these values a little bit different. Let's say divide it by 600 and divided by 10. That way, we are combining different sign curves, which makes the whole thing look much less predictable.
462:12
Speaker A
As a result, we are getting something that looks a bit more organic. Quite hard to see, but in practice, this is going to make a difference. But anyway, I think this part has gotten quite long, so let's finish it here. To
462:27
Speaker A
get an actual game, we are going to need lasers and meteors. That's going to be the next major step. And well, at this point, we can basically do all of this already. So, let's work right away in good. Here we are. Once again, I want to
462:44
Speaker A
create a new scene where the root node is going to be an area 3D that I can rename to laser.
462:54
Speaker A
Save all of that inside of the scenes folder. Save. Then we will need the actual laser graphic.
463:03
Speaker A
This you can find inside of the files under red.gb. If you drag this in there, you can see the laser.
463:14
Speaker A
And just as before, click on make local. That way, you're getting the mesh itself, which feels a bit more organized.
463:24
Speaker A
Make sure that under transform, all of this is set to zero. Although, that being said, if the rotation is set to zero, this thing is pointing upwards, which is really not ideal.
463:37
Speaker A
In our case, the ship is facing down the negative Z axis and the laser should look in the same direction, meaning we want to rotate it 90° in that way. So, it's facing down this way away from the
463:53
Speaker A
blue arrow. If you are looking in a different direction, go with that. Finally, for the laser, we are going to need a collision shape. This can be done in a couple of ways. You can either click on mesh, create a new collision
464:11
Speaker A
mesh, sibling tray mesh and that way we are getting a very nice mesh that I think would be totally serviceable.
464:21
Speaker A
Alternatively, you could get rid of it and then create a very basic collision shape 3D with I guess a sphere shape that you can make just a bit larger and then move it to the front of the projectile
464:42
Speaker A
roughly here and then you would get a similar result. There are different ways of doing collision shapes. I think I am going to go with the first version. Mesh create new collision shape and then sibling try mesh. That one is definitely the most
464:58
Speaker A
precise one, but in many cases you don't need that much precision, especially for a simple game like this. Next up, inside of the game to keep things a bit organized, I want to add a note 3D for lasers.
465:18
Speaker A
All of the lasers that we are going to create will be children of this node.
465:22
Speaker A
And lasers are going to be created when the player presses a button. Which means instead of project project settings, the input map, we will need a laser button.
465:33
Speaker A
Could also be called shoot. It doesn't really matter. In my case, I want to look for the space button. There we go.
465:39
Speaker A
Space physical. That's all we need. After that, we have to work inside of the player character. Inside of physics process, we can simply check if input is action just pressed or laser.
465:57
Speaker A
Then we want to do something really important. At this point, we want to have the lasers inside of the game scene. But currently, we're checking for input inside of the player scene.
466:09
Speaker A
Meaning, we have to connect these two scenes. I think the easiest way to do all of that is via a signal shoot laser with one argument, the position, which always needs to be a vector three.
466:25
Speaker A
If the player presses the laser button, I want to shoot laser and emit with the global position of the spaceship. That way, we make sure that inside of the game, we always get the right position for this spaceship. Next up, we can work
466:44
Speaker A
inside of the game scene. First of all, we will have to attach a script to it.
466:49
Speaker A
As always, the defaults here are totally fine. And most importantly, I will need a var laser scene that always needs to be a packed scene by preloading laser.tscn.
467:08
Speaker A
Besides that, we want to get the player. Go to node and shoot laser and connect it to the game scene. On player, shoot laser. So, it's fine. Connect.
467:21
Speaker A
Now, we can check when the player shoots a laser inside of the game scene. Just for testing purposes, let's print a position that we are getting and run the entire thing. I can press space and we're getting some kind of position.
467:36
Speaker A
Now, we don't just want to print a position. Instead, I want to create one instance of the laser scene. I'm just going to call it laser. And this we create via laser scene dot instantiate.
467:51
Speaker A
As an added bonus, I want to instantiate it as an area 3D. That way, we're getting the autocorrect stuff, which can be handy. Just make sure that your laser is an area 3D as well.
468:05
Speaker A
If you don't have that, you're going to get some weird results. Once we have a laser scene, we have to give it a position and add it to the scene tree.
468:14
Speaker A
To add it to the scene tree, I want to get the lasers node 3D and add a child, which is going to be the laser that we just created. This should already do something. Let me run the entire thing.
468:26
Speaker A
And now, if I press space, we are getting the laser. Although if I press it multiple times, nothing is going to happen on the surface. But if you look under remote game and lasers, we're getting a whole bunch of lasers. They just happen to be
468:43
Speaker A
in the same position, so you can only really see one. Things are working, though. The final thing that we have to do is update the position of the laser by changing the position to the pause that we're getting
468:56
Speaker A
from the parameter. Once we have that, I can press space. We're getting a laser.
469:02
Speaker A
We're getting another laser. And that looks pretty good. With that, we can create lasers. That's working pretty well. Next up, the laser has to move.
469:14
Speaker A
For that, we want to give the laser a script. As always, the defaults here are totally fine.
469:21
Speaker A
And then for the laser, I want to have funk physics process. All we need for this one is to move it down one of the axes.
469:32
Speaker A
We are still pointing the negative Z direction, which means we want to update position.Z and then subtract values.
469:42
Speaker A
For now, let's go with 15 * delta. Run the scene. And now the laser should be moving in the right direction. And it is. That looks pretty good. To keep things more organized, we do want to have var speed, which is going to be 15.
470:01
Speaker A
And this should always be an integer. That way, we're getting this speed here, and things are a bit more understandable. All of this is giving us a reasonable laser. But by default, this just doesn't look very good because the
470:15
Speaker A
lasers are on top of the player and they're just way too big. To fix that, I want to scale them up when they are being created, which means I want to have funk underscore ready and then set a default
470:30
Speaker A
scale of vector 3.0. That way, the lasers are not going to be visible by default, but we can scale them up using a tween in just a second.
470:42
Speaker A
Although first of all if I run the game and create a laser good is going to be really really unhappy. That is because we're getting invert condition that is equal to zero is true. That happens when you try to scale
470:59
Speaker A
a physics object to a complete zero. If you set this instead to 0.1 and 0.1 this error is not going to happen.
471:10
Speaker A
Let's run again. And now we're getting a very very very small laser. Good enough for our purposes. I want to create a tween via create tween and then tween dot tween property with self. I want to target this scale.
471:32
Speaker A
The target value is going to be vector 3.1 and the duration can be 0.4 seconds. The default scaling of the laser is going to be 0.1, but afterwards via tween, we are scaling it up to a size of one over a
471:49
Speaker A
duration of 0.4 seconds. That is going to make the entire thing feel much much nicer. What you could also do inside of the game when you're setting the position, you can add just a bit of an offset by simply adding a
472:05
Speaker A
vector three where we have to set X, Y, and Z. Once again, you want to make sure you are on the right axis. We want to offset this laser by some negative amount on the Z axis.
472:19
Speaker A
X is going to be zero. Y is going to be zero. And Z is going to be for something strong -10. That's going to be way too much. But you can see we are at least going in the right direction.
472:33
Speaker A
If I change this to a -1, we have a much more reasonable offset. I guess this could be a -2. Possibly a bit too much now.
472:47
Speaker A
Yeah, definitely too much. But play around. This could be negative 1.2. That way looks a bit better. We are actually nearly done with the lasers. The one final thing I want to do for them is that they should disappear at some
473:05
Speaker A
point because at the moment we can create lasers indefinitely and they would never disappear again. If the game is running too long, this means we have more and more objects. Not great. A very simple way of fixing that would be to
473:20
Speaker A
check if position. Z is greater or equal to let's say for now. So we can see something 15. If that is the case, we want to get rid of the laser.
473:34
Speaker A
If I now inside of the game shoot a laser, the laser should disappear at some point.
473:42
Speaker A
And it does not because the Z values are getting smaller and smaller. So instead of being greater than, we want to check if they're smaller than -15.
473:53
Speaker A
Next attempt. And now the laser disappears roughly around this point. The negative numbers here do get a bit confusing. If you want to have this more organized in your game, you might want to rotate all of this around the Z or the Xaxis.
474:11
Speaker A
I think for our purposes, this is still good enough. Although this number needs to be much larger than -15 or well much smaller. So let's go with -200. So it's going to take a while for the laser to
474:23
Speaker A
disappear and the player's not going to see it. Perfect. That covers the lasers. Next up, we have to create the meteors.
474:32
Speaker A
This part is going to be your exercise. I want you to create the meteors and spawn them via a timer. Every time the timers out, create a new meteor and then move that meteor towards the player.
474:46
Speaker A
You can add some randomness to it, like a bit of a random direction or rotation.
474:51
Speaker A
Just see what looks good. You can find the meteor graphic inside of the resource folder and the root node should be an area 3D like the laser. Pause the video now and see how far you get.
475:05
Speaker A
First of all, I want to create a new scene where the root node is an area 3D.
475:12
Speaker A
Let's rename this right away to meteor as a child to it. You could look for meteor inside of the resource folder. It is there. We have meteor and meteor detailed along with meteor half.
475:26
Speaker A
Although I only want to use the meteor itself. You could add this right away or you could attach a child scene. If you look for meteor, you can find meteor.gb the imported graphic. Both would work.
475:41
Speaker A
There we have a meteor. And just as before, I want to make this thing local.
475:47
Speaker A
Attach it to the root node. Get rid of the node 3DS. and then reset the transforms. That way we are getting a meteor although I want this to be in the perfect center which I have done by changing the transform Y to0.3.
476:06
Speaker A
After that we will need a collision shape and I guess we can do the usual thing. Go to mesh create collision shape sibling try mesh and that looks really really solid. Although keep in mind here the collision is basically a sphere.
476:23
Speaker A
You could get away with much fewer points which would be good for performance. Not an issue for our game because it's so simple performance will not matter.
476:32
Speaker A
But for a more complex game, you would want to keep as few vertices as possible. The fewer you have, the easier your game will be to run. Once we have all of that, save the scene as meteor.tsn and then we can work with it. to
476:47
Speaker A
actually use it. For now, I want to attach one instance of the meteor. And make sure you have meteor.tsn, not meteor.glb. That is the wrong one. I want to add meteor.tsseen.
477:01
Speaker A
And then we want to move this thing just a bit forward so we can see it inside of the game. Now we can run the whole thing. And we are getting a meteor. That looks perfect. Next up, to animate this
477:16
Speaker A
meteor, we want to give it a script. The defaults here are fine, just as usual.
477:22
Speaker A
And for the most basic effect, I want to create funk physics process where we are updating position.
477:32
Speaker A
Z. We want to move towards the player. So, I think this should be plus equal some kind of speed. Let's go with two for now. is we have to multiply with delta. After that in the game we're getting the meteor moving towards the
477:49
Speaker A
player. That is working pretty well. For better organization I want to create var speed with a default value of two. And I want to have var direction underscore x. That way we are going slightly left or right when the meteor is moving. And this
478:10
Speaker A
should be some kind of float. that we will set in just a second. Whenever this meteor scene is ready, I want to update direction.x and set a random value which we get via rand f range where I want to go from0.1
478:30
Speaker A
to positive0.1. A very small amount here is totally fine. After that this value should actually be used in my case position dot x plus equal direction dox multiplied with delta. That way we are very very slowly going left or right on the
478:54
Speaker A
xaxxis. Let's try. And we can't really see very much. These values might be a bit too small. Let's go with -1 to 1.
479:07
Speaker A
And that is looking much more random. One more attempt. That works. While you're here, you can also do things like rotate X with some kind of speed. Let's go with 1.5 time delta. That way, this thing is going to
479:28
Speaker A
rotate. Makes it feel much more organic. You can do the same thing for rotate.z.
479:39
Speaker A
And that way we're getting a lot more rotation. These are fairly small things. If you want to customize them, just play around a bit more. But for now, they're not too important. What actually matters is that inside of a game, we are
479:53
Speaker A
spawning meteors when a timer times out. For that, I want to add a basic note.
479:59
Speaker A
Rename it to timers. and then attach a timer note that should be called meteor timer. The iteration for this one is going to be 0.25.
480:13
Speaker A
It should auto start and it should not be one shot. We want this thing to run over and over again. I want to connect the timeout signal to the game scene.
480:22
Speaker A
Connect. That is totally fine. And then do pretty much the same thing that we have seen for the laser bar. Meteor scene. We want to create a packed scene and then preload the meteor.tssemn scene. Once again, make sure that you're
480:43
Speaker A
getting scenes meteor.tssem. You do not want to get the GB file. After that, once the timer types out, I want to create var meteor via meteor scene.stantiate.
480:57
Speaker A
[Music] After that, we have to find some kind of parent container for all of the meteors.
481:05
Speaker A
And I suppose what we can do is add another node 3D with the meteors.
481:14
Speaker A
You could actually have the same parent container for the lasers and for the meteors would be fine. I guess we can actually do that. Let's get rid of the meteors and rename lasers to projectiles.
481:28
Speaker A
Make sure then you are adding the lasers to the projectiles like so. They shouldn't be lasers anymore. And then we can use projectiles once again and add a child that is going to be a meteor this time. Keeps things just a bit more
481:44
Speaker A
organized. Then we can get rid of the meteor that we have just added. Run the scene again.
481:52
Speaker A
And now we're getting a whole bunch of meteors whenever the timers out. Good start. Although we might have to update the position of the meteors when they are being spawned just a bit. When a meteor is ready, I'm going to set
482:09
Speaker A
position Z to some large negative value. Let's try 30 for now. That way should already look a lot better inside of the game. Now the meteors start from much further away.
482:25
Speaker A
We're going to fine-tune all of this later on. So, don't worry too much about it for now, I guess, so we can see something. Let's set this to -10.
482:33
Speaker A
That way, we can actually tell what's going on right away. And that looks okay. Besides the position, I also want to change the scale to some slightly more random value. Before we're getting to the scale, I want to create var
482:50
Speaker A
random scale which we can get via rand f range with a value that goes from 1 2 3.
483:02
Speaker A
Then the actual scale is going to be a vector of three with the random scale for x, y, and z. So random scale, random scale and random scale.
483:16
Speaker A
That is going to make the meteors look much more different. And now we are getting different scales.
483:24
Speaker A
That is going to look quite a bit nicer. I suppose the final thing that we can change is the speed. This one should also be a bit more random.
483:35
Speaker A
Speed is going to be rand f range. let's say between three and five. And for that to work, this speed doesn't need a default value of two for the integer.
483:48
Speaker A
Instead, I just want to have a float with a default value of zero. We overwriting all of this anyway in the ready function. So, the default value doesn't really matter. Final attempt. And now the meteors should move at different
484:03
Speaker A
speeds. And they do. That looks fairly all right. And you could have randomized the rotation a bit, but I'm not too concerned. I think we have all of the important parts. So now we have the meteors and we have the lasers.
484:17
Speaker A
Lots of progress. Next up, we are going to work on collisions between the player and the meteors and the lasers and the meteors. While doing that, we are also going to work on a very basic flash shader effect. Let's get started right
484:32
Speaker A
away. Here we are in GDO. And for now I want to check the collision between the lasers and the meteors.
484:40
Speaker A
Both of these are area 3Ds. So one of them can be used via the signals. Check for area entered. That way we can connect the two fairly easily. Although first of all we should go to project project settings
484:59
Speaker A
3D physics and then set some physics layers. I want to have terrain, player, lasers, and meteors.
485:12
Speaker A
That way, all of this is much more organized. The player is going to be on collision layer 2, I think. Yep. And can see the terrain and the meteors. Nothing else needs to be visible. The lasers are going to be
485:30
Speaker A
on the laser layer, obviously. and they can only see the meteors. The other way around for the meteors, they are on the meteor layer and they can only see the lasers like so. That way we don't get any accidental collisions
485:47
Speaker A
which is quite nice. Next up, I am going to keep the logic for collisions organized inside of the meteors. Meaning in there I want to have a signal for area enter.
485:59
Speaker A
Click on connect and then we can write some code. For now, when an area entered, I want to simply print the area to check if this is working in the first place. Let's run the game. And if I
486:13
Speaker A
shoot a laser at a meteor, we don't get anything. So, something went wrong. Although, we are getting a debugger warning. Soft static collisions between two concave shapes are not supported.
486:27
Speaker A
In other words, the current shape of the meteor and the laser don't work together. GDO simply cannot check a collision here, which arguably is a bit annoying. But the way to fix that is for the collision shape. We have a concave
486:42
Speaker A
polygon shape. Same for the meteor where we also have a concave polygon shape. And for some reason, these two cannot be checked for collisions. The way around that is for the meteors in our case to get rid of the shape and then create a
486:58
Speaker A
new shape for sphere which we can just move up a bit and then scale it down a tiny bit so it fits just right like so. If you do the same thing now I can shoot a laser and we get the
487:16
Speaker A
expected result. That looks pretty good. For these kind of issues, you really want to read the debugger. That way, you know what's going wrong. Otherwise, this is going to be super confusing. And I realized I forgot one thing for the
487:29
Speaker A
meteors. The meteors should see the lasers and the player, obviously. Now, fundamentally, what we want to do once there's a collision, we want to Q3 the meteor and we want to Q3 the laser, which is going to be the area
487:47
Speaker A
3D. If I try this now, I can shoot at the meteors and stuff disappears.
487:53
Speaker A
Although it's not really satisfying. I guess it kind of works. To make this a bit more interesting, we can add a timer. For that I want to first of all stop the movement once this function has run which we can do by
488:09
Speaker A
adding another variable can underscore move which is going to be a boolean with a default value of true.
488:18
Speaker A
After that into the physics process we want to all of this only if the meteor can move and once an area has entered can move should be false and for now let's focus on the meteor this one should disappear
488:38
Speaker A
but it should only disappear after a short amount of time for that we can either create a timer or we can use a wait get underscore tree and then create a timer in GDScript. One argument in here is going to be the duration which I
488:55
Speaker A
want to set to 0.4. Then we have to wait for the signal that is called time out. That way we are waiting 0.4 seconds to run this line.
489:07
Speaker A
After that I can wait for a meteor shoot a laser. The meteor stop moving and after about half a second they disappear.
489:16
Speaker A
That looks pretty all right. Although the laser should also stop moving. To keep that one organized, let's create a function inside of the laser.
489:26
Speaker A
Which means area which is going to be the laser. Let's call it destroy. That means inside of the laser we will need funk destroy.
489:37
Speaker A
No need for parameters. And fundamentally we want to do the same thing that we have seen inside of the meteor. Basically all of this.
489:47
Speaker A
Let's paste it in there. And we have to create can move var can move a boolean default is true. And then the movement should only happen if can move is the case. Like so. If I now run all of this,
490:06
Speaker A
I can shoot a laser. We get an error that we try to call the function destroy in base previously freed on a null instance.
490:16
Speaker A
That happened because of a silly mistake. Just think about these four lines of code and I think you might be able to see it already. Let's go through it step by step. Number one, we set can move to false. So none of this happens
490:30
Speaker A
anymore. That part is totally fine. Then we wait about half a second, destroy the node, and then call a function on another node.
490:41
Speaker A
There are two issues here that are pretty bad actually. Number one, the most obvious one is that we are destroying this node on this line, meaning nothing else afterwards is really going to be run because the node has been destroyed. And that, by the
490:57
Speaker A
way, is the error message here. This one should definitely come before Q3. That way, we are calling a function on an existing node, which is what we have to do. But on top of that, this line should come before a wait.
491:12
Speaker A
We want to stop the laser right away. We don't want to wait half a second. That would be kind of weird.
491:19
Speaker A
But once we have both of those, I can run the code again. Shoot at the meteor.
491:23
Speaker A
And now we can destroy meteors just fine. And if there's a bit more space between them, this would also look better. We'll work on that in just a bit.
491:33
Speaker A
For now, I'm reasonably happy. Although to make all of this look much nicer, I want to add a shader to make the meteor and the laser flash in white once there's a collision. For that, we have to work on shaders, specifically inside
491:49
Speaker A
of the mesh. That's the only visible part of the scene. And when it comes to 3D stuff, there are multiple ways to add a shader. Actually, if you click on the mesh, there you have surface and there you
492:03
Speaker A
have a material. to this material, you could add a new shader material. That would be one way. Besides that, if you look under surface material overwrite, you can add a surface material override. The name explains itself. Finally, instead of geometry,
492:20
Speaker A
you have a material overwrite and a material overlay. I think the difference between them makes sense. The overwrite overwrites the current surface. The overlay doesn't get rid of it, but it lays something else on top of it, which
492:33
Speaker A
is actually what we want to do. So, in material overlay, I want to create a new shader material. Then, we get the usual stuff. We want to create a new shader.
492:45
Speaker A
We want to create a base shader. Now, the mode has to be spatial. And then, we need a name. The name should be flash shader because this shader should be applied to the meteor and to the laser.
492:58
Speaker A
Also, I guess what we can do is create another folder with shaders. Not necessarily needed, but I think it's good practice. After we have that, create.
493:10
Speaker A
And then the meteor becomes pure white, which is the expected behavior. So, all good so far.
493:18
Speaker A
After that, we're getting the usual stuff. We have a vertex shader and a fragment shader. For now, we don't need the vertex shader whatsoever. we can get rid of it entirely. We also don't need the light shader. We only want to work
493:32
Speaker A
inside of fragment. Unfortunately, 2D shaders and 3D shaders are quite different. For example, in a 2D shader, you can simply set the color, which doesn't work in 3D. For that, for the color, you want to target albido, which
493:48
Speaker A
wants to have a vector three with some kind of value. If you set this to 1, zero, and zero, then you are going to get a red color. We have the full amount of red, no amount of green, and no
494:01
Speaker A
amount of blue. If you want to look more into this kind of shader thing, the best way to get started, I think, is to look at the material and then you basically get the names that you want to target
494:13
Speaker A
from all of these parameters like albido, metallic, roughness, and so on. Speaking of which, the next part that we want to target is going to be alpha, which is simply called alpha.
494:27
Speaker A
This value is a very simple float. If you set this to 0.0, don't forget the semicolon. Then we get the base color.
494:37
Speaker A
But this only applies because we are adding a material overlay. If you have material override, the entire thing would be invisible because we are hiding the actual texture. But now we are only hiding the overlay. So I hope that part makes sense. Anyway, for
494:54
Speaker A
this shader, all I really want to do is to create a uniform float progress with a hint range of 0 to one with a default of 0.0.
495:10
Speaker A
This value is then going to give us the alpha value. So progress in here. And the actual color that I want is going to be 1.0 for RG&B. Meaning we're getting a pure white. Once we have that inside of
495:24
Speaker A
the shader, we have shader parameters progress. And by that we can toggle a white flashy kind of thing which we can then use when there's a collision. So on area entered before we are awaiting the timer I want to get the meteor on the
495:44
Speaker A
meteor I want to get the material overlay really important don't get overwright and in there we can set shader parameter of progress to 1.0 zero. That should be it. If I now shoot a laser, we are getting a white flash. Although
496:06
Speaker A
now we are making all of the meteors white. Not exactly ideal. To fix that, all we have to do is under resources local to scene and then this should be fixed. Next attempt. Now some meteors become white but
496:23
Speaker A
the others keep the same color. Perfect. With that, we have the basic logic for the meteors.
496:32
Speaker A
The same thing I want to do for the lasers. They should also flash up from a shader. That part is going to be your exercise. Apply the flash shader to the laser and trigger it when there's a collision like you have seen for the
496:46
Speaker A
meteor. Pause the video now and see how far you get. inside of the laser. First of all, we have to apply the shader to this mesh which is called red. I suppose we could rename it to something a bit more
497:04
Speaker A
descriptive. Let's call it mesh. Fairly minor part. The actually important bit is under geometry we have material overwrite. In there we want to create a new shader material and for the shader we want to quickload the flash shader.
497:21
Speaker A
That way under shader parameters, we can toggle progress and change the color super efficiently. That looks good.
497:29
Speaker A
That's all we need in here. Next up, inside of the laser in the destroy method before weight, we want to do the same thing we have done for the meteor, which means we can copy the line and then call it like so, except meteor
497:46
Speaker A
should be mesh. That's pretty much it. Let's see if this works. And that looks pretty good.
497:57
Speaker A
The game is slowly coming together. The meteors need to spread out quite a bit, but that we're going to work on in just a bit. Next up, I also want to check if there's a collision between the ship and
498:09
Speaker A
the meteors. If that is the case, we're going to shut down the game. That way, we don't have to worry about UIs or resetting the game. That keeps things a lot more simple. Inside of the meteor, we want to check the signals and then
498:23
Speaker A
look for body entered. This we can connect to the script at the bottom. And well, basically there's only one body that could be entering, which should be the player.
498:38
Speaker A
Let's try print body. And now once there's a collision between the player and the meteors, we should get something printed out. And we do.
498:48
Speaker A
That is working beautifully. We should be renaming this parameter to player. And we are expecting a character body 3D. Makes the code just a bit clearer.
499:01
Speaker A
That being said, we don't actually need any of this. All we want to do inside of this function is end game, which we can do via get three and wait. Next attempt.
499:14
Speaker A
Let's wait just a second. And there we go. The game ended. With that, we have the very, very basic setup. There are a few major parts that we have to work on. Number one, the camera needs to look at the different
499:30
Speaker A
angle. Number two, the meteors need to spread out quite a bit. And number three, we can add a couple of things to the ground so we have some obstacles.
499:42
Speaker A
Makes everything look just a bit better. These are also going to be collidable. So basically we have a few more projectiles back inside of the game.
499:51
Speaker A
Most importantly for now the camera needs to look much further down so we can't see the horizon.
499:59
Speaker A
For that we want to look at transform and first of all move the camera up quite a bit. I went with 6.5.
500:08
Speaker A
That means we can see the horizon quite a bit more. So we need to rotate this thing a lot more. For the X rotation, I went with negative 45. And that way, this is already looking quite a bit
500:22
Speaker A
better. To make this look just a bit more interesting, we can rotate the camera around the Yaxis to something like this. Let's see how that actually feels inside of the game.
500:36
Speaker A
And I think that is working reasonably well. You can also change the Z rotation a tiny bit.
500:46
Speaker A
That's the blue line. So you get just a bit of a very slight rotation there.
500:52
Speaker A
This should be a very low number. Something like 0.5. Otherwise, it's going to feel very very strange. Let's try.
501:03
Speaker A
And didn't do very much, which I guess is fine. For the most part, you want to work with the X and the Y rotation. Also, while looking at this, we do have these corners here where we don't have a
501:16
Speaker A
background. That is quite easily fixable. We just have to move this thing a bit forward. Then look at the camera.
501:25
Speaker A
And nearly there. Move it over a bit here. And well, I guess we can make it a bit larger.
501:36
Speaker A
30 in both dimensions. That should cover it. Not quite bit over here. There we go. Now we have covered the entire floor.
501:48
Speaker A
And that is working pretty well. Obviously now the entire floor looks incredibly boring, but that we can fix as well. First of all though, the meteors need a better start position.
502:03
Speaker A
Right now they start in this one point which looks really really silly. At the moment we are spawning the meteors and they're always spawning in the same position. That shouldn't be the case.
502:14
Speaker A
And for that we can work inside of the meteor specifically in the ready function. We are setting a Z position of -10 and that's the start point. This number should be quite a bit lower.
502:28
Speaker A
Let's go with -40. That way they should spawn outside of the window. That looks about right. And on top of that, we want to give them a random X position. Position.x is going to be rand F range between -10 and 10.
502:48
Speaker A
Let's see how that looks. And now we have a good bit more spread. This could even be more spread out.
502:57
Speaker A
Let's say 20 to5. [Music] And that is looking reasonably okay. Obviously, you can fine-tune all of this quite a bit, but I am happy with that.
503:17
Speaker A
Once the game is running for a bit, the player is not going to know. So, this is pretty all right. And now if you hit individual meteors, you get a much better effect. Before continuing, I forgot one thing. At the
503:34
Speaker A
moment, we keep on creating new meteors and the meteors never disappear. That shouldn't be the case.
503:41
Speaker A
We could fix that like we have fixed the lasers. Or in other words, we can check if we are crossing some kind of position and then call Q3. Alternatively, for the meteors, once they leave the screen, we can also destroy them.
503:58
Speaker A
For that, we can add a visible onscreen notifier 3D8. This thing is going to have a shape.
504:07
Speaker A
Doesn't need to be too precise, but we do want to cover the meteor reasonably well. Something like this. And on this note, we can get screen entered and screen exited. Once the meteor leaves the screen, we can let's for now simply print that
504:27
Speaker A
this is working. I want to print. Meteor exits. Getting a result from this one is going to take a second. I am probably going to speed up the video just a bit.
504:43
Speaker A
Righty. This meteor should trigger the first signal. And there we go. Now we start to get lots of meteor exits. This is working.
504:51
Speaker A
which means all we have to do in here is call Q3 and that way the meteor is going to disappear as soon as it leaves the screen.
505:01
Speaker A
Different ways of doing that both would be fine. We could have done the same to the lasers would be a bit cleaner I guess but for this kind of game it just really doesn't matter.
505:12
Speaker A
And all right that is already cleaning up the game a lot. Next up, the game at the moment looks incredibly empty that we have to work on. And for that, I want to create obstacles for this scene. The root note
505:28
Speaker A
is going to be an area 3D. Let's rename it to obstacle right away. Save the entire thing. And then we have to give it a collision shape 3D so good stops complaining. For now, I want to work with a box shape.
505:49
Speaker A
We're going to refine this in just a second. First of all, though, the actually important bit is going to be that we want to pick a whole bunch of graphics and show one of them at random.
506:02
Speaker A
So, for example, we want to have a couple of rocks, a rover, a satellite dish, and a few more objects inside of this scene. And then once the scene is ready, only show one of them. For that, I want to add a note 3D
506:17
Speaker A
with the actual meshes, the shapes that I went with. And the easiest way to get them is by using the filter. I want to have a rock. Let's simply drag it in there and make sure it's reasonably centered. This one looks all right,
506:33
Speaker A
although it should be part of meshes. Like so. Besides that, we have rock crystals. Drag this one in there. And then we're getting basically the same skin except with crystals which should be in the origin as well vaguely here.
506:49
Speaker A
This doesn't have to be too precise. Although make sure that you only move it on the X and the Z axis. It shouldn't go up or down. Besides that, we have the rover. This one should be part of the
507:02
Speaker A
mesh as well. Like so. Move it to the origin point vaguely. Next up, I want to have a satellite dish. And there are quite a few. Let's go with large. That looks pretty nice.
507:17
Speaker A
Once again, needs to go into the origin point. Finally, to add one more mesh, you can instead of dragging stuff in, simply instantiate a child scene. The one that I'm looking for is called tit double. Drag this one into the center as
507:34
Speaker A
well. And there we go. Now we have a whole bunch of objects that we can select quite easily from the meshes. We just have to get the children. Although first of all, the collision shape should be at least vaguely fitting here.
507:52
Speaker A
This part isn't going to be too important. So I'm not going to be too precise here. But what you can do is first of all get the front view and then move the collision shape to roughly fit all of these shapes. Make sure that this
508:07
Speaker A
shape is fairly small. The bottom part doesn't actually matter. And for the top part, we can put it vaguely here.
508:17
Speaker A
Besides that, we can look from the right and make sure that this thing isn't too long. put it to something like so.
508:29
Speaker A
That way, we have a reasonable shape that mostly covers the area. Obviously, for a real game, you want to have a shape for every single one of these meshes. That works a lot better. But that would take too long for this
508:40
Speaker A
tutorial. Instead, I want to spawn a whole bunch of these obstacle on the map to make the entire thing look much more populated. This should happen on the tick of a timer, which means I want to add another timer.
508:56
Speaker A
Let's call this one the obstacle timer. It's going to have a wait time of 2 seconds and it should auto start.
509:05
Speaker A
I suppose we can connect the timeout signal right away to game. Most importantly, we need to have this scene ready inside of the game scene.
509:15
Speaker A
Which means, like we've seen for the meteor and for the laser, I want to have an obstacle scene, which we get via scenes and obstacle.
509:27
Speaker A
After that, once the timer times out, I want to create a random amount of these obstacles that we can do via a for loop for I in rent I range. I want to create between three and six objects. This we
509:44
Speaker A
can do in the usual way. We have obstacle is going to be obstacle scene dot instantiate.
509:52
Speaker A
Next up, we have to add that to a note. Meaning we have to find a parent. And once again, we can add all of this to projectiles because effectively those are projectiles. Maybe not the greatest name, but it's good enough. So to that,
510:06
Speaker A
we want to add a child, which will be the obstacle. If we now run the whole thing, let's see what happens.
510:18
Speaker A
We are getting obstacles right on top of the player. That is at least something.
510:26
Speaker A
And also make sure that for the obstacle timers, auto start and wait time are enabled. So you get this kind of thing constantly. Now at the moment, this isn't too visible because we always spawn things in the same place. Not
510:41
Speaker A
great for that. We want to go back to obstacle and then add a script to it. So we can randomize things a bit. As always, the defaults here are totally fine. create and then once the scene is ready bunk
510:59
Speaker A
ready I want to do a couple of things let me add pass for now number one I want to randomize the scale between one and three meaning we can have the default scale or scale up by a factor of three and find some kind of
511:17
Speaker A
float between those values then I want to have a random rotation around the yaxis.
511:26
Speaker A
That one should be straightforward. And finally, as a separate function, I want to set the x z position with x and z as an argument. And this we are going to call from the game class after we created one of the obstacles.
511:44
Speaker A
That's going to become important later on. But for now, there are three things that we need to do. This is going to be your exercise. Randomize the scale and the rotation of the obstacle once the scene is ready and create a function for
511:57
Speaker A
the X and Z position. Pause the video now and see how far you get.
512:05
Speaker A
Let's start with the really easy part, the function to set the XZ position. And I should be a bit more organized here.
512:14
Speaker A
For both data types, we are expecting a float and nothing else should be accepted. All we have to do in here is position.x is going to be x and position dot z is going to be z. That way from inside of
512:31
Speaker A
the game class we can call obstacle dot set xz position with some kind of value. Let's say for now zero and -5. That way all of the obstacles should be spawned a bit further in front of the player. And if
512:51
Speaker A
you write the name of the function properly, this is also going to work. Let's try again.
512:56
Speaker A
And now we get the obstacle a bit further in front of the player. That worked. Besides that, for the ready function, I want to update the scale.
513:06
Speaker A
And this has to be a vector three. Well, we want to have values for X, Y, and Z.
513:12
Speaker A
And all three of those should be the same. I think the easiest way to approach that is to create another variable. Let's call it scale random which we create with rand f range where we go from 1 to three. This value we
513:29
Speaker A
then plug into x y and z like so. That way we keep the scaling proportional.
513:37
Speaker A
That should actually be all we need. Let's try. So now we should be getting obstacles that are different in scale and that definitely worked. The first one was really large so it's a bit hard to see but this worked. That covers the
513:52
Speaker A
first part. Next up a random rotation around the yaxis. All we need for that is rotate y and then a random range. Once again rand f range and the values here go from zero to toao. tow is simply 2 * pi and rand f
514:13
Speaker A
range is working in radians meaning the full range goes from 0 to 2 * pi in other words this covers the full rotation and finally one thing I forgot to mention is that at the moment we have five children and we only want to make
514:30
Speaker A
one visible this could be an extra challenge if you want to figure it on out pause the video now and try to only make one of those visible once the scene is I want to get all of the meshes
514:47
Speaker A
and then get the children. This is going to return an array with all of the children from which we can pick one at random and this we want to show.
515:02
Speaker A
For that to work though, we have to make sure that by default all of them are invisible. Like so. with that. Inside of the game, we should only be getting one object. And this kind of worked. The reason why it looks weird is that inside
515:18
Speaker A
of the game, we are spawning between three and six objects at the same time.
515:22
Speaker A
Meaning, even if we only have one of those visible, we still see multiple. We're going to fix that in just a second, but for now, inside of the obstacle class, we have nearly all that we need. The one additional thing that I
515:36
Speaker A
want to do inside of the game, the floor should be a bit further down.
515:43
Speaker A
At the moment, in my case, the Y position of the floor is 0.9 or negative 0.9 to be specific. The floor is a bit further down compared to the player.
515:55
Speaker A
This, I think, should be lower. Let's go with -2. That way, there's a bit more space between the player and the floor.
516:02
Speaker A
This however means at the moment for the obstacles that they are floating. This we should really fix and for that we will need position doy and this should be -2 or whatever value you set for the floor of the game. And
516:17
Speaker A
by the way this mesh instance should just be the floor. Makes a bit more sense. Let's try off this now. And now the obstacles shouldn't be floating anymore and they're not. That looks all right with that. Finally, we can randomize the
516:36
Speaker A
position of the obstacles via the set XZ position. In my case, for that I have created another variable called game size and this tracks the scale of the game which is going to be a dictionary.
516:55
Speaker A
In there we have the left side. We are going to have the right side.
517:03
Speaker A
Then we have front and finally we have back. The left side in my case is -15.
517:11
Speaker A
The right side is positive 15, the front is -2, and finally the back is 40. Effectively inside of the game, this area is all of this bit here. And we want to spawn an obstacle inside of this area.
517:33
Speaker A
Although we do have to be careful. These obstacles should be like the meteors at the top end of the window. In other words, first of all, I want to cover the X part of the function. I want to have
517:48
Speaker A
rand f range where we go from the game size dot left and then game size and right. That way we are going left and right. This we can duplicate for the Z values.
518:06
Speaker A
And let's say just to get started I want to go from the front to the back. That way, we are spawning an obstacle in the entire available range, which isn't actually what we want to do, but let's try.
518:23
Speaker A
Now, we're getting some obstacles here. We're getting some there. That looks pretty all right.
518:29
Speaker A
The problem is these shouldn't just pop in and start existing randomly inside of the game. They should start at the top of the game and then move down. Just like the meteors, I want to have game size and back
518:43
Speaker A
for the first value, for the second value, game size. Plus five. That way, they all spawn in the back, which at the moment isn't ideal because they should also be moving cuz remember the spaceship itself doesn't actually move. We are simulating
519:01
Speaker A
movement by having the meteors and the obstacles moving in this direction. Which means the obstacles will also need a funk physics process in which we are updating their position specifically position.z and let's keep it simple plus equal 2*
519:23
Speaker A
delta. That way they should be moving. And let's try all of that. Now we should be having obstacles coming towards the player. And that looks okay.
519:35
Speaker A
Once we have a bit more stuff here, this is also going to look a bit more realistic. But I think this is working decently well to make all of this feel even better. What we can do once the
519:48
Speaker A
game scene is ready, and let's do this all the way at the top. Bunk underscore ready. I want to create loads of obstacles. We can simply copy this for loop like so and then spawn between let's say 50 and 60 obstacles
520:07
Speaker A
and those should cover the entire available range. Meaning we want to go from the front to the back. That way if I run the whole thing again we are getting right at the start a whole bunch of stuff and that way the game looks a
520:22
Speaker A
bit less empty. And that is working pretty well. Cool. Not perfect, but I think for a basic game, this is good enough. The last minor thing that I want to do is if the player happens to collide with an
520:42
Speaker A
obstacle, the game should still end. Which means first of all for the obstacles, we have terrain. and for the master the player. If that is correct, we can check for body entered. And if that is the case, we can simply get the
521:00
Speaker A
tree and quit the game. Now, this is going to be quite rare because all of these meshes are fairly far down, but the player should still be a little bit careful. So, we are nearly done. In the next part, we have to add sounds and
521:16
Speaker A
work on a very small shader. But other than that, we are pretty much good to go.
521:22
Speaker A
It is time to finish up the game. There are three major things that we need to do. Number one, we have to add sound.
521:30
Speaker A
Number two, we have to clean up some very small things. And number three, I want to add a floor shader. That way, we get a proper terrain at least somewhat.
521:40
Speaker A
All of this we can start with an exercise right away. I want you guys to add the sounds to the game. There are three that you want to add for lasers, collisions, and the background. This is going to work like in a 2D game. Just
521:53
Speaker A
keep in mind an audio stream player 2D will become an audio stream player 3D.
521:57
Speaker A
Other than that, nothing really changes. So, pause the video now and see how far you get.
522:06
Speaker A
Here we are in the project. And if you look at the audio folder, we have three files. Explosion, laser 8, and spaceship. These we want to play at specific instances. For example, when we are shooting a laser, I want to play the
522:19
Speaker A
laser sound, which we can do very easily by adding an audio stream player 3D. And then we get the usual stuff where we want to play an audio stream.
522:31
Speaker A
This should be laser 8. And if you play it, you get a laser sound. You can also change the volume. It's pretty straightforward. We play this thing inside of the script when we are creating the laser. So inside of ready,
522:48
Speaker A
we also want to get the audio stream player 3D and play it. That's literally all we have to do. If I now run the entire game and shoot a laser, it works pretty well. When the laser hits a meteor, I want to play
523:04
Speaker A
explosion.wav means to the meteor I want to add an audio stream player with explosion.
523:12
Speaker A
Let's see how that sounds. Pretty loud. Let's make it a bit less loud. But once again, experiment and see how this works for you.
523:22
Speaker A
When a laser area entered, we want to play that sound. Which means before we're doing anything else, I want to get the audio stream player and lay it.
523:35
Speaker A
Once we have that, I can shoot the laser. Let's hope I hit something important.
523:44
Speaker A
And that works perfect. Finally, inside of the game, I want to have the background music.
523:52
Speaker A
For that, I want to have a plain audio stream player. The background music doesn't care about the distance to the player, which as a reminder is why we have an audio stream player 2D, 3D, and a plain one. 2D and 3D care about the
524:06
Speaker A
position. The further away the sound is from the camera, the quieter it will be.
524:11
Speaker A
The audio stream player, on the other hand, doesn't care about that. This is what we want to get. And for that, I want to have spaceship.wav.
524:19
Speaker A
Let's see how that sounds. Background music. That is definitely background music. And on top of that, when you are importing the file inside of the loop mode, this is set to forward.
524:33
Speaker A
If it is disabled or set to ping pong or backward, you are going to get some weird behavior. This should be forward.
524:41
Speaker A
If it's set to disabled for you, press forward and then click on reimpport. I don't have to do it because I already had that setting. And this we want to autoplay. That way we getting looping background music, which usually should
524:54
Speaker A
be a bit quieter. Negative 20. Let's try off this in the game. And that's coming together reasonably well. With that, we have sound. Next up, I want to fix a couple of smaller things. The first one is the debugger is
525:14
Speaker A
unhappy with us because in on body entered for the obstacle we don't use the body. So there should be an underscore.
525:22
Speaker A
That was a very easy fix. The more important one is there actually two things we have to work on. Number one inside of the game the player can move to the right and simply leave the screen which does get a bit weird.
525:36
Speaker A
To fix that, what we can do inside of the game, we can simply add aesthetic body 3D along with a collision shape 3D where we just need a box shape. And this is going to be a pretty basic wall that
525:54
Speaker A
needs to cover just about the player. Something like this is fine. And this you want to move to the right so you get something reasonably large. To test this inside of the game, you want to go to debug and then visible collision shapes.
526:09
Speaker A
So, we can see the collision shapes. Let's see how that looks. You can see a faint blue outline. That's the collision shape. And at the moment, I guess that's basically all right. Then we can duplicate the collision body,
526:25
Speaker A
move it to the left. And this is quite hard to see, but we do have a collision shape here. I guess if I disable the floor, this is much easier to see.
526:39
Speaker A
I guess we can go somewhere hereish. Let's try the game now. And I guess that works also. Okay, cool.
526:52
Speaker A
That way the player is constrained to the actual game and that makes the entire thing feel much better. Besides that for the meteors once they leave the screen they still exist meaning we are creating more and more meteors. For that I want to
527:11
Speaker A
have a visibility oncreen notifier 3D. If you that you get a collision shape that is a basic rectangle and this should roughly be the size of the meteor. Doesn't have to be too precise. The basics here are totally
527:27
Speaker A
fine. Something like this. This note simply checks if the note is well on the screen or not. Instead of the signals, we can check if this node entered the screen or exited it. In our case, we want to check if it exited the window.
527:43
Speaker A
Click on connect. And if that is the case, I want to Q3 that node. That way, the meteors disappear once they go past the player. A similar system might be good for the laser as well, but you can implement that on your own.
528:02
Speaker A
Those were the two smaller parts that I want to work on. Finally, the last major bit is at the moment, if you look at the floor, this well doesn't really look like a floor. It's perfectly flat and that just doesn't look good.
528:17
Speaker A
To fix that, we can write a basic shader. Specifically, we want to create a vertex shader. For that, if you click on the mesh, at the moment, this thing has a size of 130 and a subdivision for width and depth of zero, which means
528:32
Speaker A
inside of perspective, we are getting basically just these vertices, which isn't really ideal. Via the shader. We want to move some of these vertices up and some down. That way we're getting a random terrain, but that we can't do at
528:49
Speaker A
the moment because we don't have that many vertices. To fix that, we want to change the subdivision to let's say 100 for X and Y. That way, you can already see we're getting a lot more points. And these
529:04
Speaker A
points we can change via a shader. You can actually do something interesting. If you click on the arrow on the material, you can convert the material to a shader material. If you do that, then first of all, nothing happens. But
529:17
Speaker A
if you now click on this thing again, you have a shader, which already has a ton of stuff, which we don't really care about. All that we want to do is add a bit of stuff to the vertex shader.
529:30
Speaker A
Although, all of this is a pretty good way to learn about shaders in terms of what happens under the hood.
529:36
Speaker A
but not our problem at the moment. Instead, what I want to do via the vertex property inside of the vertex function, you can target the position of every single vertex inside of this mesh. This is going to be a vector 3 that you can read
529:57
Speaker A
and overwrite. So, for example, what you can do is vertex plus equal vector 3 and then you have x, y, and z. Meaning if you want to move up all of this by two units, you simply need a vector 3 with 0
530:13
Speaker A
to 0. And then all of this is going to be moved up tiny bit there. You can see it, especially around the corner. This is the original mesh and we're moving all of this up by two units because of
530:26
Speaker A
this number. If I change it to a one, then we're going down a bit. And if I change it to a 10, then we're going up by quite a lot. There you go. That's the basic idea. But this we have to
530:39
Speaker A
randomize. And for that we will need a random texture. The way you're creating that is first of all you want to have a uniform. So you can change it outside of the shader. And then the data type is a
530:52
Speaker A
sampler 2D. By that you can create textures inside of a shader. The texture that we want to create is a noise texture. You'll see in a second where this is going. If you add a semicolon, then nothing really happens. But if you
531:07
Speaker A
look at shader parameters, first of all, we get a lot of stuff that we don't care about. The only thing that we care about is noise texture at the bottom. And there we can create a noise texture 2D.
531:20
Speaker A
If you click on that, you get a few more options that we also don't care about.
531:24
Speaker A
But then once again, at the bottom under noise, we can create a new fast noise light. Click on that and then you are getting a random noise. That is actually what we need.
531:37
Speaker A
This is effectively a 2D texture where we have lots of random black and white values with lots of gray in between. For example, in here we have a pure white color and here we have a pure black color. The range always goes from zero
531:52
Speaker A
to one with zero being black and the white bits having a value of one. Or to be a bit more specific, we working with RGB values where a white color has an RGB value of 1, one, and one and a black
532:04
Speaker A
color has an RGB value of 0 0 and 0. All of this you can fine-tune as well. There are, for example, different kinds of noise.
532:16
Speaker A
And if you look at the bottom options, you can change a few more things. So you can create some pretty funky behavior.
532:23
Speaker A
In my case though, I want to have simplex. That way, we're getting something. And by the frequency, you can scale in and out. This really doesn't have to be too precise. From this texture, we want to sample the colors, which we do via
532:40
Speaker A
inside of the vertex function. I want to create a float noise sample. To sample a color, we need first of all the texture function. And this wants to have two arguments. Number one is the sampler. This is the thing
532:56
Speaker A
that holds the texture. That is very easy. We want to have a noise texture.
533:02
Speaker A
Then we need the UV coordinates. Those tell us where we are on the texture.
533:09
Speaker A
In practice, all you need in here is UV and then you are getting something effectively via this. We're getting all of the points on this texture, but it returns a vector 4. So, RGB and A, but we need a float. The way you're
533:25
Speaker A
converting that is simply by looking at one of these values. RG or B are all going to be fine. Let's go with red.
533:32
Speaker A
Grayscale values like this texture RG and B are going to be the same. So, it doesn't matter which one you choose. But effectively now for every single pixel on this mesh we get one associated value on this texture. For example, the top
533:49
Speaker A
left point would vaguely be somewhere up here. Or if you are vaguely here, then you might be on this point, which for the red value would be basically zero.
533:59
Speaker A
If you are somewhere down here, which would be vaguely here, then you would get an R value of close to one. And that we can use simply by adding the noise sample to the vertex position. If you're doing that and you look from the side,
534:16
Speaker A
you can see that now we are getting a bit more of a terrainy look. It's quite hard to see. To make this more visible, we can multiply the noise sample by a factor of 10. And this is going to be
534:30
Speaker A
really visible. And there you go. This looks much much better. And I hope you understand the logic here. Basically, we are laying a texture on top of all of this, this texture here. And then via the position, we are sampling one of
534:43
Speaker A
these grayscale values and get a value between zero and one. If the value is zero, we are somewhere here. Meaning we didn't move up the vertices by a lot.
534:53
Speaker A
But if we are on this bit, then we get a higher value. This would be roughly here in a texture. And all combined, we're getting a pretty cool effect. If you go back to display normal, this is arguably
535:06
Speaker A
a bit less visible because we don't have a lot of lighting. And also, this shouldn't be that strong. Let's change it to 0.5. This really shouldn't be that tall. And somewhere in there, we have the player. There we go.
535:21
Speaker A
And right now, you can't really see that. Let's change this a bit more. So, we are getting something. Always make sure you're multiplying this with 2.0.
535:31
Speaker A
Otherwise, GDO is going to complain. And now this looks a bit more realistic, but this isn't going to be too strong in the game. It might be just about visible.
535:43
Speaker A
I guess we're getting a slight effect. This is the kind of thing that you want to play around with a lot just to make sure we are not breaking the rest of the game. I'm going to set this to 0.5, which makes it barely
535:55
Speaker A
visible, but at the very least, it's going to do something. [Music] And all right, with that we have the finished game. Make sure on the debug the visible collision shapes is disabled so it doesn't look too weird. But other
536:12
Speaker A
than that, you have learned about the basics of 3D game development. You can either continue with the course where you're going to learn about a 3D platformer and a firsterson shooter.
536:22
Speaker A
If you don't really care about the course, I have also made a Zelda game that goes into a lot more detail about 3D game development. This one is entirely on YouTube, so just check it out if you are interested. In there, I
536:33
Speaker A
cover a lot of animation logic, a bit more on shaders, enemy behavior, and honestly, a lot of stuff. The video is quite long.
Topics:Godotgame developmentgame enginecoding tutorial2D games3D gamesgame programmingopen sourcebeginner friendlyClear Code

Frequently Asked Questions

Do I need prior coding experience to follow this Godot course?

No, the course assumes no prior coding knowledge and starts from the basics, making it suitable for complete beginners.

Is Godot free to use for game development?

Yes, Godot is a completely free and open source game engine that works on multiple platforms.

What types of games will I learn to create in this course?

You will learn to create seven games including a runner, platformer, farming game, monster battle, 3D space shooter, 3D platformer, and 3D shooter.

Get More with the Söz AI App

Transcribe recordings, audio files, and YouTube videos — with AI summaries, speaker detection, and unlimited transcriptions.

Or transcribe another YouTube video here →