You are on page 1of 186

Your First Script

In this lecture, we are going to create a new game project for Project Boost.

This is going to involve making our player and writing our first script in Godot dedicated
language

script.

So from where we left off in the introduction, we have this project.

We want to return to the project manager so that we can create Project Boost.

In the top bar on the left, click the project menu button and in the dropdown select Quit to
Project

List.

This is going to exit us out of that project and return us to the project manager.

From here, we can click the new project button in the top right.

Create a new project.

For the project path, I'm going to select the folder we created in the introduction for my games.

And select that as the current folder.

And then we're going to want to name this project boost.

And we can click the Create Folder button in the top right.

Create an empty folder for all of those game files.

With that all set up, we want the default forward plus renderer and we can click Create and
Edit.

Now we are in Project Boost.

The first thing we're going to want to do is make a change to our editor settings.

That will make the code we write a bit better.

In the top bar on the top left, click the editor button and from that dropdown select Editor
Settings.

Within editor settings.


Search for type space hint.

This will restrict the tree view on the left and show us this completion option that if we click
on,

will show a value called add type hints.

This is already enabled because I enable it in every project I run, but you'll just want to click
the

check mark next to the word on and it will enable add type hints.

If we hover over this property, it will tell us a bit more about what this property does.

But essentially when writing scripts, Godot will now automatically add variable types to
variables

we work with.

Now we've not got into what variables are yet, but you'll need to trust me a little bit that this
will

make our coding more precise when we get to writing our scripts.

So let's try and get to writing scripts as quickly as possible.

With Add Type hints enabled, click the close button.

And now we're going to want to create a new 3D scene.

In the top left in the scene tree, select 3D scene as the root node of our scene and then rename
that

node to player.

This node will be the player in our scene.

It will be the main character we're controlling, and it is what we are going to attach scripts to.

So scripts are a way of giving instructions to the game engine.

You can declare a list of things you want to happen at specific points, and then the script will
make

those things happen exactly as you told the machine to do.


There are two ways we can add a script to a node.

You can either.

With it selected in the scene tree.

Look at the scroll and click the scroll with the little green plus in its bottom right to attach a
script

to it.

Or you can right click on the node and select Attach Script.

It's worth knowing one node can only have one script attached to it, but in a scene, any number
of

the nodes can have a script attached.

So you can have multiple scripts in one scene.

We're going to attach a script to this player node and it will open the Attach Node Script
dialog.

One thing we're going to want to do is enable this template option, which is just going to set
up our

scripts with a few default functions.

One thing that's worth noting is Godot does support a bunch of different languages.

Gdscript is the built in and default language, and it really has a bunch of very nice features that

will make your life very easy.

And it really is just one of my favorite ways to do programming regularly.

So we have Gdscript selected as the language.

And we have a path.

It's going to default the path for this script file we're creating to have the same name as the
node

we attached it to.
So it's going to call it player.

And it's got the suffix gd which indicates that it is a GD script file.

Click create and that file will be opened and we will change our view over to the script main
screen.

We can now see a script in the middle replacing the viewport.

Now, depending on the size of your screen, this may or may not be easy to see.

So I'm just going to quickly cover how you can make things more visible.

If you want to hide the tabs on the left and right, the scene tree, file system and Inspector, there

is this button in the top right of the main screen called distraction free mode, which will hide
those

side windows, and you'll see the main screen takes up the full width.

You do then need to remember that you need to either click that button again or push the
shortcut Ctrl

shift F11 to then return the view of those side docks.

Another nice way to make the screen take up the full screen is to make this window floating.

If you click the button below that distraction free mode, there is a button to make this entire
main

window float, and you'll see it is now a window that I can move around.

Maybe move on to another screen and get rid of any distractions.

It's worth noting that if you close this floating window, it will return to where it was.

If you change the main screen back to the script view, it will be back where it was.

I'm going to use this floating window so that I can focus entirely on the script we're dealing
with.

So now we can look at how Gdscript scripts work.

The first thing that is worth understanding a little bit is this very first line in the script which

says extends node 3D.


When we attach the script to a node, the script gets access to all of the properties and functions

that the node we attached it to has.

That means because we attach the script to a node 3D, it has a 3D position.

That means that this script knows it has a position on the y axis, the x axis, and the z axis.

And there are a bunch of other built in properties that the script has access to.

The next thing we need to look at are these two functions that were added by default.

Functions are a list of instructions that get completed in order when the function is called.

I'm only going to focus on this first function ready to start with.

This function gets called the first time the node runs.

So when we first run our game, this ready function will be called and everything inside it will
be

run one at a time sequentially.

When we added editor type hints as an editor setting, it added this extra bit of syntax.

This syntax says the data type that functions or variables are interacting with.

This part in particular means this function doesn't return a value.

I'll get a bit more into what that means later on.

Let's start making our game.

Understand how to follow instructions by making our game do something when it loads.

Within this ready function.

It currently says pass.

That is a placeholder keyword.

That just means don't do anything.

The game engine doesn't like it if you leave a function empty.


So you often need to use a keyword like pass just to let it know that we are intending for this
function

to not do anything at the moment.

I'm going to replace this with a function that all scripts can call, which is print.

The print function will output some text that we provide to it in the output panel when the
game is

running.

You can tell something is a function because it is a name, followed immediately by an opening
and closing

parentheses.

You can see ready.

Above is the word underscore ready, followed by an opening and closing parentheses.

We can pass values to the function within these brackets.

So in order to print something out to the console while the game is running, we need to pass a
string

in.

And a string is a set of words surrounded by double quotes.

I'm going to type a double quote and then hello world!

The syntax highlighting makes Hello World go yellow.

But in short, when this is run, the script will see.

This node has loaded.

So I will call its ready function, and its ready function will perform all of the code that is
within

the function.

You can tell the nodes within a function because it is indented.

That's indicated by this sideways pointing arrow here.


If you press the Tab button.

A line will indent further to the right.

If you hold shift and press tab, it will indent back into the left.

If I indent this function all of the way, you will see the line has gone red and there is an error

because it expects there to be an indented block after we declared this function.

Essentially, after this function and the colon, it expects there to be something indented upper
level

on the following line.

And then everything that's at this indentation level immediately after this function is what will
be

called when that function is run.

Anyway, that's enough talking.

Let's see this in action.

I'm going to close that script view.

And I am going to save this scene.

I'm going to save it as player scene.

I saved it by hitting Ctrl and S and now we can run the scene.

I will click the Play Current Scene button in the top right or use the F6 key.

As before, this scene has a grey view because we don't have a camera or a walled
environment, but

we don't care too much about that.

What we care about is if we move this window out of the way.

In fact, let's just close it.

If we get rid of that window, we can see in the output tab in the bottom panel.
Here we can see a bunch of startup text and then hello world.

That means our game ran this node 3D loaded.

It's ready function was called.

And the print function that said the words hello world was then called as well.

Reopen the script.

You can get to the script quickly by clicking the icon with the script attached to the player, or
by

clicking that script tab.

I'm going to click the script icon and it will reopen that main window.

And then I'm going to make it full screen again.

And we have our challenge.

So for our challenge, I want you to do two additional things.

I want to make your game run and print out the following lines of text sequentially.

We already have.

Hello, world.

But I want you to also print out.

Don't panic.

Afterwards.

And then afterwards print the number 42, and I will see you back here in a moment for the
solution.

Returning to our game scene, we want to print those extra lines sequentially.

I am going to click the little script button next to our node in the scene tree to open the
associated

script in the script view.

And then in here we want to print more lines of dialogue sequentially.


Everything within the ready function will run one at a time, so we can just add a new line
afterwards.

Type out print.

And then the next line was don't panic.

I'm going to type that in remembering to surround it with double quotes.

Let's see that in action.

I'm going to close this and I'm going to click the Play Current scene button.

Close the window that opened and you will see our output panel is saying hello world.

And then it's saying don't panic.

If I returned to that script.

Make it full screen.

The last thing we wanted to add was printing the number 42.

We type print again on a new line and then in double quotes the number 42.

Now these double quotes mean that this value is a string.

Interestingly enough, we can actually delete these double quotes and print just the number on
its own.

And that's because the game engine treats numbers differently to text.

If we tried to print Don't Panic without quotes around it.

It's trying to read these words as either functions or variables, and it's getting very confused.

And because it's got punctuation and spaces, we need to surround it in double quotes for it to
know

that is one entire string I'm going to treat as one value I can access and use.

I'm going to save that, and I'm going to run it.

And we will see that it prints out Hello world, don't Panic and 42.
In the next lecture, we will be learning about the process function and start using inputs from
the

player.

Scripting Essentials
In this lecture, we are going to build on our scripting knowledge, learning about the process
function,

how to get input from the player and how to use variables.

So when we started we have this ready function that is currently printing three things out to the
console.

We want to start learning about this process function.

For a game to be responsive, it's going to have to update the screen many times every second.

These updates are called frames and your frame rate is going to depend on your machine.

So typically if you have a machine with better hardware, it will have a higher frame rate and
worse

hardware.

It will have a lower frame rate.

But also frame rates can vary just across time.

When you're using your machine, sometimes processes will run in the background.

They'll eat up some resources and your frames will drop.

The process function lets us run code every single frame.

Because the frame rate can differ machine by machine.

That means we can be running a different amount of code in the same amount of time.

Because of this, we need the delta parameter as a way to keep our code consistent across
different

machines with different frame rates.

So a parameter is a value that we pass into a function.


When we were calling the print function earlier, we were passing in text as a parameter that
the print

function could then output to the console.

In this case, our process function is called and it is provided delta a value saying how long it
has

been since the last frame and seconds.

Typically this is a very small number, about one divided by 60.

But given that, let's start seeing our game print something out every frame.

In this process function, I'm going to replace the pass keyword with a print statement.

And this print statement is just going to print.

Hello.

Now because this is printing every frame, it's going to very quickly become unmanageable.

I'm just going to run that as is.

And we can see our output in the bottom panel is full of hellos, and you can see on the right it's

printed at 400 times, 500 times, 600 times.

Just a whole load of hellos.

Far too many greetings if you ask me.

So we know we can print something out every frame.

Let's try and find out something interesting.

Let's find out how big Delta is on our machine.

So instead of printing hello I'm going to print Delta and run the scene.

Now you can see there the number was changing every so often.

So it's 0.016 which I think is about one divided by 60.

And if I pause this there's a playback control on the top right where we can pause the running
project.
Now that output is going to stop continuing.

It's it has stopped the game while it's running.

And we can resume by clicking the play button.

But this is going to let us dig through this output console in the bottom left.

So you're going to want to make sure you're viewing the output by clicking the output button
in the

bottom left of the bottom panel.

And we can scroll all the way up to the top, because I saw something interesting which was
over the

first few frames, it printed what was in our ready function and then it printed the delta.

And the delta varied quite a lot because the game was setting up, so the frame rate was
varying.

With that understanding, I'm going to close and shut that off.

This process function is running every frame.

I want it to check if the player has pushed a key on their keyboard, and if they have, print
something

out.

An if statement starts with the word if and then it checks if a condition is true or false.

If the condition is true, it will do something, and if it isn't, it won't do that thing.

So a simple condition in this case is going to be if the player is pushing a key.

We can access whether the player is pushing a key through a singleton called input.

Not going to go into too much detail on it, but want to check if the player has pushed a key and
I

can do that with input.

Dot is and you can see we have code completion for a bunch of the options we want.
Is action pressed.

And you can get that code completion by either using the arrow keys to go down and hit enter,
or just

click on it.

And then we want to check if the action that was pressed is accept.

And that's an action that's bound to pushing the space bar or the enter key.

So that's quite a long line of code.

We close off this if statement with a colon, which then separates out.

So afterwards, all of the indented lines of code will be run when the if statement evaluates to
true.

In short, this says if we have pushed the spacebar, do whatever is indented after the if
statement

so we can print something here I'm going to print spacebar was pressed.

And now if we run this code, whenever we press the spacebar, it should print out this line.

I'm going to run the game.

We can see the window running here.

If I push space, we get a whole bunch of space.

Bar was pressed inputs.

That's actually because I selected a slightly different input event to what I wanted.

I actually wanted if I return to it, is action just pressed?

What was happening there was while we were pushing the space bar down, there were
multiple frames where

the space bar was pressed, and on all of those frames it was printing out.

This line input is action just pressed?

Just returns true the first time we've pushed the key down, and doesn't ignore the subsequent
frames
where we're still holding the key down.

So I'm going to run that.

I'm going to push space and it says spacebar was pressed whenever we do that.

I'm going to go into much more detail about using if statements and how you can use player
input in

subsequent lectures, but for the moment, this is a good starting point for us to just access that

information.

So now we've learned about using the process function.

We can learn a bit about how we can actually handle these values we're printing out.

Typically we will want to store a value so we can interact with it.

That might be a number or a bit of text.

We might want to increase a number over time or decrease it.

For example storing the player's current health.

We might want to store a number about 100.

And when they take damage, take eight off of it, or take some number off of it and then store
what

their health is now after they've taken that damage.

In order to have these values that we store and interact with, we need to use variables.

So variables are a way of storing values, and we can store specific values in them.

So for example, if I were to declare a variable called my string and set its type to be string, I

could store some text like hello World, which is what we were passing into our print
statement.

If I have this Hello world value stored in a variable called my string, I could pass my string
into

a print statement and it would print out the value that was stored in this variable.
We can also store different things in variables.

We could store integers.

So a whole number is an integer.

So for example that value 42.

And if we wanted to store something with a decimal decimal place we could use a float which
would be

something like 1.5 or 0.3 or whatever else, just something with a decimal place in the middle
of it.

Now, a variable doesn't have to have one of these set types.

We don't have to say it's a string or an integer, but it's an option.

And in fact, when we went to edit settings in the last lecture and we enabled type hints, that
was

us opting in to gdscript generating a bunch of these types.

Now, the reason you'd want to do that is when Godot knows what kind of data is in a variable,
it will

actually run a bit better because it can allocate its memory more effectively and other things
like

that.

So you will actually get better performance when you use strong typing.

It's also generally considered to be more readable if you're telling someone this variable I'm
dealing

with that stores the health is meant to be a number and not a word.

So given what we've just learned about variables, let's try and replace some of the stuff in our
ready

function with some variables.

I'm going to add a new line afterwards and create my very first new variable.
I'm going to create var my number.

Allotment equals ten.

And now, if we try and print this, as I was saying, it will print out ten so I can print.

My number.

Now there's a lot of things going on.

So I'm going to get rid of these previous print statements.

So it's not too distracting.

And when we run this scene we will see it's printing ten out here.

We can do a lot of things with this value.

Now it is a variable.

We could, for example, add a value on top or multiply it together.

And there are lots of arithmetic operations.

But I'm going to show you how we can add one to it.

If after my number we add a plus and then we add one, what will happen is it will run that
operation

on this variable before it gets passed into the print statement.

So what the print will receive is actually ten with one added onto it.

So if we print that we will get 11 coming out.

There we are.

We can also take advantage of this in our process function.

So I am going to declare a new variable.

This time I'm going to declare a variable outside of the function when we declare this variable
inside

the ready function.


Only the ready function knows about this variable.

My number because of the indentation.

This process function won't know that variable exists or be able to access it.

So if we want to create a variable that both of these functions can access, we want to define it
outside

of both of those functions.

So at the top of the script I'm going to create a new variable.

I'm going to call this timer.

And I'm going to call it a float, and I'm going to set it to be equal to 0.0.

In the process function.

What I'm going to do is I'm going to print out what timer is set to.

And if I run that at the moment, it should just keep printing zero.

But I'm also going to change what the value of timer is.

I'm actually going to add delta on top of it.

So I'm going to say timer equals timer plus delta.

And now every frame that small number about 0.016 is going to get added onto what timer is
set to.

And then time will be 0.016.

And then in the next frame it will add delta on top.

And it becomes 0.03 or whatever.

And it's going to keep getting bigger over time.

So if I run this script.

You will see this number is going to grow and keep a track of how many seconds it's been
since the application

started.
So with all of that knowledge, I have a challenge for you.

And that challenge is I want you to create a new variable that both the functions can access
that stores

an integer.

And whenever the spacebar is pressed, I want you to make that value bigger.

So I want you to add something to it.

It doesn't matter.

It could be delta.

It could be a whole number.

It could be a really big number.

And then afterwards I want you to print the value of that new variable.

So I will see you back here in a few moments.

Welcome back.

So back in the script I am going to create a new variable to store this new number.

I'm going to declare a variable with the var keyword and I am going to store.

I'm going to call it growing number.

And it's going to store an integer.

I am then going to set that equal to starting value.

I'm going to set it equal to 42.

And then we want to start adding a number to it every time the spacebar is pressed.

At the moment, because we're printing something in the process function, that number that's
getting

printed out is actually going to get in the way of what we're trying to see be printed out.

So I'm actually going to get rid of this timer part.


And then in the if statement, I'm going to add an extra section that both increases our number
and

prints what the new number is.

I'm going to say growing number.

Is equal to growing number.

And then with another value added on top, let's say add five.

So now every time we press the spacebar, we are going to add five onto the number that's
already stored

there.

And then we can print out whatever that is.

Print growing number.

If I run that.

Whenever we press the spacebar, it will say that we've pressed the spacebar and it will say the
value

that is stored in that variable growing number, which is 47.

And now it's 47.

The next time we push space, it will add five on top of that and we'll go up to 52 and so on
indefinitely

getting five bigger every time.

In the next lecture, we are going to put this theory into practice and start using our script to
make

the player controllable and able to move.

Controlling the Player


In this lecture, we will use what we've learned about scripts so far to start giving instructions to

the player.

So in order to have a player that we can see and interact with, we are going to need to give the
player

a mesh, something visible.

Now we can do that by clicking on the player in the scene tree, clicking control A to open the
Create

New node prompt, or clicking that plus button in the top left and searching for a mesh instance
3D.

And this mesh is 3D.

You can have a whole bunch of shapes attached to it.

If we go over to the inspector with it selected in the scene tree and we can see its mesh
property,

we can click the drop down to the right of that and we can select a new cylinder mesh I think
will be

fine because we're going to be creating for this project.

Is something a bit like a rocket ship.

So that kind of hard surface shape will do fine.

And we will now default to having this about a metre tall mesh.

We now need to do the rest of the essential steps for making our 3D scene visible, and that is
adding

a camera, adding a world environment, and adding a directional light.

Now we can add that environment and directional light with those three dots at the top of the
viewport

that add the preview sun and environment.

And we can click Add Sun to scene and we can click Add Environment to scene.

And now we need a camera.

So with the root node selected hit control and A.

And then in the create new node bar we will search for a camera 3D.
Click create to add this camera 3D to the scene, and you'll see it's currently inside of where our

player is.

So we're going to need to move it some distance back so that we can actually see the player
with the

camera 3D selected in the inspector.

Go down to the transform dropdown, expand that, and we will use its position property to
move it further

back.

I'm going to move it five meters back by setting the z value of the position property to five.

We can't see it now.

If we scroll the mouse wheel out, we will see it's five meters back and you can see the grid
showing

the number of meters there.

So it's currently five grid spaces away from the player.

If we want to see how that looks we can click the preview button.

We can see the player's relatively small in the middle of our screen.

Now we're going to encounter one problem.

At the moment, if we start moving the player around with the camera here and that is the
camera is

a child of our player node.

That means when the player moves, the camera will move with it.

So I'm going to select the player root node.

And I'm going to use the gizmo to move it up.

And you'll see the camera goes with it because the camera follows it around.

We actually won't be able to see that the player is moving up or down, because the relative
view is
going to be the same as the camera moves with the player.

I'm going to undo those changes to the players transform by expanding its transform property
and clicking

this undo arrow.

Thankfully, there is one little shortcut we can do to make it so that the camera won't move
with the

player even though it's a child.

Normally, we'd have to create another scene and keep the camera parented to the root of that
scene

so that it's not a child of the player.

But built into nodes.

There is a top level property.

If we select the camera and in the inspector, go all the way down to the node 3D section.

I think it's in transform.

Yes.

In the transform dropdown there is a top level property.

Now this is a really handy feature for making it so that a node will not move with its parent.

There are an awful lot of useful applications for that.

Say you have a gun that fires bullets and you want the bullets to not move.

When the gun moves, you can set the bullets to be top level, even though they're a child of the
gun,

and then they will move independently.

So I'm going to enable top level.

And now when we move the player that camera should remain fixed in position.

You can see this all in action.


We can run the scene and you will see the view we got in the preview a second ago.

Now we can move on over to the script, change over to the script tab, and I'm going to enter
distraction

free mode so that it takes up the full space.

We have all of the scripting we were doing previously in here.

We actually don't need any of this anymore.

We're not going to do anything in the ready function, and we're not going to use any of these
variables,

so am going to get rid of all of that code.

So we're left with just the process function.

And I'm going to get rid of this growing number stuff.

So one thing we can do to start with is we can start moving the player up when they push the
space bar.

Now we do that by changing the player's position.

And a position is a vector three.

A vector three is a very fundamental object.

We're going to interact with them an awful lot.

So it's worth understanding a bit about how they work.

They are a way of representing 3D coordinates within a vector three.

We have three values an x position, a y position, and a z position.

So that's the how far they are on the x axis, how far they are on the y axis, and how far they are

on the z axis.

We represent a vector with the vector three object, and we can create a new vector using this,
which

is a constructor.
It creates a new vector three object.

The vector three has the first parameter giving its x value.

The second parameter giving its y value, and the third parameter giving its z value.

So this means this vector is roughly the same as saying it's a point in space two metres to the
right,

five metres up and zero metres forward or back.

So our player's position is a vector three.

It has this property called position.

And in it it has an x value for how far to the left or right it is, how far up or down it is on the

y value, and how far in or out of the screen it is on the z value.

So if we want to move the player up, what we can do is we can access their position, access
their

Y value, which is how high they are, and we can increase it or decrease it like that growing
number

from the last lecture.

With that in mind, what we want to do is when we push the spacebar, we want to move the
player up.

I am going to replace the print line here.

I'm going to say position and it will see it's auto completed that we have a position property.

If I hit Dot, we'll be able to see all of the functions and properties within that vector three,
which

includes its x value, its y value, and its z value.

I'm going to get its y value and I'm going to add a number to it.

I'm going to say position dot y equals position dot y plus two.

So now when we press the spacebar the player will move two meters up.
And if I run that hit the spacebar and they jump up and they keep going off.

You'll notice that was very stuttery.

It was moving two whole meters at a time.

And also it was only moving on the individual times.

We pushed the space bar.

So I'm going to make two changes to this to make it so that the motion is smooth.

First of all I'm going to change this input.

Is action just pressed to be input.

Is action pressed instead.

So now every frame where we are pushing the spacebar a value will be added to position dot
y.

And then I'm going to do a very important step for making code like this.

Run the same on different machines.

And that's I'm going to use this delta value.

I'm going to say position dot y equals position y plus delta.

That means every frame while we're holding the spacebar, the player is going to move up by
how many

seconds it's been since the last frame.

Let's show it in action.

So now if I hold space, the player moves up.

Roughly at a meter per second.

That's nice enough, but this is a good opportunity for us to see some shorthand.

At the moment we're having to say position dot y twice, and this line of code is just a bit
longer

than it needs to be.


There is a built in shortcut for adding a value on top of what a number already is.

We can replace this whole line.

With position dot y plus equals delta.

That's shorthand that says we're going to set position dot y to be equal to whatever it already
is.

Plus delta.

There are a bunch of similar functions like this for minus equals or multiply equals or divide
equals.

But I'll just show you that in action.

So you can see that this is fundamentally the same as saying position dot y equals position dot
y plus

delta.

And there we have it.

So now we can move the player up when they push the space bar.

Let's go a step further and try and rotate the player.

So we want to check if the user is pressing left or right.

I'm going to use the left or right arrow keys because they're the easiest to access on a new line.

I'm going to say if input dot is action pressed, and I'm going to check if they've pressed UI
right.

Now I'm going to check if I press left to start with.

I think that's a better starting point.

I'm going to check if they've pressed left, so that's if they've pressed the left arrow key.

If they've done that, we want to rotate our shape anti-clockwise around the z axis.

And the way to do that, as simply as possibly is with the rotate z function.

You can see we've got a rotate X, rotate Y, and rotate z function.
We want to use the rotate z function and we want to pass in an amount.

We want to rotate the shape by.

I'm going to pass in delta as well.

Now the value that rotate Z takes is actually a unit called a radian.

All we need to know about this is that as we increase the number we're rotating Z by, it will
rotate

more counterclockwise.

If I start running this.

And I hit the left arrow key.

You'll see our shape rotates counterclockwise.

And with that, we can move on to our challenge.

For this challenge, I want you to rotate the player clockwise when they press the right action.

Now you're going to need a little bit of a hint here.

And that is you can rotate your shape positively or negatively around that z axis.

Okay with that?

I will see you back here in a few moments.

Okay.

So our starting position is we want to do something when they press the right action instead of
the

left action.

So on a new line I'm going to say if input dot is action pressed UI right.

And now we want to do something differently under this condition.

So when we increase the value we're rotating z by is rotating counterclockwise.

If we subtract this value it will rotate clockwise instead.


So the way we can make a value negative is by using a minus sign.

So I'm going to say minus delta.

And you can use this minus symbol in the same way we've been using the plus symbol
previously.

You can decrease value by subtracting it anyway.

Let's see that in action.

I can rotate left, and if I push the right arrow, I will rotate right.

And that's it for this lecture.

In the next one, we are going to move on to blocking out our first 3D level using 3D shapes.

Blocking Out the Level


In this lecture, we are going to lay out our starting level with 3D shapes and colors.

So our starting point should be figuring out how we want our level to look for Project Boost.

Our level has a few key components.

We have the ground, and we have a launch pad where our rocket is going to start the level, and
a landing

pad where our rocket is going to want to fly to and land.

So the three core things we're going to want to lay out in this level scene are the box that is the

ground, the box that is the launch pad, and the box that is the landing pad.

We're going to want to create a new level as a new scene.

So click the plus icon at the top of the viewport to create a new scene.

And we're going to want to set a 3D scene as the root node.

I'm going to rename this to level.

So the node we are going to use to construct our 3D geometry is a CSG box 3D.

CSG stands for Constructive Solid Geometry, and it's a very helpful prototyping tool that will
allow
you to create interesting shapes dynamically.

And it's very good for prototyping a level.

And then you can then export those meshes out into another piece of software, like blender, or
another

3D modeling software to create higher fidelity level assets.

So we're going to want to add a new node to this scene with Ctrl A, and we're going to search
for CSG

box 3D.

Just by starting with CSG, you can see all of the options for different CSG shapes.

But we want a CSG box and you will see we have a one metre by one metre by one metre
cube.

So we can control the size and dimensions of this box.

Either with these little orange dots, you can click and drag them to resize, or we can use this
size

property in the inspector while the box is selected.

I am going to use the size property because I have a good idea of how big I want this level to
be.

I want it to be 30m wide.

And then I want it to be about five meters deep.

So I'm going to set the z value of the size to five.

And I'm going to make it quite tall as well.

So I'm going to make it eight meters tall.

So we have this large area.

Our ship is going to be on top of landing pads on top of here.

So sort of flying from around here to over here.


I want to line the top of this box with the floor of our world.

So that ground level is zero on the y axis.

So because it's eight meters tall, well, the dimensions are eight meters.

It spreads four meters out from the zero point that way, and it spreads four meters downwards.

So if we set its position to negative four, the top will line up with the middle.

So I'm going to go down to the transform property and set its positions y value to negative
four.

And now we have this big box that will act as the floor of our level.

I'm going to rename this box by double clicking on it, and I'm going to call it floor.

And I'm also going to enable the use collision property.

Later on, we're going to want our ship to be able to stand on the floor or crash into it.

And for that to work, our shape needs collision.

So enable use collision.

Now we want to set a color for this floor.

You'll see it has a material property.

A material controls how 3D objects will render in our game world.

If we click the dropdown to the right of a new material, you will see a few different objects we
can

choose from.

We can create a standard material, an material or a shader material.

We're going to create a standard material.

This has made it a little bit lighter, and it's going to let us choose a color for this mesh.

If we click the dropdown, this is an object that we can access in the inspector.

And it has a whole bunch of properties of its own that are distinct from the properties of this
box.
So if I click on this sphere in the viewport, it will expand.

And you can see it's got a blue border because this is all one object, but it has a whole host of
properties.

It's got things like transparency, metallic roughness, emission to make it glow, all of that stuff.

Now that means it's not too trivial to find where the color is.

You need to know that color is usually referred to in 3D software as an albedo.

So under the albedo dropdown you will find the color of the shape.

And if we click on this color property, we will get a color picker that lets us choose the color
for

our shape so we can get rid of all the red.

And our shape will become blue.

We can get rid of all of the green and our shape will come even more blue.

So we have access to this color picker and you can select whichever color you want.

I'm going to choose a sort of pale, desaturated ish brown.

I think that works for me.

We get a whole bunch of options in here for controlling this color.

We of course have the red, green and blue channels, but we also have hue, saturation and
value.

So you can choose how saturated and how vibrant the colors are.

And also you can deal with the color on a scale of 0 to 1, rather than a value of 0 to 255.

So I'm going to make the value a bit lower.

It's worth noting that the CSG box, while it's selected, highlights in a bit of a blue tint, which

is going to make it hard to see these changes until we unselect the box.

And then I think I'm happy with that as a color for our floor.
So now we know how to make a box, we know how to resize it, and we know how to give it a
color so

we can start our challenge.

I want you to make the launch pad, and I want you to make the landing pad.

Now both of these need to be CSG box 3DS.

They both will need to be renamed, so one of them should be called launchpad and the other
should be

called Landing Pad and they need to be repositioned and resized.

And lastly you need to pick unique colors for them.

I'll recommend making the launchpad a shade of blue and the landing pad a shade of green.

And with that, I will see you back here in a few moments.

All right, let's start with the launch pad.

I'm going to click on the root node of our level.

And I'm going to add a new CSG box 3D by hitting control A to open the Create New Node
dialog.

And I'm going to select CSG box 3D and click create.

I'm going to rename this box to launchpad.

And we can see something interesting to start with because it's spawned in the middle of our
world,

it's currently clipping into the floor.

So if we want this to not clip into the floor, we're going to need to move this up at some point.

But to start with, I am going to position it roughly where I want.

I'm going to move it a bit to the left, and I going to make this shape a bit wider.

So I'm going to set its size to be two meters on the x axis.

Okay.
Its wider that way.

And now we can increase its depth by setting the z size to two meters.

Now we have a pretty nice big chunky box.

I'm going to decrease its height on the y axis to something like 0.4.

And now we have a smaller box.

So we need to lift it up less far to make it not slip through the floor.

And because it's 0.4m tall, if we move it 0.2m up, its bottom will touch where the floor is.

So I'm going to go down to its transform property, and I'm going to set the Y position to 0.2.

And was hovering over it to 0.2.

I'm actually going to set the position to a nice round number.

I'm going to set it to -7.5.

So we have our launch pad.

We want to enable collision on this.

We're going to want to set its color to a blue shade of some description.

So under its material property we can click the drop down to the right and select New Standard
material.

And as before under the albedo property we can find the color property.

And in here we get a color picker where we can pick a blue sort of color.

Now if you want to see what these colors are immediately I think this is a bug.

But I think if you decrease the value on the right because it's starting at full brightness, you
can't

see the colors in the color picker.

But if you decrease the value by dragging that slider down, you'll start to see what all the
colors

are.
So I'm going to select a sort of pale blue.

Something about there.

I'm quite happy with that.

And now our material has a blue color.

So that's our launchpad.

Done.

When you're moving around the viewport like this, you might want to move the camera to the
right or

to the left.

You can easily do that by holding shift.

And then when you click your middle mouse button in and drag your mouse around, you will
pan the camera

at whatever orientation it currently is.

So now if I drag my mouse to the left, I'll move the camera straight right, and I can look all the

way over to the other side of the screen, rather than having to fiddle around by rotating the
view.

So I'm going to create another node that is the landing pad.

I could copy this and edit it, but I'm going to show it from the ground up again just to reinforce

how you do those steps.

I'm going to hit select the root level and I'm going to add a new child.

I'm going to add a box 3D.

I'm going to move it over to around where I want to land.

Somewhere around here I think.

And then I'm going to set its size to two meters on the x axis, two meters on the z axis, and the
height was 0.4 I think.

There we are.

I'm going to enable use collision under the transform property.

I'm going to move it up to 0.2 so it's no longer clipping through the floor.

And then I'm going to give it a color by selecting the material and adding a new standard
material.

And within there I'm going to scroll down to albedo.

Open the color property and set the color to red.

So I'm going to drag to a value that's a bit more readable and pick a sort of orangey red there.

Now I want that to be a bit more vibrant.

And so I'm going to go into the hue, Saturation and Value tab within the Color Picker.

And I'm going to increase the saturation.

So it's a much brighter red.

But decrease the value of it.

So it's a bit darker and I think I'm happy with that.

So I'm going to click off of it.

And now we can see we have a blue launch pad and a red landing pad.

And I've been very silly because I forgot it's supposed to be green.

So let's go ahead and change that over to a green color on Hue Saturation value.

I'm going to keep the same saturation of value, but change the hue over to a green.

Something like that.

And now we have a green landing pad.

And of course we want to rename it to Landing Pad.

And with that, we have something approaching a level we can get started with.
In the next lecture, we are going to get our rocket into the level and work a bit more on the
code

for moving that from the launching pad to the landing pad.

Instantiating the player


In this lecture, we are going to instantiate our player scene in this level as well as finish off
getting

this level set up.

I'm actually going to start things off this time with a challenge, reinforcing something you've
done

twice before, but this time in the level seen.

I want you to add a world environment to the level.

At a directional light 3D to the level.

And then add a camera 3D to the level and try and aim it so that you can see both the launch
pad and

the landing pad.

And of course, in a few seconds you'll get to see me.

Give that a go.

I will see you in a moment.

I wanted to start off with this challenge, because knowing how to add a world environment in
a directional

light is very important whenever you're setting up a scene, as you might be able to see things
otherwise.

So it's good to get that hammered home.

So if you look at the top of the viewport, there are the three vertical dots.

And in there we have our preview son and our preview environment.

And click the Add an Environment Scene button and the Add Son to Scene button.
And now when we run this level, it will have the preview environment we can see in the
viewport.

Next we want to add a camera 3D.

We select the root node, we hit control and a search for camera 3D, which clearly I've done
recently.

And select create.

So making sure that camera can see these two points requires a little bit of fiddling with its
position

and its rotation.

What I like to do is I like to drag it roughly into position.

So I'm going to use the 3D gizmo and move it back until I think it can about see those two
points.

And then I like to change over to the preview view.

Now you can see we are looking straight on at the side of the stage.

We actually want to angle the camera down a bit.

So whilst still in this preview mode, I'm actually going to use the values in the inspector to
update

the transform properties so that I can see in real time how it looks.

So with the camera 3D selected, scroll down, expand the transform dropdown and in here I
want to move

the camera up.

I actually want to move it closer.

I think I went too far out.

I'm going to change it to about.

Uh, closer than that.

Yeah, about 12m.


Looks good.

I'm holding shift and dragging to have a bit more fine grained control.

And then I want to rotate the view down a bit.

So I'm going to hold shift and I'm going to drag down to decrease the x rotation minus.

Oh -12 looked good.

I'll type that in.

And now I'm seeing I can see a little bit of the underside of the stage.

So I'm actually going to move the the camera higher up.

And now I'm noticing I can see the back corners, so I'm going to move it closer again.

And I think that's something I'm happy with.

So now when the game runs, we'll be able to see the landing pad on the left and the the launch
pad

on the left and the landing pad on the right.

So I can just run that, try and see it in action.

And then I think I'm going to be prompted to save the scene.

There we go.

I can save this scene.

I'm going to call it Level scene.

In fact, I'm going to put it in a folder.

I might want to group things with this level scene.

So I'm going to create a folder in the root directory in the top right I can click create folder and

I'm going to name it level and hit enter.

Now we have an empty folder called level where we can keep all of these scenes and scripts
related to
our level.

So I will save it in there.

And now the game will run and we can see those two points, although we can still see the back
corners.

So I'm actually going to move it a little bit closer because the viewport doesn't have exactly the
same

dimensions as the window we're running.

It wasn't perfectly showing us what it could see.

So.

Although actually now that I've relaunched it, it is perfectly showing me what it can see.

So let's just drag that until we can't see the corners of the level at least.

I think that looks good.

I'll try rerunning it to make sure this looks okay to me.

And we can see after saving that level in its own folder, we now have a level folder in the file
system

and that contains level seen.

So the next thing we want to do, I'm going to exit that preview and collapse.

Collapse that output is we want to add our player to this scene.

Now we can instantiate the player in two ways.

We can either right click on them in the file system and click instantiate.

Or we can right click on the root of our level scene.

And we can click Instantiate Child Scene.

And it will let us search for the player scene, which we can see there, or the level scene.

I'm going to do this route and instantiate the player scene.

So instantiating effectively creates a copy of our player in another scene, and whenever we
edit our

original player scene, those changes will be reflected in any instantiated players in other
scenes.

It's a very, very powerful system.

And we now have the player, and the player has been positioned in the middle of our level.

We can also see that the player has got that camera attached to them.

And actually the player has a few nodes inside it that we do not want in this level scene.

So I'm going to save this and I'm going to open the player scene.

Now when you instantiate a scene in another scene, you can quite quickly get to them.

You can see I have this player scene, and it's got this little clipboard with an arrow to the right

of it.

If we click on that clipboard, it will open that player scene in the actual main viewport.

So if I just click there, it will straight away open up our player.

Now because our level has a world environment, a directional light and a camera, we don't
need any

of those in here.

So I'm going to delete all three of those nodes.

And then save the player scene.

And if we reopen the level, those changes will have already taken effect because this just loads
whatever

the latest saved version of that scene is.

Now we want to move the player over to the launch pad.

There's a nice, easy way we can recenter the player on the launch pad, and that's to do with
relative

transforms.
Because when you move a node, all its children move relative to it.

When I set the player as a child of another scene, its position will become relative to that
parent

node.

So the player, its transform at the moment says it's at position 000.

If I make it a child of the launch pad and now look at the player, the player is still at 000, but

its position has been set to 7.5, -0.2.

That's because this global 000 position is 7.5 to the right of that launch pad and 0.2 down.

If I now reset this position, it will have its position set to 000, but locally to that launch pad.

So now it's centered where that launch pad is.

And I can move it up a little bit.

And now it's effectively starting on the launch pad.

Now, I don't actually want it to be a child of the launch pad.

So now it's got that new position.

I can reparent it to the level and it's going to stay where it was, but it's going to have its
position

be relative to the whole level.

So now it's set to -7.5 and 1.4 ish up.

I'm actually going to neaten that up a little bit and set it to exactly 1.4.

And now we have a player in our scene.

And if we run this.

A script on the player should still work.

So when we push space, it should go up and when we push left, it should rotate left.

We push right.
It should rotate right.

So that's it for this lecture.

Next time we are going to learn about rigid bodies and really improve the way the player script
runs.

Rigidbody3d and physic


In this lecture, we are going to learn about the rigid body 3D node and how to get set up.

Applying physics to our 3D scenes.

So where we left off, we have our player in our scene, but it has a lot of aspects of it that are

very lacking right now.

For a start, gravity isn't applied to it.

It can own, so it can only move upwards whenever it moves upwards.

It's not moving up relative to itself.

It's only ever moving globally upwards, no matter how it's related.

For example, if it was angled like this, we'd want it to move that way.

But at the moment when we push up, it moves in the direction of the green arrow.

So in order to tackle that, we are going to need to introduce a new kind of node for handling
physics

operations.

And that is a rigid body 3D.

So a rigid body 3D is a 3D physics body that is moved by physics simulations.

So we control the body itself by applying forces to it.

We can apply force in a direction and it's got a mass.

And depending on what its mass is and the size of the force we apply, it will move in that
direction.

And if we want to rotate it, we apply a different kind of force called torque.
And those are the two key functions and two key forces we are going to use to control our
body.

So we want to take our body that is currently a node 3D and turn it into a rigid body.

Now we could just recreate the scene as a new one, but I want to keep what we've done and
show you

how you can change what a scene is.

Well, change what node a scene is.

So I'm going to open the player scene and in here I'm going to select this root node.

And I'm going to right click on it.

And in the dropdown you will see an option called Change Type.

Change type lets us re select what kind of node this node is.

So we've got this change type bar at the top.

And I can search for rigid body 3D.

So I'm going to click change.

And you can see in the inspector on the right that the node is a rigid body.

But the actual symbol has an updated.

The reason the symbol is still a bit confused is because we have a script attached to it.

I'm going to open that player script and in there you can see the top line says it extends a node
3D.

So currently this is a script that gives us all the functionality of a node 3D, but doesn't give us

the functionality of a rigid body 3D.

I'm going to change that first line to say rigid body 3D.

And now this script will give us all of the properties of the rigid body 3D.

I'm going to save that scene, and I've noticed that the actual symbol for the player doesn't
update
until this scene is closed and reopened.

So I'm going to close that player and I'm going to well, you can already see in the level the
player

is updated to have the correct symbol.

But if I reopen the player scene now, we can now see that this node is a rigid body 3D.

The scene is a rigid body 3D.

We've got this error message.

The error message is essentially saying that our body can't interact with the physics of Godot
until

it has a collision shape, and now a collision shape is similar to a mesh.

It's a shape, but it's a shape that's only used internally for figuring out how an object is
colliding

with another object.

I'm going to add a collision shape to this player.

I'm going to with the player selected in the root node, hit Ctrl A to open the Create New Node
dialog,

and I'm going to search for Collision Shape.

And its collision shape.

3D is what we want.

Going to select create and we now have a new collision shape node.

This collision shape node is saying that it currently doesn't have a shape set in its shape
property.

If we look over to the inspector, that collision shape can have a variety of shapes attached.

If we click the drop down to the right of shape, you'll see it could be a sphere, a box, a capsule,

a cylinder.

And then there are other interesting ones like world boundaries and height maps.
I'm going to select the same shape that our mesh has, which is a cylinder, and you can see if I
make

the mesh instance invisible.

We have this cylinder here that is exclusively used by the physics engine for checking whether
this

body is colliding with something.

So when the bottom of this is resting on the floor, our rigid body will stop falling through the
floor

at that point.

With this rigid body, there are a few properties we want to update.

For a start, when we're moving our player, they're going to only be moving up and rotating
around

that Z axis and then landing somewhere else.

So we don't want them to rotate along any other axes, and we don't want them to move in or
out of the

screen.

So I'm going to select the rigid body and in its properties.

Scroll down until I find Axis lock.

And in axis lock I'm going to limit a bunch of the motion and rotations that can be applied to
this

rigid body.

I'm going to lock linear z movement so it can no longer move on the z axis.

And then I'm going to lock angular x and y rotations.

So now our shape can only move on the x and y axis.

So it can only move this way and this way.

And it can only rotate this way.


There are two other properties I want to tweak.

If we go to the linear dropdown there is an option for damping.

Damping lets us slow the motion over time and we'll just make the movement a bit more
sluggish, which

may not sound appealing, but actually, when using a physics simulated body, having damping
really

makes it feel a lot better.

I'm going to bump the linear damping up to one, and I'm actually going to bump the angular
damping

up to three.

That's going to mean the rotation is a lot, is much more damped than the movement is, but it's
going

to mean that the shape loses its rotational velocity a lot quicker.

So we have a bit more control over the player as they rotate.

With all of those properties set up, we can start to look at the actual controls for this rigid
body.

I'm going to open that player script and make it take up the full screen.

And we're no longer going to be controlling it by accessing its position dot y and increasing it,
or

rotating it with rotate Z.

We're going to be applying forces.

So we want to move the player up.

If we move them up naively, what we can do is we can apply a central force.

And that's going to apply a force that will move the shape in a direction of our choice.

And I'm going to move it globally upwards.

Now when you have a vector three, we could define it as by passing in the values of the x, the
y and

the z axis.

But actually there are a bunch of predefined vector threes that we can use as shortcuts.

You hold Ctrl and click on the up part of vector three point up.

It will open the documentation for vector threes.

And you can see that these are a bunch of constant vectors with set values.

So vector up here is exactly the same as declaring a vector three with zero on its x value, one
on

its y value, and zero on its z value.

So it's just a shorthand for this particular vector.

I'm going to click the back arrow in the top right to go back to the documentation.

You can alternatively click on the player dot file name in the top left here to go back to the
player

script.

So now we can see this is applying a force straight upwards.

I'm going to multiply that by delta because we want to make it frame rate independent it.

And lastly, we're going to want to choose the magnitude of the force.

So you can essentially split a vector three into two parts a direction, what way the vector is
moving

and a magnitude how far.

Imagine aiming throwing a ball in a direction, and the magnitude is how far you're going to
throw it

once you've picked your direction.

At the moment our shape is quite heavy and the value of delta is quite low.

So this is a very small force we're applying.


I'm going to multiply this by 1000.

And that's going to apply a large enough force that we will see the shape start to move if we
play.

So I'm going to save that and I'm going to click run.

I have run the wrong scene though.

I want to run the level.

So I'm going to run the level.

And now when I push space, a force is applied and gravity pulls it back down because it is a
rigid

body with physics simulations.

Now we have vertical motion.

Let's move on to handling rotation with torque.

In the left function.

We are currently rotating on the z axis because we're rotating around the z axis.

We want to apply torque around our z axis, so I'm going to apply torque.

And in there I'm going to create a new vector three.

I want to pass 0.0 into the x axis, 0.0 into the y axis, and then an amount of torque into the z
axis.

I'm going to pass in 100 because as before, we need quite a large number because we're about
to multiply

it by delta.

And then I'm going to multiply it by delta.

So now when we push the left arrow key, torque is going to rotate our shape.

I'm going to run that scene.

Spacebar moves me up.


The left arrow key rotates me left.

Let's move on to our challenge.

Given that we've just applied torque to make our shape rotate left, I want you to do the same
thing

in the opposite direction and make our shape rotate right.

You still have all of the boilerplate code for rotating on the z axis using UI, right?

Which should lead you in the right direction to figuring out how to use torque to rotate
clockwise.

And I will see you back here in a moment.

Welcome back.

So we want to apply torque to rotate clockwise when we press the right key.

I'm going to copy everything we said for left, because we're going to be doing a very similar
action

in the same way, rotate Z controlled, whether it was clockwise or counterclockwise, using
whether

the value is positive or negative, we can change whether our torque is positive or negative to
control

the direction of rotation.

So I used control C and control V to copy and paste that apply torque function in.

And then I'm going to add a negative symbol before the 100 in the apply torque function, to
make it

act in the opposite direction around the z axis.

And now when we run that.

I can hit space.

If I hit left, it'll go left.

If I hit right, it'll go right.


So now we can finally move on to making us move up relative to the direction our rigid body
is facing.

So we know we have a global upwards direction stored in vector three point arc.

But if we want to find out what direction is locally upwards, we need to access a rotation that
is

known as a basis.

So our character stores what way it thinks up, left, right, forward and back is in a object called

a basis.

And we can get whatever direction is locally upwards in the Y property of that basis, that Y
property

is effectively a vector pointing locally upwards.

And it's also got a z value pointing locally forwards and an x value pointing locally to the side.

So we're going to want to use this basis y value instead of vector three point up to move
locally up

instead of globally up.

But this is a simple enough change.

Then we just want to take vector three up and we want to swap it out with basis dot y.

And now that is giving us a local up direction that we're multiplying by delta and then by
1000.

So if I run this thing.

I pushed space.

It'll go up.

If I rotate right and push space, it'll start going to the right because up is a value slightly to

the right.

If I push left, it will start going to the left because up is slightly to the left and depending on

how steep that is, the amount it moves will be greater or lesser.
And now we have a physics simulated rocket ship that we can control and make land on our
landing platform.

In the next lecture, we are going to look in more detail at binding inputs, so we can start using

more convenient keys than the left and right arrow keys.

The Input Map


In this lecture, we are going to learn the best way to handle inputs from the player and
customize

the keys that control the player.

So at the moment we are controlling whether the player moves using these built in input events
UI except

UI left and UI right.

These are built in actions designed to help the user navigate user interfaces.

Now we don't want to use these built in actions.

We want to define our own, and we want to choose what keys will control that action.

And this is a very powerful system because it lets you do things like have a key on a keyboard,
control

an action, and have a different key, well, a different button on a controller trigger the same
action.

So with that all said, let's dive into the input map.

If you go and look in the top bar, look at the menu buttons, click project, and in the drop down

menu click Project Settings.

You'll see that we have a tab called Input Map.

If you click on the input map, this is where we can define a new actions and choose what keys
control

them and see built in actions.

At the moment this is empty, but UI left, UI right and UI accept are in here.
They're just hidden.

We can click this toggle in the top right to show built in actions, and you will see all of the
actions

that are built in so that UI accept action we were using to make the spaceship fly upwards was
controlled

by pressing enter or space on the keyboard, and UI left is pressing the left key or pressing left
on

a directional pad, or pressing left with a joystick.

We don't want to use those built in actions.

We want to define our own.

And we can add a new action by clicking on this text box at the top that says add new Action,
and we

can type the name of an action we want.

We want a boost action.

That is, when we move upwards that's going to be controlled by something like the spacebar.

So I'm going to type boost in here.

And then I'm going to click the add button to the right of that.

And now the boost action has been added to our input map.

Now we want to attach key presses to this boost action that will trigger it to the right of it.

There's this plus icon.

And this bin icon bin will get rid of the action.

Plus we'll add new key presses to the action.

Click the Add Event button.

And now we get an Event Configuration window.

And in here the game engine is currently listening to keyboard presses.


So if I that's you can tell that because it says listening for input here.

So if I push the Or S or A it will select whatever key we just pushed.

We want to bind the boost button to the spacebar.

So I've pushed the space key and you can see it's selected space physical as the top.

That is the key we want.

So I am going to click okay.

And now you can see boost is triggered by the space physical key press.

I also want to bind it to the W key.

Because typically your control movement with W, A, S and D and PC gamers tend to associate
W with

moving forwards.

So I will click the add event button.

And this time I will push the W key and it's detected the W physical key press and I can click
okay.

There are additional options here.

For example, you can make the event only trigger when the user is holding alt and pressing
that key,

or holding shift and pressing that key or any of the other typical modifiers.

But we just want w.

Now we have boost triggered by those two key presses.

I can close the input map and I can change our.

Function that triggers the boost to.

Instead of using UI, except use the boost input event action.

Now because that event is in our input map, we are going to get code completion here.
If I hold control and hit space while is action pressed is empty, it will open code completion
for

us and start predicting what actions we might want to enter.

And because boost is the only action we've defined, that's right at the top of this list above all

of those default actions that were already there.

So I'm just going to select boost from this list.

And now it's all hooked up.

When we push the boost key it will apply our force upwards.

And if I run.

I can hold W and it'll move up, which it did not do before.

So that means we can move on to our challenge.

I want you to add two more actions to that input map.

I want you to add one called Rotate Left that is bound to the A key and the left arrow key.

And I want you to make one called rotate right.

That is bound to the D key and the right arrow key.

And then afterwards I want you to update the player script to use those two new actions
instead of left

and right.

And I will see you back here in a few moments.

Okay.

Welcome back.

Let's define those two new inputs.

So of course we set up those inputs in the input map.

So back in project Project settings input map we want to define a new action, one of them
being rotate
left.

So in the Add new action text bar at the top I'm going to type rotate left.

I'm going to click add.

And then I'm going to bind two key presses to that.

I'm going to add the A key by pressing A in event configuration and clicking okay.

And I'm going to add another key.

And this time I'm going to press the left arrow key and click okay.

And now rotate left is all set up.

We want to repeat the process for rotate right.

Add a new action.

Rotate right.

I'm going to hit enter this time because that does the same as hitting the add key there, the add
button

there.

And I'm going to add a new key to this.

I'm going to add the D key and click okay.

And I'm going to add another key.

And I'm going to click the right arrow key and click okay.

Up to events in our set up.

I can close this and I can replace UI left and UI right with rotate left and rotate right.

I'm going to select the UI part, get rid of it and type rotate in and we've got rotate left and
right.

You can actually see the code completion is already trying to offer us the two available input
events
from that input map.

It's trying to offer us rotate left and rotate right.

But I've typed it out there and for this one we want rotate and this time rotate, right.

And with that done, when I run the scene, I should be able to control it with the A and D key.

I can hit W to go up, D to rotate right and A to rotate left.

And that's how you add inputs and select what keys control them.

It's a very powerful system and really well worth knowing the ins and outs of.

In the next lecture, we are going to start detecting collisions to find out when our player has
landed

on this landing pad.

Collision Detection
In this lecture, we are going to learn how to detect when a player touches the landing pad.

So there are a whole host of different ways to detect when one object starts colliding with
another.

But there is one method built into rigid body 3DS.

And in order to understand that, we need to know a little bit more about signals.

So signals are the main tool for letting game objects communicate with each other.

Objects like nodes, but not limited to nodes, can emit signals in code.

You can connect a signal to any number of functions provided the parameters match.

So for example, if I have a signal that is trying to send an alert out with a string parameter, the

method I connect it to has to at least accept that string parameter, or there will be an error.

You can connect signals in the editor or in code.

And I'm going to show you how to connect signals from the rigidbody 3D in the editor to
code.

So our first step, I'm going to exit distraction free mode and go into our player scene.
Change the 3D mode so we can see we're dealing with just our player.

We want to edit this player scene, because if we edit the player that's in the level, it will only

affect that instance of the player.

And we want this to affect any player we instance in any other scene.

So we can access the signals that a node has through a tab next to the inspector, I'm going to
select

the player root node in the scene tree.

And over in the inspector on the right I'm going to click the node tab at the top.

And this gives us a new window with some interesting things.

Firstly we get signal options and just next to that we have group options.

And you can see we have signals that come from the rigidbody 3D and from the various nodes
that rigidbody

3D inherits.

We want to detect when another node or another body like the landing pad touches our player.

We can do that with the body entered signal.

Whenever this body touches another body, that signal will fire and tell us in code what body
has touched

this one.

So I'm going to click on the body entered signal.

And I'm going to click the connect button in the bottom right.

And that opens up this dialog for connecting signals to a method.

What it's going to do at the moment is it's going to take this body entered signal from this rigid
body

3D, and it's going to attach it to this node.

So the same node that's emitting the signal.


But in this script and it's going to create a method for it to connect to.

We can pick an existing method or we can change that.

But at the moment the default is fine.

It's just going to create a new method in that script that the signal connects to.

So with all the default settings, we can just click the connect button in the bottom left.

Now what's going to change over to the script view.

And in here we can see we have a new function called on Body Entered.

And it takes a body parameter.

And that body can be any kind of node.

So now we want to handle what our script should do.

When our body touches another body.

The first thing I'm going to do just for debugging purposes is print the name of the body we
landed

on.

So I'm going to print without capslock.

I'm going to print body.

Dot name.

Because we've set the names of all of the physics objects in our scene, we should see that print
a

variety of different things.

There's one more step we need to go through for this to work, and that's related to us using a
rigid

body rather than something like a character body.

It's not typical for you to want to check collisions for all rigid bodies in this way, because you

may have very many rigid bodies in your scene.


So you had a room with about 30 bouncing balls in it.

You don't want them all to detect whenever they touch with each other, typically.

So you have to opt into collision detection on a rigid body 3D.

And we can do that in its properties in the inspector.

So exit full screen mode and I'm going to select that root node and go back in the inspector to
the

inspector tab.

In here we can enable contact monitor.

And this is the property that says the rigidbody will emit signals when it collides.

Now the thing is it limits how many contacts it will send signals about.

This just lets you be more performance conscious when you're handling rigid bodies that
might have an

awful lot of collisions, but because we only care about this one player, I'm actually willing to
have

this the number of collisions we are going to monitor quite high.

And we did that with the max contacts reported property that if I hover over it here, you can
see the

tooltip for.

But I'm just going to set this value to about ten.

And that means in a frame up to ten collisions with this body will be reported.

So we really shouldn't be missing much.

And with that, everything should be working.

So if I run the game, I haven't set our level as the default.

So let's do that.

To make life a bit easier, I am going to run the scene and I'm going to select a default scene
because

at the moment I don't want to run the player scene, I want to run the level scene and will
typically

want to going forwards.

So I'm going to click the select box from that selected default scene page, and I'm going to
open the

level directory.

And I'm going to select Level Scene as the default scene for our game.

And now it's running.

I'm going to move it up a bit so that we can see our our output panel.

And you can see it's already said all I've I've touched the launch pad.

That's the first thing I've contacted with.

And if I fly up a bit and go down again, it should say there we go.

We've had another collision with the launch pad.

So what I want to check is what it says on the ground and what it says on the landing pad,
which should

just be the names, but let's see it in action.

We have the floor.

And we have the landing pad many times and then the floor because we fell over.

But perfect.

We now know when we're touching the landing pad.

So we could now use something like an if statement to say if we've touched the landing pad,
win the

game.

And in fact, that's exactly what we're going to do.


So we're going to make that full screen, get rid of the output panel.

And in here I'm going to in fact, let's copy that name.

From there I'm going to hit Ctrl C after selecting landing pad so that I don't accidentally
mistype

it I'm going to say if body dot name.

Equals landing pad.

So this double equals is a essential way of testing equality.

So in an if statement it checks if the condition after the if is true.

And if so does the indented lines of code afterwards.

Exactly as with here.

If this thing is true we do the indented lines.

Here we need to turn body dot name being equal to landing pad to be either a true or false
value.

And that's done with this equality check.

This just turns these two objects into that either true or false value, giving us true.

If body dot name is the same as landing pad, and false if it isn't letting us use it in this if
statement.

So now with that done, I should be able to fly the ship again, and this time it will only print out

the name of the landing pad if we get there.

But actually I want to change that line.

I want to instead say, you win the game.

You win.

Now let's run that again.

And we have a vague win condition.

Even if it's not supported in code, we at least can test out as though we actually win the game
here.

So let's land.

And we win.

Perfect.

Now, this is a very fragile way of testing equality at the moment.

If we ever change the name of landing pad, this little check here will stop working.

In order to get around using this magic string, we can instead opt to use a slightly different
kind

of check to check if that body is the landing pad, and that's going to be using groups.

And the convenient thing about groups is we set groups in a very similar place to where we set
signals

going to exit full screen mode, close the output panel, and I'm going to go to the player.

No, I'm going to go to the level.

And in the level I'm going to select the landing pad.

Uh, or when you've got it selected in the scene tree, you can hit F and it will center your view
on

that object.

So with this landing pad selected, I want to add a little tag onto this landing pad saying this is

a win condition or this is a goal.

And we can do that with groups.

So with it selected in the inspector on the right, click the node tab again.

And this time we'll see the signals.

But to the right of this blue signals button there is a button that isn't selected called groups.

And if we click on that we will get option to add groups to this node.

What we can do is we can add a string in here and it's effectively attached to that body.
We can do a lot of things with groups.

We can check if a body has a group, or we can go ahead and get all of the nodes that have a
specific

group in a scene.

They're very flexible and useful, but I'm going to add goal as the group onto our landing pad.

And I'm going to click add.

And then going to copy that, because this does still use string references, but it's a bit easier

to refactor.

So I'm going to dip over back to our player and I'm going to go full screen again.

And now instead of checking off our body name is equal to landing pad.

I'm going to check if our body is in the goal group.

What I can do is I can check if goal.

I'm going to get the string goal.

And I'm going to check if that string is in body dot.

Get groups.

So our body can have multiple groups.

We could add another goal, another label to it saying it's green, or that it's a target or that it's

movable.

We can add any number of groups.

And so because of that, we need to check if this string is in the list of groups, that is the groups

the body has.

Anyway.

Now when we touch the landing pad, it will use the groups of the body to check if we've won
instead
of the name of the body that we're much more likely to change.

But run the scene.

And see if I can get it.

Way to say you win and it does perfect.

And with that, we can move on to our challenge.

I want you to add a group to the floor box 3D.

And then I want you to detect that group in the players on body entered function.

And then you should print something unique to the output panel.

Okay.

I'll see you back here in a few moments.

Welcome back.

So the first thing we need to do is add a new group to this floor.

Winter to distraction free mode.

I am going to select the floor in the scene tree.

I'm going to hit F so I can see it.

There we go.

We have the floor selected.

And I've still got the group's tab open.

But if you can't find it in the inspector, change it over to the node tab.

Change it from signals to the Group tab.

And I'm going to add a group called hazard.

The reason I'm calling it a hazard is I'm at some point going to make it so that when the player
touches
something that isn't the landing pad, they'll crash.

So everything that isn't the landing pad is a hazard in my eyes.

So I'm going to add a group called hazard.

I'm going to copy that and I'm going to return to the player script.

Into full screen mode.

And now I just want to copy what I did here, but this time for hazard instead.

So on the line below, I'm going to say.

If hazard is embodied.

Bodykit groups.

And then I'm going to print something unique was the last part.

So I'm going to print.

You crashed.

And that's all there is to it.

So let's run that scene.

And I'm going to fly and I'm going to touch the floor.

And you crashed.

There we are.

And with that, we've learned how to add collisions to our game and how to use signals and
groups at

the same time.

In the next lecture, we are going to start improving our code by learning all about the export
annotation.

The Export Annotation


In this lecture, I am going to introduce annotations and how we can use them to make our code
easier
to test.

So we've encountered a bunch of keywords so far.

Words like if and func and var that are all reserved words within the engine.

There's an extra set of these reserved words that are known as annotations, and they begin with
the

at symbol and they have a distinct orange highlighting.

They are things like at export Onready, RPC, warning, ignore, and there are a few others.

They're all grouped together so that we can reduce the number of reserved words that are in
the engine

and improve code completion when we're trying to use those annotations.

The annotation we're going to start with is the export annotation, which is really useful for
making

your code easier to test.

So at the moment, in something like our process function, we are applying a bunch of forces
that are

all using magic numbers.

And magic numbers are numbers that we've hardcoded into our functions that someone
reading it doesn't

necessarily know what they are or mean.

So something like this 1000 is the amount of thrust.

We're multiplying our direction and delta value by.

But someone reading this wouldn't necessarily know what that 1000 means.

And we can use variables to replace those magic numbers.

And the way we'd do something like that is by at the top of our script, declaring a new variable
of

the type.
So I'm going to create a variable called thrust.

And I've said it to be a float.

And I'm going to set it to be equal to that 1,000.0.

Now we can go to our function and we can replace that variable with thrust.

Now this is nice and we know if we want to change the amount of thrust we've got, we can go
to where

our player is.

We can open this script and we can change this value here.

But if we want to make things less code centric and a bit easier to edit in the editor, we need to

export the variable, and exporting a variable makes it available in the inspector.

I'm going to do that right now by just before this variable keyword adding the at export
annotation.

So I'm going to type at export.

And you can see it's doing code completion for a bunch of different kinds of export.

We don't need to worry about those at the moment.

What we want to do is we want to save this, and we want to change over, to have our panels
visible

on the side and go into our player scene.

And select the player and go over to the Inspector view and you will see at the top of the
inspector

we have this new variable called thrust.

And that is a value that's 1000.

And we can type a new value in here.

And I think we can drag it from side to side to increase or decrease it.

So this is really nice for testing.


I can do something like this.

Let's click on this inspector and make it floating.

There's I'm going to click the three dots in the top right of the inspector and select Make
Floating.

And now it's a window that can move around independently of my screen.

The reason I've done that is I want to be able to use this next to the running game window in a
second.

So I'm going to start running the game.

I'm going to have that inspector panel open, and I'm going to have this game panel open.

I can click on the to without losing view of the other.

At the moment when I push the spacebar, I have 1000 newtons of thrust being applied
vertically every

frame.

What I can do is I can try out a different value.

Let's try something like 750.

So 250 less.

Let's see how that affects my thrust.

You can see the ship is much slower now.

And if I increase this to something like 2500 it'll be really, really fast.

There we go.

And it's probably going to come crashing down.

There we are.

So this lets us test new values much quicker than, say, going back in and updating the value in
code.

We can actually do a little bit more to make this nicer.


One thing we can do is we can add a description for this variable.

So someone hovering over it, you see in that tooltip it says no description.

We can give a description there.

And we can also set boundaries for this value.

So it can't go above or below certain values.

So I'm going to close this and I'm going to close that floating window.

So this resets back to its original position and open this script.

First things first, I'm going to add a definition for thrust.

And the way we do that is with hashtags.

You can see before the process function we have this line here that says process is called every
frame

and tells us what delta is.

That's a comment.

You can create a comment by typing hash, or you can turn any line into a comment by hitting
control

and k, and it will comment the code out.

And when something is a comment, it's just treated as words.

It doesn't execute like code, so it lets us write things about our code without affecting any
code.

If we do two hashtags, it will create documentation for this at export variable.

So now this will set the description when you hover over it in the inspector.

So I'm going to set this to how much vertical force to apply.

When moving.

And I'm going to save that.

I'm going to exit distraction free mode, and I'm going to try and hover over that property.
And now you can see it says how much vertical force to apply when moving.

So we've got documentation for that exported variable.

The other thing I wanted to do was set a range.

Swirly arrows pointing out when you type at export there is a bunch of code completion, and
that's

because there are many different types of export.

You could export a file or an enum, or you can set categories in the inspector.

There's lots of different things you'll want to export, and you'll want what you are exporting to
change

what that inspector shows up as the available options, so we can set an upper and lower limit
for our

float with the export range.

Annotation.

So if I go back here, I go to the end of our export and I type underscore range.

You'll see.

It gave us some code completion there.

And this lets us pass a parameter to the export.

So just like when we have any of these functions with parameter passing delta into process or
passing

a force into apply torque, we can pass some values into this.

And the first value we pass in is going to be a lower boundary for the range.

And the second value we pass in is going to be an upper boundary for the range.

So I'm going to set my minimum boundary to be 750 because that was quite slow.

And I'm going to set my upper boundary to be 3000 which is really big.

But those should be sensible boundaries for our player.


So if I save that exit distraction free mode look over here.

You can see below thrust.

We have a slider and we can slide all the way from our minimum value of 750, all the way to
our maximum

value of 3000.

And that's a really handy way to test things out.

So we've exported our range for our thrust, but we still have two more magic numbers in our
torque

values for our challenge.

I want you to create another exported variable for torque thrust.

This doesn't need a range.

I just want you to export a float.

And then I want you to replace the 100.0 magic numbers in the applied torque functions with
this new

exported variable.

All right with that.

I will see you back here in a few moments.

And welcome back.

So the two values we want to change are the 100.0 here and the 100.0 here.

We are going to create a new value that's exported and just replace those numbers outright.

So below this I am going to export another value at export var.

I'm going to call this torque thrust.

And I'm going to set it to be a float, and I'm going to set its default to be 100.0.

Now I can take that torque.


Thrust value.

I'm going to Ctrl C to copy it and I can paste it in these two slots.

So I'm going to hit Ctrl and V with the 100.0 selected there.

And with the second one it's -100.0.

We don't want to lose that negative sign, but we do want to replace the 100.0.

We can just make it negative.

Our torque thrust value.

So now when we rotate left we will have our torque thrust value applied.

And it will go counterclockwise.

And when we apply the negative one and rotate right it will go clockwise.

And I'm going to be able to edit this.

So let's do the same thing I did earlier to make that value.

That inspector floating I'm going to collapse that down.

Hit save.

We can see our torque thrust values visible here just below the thrust, and doesn't have the
slider

because we didn't set a range yet because we don't know what the upper or lower bounds
should be.

I'm going to click these three dots in the top right of the inspector and select Make Floating so
that

this window floats.

It's worth noting if your screen is big enough or if you're running on another monitor.

You won't need to make this floating.

It's just because I'm working in a confined space.

This makes life easier.


And then after that, I am going to run the scene and put these two by each other.

So at the moment, if I go up, I rotate right and left.

It moves quite slowly.

I'm going to set it to be much bigger and we should see just how much torque is applied now.

You can see that's pretty ridiculous.

But it means we can customize that value and we can test out new values of talk as we go.

And now this is a really essential skill to learn, because whenever we're creating these scenes,
like

the player or other ones, we're going to want to expose variables.

Because when we instantiate those scenes, the scenes where they're instantiated might want to
customize

those values.

So I'm just going to close this.

And we're going to see at the moment we have set this scene to have a thrust of 750 and 1000
respectively.

Those aren't the defaults.

So we get an undo value.

I'm going to set those back to their defaults, because actually 750 was a bit low.

Actually for testing, I am going to up the torque to 200, because I'm going to show you that if
we

go over to the level seen where the player is.

So this has an instance of player over here, and in here it's got torque set to 200.

It may be on one level I want the ship to have a higher thrust or I want it to have lower torque
if

I change it here, if I make this ship in the level, have 2000 thrust and save it, if I go back to
the player, it won't have overwritten these values.

It's only that instance that has the new exported values.

And that's one of the main reasons why exporting a value like this is so helpful, because it
means

we can have different places, have different values for the same variable.

So that's an introduction to the export annotation.

In the next lecture we are going to be making new obstacles for the player to collide with and
actually

making the player get reset to the start of the level when they crash.

Crashing and Respawning


In this lecture, we are going to modularize our code with functions and introduce the scene
tree in

code, which lets us restart levels and quit the game.

So presently in our collision detection, we check if the body we collide with has a goal group,
and

if it does, we just print.

You win.

And if it has a hazard group, we print you crashed.

I'm going to create new functions that handle what we should do, all the different steps that we
should

do when we either crash or win.

So we can define a new function in the same way that these process functions and on body
entered functions

are defined on a new line at the end of the script.

I'm going to start the definition with func, and then we need to pick a name for our function.

I'm going to call ours Crash Sequence.

Following that, we need an opening and closing parentheses.


In here we could define parameters.

We might want to pass to the function.

But we actually don't need to pass any information to this.

And now we have our optional typing where we can say what this function returns to the place
that it

was called.

But we don't want to do anything like that at the moment.

And the way we tell it that is by putting a hyphen and the greater than symbol, and then typing
out

void to say that it shouldn't return any information.

After that we put a colon, and then when we hit enter we'll be indented and everything on
these indented

lines will be run whenever we call the crash sequence function.

I'm going to make this print something slightly different so that we can see it in action.

I'm just going to print.

Kaboom!

And now we want to replace our hazard detections print function with this new crash sequence
function.

So I'm going to return to if hazard in body groups.

So the place where we've found out okay the body we've touched is a hazard.

Instead of doing this print here I'm instead going to call this function.

And that means we can just have lots and lots of things happen as part of that crash sequence
being

started.

So I'm going to type crash sequence.


And I'm an opening and closing parentheses where we could pass in parameters if it took any.

And now whenever our script gets to this point, it will jump down and start running everything
in here.

And you can see if I hold control and click on that.

It takes me to the function we've defined.

So we can see that running.

Right now I'm going to run the scene.

And I'm going to touch the floor.

Kaboom.

So it's using our new function.

One thing that was interesting there is our player still had a very high thrust, and that's because

I didn't reset any of the properties I fiddled with in the last lecture.

So let's do that quickly.

I'm going to exit this view.

I am going to go to the player scene.

I'm going to select the root node and I'm going to reset torque thrust.

Thrust is okay here.

So I must have overridden thrust in the level scene.

So I will go to the level I'll look at the player here.

And here the player has their thrust set to 2000.

And I'm going to reset that to the base.

So now that's reset.

And we have this new function call set up.

Now in order to find out how to do new and interesting things with the level itself, I'm going
to need

to introduce the get tree function.

So get tree is a function that is globally accessible.

We can call it anywhere and it will give us access to the scene tree in code.

And the scene tree actually contains a bit more than what we see in the top left when we're
fiddling

with the local scene tree for our actual scenes.

The same tree that we access when the game is running contains whatever our running scene
is.

The viewport when we launch the game, and it's what's in charge of our game.

Looping and updating all the process functions.

Using this sentry object, we can change, restart and quit levels.

Pause the game and do a whole bunch of other things.

So, returning to this crash sequence after we print kaboom, I am going to get access to the tree
and

we do that with the Get Tree function.

You can see the code completion was showing up there for gentry at the top.

It's this function here, and it gives us access to a whole load of extra functions.

So for example, create timer, create a tween.

You don't need to know what those do.

Quit.

Reload.

Current scene.

Reload.

Current scene is actually the function I want to call, and what that does is it unloads whatever
the

running scene is and then restarts it from the beginning.

So now whenever our player crashes into a hazard, our scene will stop and reload and the
player will

respawn back where they started because the whole scene has reloaded.

So let's try that out in action.

I'm going to run the scene.

The player should move at a normal velocity, and if I touch the floor, it should reload the
scene

and they'll go back to the start.

There they go.

And we have the kaboom in the log as well.

That's how we reload the current scene and we can move on to our challenge.

So I want you to create another function similar to the crash sequence function I just added.

And I want you to call it complete level.

And I want you to call that function when the player touches the landing pad.

So when they meet the object with the goal group.

Within that function.

Just like get treat reload current scene, I want you to call the get treat quit function when they

touch the objective at the end of the level.

All right, that's everything.

I will see you back here in a few moments.

Okay.

Welcome back.
We want to define a new function just in the same way as we did with crash sequence.

Go down to the end of the script and I'm going to define a new function.

And this one is called complete level.

Func complete level.

It takes no parameters.

So just open and close parentheses and it doesn't return anything.

So I'm going to the hyphen the greater than arrow and type in void.

In here.

I'm going to print level complete.

That wasn't part of the challenge, but I'm just going to replace the existing print and we want
to

call the get quit function exactly the same way as here.

We are going to type in get three.

Don't and then quit all one word and you can see that function showing up here.

And what that function does is it will exit our game completely the same as us clicking the
stop button

or closing the window.

So now.

I need to remember that.

I also need to call this function when we are in our on body entered function.

If the body we've touched as the group goal, we want to call the complete level function.

And that should be everything.

So if I run the scene and I fly and I touch the floor.

Our level reloads.


And if I run the scene and go over to the end.

The whole scene will quit.

There's one extra thing that I think's helpful to know about when it comes to understanding the
scene

tree, and that's knowing about the remote view when the game is running.

So I'm going to run the game over here.

I'm going to move it to the right.

And you will see that on the left in the scene tree there are these two tabs.

There is one called local and there is one called remote.

Now local is showing us the scene tree for this level scene but remote.

If I click on that and reopen, this actually shows us our scene tree as it's running.

In fact, I'm going to make this floating so that I can see them side by side.

There we go.

Remote actually shows our scene tree as it's running.

So if I click on this route, this is what we're getting access to when we're accessing the scene
tree.

I move this to the left.

You can see it's got a bunch of information about our window in the inspector.

It's got information about its minimum size.

And it's what holds all the functions like reload, current scene and all the rest of that stuff.

And when our game's actually running, our level gets instantiated as a child of that root node.

And this gives us access to some cool things.

For example, the tree has a function to load a new level.

And when we do this scene gets instantiated and a new one gets instantiated to replace it.
This can also be very helpful for debugging our level in real time, because we can do
something like

click on the level and expand it and look at whatever the current position of the player is
separate

from the position of the player and the level that won't have updated.

All right.

And with that done, you should know a bit more about creating your own function calls and
using some

of the built in get tree function.

In the next lecture, we are going to be progressing onto new levels when our player character
touches

the end goal.

Loading The Next Level


In this lecture, we are going to learn how to export file paths so we can use the landing pad to
load

subsequent levels.

So previously we've learned how to export floats on our player.

We've exported thrust and torque thrust.

In this lecture we are going to learn how to export file paths, which means we can have our
landing

pad store the path to the next level we want to load when the player touches it, and then that
will

set us up to make any number of levels going forwards, pointing our landing pad to whatever
the next

level should be each time.

So in order to export a variable we need a script.

So let's select our landing pad and let's right click on it and click Attach Script.

And this will create our script called Landing Pad, the same name as the node we're attaching
it to.

And it's putting it within the level directory because that is where this level scene is.

So we're going to click create.

Now we have that new script and we're going to want to export a value.

Now this is going to use the export file annotation which is a little bit different to exporting a
float,

but similar to when we exported a range to define upper and lower boundaries for our float.

So I'm going to start with at export and we're going to get some code completion.

We can see export file is one of the available annotations there.

And it gives us an opening and closing parentheses.

Because we can pass a parameter into this to restrict the number of valid files we can look at.

But I'll show you why we want to do that by not using it first.

So we're going to declare this as a variable.

And we're going to give it a name I'm going to call it File Path.

Now we have this file path.

We can exit distraction free mode, select the landing pad in the scene tree, and you can see
we've

exported file paths of variable.

And we've got a directory button on the right.

So we can select what file path we want.

So I'm going to click that.

And it will open the file system.

And it will let us select any file in our project.

The problem we have at the moment is we can select literally any file.
We can select SVG files, get related files, our file.

But we only want to be able to select scene files like our level.

So I'm going to go back and I'm going to show you how we can do that.

Within these parentheses for the export file annotation, we can pass in a string telling the
annotation

what kind of file we want to have.

And this starts with an asterisk which is a wildcard operator.

That means this can match to any kind of text.

And that will make sense in a second when I follow it with Dot TSN.

So this is saying it will only let us select files if they have any characters at all.

So they can have absolutely any name, but they have to end with the suffix TSN.

So this will restrict us to just viewing scene files.

So now.

If I accept distraction free mode, select that landing pad again and click the open a file prompt.

You'll see we can only select scene files for this.

I'm going to select the level scene file.

This will behave a little peculiarly, but it will work for us for the moment.

At the moment this means we have a reference to this scene attached to the landing pad.

So when we go and land on the landing pad, we can try and load that level, which will do the
same

as reloading the current level.

Exactly the same as when we do get treat reload current scene.

But later on when we make new levels, we'll be able to point that path to a new level.

So now we have that file path.


We need to add our code that will actually load the subsequent level.

And in exactly the same way as get reload current scene and get dot quit.

This will use the tree because that manages our scenes.

So in our player script going to full screen that we want to make changes in our complete level
function.

So at the moment when we use complete level it calls get tree dot quit.

We don't want to call get tree dot quit anymore.

We want to change the scene and we want to change the scene to the file that is stored in the
landing

pad we just touched.

So we want to change.

Quit to change scene.

And this will give us two prompts.

Either change scene to file or change scene to packed.

We want change scene to file because that uses a file path to load a new level.

And we want to pass a file path into here.

I'm going to say I'm going to call this variable next level file.

And I'm going to introduce us to passing parameters to our functions.

So in complete level, we want to pass in a new variable with this name.

I'm going to put that in the open brackets here in the same way as process takes delta in and on
body

enter takes the body in.

This function is going to take a variable called next level file in which is going to be a file
path.

So now whenever we use this complete level function, it expects us to provide a string as well,
telling
us what level we want to load.

And then all of this code inside will run, printing out level complete, and then changing our
scene

to the file with that path.

So back in on body entered.

It's having an error because it doesn't like us not passing in the file path.

We can get access to the file path we saved here.

So now in here we know we have touched the landing pad because it has this goal group.

We can pass in that body's file path in here.

So at the moment this body is the landing pad.

So it has all the member functions and variables that that landing pad does.

And that includes file path.

So I'm going to type body dot file path in here.

Now this is a little bit fragile at the moment.

If we add a goal group to a body that doesn't have that file path variable that our landing pad
does,

this will throw an error, which is something we can make more resilient code to guard around
later

on, but works fine for right now.

So as it stands, when we touch the landing pad, it should reload the current level using this
change

scene to file function.

So let's try that out.

I am going to.

Lie.
A little bit ineffectually, but I did make it.

And then let's touch the landing pad and our scene reloaded.

And that was using the path to this level that was saved within the landing pad.

This means we can now make new levels, and we can change the landing pads file path to
point to the

new levels, and let's dive straight in with that.

Let's make level two.

So we can go in our file system to the level directory.

And within there we have level seen.

I'm going to create a new very similar scene called level two.

And the way I'm going to do that is by duplicating this level I'm going to right click on it.

And in the pop up I am going to select duplicate.

And I'm going to pick a name for this.

I'm going to call it level underscore two and click duplicate.

So we now have a scene called level two.

And it contains an exactly identical scene tree as level one did.

Because it's identical.

We won't be able to see any difference at the moment.

So we want to add something in here that will make us able to see a difference when we load
the new

level.

And the way I'm going to do that is by adding a little obstacle.

I am going to select the floor and I'm going to duplicate that.

I'm going to right click on it and I'm going to select duplicate.


You can also hit control and D.

In fact I'm going to show you hitting control and D.

So now we have this identical box 3D called floor two.

I'm going to call obstacle.

And I'm going to make it much smaller.

I am going to make it three meters wide and three meters tall.

No, three meters deep and two meters tall.

And I'm going to move it up above ground level.

So I'm going to set it to be about here.

So now it's just a little bit of extra height.

We have to go over if we want to touch the landing pad.

But it's the same color as the floor at the moment.

I am going to make that a little bit distinct.

I'm going to select the obstacle and under the material property, I'm going to add a new
material to

it with a slightly different color.

So I'm going to click drop down to the right of material and click New Standard Material.

The reason I'm not editing the one that's in here is because the resource will be shared between
these

two objects.

So if we currently change this brown color to something else, the floors brown color will
change as

well, which isn't what we want.

So I'm going to make a new material.


I'm going to expand that.

We can find the color under the albedo dropdown.

So I'll go down to the albedo dropdown and under color I will use the color picker to select a
color

of my choice.

I'm going to do a sort of magenta color, but a little bit softer and maybe a little bit paler.

You know, we now have a pink obstacle in the way that we need to get over.

And because this obstacle has the same group as the floor, it has the group hazard.

If our player touches it, the level will restart.

So we can save this.

We need to hook the landing pad in level one to redirect us to that level two we've now
created.

So I'm going to click on go into level one, select the landing pad and in the file path exported
property

going to open the file system.

And I'm going to select level two.

So now when we touch that landing pad, we'll get the path to level two.

The player will load the level with that path.

Level two and our game will change over to here and now when we touch the ending landing
pad, because

that's still set to level one, I believe.

Yeah, it looks like it.

It's still set to level one.

When we touch the end, it will go back to the start and we'll be able to replay these two levels.

So let's try running.


It will run our main scene which is level one.

I will fly to the end.

And now we've loaded level two.

Perfect.

And if I can, I'll touch that hazard to show it working.

Let's see.

It caused a crash and I'll try going over.

And now, if I touch the end, we should go back to level one.

Perfect.

That is all running A-ok.

And with that, we can move on to our challenge.

For this challenge, I want you to create another level called level three scene.

I want you to resize and reposition the hazard to make this level visually distinct.

And I want you to update the exported variable at the end of level two, attached to the landing
pad

to direct to this new level three.

And with that, I will see you back here in a few moments.

Welcome back.

So we want to make level three, and we can do that in exactly the same way we made level
two.

I want to go down to the file system.

I want to select level two, this one with the hazard.

I'm going to right click on it and click duplicate.

And I'm going to call this level three.


So we now have level three.

And this is distinct from level two.

We want to reposition and resize this box.

And I'm going to make this a bit tricky.

I'm going to move the box above the player and I'm going to make it much wider.

I'm going to set its x size to about ten metres.

So now if we want to make it to the end, we have to fly below this, which is going to be a bit
harder

I think.

The last step we need to hook this up is to make the landing pad at the end of level 2.2, level
three.

So I'm going to go into level two.

I'm going to click on the landing pad.

I'm going to set the file path to be set to level three point scene.

And with that, we should be able to go from level one to 2 to 3.

Let's see it in action.

I am going to fly up over to the landing pad.

All right, one down.

Let's try and get over this one and hopefully be able to make it onto level three.

And we've made it to level three.

Perfect.

Am I actually good enough at this game to be able to get under there?

Of course I am.

Like a glove.
And with that, you now know how to export file paths and change scenes to new levels.

And with this, you can create absolutely any number of levels by varying the hazards we have
to get

past.

In the next lecture, we are going to start tackling using the tween node to animate changes.

Introduction Tweens
In this lecture, we will start learning how to use tweens to sequence events in code.

So a tween is a whole new concept.

It is an object you can create in code to animate and sequence changes.

So that's worth noting.

It isn't a node, it's just something we can create in scripts.

Its name comes from the animation term for inbetweening, where you would create a point in
between

frames, so it is for animating changes every frame.

Typically interpolating its way there.

Tweens are ideal for simple animations, and you can use them to do a whole bunch of things,
including

animating properties.

So, for example, changing scale over time or changing the position of a node.

They can also call functions and you can make them wait a certain amount of time.

In order to use a tween, we need to create it in code, and then we need to give it a series of
instructions

to perform.

So the case we're going to start with for this lecture is we're going to create a tween with the
create

tween function.
And then we're going to use the tween interval function to make it wait for one second.

After that, we can make the tween call our function that reloads the current scene.

So for example, when we crash our ship, this will make it so that instead of immediately
reloading

the scene on a crash, we will get one second to view the ship ragdolling before we actually
reload

the scene and can start playing again.

Now this syntax is a bit interesting and distinct.

We've not seen something like this before.

This get treat reload current scene.

Usually we would have an open and closing brackets after reload current scene, and that would
call

the reload current scene function to make it immediately reload.

We're telling the tween the name of this reload current scene function so that it can call that
function.

So that's why there aren't opening and closing brackets on the end.

So we know the actual changes to code we want to make.

So let's jump over to our script view and a distraction free mode and jump down to our crash
sequence.

So at the moment we call our crash sequence print kaboom and then reload the current scene
just above

it.

We want to create a tween, so var tween equals create tween.

And then afterwards we want to call the tween interval function to wait a set amount of time.

So you can see here we can pass an amount of time in as a float.

This is measured in seconds.


So if we passed in 1.0 we would wait one second.

We passed in ten.

We'd wait 10s 0.5.

Half a second.

We're going to wait for one second.

So do 1.0.

So lastly we want to call this Reload Current Scene button.

And we do that with the tween callback function.

So after that we go tween dot tween callback.

And then in here we pass in a callable.

And that's that interesting syntax I was talking about of having the name of a function without
brackets

after it.

That's what a callable is.

So we can pass in this part of the function as the callable without the brackets.

You can cut that out of there and paste it in here.

Get rid of those brackets at the end.

And now when we crash we will print kaboom.

We will wait one second and then the scene will reload.

So let's see that in action.

I just need to touch the floor.

And now in a second, there we go.

It said kaboom.

And then a second later it actually reloaded the scene.


Now, this isn't quite perfect at the moment.

If I touch the floor and then start holding space again, I'll keep flying.

It would be really nice if the moment we touched the floor, we lost control of our player.

And there's a neat shorthand we can do to actually do that.

I'm going to close this.

And I want to point out that all of our movement and force is being applied is occurring within
this

process function.

Now, there are many cases when you might not want a process function to run, and in order to
account

for that, there is a built in function that lets us disable this function as a whole, so it will no

longer be called every frame.

And if we disable it, we will no longer be applying forces when we're holding down keys, and
it will

make our ship start to ragdoll.

And the way we control that is with the set process function.

So I'm going to go down to the crash sequence just after we print kaboom.

I'm going to disable controls by calling set process.

And we can see process takes in a value called enabled, which is a bool.

Well, a boolean and a boolean is a true or false value.

So we're either setting process to be true, in which case we are processing or we're setting it to

be false, in which case we're not, and we want to set it to false.

So we stop calling the process function.

And if I run that now, I can crash.


And if I hold space afterwards, it doesn't matter.

I am no longer applying forces, as you can see there, it just fell over.

And you'll have to trust me a little bit.

I'm holding space, so that's all well and good.

You'll notice that I've only crashed a couple of times, but it said kaboom many more times and
that's

because we have touched.

Sometimes there we've crashed into the floor and we've started crash sequence.

And then as say, the top half of the body falls over and touches the floor.

A different part of the body starts the crash sequence and it will print kaboom a second time,
and

this other tween will start running, attempting to reload the scene.

Afterwards, it would be much nicer if we only called crash Sequence once, and then once
we've done

that, stop calling any more of the complete level or crash sequence functions.

And the way we're going to do that is with our own special boolean.

So I'm going to close this panel.

And at the top I'm going to declare a new variable just below these exported ones I'm going to
create

a new variable called is transitioning.

So I'm going to say var is transitioning.

And I'm going to set it to be a boolean.

So colon bool.

So it's a true or false value.

I'm going to set it to be equal to false.


And now when we're in our body entered function, I'm going to use whether or not we're
currently transitioning.

So that can be for either crashing or for changing the scene I'm going to use whether or not we
are

transitioning to determine whether or not we should call another one of the functions that starts
a

transition.

So I'm going to go to the on body entered function.

And in here, if we are transitioning, we don't want to call any of these functions.

And if we aren't transitioning, we do want to call these functions.

And we can do that all in an if statement.

And that is we're going to say if is transitioning.

Is false.

So that's when we aren't transitioning yet.

We want to do all of this stuff.

I'm going to put a colon and I'm going to select these lines of code.

And I'm going to hit tab.

And that's going to indent them all.

So all of those lines of code are within this if block.

So now we want it so that when we start crash sequence or when we start complete level, we
set is transitioning

to be true.

So in crash sequence, because that's the one we're handling at the moment just after set
process.

False.

I'm going to call I'm going to update the value of is transitioning and set it to be true.
So now whenever we crash, we stop processing and we notify our script that we are
transitioning and

don't want to handle any body entered function calls anymore.

And with that we should see.

Now we only get one kaboom when we touch the floor and fall over.

Here we go.

Just one.

Perfect.

And with that, we can move on to our challenge.

So I want you to use a tween to add a one second delay to the complete level function in
exactly the

same way as we did with handling the crash sequence.

Now, in order to do this, I'm going to need to give you the callback function that you're going
to

call at the end of it, because reloading the current scene was easy enough, but we need to use a
bit

of a unique function call in order to change the scene to a new one.

And that is, we are going to do this.

The last step of your tween is going to be adding a tween callback, and it's going to call get
treat,

change scene to file.

That part is the same as with reload current scene.

But afterwards we need to tell this function the string name of the file it wants to load.

And in order to pass that into a value without using brackets that would call the function, we
need

to use this bind function at the end and then pass the next level file in.
So just make sure that you've got these lines, just as I've put here at the end of your tween after

your delay, and you should do just fine.

And with that, I will see you back here in a few moments.

Welcome back.

So we can dive back into our script.

I am going to close the bottom panel, and we want to do exactly the same as we were in the
crash sequence,

but in complete level.

So we could just copy and paste.

But I'm going to I'm going to do them step by step.

So I'm going to create a new line after level complete.

And I'm going to create a new tween.

So variable tween equals create tween.

So we've created a new tween that we're going to give some instructions to.

The first instruction is going to be to wait for one second.

So tween dot tween interval.

Pass in the amount of time, so 1.0.

And then lastly we want to do that last function call I did, which will let the tween call this
function.

And the way it did that was it called tween dot tween callback.

Now in order to get onto a new line and indented so that this just isn't one really long line of
code,

I'm going to hit enter inside here.

Now you'll see it's put the closing bracket on a new line and it's indented us within this
function
call.

And now we want to pass in.

Get tree.

And then we want to call the change scene to file function.

So change scene to file getting rid of those curly parentheses at the end.

And then we want to bind this next level file parameter to it.

So add on dot bind is the way to pass in that parameter.

And then type in next level file.

And with that, we are now delaying our change of level by one second.

So if I run this.

And I land on the landing pad rather than the hazardous floor.

It should wait for one second before the scene changes.

There we go.

The last thing we want to do to finish off our complete level function is we want to change the
value

of set process and updating the is transitioning variable.

And we're going to do that in exactly the same way as crash sequence.

So I'm going to copy this set process false.

And is transitioning equals true these two lines.

And then after we print level complete I'm going to do exactly the same thing.

And with that all said and done, we will now lock our inputs when we land on the landing pad.

Whilst we start our transition to the next scene and we won't be able to trigger any new on
body entered

function calls.
So that's all nice.

One of the big benefits of having an extra second delay like this is we can add animations or
particles

or sounds later on, and let the user actually see them before just making a hard jump cut to the
next

scene.

And with that all said and done, in the next lecture we are going to be improving our tween
knowledge

and we are going to be using tweens to start animating some of these obstacles.

Tweening Hazards
In this lecture, we are going to be building on our tween knowledge and start using tweens to
animate

hazards to make them move around our levels.

So we're going to want to jump into a new level so we can start adding these animatable
hazards in.

I'm going to do that by going down to the file system, right clicking on level three and
selecting

duplicate, and renaming this to level four.

I'm going to click that duplicate button.

And then I'm going to open that new level four scene.

Now, we're not going to want this obstacle up the top.

Instead, we're going to be creating an entirely new obstacle, and that's going to be using a node

which is an animatable body 3D.

I'm going to select the root node, and I'm going to hit control A, and in the Create New Node
dialog,

search for Animatable body 3D.

It's shown up down here, and you can see a little description at the bottom saying that this is a
3D

physics body that can't be moved by external forces, and when moved manually, it affects
other bodies

in its path.

When it refers to being moved manually.

That's what our tween is going to be doing.

So I'm going to add this body to our scene, and we're going to want to add a mesh instance and
a collision

shape in exactly the same way as with our player rigid body.

We needed to add a mesh instance so we could see it and a collision shape so it could interact
with

the physics of our world.

I'm going to rename this to Moving Hazard.

And then I'm going to add a mesh instance 3D as a child of that moving hazard.

This mesh instance, 3D is going to be a box mesh.

So I'm going to select that and century over in the mesh property in the inspector I'm going to
select

a new box mesh.

I'm going to expand this box.

And I'm going to get access to its size properties to make it a three meter by three meter cube.

So three meters in all dimensions.

See as clipping through the floor.

At the moment, I'm just going to move it a little bit higher so it doesn't do that anymore.

About here is fine, and I'm going to do a little shortcut to create the collision shape.

So we could add a collision shape and resize it.


But this is something that happens often enough when you add a mesh instance and you just
want a similar

collision shape.

Guido has a built in shorthand.

If you select the mesh instance 3D and the scene tree at the top of the viewport, you'll see this
contextual

mesh drop down.

We click on that, we will get access to a whole bunch of additional options and including what
I've

selected here, which is Create Simplified Convex collision Sibling.

That button will create a collision shape with the same dimensions as this box, and it's going to
be

simplified.

You can also do things like create an outline, or there are a few other things you can create
from

here.

But creating a simplified shape is what we want.

And now if I scroll down, you can see we have a collision shape.

If I make the mesh instance invisible, you can see we have a collision shape with exactly the
same

dimensions.

So that just saved us needing to add another node and set it up manually.

Going to make that mesh instance visible again.

Now the plain white doesn't look quite right to me, so I'm going to want to give this a material
with

a color.

So I'm going to select the mesh instance 3D.


And I'm going to go to the geometry dropdown.

And in here we have a material override.

Now this is where we're going to add a standard material 3D.

You'll notice this is just a little bit different to a CSG polygon 3D where it had a material right

at the top we could set up.

That's just because mesh instances have a lot more options because the CSG polygons are
intended for

prototyping.

So I'm going to find this material override property.

And I'm going to create a new standard material 3D.

Once I've added that, I can expand it, and under the albedo dropdown I can choose a color.

And this time I think I'm going to opt for sort of a pale yellow.

I think that looks.

Pretty good to me.

Actually.

Paler than that.

There.

I think that's about nice.

So we have this yellow box.

So now we have this moving hazard.

We might want to reuse it in a variety of other scenes.

And in order to accommodate that, we want to save this as its own scene so we can instance
more of

them elsewhere.
Now, the quick way to save something we've created in a scene tree as a scene is you can right
click

on it and you'll see the Save Branches scene option.

Now this will set whatever we've selected as the root node of a new scene, and let us save it
straight

to the file system.

So I'm going to select Save Branches scene.

And in the root of this directory I'm just going to save it as Moving Hazard Scene and click
save.

Must save this level for now.

I'm going to go ahead and open that scene.

So in the scene tree I'm going to click on Moving Hazard down here in the bottom left.

And you'll see we have an empty scene with just this moving hazard and the mesh instance
and the collision

shape.

And here we can start focusing on the script.

So select the moving hazard at the root of the scene tree and click the Attach script button.

And it will create a new script called Moving Hazard.

We can click create.

And in here we're going to want to export two variables.

The first variable is going to be a vector three saying where we want the body to move to.

And the other one is going to be a float saying how long we want that movement to take.

So the way we do that is we add export.

Let's make this bigger so it's easier to see.

Going to add export a new variable.


And I'm going to call it destination.

And then I'm going to set the type to be a vector three.

And now, just like our size and our position, this will export a value with an X, a y and a z
value.

And we can use this to tell our box when to where to go when it's moving.

And after that, in the same way we want to set a duration for this animation, I'm going to
export

another variable and I'm going to call it duration, and I'm going to set it to be a float.

So we have those two values.

If I collapse that down and select moving Hazzard in the inspector, you'll see we have a
destination

that I just accidentally set the y value for.

And we have a duration in seconds.

We can set sensible defaults by setting these equal to something.

So for example, if I go back in and I set the duration to be equal to one.

When we go to the inspector back there, you'll see it defaults to whatever value we set in the
script.

So we have our two variables.

We now want to use a tween, and we want this tween to move the animator body from where
it is to wherever

this destination is.

Now I find this a bit easier to use if the destination is a local distance from our body.

So for example, if the y value of our destination was one, if that destination was moving one
meter

up from where we started.

Now I'm going to show you exactly how I do that.


In the ready function I'm going to create a tween.

This is going to be the object responsible for moving our shape around.

And I'm going to want it to tween a property of the animatable body.

And that property is going to be its global position.

Now, the way you tween a property is we call tween dot tween property.

And in twin property.

You see we have these four separate parameters we pass in.

The first parameter is the object we want to tween.

The second parameter is the property we want to tween.

So like the scale or the position.

The third value is the value we want it to animate to.

So the destination and the last value is how long we want it to take.

So in this case the object we want to tween is self.

Self is a reference to this animatable body.

We also want to tween its global position.

And its global position is given as a node path.

So we just want to pass in a string the word global position.

So now our tween can access this object's global position and we can animate it to a
destination.

And I'm going to set the destination to be our current global position.

And I'm going to add the destination on top.

So this is now all one vector three.

That is where we currently are with this value and added on top.
So if this, as I was saying earlier, was just a y value of one meter up, our destination will be

one meter above where we started.

And then we can finally use the duration, which is just going to be the duration we set in our
exported

variable.

So now when we run this well, we're going to rerun a scene with this moving hazard in it over
one second.

Our global position of our animatable body will move from where it is to wherever we set the
destination

as.

Let's try that out quickly.

I'm going to return to level four and I'm going to find our animatable body.

I'm going to say over three seconds because it's going to take a little while to load.

I want this shape to move two meters upwards.

And if I run that scene now, you'll see our shape is moving upwards.

And that's a physics object we can collide with.

So with that done, I can move us on to our challenge.

So I want you to add another tween property function to return the hazard to its starting
position after

it's moved to that destination.

Now, it's worth noting for this that tweens use the value of variables the moment we set them
up.

So if you set a destination to be the global position, it will be the global position when the
tween

is first set up.

All right.
And with that said, I will see you back here in a few moments.

Welcome back.

So we want our shape to move back to where it started after it moves up.

And in order to do that.

We are going to need to return to our moving body script.

Moving hazard script.

And we are going to want to copy the stream property, because every event that happens in the
tween

will happen sequentially, one after the other.

So I'm going to just copy and paste this line of code.

So after we've moved from our starting position to our starting position plus our destination, I
want

us that to then move back to our starting position.

And as I was saying a second ago, that uses the value of these variables when we first set up
the tween.

So global position is not going to update to something new after it's moved to the first
position.

Which means we can just get rid of destination, and our tween will move our body from its
starting

position all the way up, and then back down to the same starting position when this tween was
created.

And if we run level four, we can see that in action.

We'll take three seconds to move up, and then I'll take three seconds to move down.

Now we've hit a snag, which is the tween has stopped.

We want it to loop.

Thankfully, tweens have a built in function that will make them loop, and they will just
continue
to iterate back over their instructions endlessly.

The way we do that is when we create our tween, we can get Ahold of our tween.

And we have a bunch of options for controlling how our tween should behave.

And one of those is a set loops.

And when you call set loops, you can either pass in a set number of loops you want to
perform, but

if you don't pass a set number of loops, it will continue to do the following actions indefinitely.

So now if I run the scene.

The body will move up.

And it will move down.

And then we'll move back up.

Now.

At the moment the movement looks a little bit mechanical and there's a really nice way we can
get around

that.

And that's tweens animate with something that are known as transition types and easings.

One extra step we can make here is we can do tween dot set trans and that will set a transition
type.

And you can see we have a whole bunch of different transition types.

We can pass in.

We can pass in an elastic transition type an exponential one a linear one is what we're
defaulting to.

And that's what's giving us that straight movement.

If we pass in trans sign, our tween will use a sinusoidal transition, which just looks a bit more

circular as motion goes and a bit more fluid.


So if I run that now, you will see our shape speeds up in the middle and slows down near the
top,

and it sort of has a visible momentum that changes as it moves up and down.

And if I try and fly into that, it should still behave as a hazard.

Actually it won't.

I need to set the group to be hazard because at the moment it doesn't care whether I touch it.

So let's make that change quickly.

I'm going to go back.

I'm going to exit distractions free mode.

I am going to select the moving hazard.

I'm going to go into the moving hazard scene.

And let me just check what the specific tag I use is on obstacle.

I use hazard and it's capitalized.

So I'll go back to the moving hazard.

I'll select that root node, I will go to the inspector and I will change to the node tab.

And I'll change from the signals section to the groups section.

And I will add a group called hazard.

And now in level four when I run it again, we should find that as I hit the moving obstacle, it
ends

and it restarts the level.

Now we have a new level.

There's one last little thing to set up and that is at the end of level three.

We can set our landing pad.

We can go over to the inspector, and we can change this file path to redirect from back to the
start

to level four.

So that's how you can use animatable bodies and how you can animate transitions with tweens.

And that's it for this lecture.

In the next one we are going to be looking at adding audio to our scenes.

Introducing Audio
In this lecture, we are going to learn how to use the audio stream player node to play one off
sound

effects.

So for this lecture, I've provided two resources within a zip file.

And I'm going to start by taking that zip file and adding its contents to my projects.

So I'm going to go into my downloads folder.

I have this audio files zip.

I'm going to right click on it and extract the folder.

From there, I'm going to have to ogg files within one called Death Explosion and one called
success.

I'm just going to.

Highlight both of those, and I'm going to drag them straight into my Godot project in the file
system

in the bottom left.

And I just made this file system a bit bigger, I can reset that.

They've actually moved within a folder.

I'm going to select those and drag them into the root of my project.

So they're available next to the player and next to the moving hazard.

I'm going to reset this because I've actually made my file system a bit bigger.
If you ever change the scale of any of the docs in your editor, you can go to the top bar and in
the

editor drop down, click on the Editor Layout foldout menu and click default and it will reset
everything

to its default view.

So with an audio file, we can either use something like an MP3 or an ogg file.

We have Ogg files here and they have the benefit of being very small.

You'll see that's 30kB.

And it's just a very compressed way of passing along audio information.

In order to play that file, we need to use an entirely new node, and that is an audio stream
player.

I'm going to open the player scene by clicking the little clipboard.

And here I'm going to select the root node.

Hit Ctrl A to open the Create New Node dialog.

And I'm going to search for Audio Stream Player.

There are a few different kinds of audio stream player.

There's audio stream player that's got a little white play head, and there's one with a red play
head

and a blue play head.

Those colors indicate whether or not the node is 2D, 3D, or neither 2D nor 3D.

Something with 3D positional information will sound different depending where it is with
respect to

the camera.

We want to play this audio clip the same no matter where it is, so we're going to use a plain
old audio

stream player, the one with the white play head down here.
So I'm going to click the create button.

And now we have this audio stream player in our scene.

So this has a bunch of properties controlling how the audio will play.

And we need to select an audio stream that it will use to play a sound from.

And in this case, we're going to start by setting up our explosion sound effect.

So there are two ways we can do that.

If you look at in the Inspector at the stream property, we can either click the drop down to the
right

of it, or we can just drag our ogg file all the way from in our file system over into our stream,

and we'll go in.

So that's one way to do it.

Or we can click the drop down to the right and you can select the quick load option.

And when you select Quick Load it will open a view of just the valid files in your file system
that

you could add into this slot.

So this will only show MP3 files, WAV files or Ogg files.

I'm going to select Death Explosion this way now.

Now we have this stream set up in our audio stream player.

We actually have the tools available to test it out right now.

If we click the on property right next to playing.

You will hear that it plays our death explosion sound effect right in the editor.

So you can hear we've got the right one set up.

And that's what will play when our game is running.

If you find this volume much too loud, you can fiddle with the volume property and make that
significantly
lower.

And when you play again, it will be much quieter.

But for me this is fine.

So now with that audio stream player set up and that stream, I want to rename this node.

I'm going to call it Explosion Audio.

And in order to make this node start playing from in code, we need to learn about an entirely
new annotation.

So we've stored values in variables before we've stored floats and we've stored strings.

But sometimes you want to store a node in a variable.

And that will let us do things like access its functions and properties.

And in order to do that we need to use the on Onready annotation, which is just like the export
annotation

we discussed recently.

In this particular example, we have seen where we have a parent node with a script attached to
it.

If we want that script to be able to access a child node, we need to use this following syntax.

And that is we use the at on ready annotation.

So we use that in the same way we use at export.

We declare a variable.

And then after that we give a name for our variable and we can set a type for it.

That's all usual.

But afterwards we get to a new kind of syntax and that is this dollar sign.

And then the name of the child node.

This is a node path.


And we can use it to describe any relationship of parents to children.

At the moment, because this child is an immediate child, we can just pass in a dollar sign and
the

name of the child we want to access.

I'll show you a bit more about how to access more complex paths.

You can let Godot generate a node path for you, which is a much more convenient way of
generating one

of these paths.

So why do we need the add on ready annotation?

We can't access sub nodes of our script until our script has called its ready function.

So when you attach this annotation to a variable declaration, it will wait until that point.

When we have access to a sub node, we can then access its properties and call its methods.

So let's put that into action.

I am going to open our player script and I'm going to make that take up the full screen.

So the very quick and easy way to create an add on ready variable declaration.

I'm going to make my my docs on the side visible.

I am going to find the variable I want to add as an on ready variable.

On the left I'm going to hold the control key and I'm going to drag that node into my script.

And if I let it go there, you will see it's created a whole add on ready declaration for that
variable.

So you can see here if I make that full screen, it has added the at on ready annotation because
it

knows that this variable needs to wait until the ready function is called.

It's given it a node name based on the name we gave the audio stream player.

When we renamed it, it gave it the right default type, and it gave us the path to that explosion
audio
variable.

And now we have access to this variable.

We can use this explosion audio variable name to start calling its methods and functions.

So let's do that.

The way we can make an audio stream player play the audio stream that it has is with a
function called

play.

So I'm going to go down to our crash function.

So in crash sequence right at the top, just after we print our debug line I'm going to access the
explosion

audio.

So explosion audio.

And then I'm going to hit Dot.

And I can get access to its various functions and methods.

If I do dot play and then an open and closing parentheses, it will make that audio stream player
at

this specific point in the function.

So that should be enough that if I click the play button.

And I crash this little ship.

It plays the audio effect.

Now we hit a little bit of a snag there.

This audio stream is longer than what we just heard, because one second into that audio
playing our

level reset, our audio just got cut off partway through.

One nice way we can work around that is I'm going to go back into my crash sequence and in
the tween

interval, where I wait until I'm going to reload the current scene, I'm going to just increase the

amount of time.

So we have enough time to hear that whole audio file play.

So I'm going to increase that wait time to 2.5 seconds.

And if I run it again and I crash the ship very quickly.

We can now hear it play all the way through and get all that reverb and trailing off at the end.

So with that, let's get on to our challenge.

With this challenge, I want you to add another audio stream player for the success sound
effect.

And then I want you to rename it to Success Audio and set its stream property to the Success
Ogg file.

Of that, you can make an onready variable for it.

And you can call the variables play function in the complete level function.

All right.

I'll leave you to that and see you back here in a few moments.

Welcome back.

So we want to start off by creating a new audio stream player.

I'm going to close this exit distraction free mode.

I could duplicate this explosion audio, but I'm going to show you creating a new one from the
ground

up.

I will select the player root node, hit Ctrl A to open Create New Node dialogue and I already
have

audio search.
I'm going to search for Audio Stream player and click the create button with that selected.

I'm going to go down to my file system, find this success ogg file, and I'm going to drag that
into

the stream property for this new audio stream player.

And we can hear that playing by clicking the playing property down below it.

Now that that's set up, we can rename this node.

I'm going to call it Success Audio.

And now we can go about setting up its onready variable.

So the last time I did this, I dragged it in by holding Ctrl.

And I'm going to show you that working again quickly here holding control, dragging the node
and dropping

it in.

And we get our variable set up.

But if you want to do it manually, one other way you can do it is if you want to find out what
the

path to this node is, you can right click on it and you can click the copy Node path option in
that

contextual dialog.

If I paste now, you'll see we've got success audio because it's an immediate child.

That is the path to the child, just the name of it.

But if, say, I had another node in the middle and I dragged this as a child of that and I copied
the

path to it now because there's a node in the way.

The path will be the name of the immediate child node, and then a forward slash and then the
child

we actually want.
So that's how those paths are changing.

But I'm just going to undo that.

And over here I'm going to get rid of that node.

So I'm going to copy the path to this success audio.

I'm going to create my new variable at Onready.

And I'm going to say it's a variable.

And I'm going to give it the name Success Audio.

I'm going to set the type to audio stream player.

I'm actually going to go full screen at this point.

I'm going to set the type to audio stream player.

I'm going to assign it to a node path, and that's done with the dollar sign.

And then the path I just copied.

And now we have our success audio node readily available.

So we want to play this sound effect when we successfully land the ship.

So I'm going to go down to our complete level function.

And in there I'm going to call success Audioplay.

And that's everything we need.

If I test it out and I fly my ship over to the landing pad.

It plays the sound.

Now, as with the crash sound that actually cut off partway through.

So I'm going to make one other slight change.

I'm going to go into complete level, and in the tween interval part of the Tweening function,
I'm

going to increase the amount of time we wait to 1.5 seconds.


Now if I run it, we should hear the whole sound when I successfully land.

One whole sound and one whole crash sound.

Perfect.

We've learnt how to completely set up one off sound effects, use audio stream players and
access variables

with the add on ready annotation.

That's it for this lecture.

In the next one, we are going to be adding sound effects for the rocket and toggling it with
code.

Controlling Audio with Script


In this lecture, we are going to add rocket sounds and use some new scripting techniques to
control

them.

For this lecture, I have provided another ogg file for our rockets audio.

In the lecture resources, download the zip file and we can move from there.

So with the file downloaded, extract it from the zip.

Within.

There you will find a file called Sound effects main engine thrust ogg and we are as before
going to

take that and drag it into our file system.

And if we scroll down, we will now see it is just below the other three sound effects files.

I'm actually going to go ahead and put those in a folder.

So I'm going to right click on the root of my file system.

And I'm going to create a new folder.

And I'm going to call it audio.


And I'm going to hit okay.

We now have a new folder for that to go into.

I'm going to hold shift and select all three of those ogg files.

I'm going to right click on them and you'll see we get a move slash duplicate to option in the
pop up.

We can then move all of those files into the audio directory and click move.

And you often want to use that move command rather than dragging files around, because it
does the

job of updating paths in various scenes to use whatever the new path we've moved those files
to is,

so we should find our explosion.

Audio still works, even though the file resource is in a new place.

One other thing we want to do.

I'm going to go in this audio folder and I'm going to double click on main engine thrust ogg.

With that open we get some importer options.

So you can do things like preview the sound here if you click the play button.

But the thing I want to do is I want to make this sound loop so that if we play the rocket audio
for

a long time, eventually it will wrap back around to the start and we won't have to do any extra
programming

for stopping and starting.

The way we do that is you check enable under the loop option, and once you've made that
update, you

can click Re-import.

And now whenever that stream is played, it will loop endlessly.

With that all set up, we can move on to our first challenge.
So from there, I want you to add an audio stream player 3D node as a child of the player scene.

Note that is distinct from audio stream player.

This is the 3D option that's got a slightly red icon that has positional information, and you're
just

going to add it as a child of the root of the player scene, then rename it to Rocket Audio and
update

its stream property to that new sound effects.

Main engine thrust Ogg file.

Finally, with that done, add an Onready variable for that new rocket audio node.

And with you.

Good to go.

I will see you back here in a few moments.

Welcome back.

So our first step was to add an audio stream player 3D node, which is slightly distinct from
Audio

stream player.

I'm going to go to the player scene, select the player root node and hit Ctrl A to open the
Create

New Node dialog and search for Audio Stream Player 3D.

So you can see it has a red play button and this plays positional sound in 3D space.

The reason we're going to use this is it means that the sound of our ship thrusting around will
be different

depending on where we are in the actual level, which is quite a nice effect to have.

So I'm going to create that node and I am going to set its stream property.

So with this audio stream player 3D selected over in the Inspector in the stream property, I'm
going
to click the drop down to the right and click Quick Load.

And from here we can see main engine thrust org.

So I'm going to click open on that.

And we should see if I click the playing property.

It starts playing and you can see the playback point.

We are through there.

And when it gets to the end it should loop back because of our looping property.

There we go.

So now we can rename this node.

I'm going to double click on Audio Stream Player 3D and I'm going to call it Rocket Audio.

Hit enter, we now have our Rocket Audio renamed and we want to set up our Onready
variable.

So I'm going to go to the top of this player script where the other onready variables are.

I'm going to hold control and I'm going to drag Rocket Audio in.

Or you can offload any of the other processes I showed you before to type out this full name,
which

is currently it is called Rocket Audio and it is an audio stream player 3D, unlike the audio
stream

player from last time and we just type in the name, we just gave it after a dollar sign for the
path.

So now we have access to this rocket audio.

We can start playing its sound when we are actually pushing the boost button, but we're going
to hit

a snag quite quickly doing that.

So our previous two sound effects are one off sound effects, and they had one trigger that
would happen
once.

We are pushing the boost button every single frame.

So if we start trying to play this sound every frame, it will constantly restart and we will get a

really horrible noise.

So we're going to need to do an extra step to make sure we don't try to play the sound if it's
already

started playing.

In the if input is action pressed block.

When we are pressing the boost button, we're going to add a new line afterwards.

And I want to say if.

Rocket audio playing.

So that's a variable that tells us whether or not it's currently playing and if that value is false.

So if it's not currently playing equals equals false.

We then want to start the rocket audio playing.

So that means if we reach this point and the rocket audio is already playing this, if block won't
execute,

I'm going to hit enter.

And in there I'm going to start playing the audio.

Rocket audio play.

So let's see this new script in action and see how it actually performs.

I'm going to hit play.

And I'm going to push space to start boosting and the audio will start going.

But then if I let go, the audio still plays.

And that's because we need to tell this audio stream to stop when we let go of that spacebar.
In order to stop the audio stream from playing, we could benefit from knowing about a new
keyword that

we've not encountered before.

There is a complement to the if statement we've been using, and that is the else statement.

After an if statement, we can add an else statement to handle if the condition wasn't met.

So if on a line we say if a condition was met, do something.

So in this case if we push the boost button, do something.

If after that unindented we have the keyword else and a colon.

This will only run if the first if block didn't do its thing.

So it's kind of like saying if not input is action pressed boost and then having that immediately
afterwards.

So essentially this lets us catch when we're not holding down the spacebar, and when we're not
holding

down the spacebar, we can stop the audio stream player from playing.

So looking back at our script, there are a few if statements and we don't want to confuse which
one

we want our else statement to apply to.

So we want.

When we don't push boost, so we want our line to be as indented as this if statement is.

So I'm going to go down to the end of this if statement.

I'm going to hit enter.

I'm going to hit backspace twice to get my cursor on the same level as that if statement.

We want this to complement.

And then we're going to type else and a colon and hit enter.

And now this code will only run whenever we are not pushing the boost button.
And what I'm going to do here is stop the rocket audio from playing.

So I'm going to type Rocket Audio stop.

And with that, when we are playing, when we push the spacebar, the boost will play.

And when we let go, it should stop.

Let's see that in action.

And there we have it.

Our audio is working as we want, and we can mix and match and start crashing and land and
have our

crash audio play fine and have our success audio play when we land at the end of our level.

That's it for this lecture.

In the next one we are going to start adding particle effects into our game.

Introducing Particles
In this lecture, we are going to learn how to control the GPU particles 3D node with scripts.

So we're going to want to start adding particles to our player.

We're going to be adding boost particles underneath and on the left and right side, so that when
you

start trying to turn right, booster particles on the left will fire.

When you start trying to turn left, booster particles on the right will fire.

But in order to start using these particles, we're going to need to know a little bit more about
them.

So particles are a tool for creating complicated visual effects, and they give you the power to
animate

thousands of meshes at the same time.

You can use particles to create effects like fire, explosions, dust, sparks, and much more.

For example, our booster particles we're going to be putting underneath our ship.

In order to use particles, we're going to need to use a node called GPU particles 3D.
Now when we have a particles three d node, it has an emitting property that we can use to
either stop

or start emitting particles.

So when emitting is set to true, particles will come out and when emitting is set to false,
particles

will not come out of the particles 3D node.

I've prepared a particles 3D node for you to download.

If you look in the associated resources for this lecture, you will find a zip file and once you've

got that downloaded, we can go ahead and start getting that introduced into our project.

So in future topics of this course, we are going to be learning how to build our own particles
from

the ground up.

But just to get you hitting the ground running and using the particles node, I've provided
particles

pre-made just for this topic.

So with the zip file downloaded for these particles, we can extract that folder.

And if we open that up, we will see a folder called particles.

And if we look in there we will see a scene file called booster particles.

And this contains our GPU particles 3D node.

I'm just going to drag this booster particles scene into the root of our file system.

So I'm going to drag that down into the file system and drop it at the root.

And now we have this booster particles scene file.

I'm going to close this with this booster particles scene in our file system.

We can double click on that and open it up.

And you will see it is already emitting.


And it is creating a very large number of glowing spheres that are going downwards, which is
going

to create the effect of a trail behind our rocket as it goes upwards.

So if I select the boost particle scene, you can see it's a GPU particles 3D node.

You can see the type below the tooltip.

There we can control whether it's emitting with this emitting property.

If we disable that it will stop emitting.

And if we enable it, it will start.

So let's go on over to our player scene.

In our player, we want to put particles immediately underneath that will fire when we push the
spacebar.

So I'm going to right click on our player.

And I am going to select Instantiate Child Scene.

That's going to show me all the scenes in my file system including this new booster particles
scene

file.

So I'm going to select Boost Particles Scene and click open.

And now we have the boost particles in our scene.

There's this cuboid bounding box around where the particles will be spawning.

But we can't see the particles at the moment.

And that's because they're entirely contained within this cylinder.

We're actually going to need to move it down a little bit before we can actually see those
particles

coming out.

And then we can see there we have particles emitting underneath our ship.
I'm going to select the booster particles in the scene tree and over in the inspector I'm going to
go

down to the transform property.

And in there I'm just going to set the positions y value to a nice round number.

So I'm going to set it to 1.0.

-1.0 even.

And now our particles are lined up with the base of our ship.

So the next step we will want to go with is we will want to make it.

So when we push the spacebar, these particles start emitting.

And when we release the spacebar they stop emitting.

Thankfully, we've already figured out all the logic for that when we were controlling the
rocket audio.

I'm going to open the player script.

And in here I am going to want to create an onready variable for these booster particles.

So I'm going to hold control and drag the booster particles from the scene tree into our script
and

drop it with the rest of the onready variables.

And if I expand this, we can see we have at Onready var booster particles.

It's a GPU particles 3D, and it has the correct file path.

So I'm going to go into our process function, where we detect when the player is holding the
space

bar.

And within this if block, if we are holding the space bar I want particles to emit.

So below apply central force I'm going to say booster particles.

And we control whether they're emitting with the emitting property.


So we're going to do dot emitting.

And now we can set that to be either true or false.

We want it to be true because we want it to start emitting when they're pushing boost.

So I'm going to say equals true.

Now, previously we set up this else statement.

So we have this condition.

If we're pushing the space bar do this.

If we're not pushing the space bar, do this.

So if we're not pushing the space bar, we want to set the emitting value of these particles to
false

so they'll stop emitting.

So in that else block we're going to say booster particles.

Dot emitting equals false.

And that's actually enough for us to see it in action.

So I'm going to hit the play button.

And you'll see if we push space particles come out the bottom.

If I let go, they stop.

And if I push again, they start and stop.

Start and stop.

So now we have that set up, we can do exactly the same thing for some of the particles on the
side

of the ship.

We're going to return to our script.

So next in the script we handle when the ship is rotating left.


So at the moment when our ship is rotating left, we are going to.

So when we are rotating left, we're going to want particles on the right side of the ship to come
out

to show it should turn around that angle over to the left.

So in order to tell what way left and right is, it's worth having a look at one of our levels.

I'm going to open level four and you will see we've got our camera over here.

So the camera being this little magenta shape that's a square with the triangles and the square
based

pyramid.

If we are looking the same way as that camera is, which we are at the moment, then our player
it's

right is where the red arrow on the x axis is pointing.

So to the right is positive x and to the left is negative x.

So I'm going to return to the player scene.

When we're rotating left we're going to want new particles to be on the right side of the ship.

So where the x position is positive.

I'm going to collapse this view and I'm going to duplicate these booster particles.

Going to select the booster particles in the scene tree.

Right click on them.

And in the context menu click duplicate.

So we now have Booster Particles two.

And I'm going to want to move them to the right because we are going to be using these to
turn left.

And you can see we now have particles on the right.

I'm going to scroll down to the transform property and set them to a nice rounder number.
I'm going to set it to 0.4 on the x axis.

So it is 0.4m to the right.

And these are going to be the particles on the right side of the ship.

So I'm going to call this node right booster particles.

So now we have our right booster particles.

We can return to our script and set up their Onready variable.

Opening the script.

Scrolling up to one ready variable's going to hold control and drag right booster particles into
our

script.

I don't know why it's set it down there.

I must have had my cursor much further down the script, so I'm going to hit Ctrl Z to undo it.

Yeah, I had items selected so it got confused.

I'm going to left click on the point where I want it to go into, and I'm going to hold Ctrl and
drag

that in.

And now we have the right boost particles going to the right part of the script.

I'm going to make this full screen.

And we are going to go to where we try to rotate left which is down here.

So if we push rotate left, we want our right booster particles to start emitting.

So I'm going to start within that if block I'm going to say right booster particles dot emitting.

Equals true.

Now we don't have an else statement like we did before, but we want to say if we're not
pushing, rotate
left, then set emitting to false.

And we do that by going to the same indentation block, the same indentation level as this.

If input is action pressed, rotate left section and we are going to say else colon and hit enter.

And on a new line within this else block we're going to set write boost particles emitting to be
false.

So write booster particles dot emitting.

Equals false.

And now if I run the scene, we should find.

As I start pushing the A key, the boost particles on the right hand side start coming out.

Just like that.

So with that all set up, we can move on to our challenge.

For this challenge, I'm going to want you to create the matching booster particles for the left
side

of the player.

So these are going to be called left booster particles.

And I'm going to want you to create an onready variable with a reference to that left booster
particles,

and then control that variables emitting property when the rotate right action is pressed.

So exactly what we just did for the right booster particles, but for the opposite side of the ship.

And with that, I will see you back here in a few moments.

Welcome back.

So let's dive straight into it.

I'm going to close that project.

I am going to go over to the scene tree for the player.

And I'm going to change to the 3D view so that I can see these particles in action.
I'm going to duplicate the right booster particles.

So I'm going to select them in the scene tree.

And I'm going to click duplicate.

And I'm going to rename these to left Booster particles.

So I'm going to replace right with left I'm going to get rid of the two that it added at the end.

Now we want these to be in the same position on the left, as the right ones are on the right.

And the way I'm going to do that is I'm going to select left boost particles in the inspector.

I'm going to go down to the transform property.

And in there I'm going to set its positions X value to be negative of what it currently is.

So at the moment it's 0.4m to the right of the middle.

If I set it to -0.4, it will now be 0.4m to the left of the middle.

You could alternatively have done exactly the same thing by just dragging it around with the
gizmo,

but that was just a little bit more precise.

So now we have these particles.

We want to control them with a script.

So I'm going to save that and go to our player script.

I am going to scroll up to where I want to add the Onready variable.

And I'm going to hold control and drag left Boost particles into line 15 of our script here.

Going to enter distraction free mode.

You can see we've got boost particles right boost particles and left boost particles.

I'm going to go into the process function.

And down there I am going to find the if statement for when we are pushing the rotate right
key.
And I'm going to want to do exactly the same thing as I did here for when we were rotating
left.

And in fact, I'm actually going to copy all of this code.

I'm going to hit Ctrl C with the setting the emitting value in rotate left the else block and
setting

the emitting value afterwards.

And I'm going to hit enter.

So I'm at the same point in this if statement as this block is in this if statement.

And I'm going to hit Ctrl and V and that's going to enter, it's going to set the value of right
boost

particles to start emitting when we rotate right, which is incorrect at the moment.

We want to now update that to be the left booster particles instead.

So I'm going to select the first word of right boost particles.

And I'm going to say left booster particles.

So now when we are pushing rotate right left booster particles will start emitting and then
otherwise.

And then we want to set this to also be the left side.

So left boost particles are emitting.

And now when we're not pushing rotate right.

The left boost particles will stop emitting.

And that's everything we need if we start running it.

If I start playing around in the level, you should see both sides of the ship have particles start

coming out as we are moving.

And even if I hold both, they'll all come out.

So with that all done in the next lecture, we are going to be learning about using one shot
particles

for our ship crashing and for when it reaches the final goal.

One Shoot Particles


In this lecture, we are going to learn about how to use one shot particles for our ship crashing
and

reaching the final goal.

So in this lectures resources I have provided a zip file with two one shot particles.

If you go ahead and download those resources, you will get a hold of the following zip file.

We can extract that and within we will find a folder a folder called particles.

And in there these two scenes explosion particles scene and success particles scene.

And I want you to go ahead and drag those two scenes into our file system.

So I'm going to take them and drop them into the root of our file system.

And now we should see we have I'm going to make this file system bigger so I can see what's
going on.

You can click the area between two dots and move them around and drag up and down.

You will see that we have booster particles and explosion particles scene and success particles
scene.

And now for maintenance reasons I'm going to move those all into a folder, just as we did with
audio.

So I'm going to right click on the root create a new folder I'm going to name this particles.

And I'm going to want to move those particles within the particles folder.

And the way I'm going to do that is I'm going to hold control, and I'm going to click on each of
those

scenes.

Boost particles.

Scene explosion particles, dot scene and success particles dot scene.
So I can select them all at the same time.

Right click on one of them and click on the move slash duplicate to option and then select the
particles

folder I want to move them into and click the move button.

So now we have this particles folder.

And in there we have all three of our particle scenes.

I want to reset my layout so that my file system is at its original size.

I'm going to do that in the editor button.

In the top bar menu button, go down to Editor Layout and in Editor layout select default.

So we now have our particles in our file system.

We want to attach them to our player, because we're going to make it so that when the player
touches

the floor, they explode and explosion particles come out.

And when they touch the final goal, there's some success particles that are bright and colorful
that

come out of the player as well.

We're going to do that is I'm going to right click on the player and I'm going to instantiate a
child

scene.

And in there I am going to select the explosion particles to start with.

So I'm going to select explosion particles and click open.

You see, we've got this new bounding box for this set of particles.

We want them to be in the middle of our player, and we can actually see these particles in
action right

now.

You'll notice they're not emitting the same way the booster particles are.
And that's because they are one shot particles.

And that means the particles will emit once and then afterwards they will stop.

So emitting the emitting property will set itself off once the particles have all finished
emitting.

If I enable emitting right now, we should see an explosion.

There we are.

So we had a bunch of square particles that came out from the player, and they changed color
and they

changed scale, and they all gave us a bit of a sense of an explosion.

If we go down to this time foldout menu and expand it, you will see that these particles are set
to

one shot.

If we disable that and we set the particles to be emitting, they will continuously emit.

But it's this one shot property that means the particles will only emit once, and in fact, it will

only be 64 particles that emit before it stops.

And that's because the amount of particles is set to 64.

One other property we can control is the explosiveness.

So at the moment, all of the particles emit roughly around when we set emitting to be on.

If we had explosiveness set all the way down, the particles will emit at even time intervals
across

the lifetime of the particles.

So if I set that all the way down to zero, there will be a constant stream of particles coming
out.

And if I set that all the way to one, the particles will all emit exactly at once.

But we had a nice middle ground of 0.75.


That meant most of the particles emit when they first spawn.

So now we know a little bit more about how we control these properties.

I am going to set one shot to be back enabled, and we can go about setting it up so that when
the player

crashes, these particles emit.

So we want to go to our player script, and we want to create an onready variable for these
particles

just like the others.

So I am going to scroll down to the explosion particles in the scene tree.

And I'm going to hold control.

And I'm going to drag those explosion particles in below the rest of our onready variables.

I'm going to expand that.

And you can see we have these explosion particles with the rest.

So we're going to control these in a very similar way to how we control the booster particles.

If I go down to our crash sequence function.

So when we've touched the floor and we start crashing and we play the explosion audio right
at the top

of there, I want to get the new particles we just added, which were called explosion particles.

So I'm going to type explosion.

And you see we've got explosion particles coming up.

And we can just set those to be emitting.

So we will do dot emitting and set it to be true.

And now, whenever the ship crashes, those particles will start emitting.

And because it's one shot, they will only emit once.

So let's test that out.


I will run the project.

I will fly up and let's crash into the floor.

And there we are.

We have a nice little set of explosion particles.

And with that set up, we can move on to our challenge.

So now we've set everything up for the explosion particles.

I want you to instantiate the success particles in the player scene.

Once you've instantiated those success particles, you can create an Onready variable for them.

And then I want you to make those particles start emitting when the player touches the landing
pad.

All right.

I will see you back here in a few moments.

Welcome back.

So we're going to follow pretty much exactly the same steps we did for those explosion
particles.

Let's close this project.

Let's go to the 3D view and exit distraction free mode.

So we want to select the root node and instantiate the success particles.

So let's do that.

Select the player root.

Right click instantiate a child scene.

And from here we want to select the success particles.

I'm going to click open.

And now we have our new success particles.


We can see how those look right now by enabling the emitting property.

And we get a bunch of brightly colored spheres coming out of the player.

And now we can go about setting up our Onready variable.

I'm going to save that by hitting control S and go to the script tab.

Going to go up to the top where the rest of the onready variables are declared, and I'm going to
hold

control and drag the success particles into our scene, into our script.

We can exit distraction free mode.

And we know these particles are called success particles.

So let's go down to where we detect when we've touched the landing pad.

And that is in our other function matching crash sequence.

We have complete level where we play the success audio and we change the next level.

So at the top of this we want to get access to our success particles.

They're called success particles.

And then we want to set their emitting property to be true.

And just like that, we are all done.

Let's run the scene and see what happens when we touch the landing pad.

Lovely.

We get a very nice series of very bright spherical particles coming out as we land.

The compliment that success.

Audio.

And with that, we're all wrapped up.

We've now learned how to use one shot particles, unlike plain particles that emit constantly in
our
scenes.

In the next lecture, we are going to be making our rocket look a lot more like a rocket with
additional

3D shapes.

Improving the Sheep


In this lecture, we are going to be using the mesh instance 3D node to make our rocket look
more like

a rocket.

So to start with, I'm going to show you how to use cylinder shape properties to try and make
us actually

have something that's got a thinner body and a point at the top.

And so to get started with, we're going to want to open our player scene.

And then when we are in there, I'm going to make what we've got as the mesh instance 3D
invisible.

At the moment.

All of the work we're going to do at the moment, we're going to want to keep within this
cylinder collision

shape we've got so that our actual gameplay will be the same regardless of how it looks,
because we're

not going to be creating any new collision shapes.

So we're going to want to create another smaller body.

So I'm going to select my player root node.

And I'm going to hit Ctrl A to add a new node.

And I'm going to search for Mesh Instance 3D.

And then I'm going to select that mesh instance 3D node.

And just like we had before.


This time I am going to go with that selected.

Go over to the mesh property, click the drop down to the right and select a new cylinder mesh.

Now this cylinder, we're going to fiddle with its actual shape properties so we can control its
dimensions.

So I'm going to expand this mesh object we've got.

And we'll get a variety of objects to control how it looks.

We have a top radius a bottom radius and a height.

We can drag these sliders around so we can make the top radius much bigger or much smaller.

And if we make it much smaller, it comes to a point which actually I think is how I'm going to
start

here.

So I'm going to set the top radius to zero.

So we have a shape with a point.

And I'm going to set the bottom radius to 0.2 I think.

So it's much thinner.

I'm then going to decrease the height down to 0.5.

And now I've got this shape, I'm going to want to move it so that the top of the shape touches
the

top.

And actually, just so that we can see the dimensions a bit easier, I'm going to click on the z
axis

on our gizmo, and we will get a flat on view from the side so that we can see when these
points are

lining up.

So I'm then going to drag this mesh so that its top touches the top of our shape, which is about
there.
I think that's going to be something like 0.75m up.

But we can check and make this more accurate.

If we look in our inspector, I am going to scroll down past all of that mesh information, go
down

to the transform property, and in there we can see what our Y position is set to.

And I'm going to round that up to 0.75.

So we now have the top of our ship.

I think it's worth renaming these mesh instances so that we know what parts they're referring
to, so

that it's easier to fiddle with them later on.

So I'm going to double click on this and I'm going to rename that to the cockpit.

So we now have the cockpit of our ship.

We're now going to want to make the body that comes down, joining up to the bottom of that
cockpit.

And I am going to add a mesh instance 3D.

Another one, I'm going to select the root node.

I'm going to hit control and a add a new mesh instance 3D.

It's already searched up.

So I can just click create and add that into the scene.

And in the mesh property we can add another cylinder mesh.

Now for this one.

We want its width to be the same as the bottom of that cockpit was.

So I'm going to expand the mesh property, and I'm going to set both the top and bottom radius
to 0.2.

So now we have a shape that's the same size.


I can then make it shorter.

I'm going to make it 1.5m tall.

And then if we move it down, it should fill out the rest of the space within our ship.

So you can see just about there.

It now fills up the rest of the space to the bottom of our cylinder mesh outlined in blue.

As again, I'm going to go down to the transform property and round out whatever number I set
that to.

So I was slightly off.

I'm going to set it to -0.25m on the y axis.

So we now have the body of our ship.

Let's rename that.

And now, for ease of use, I'm actually going to do some reparenting.

I'm going to take this cockpit, and I'm going to drag it so that it's a child of the body node.

Because it's a child.

It will be repositioned when we reposition the body.

So that means if we change the position of our body, the cockpit will move with it, which is
very

handy.

And actually, when we're building the rest of this ship, we're probably going to want to keep
everything

reparented to some sensible point on the ship so that as we move them around, we can move
all of the

sub pieces.

But from here, we're actually at a good spot to start trying to dive into our challenge.

All right.
So by adding new meshes to the 3D nodes and controlling their shape property, I want you to
customize

the rest of the rocket.

This is a good opportunity for you to experiment with all of the 3D shapes that are available
within

the mesh instance 3D node, and you just need to make sure that this fits within that cylindrical
collision

shape.

3D I was pointing out earlier, it would also be nice if you end up with three thrusters at the
bottom,

one for the main thruster and two for the left and right side thrusters, so that we can match
them

up with those particles later on, but really take a chance to flex your artistic muscles.

Maybe pick a ship you like from some piece of media and try and build that.

But just try and create your own thing here.

And with that all said and done, I will see you back here in a few moments.

Welcome back.

So there is no wrong way to go about tackling this.

The rough way I'm going to have my ship look is I'm going to have a cylindrical body piece
that juts

out here, and I'm going to have a base for the thruster here, and then I'm going to have an arm
that

sticks out and a thruster pointing downwards, both on the left side and on the right side.

And then I'm going to join all of those bottom pieces together with a Taurus, which is a sort of
donut

shape.

So let's start tackling that.


Let's add our body piece around the middle.

So I'm going to select the body root node.

Well the root node of this shape at least.

And I'm going to hit Ctrl a.

And I'm going to add another mesh instance 3D.

And I'm going to call this the midriff.

I'm going to go to the mesh property and I'm going to add a new cylinder mesh, and I'm going
to expand

that and I'm going to make this much shorter.

I'm going to make it 0.3m in radius at the top and 0.3m in radius at the bottom, and 0.3m tall
overall.

And actually that looks a bit too wide for me.

I want it to be a little bit more flush with the body, so I'm going to decrease those to 0.25.

I might move it up to exactly zero globally at the middle.

So I'm actually going to move that up to about here, which I think is 0.25m up.

So I'm going to go down to the transform property, and I'm going to set that to a rounded
number which

is 0.25m up.

So I have this midriff point.

I'm now going to use something similar to make the base larger where the booster is.

So I'm going to start off by duplicating this midriff I'm going to duplicate it.

And now we're going to notice something interesting.

If I move that down.

If I open this mesh property up and I say start increasing its top radius to something like 0.5,
you'll
notice both of these shapes have updated because I duplicated the previous midriff.

It has exactly the same mesh property.

They're actually sharing the resource at the moment.

So when we update one, the other will update.

Now there are a few ways we could work around that.

We could replace the mesh in here with a new one, but we want to keep the same properties,
so that's

a bit of hassle.

The actual way we'll separate these shapes is via undo what I did there.

We can click the drop down to the right of this mesh.

And at the bottom of this list there is the make unique option.

That's going to just turn this mesh into an entirely unique mesh and make its changes, not
share between

any other meshes that it's copied.

So select make unique.

And now if I increase that top radius you'll see this one changes but the old one doesn't.

Going to undo that I'm actually just going to make this taller.

I'm going to make it 0.4m tall.

And I'm going to move it down to the base and try and get it to line up.

Let's go into Z view so I can see when it's lining up, and I'm going to drag it up a bit just so it

lines up with the floor.

That's about fine for me.

So now we've got a big thruster at the bottom, and we can start moving on to making these
arms that

are going to come out the side.


Oh, I'm also going to rename that to thruster.

So the way I'm going to make these arms is I'm going to have a cube that juts out, and then
another

cylinder that points down to where those particles are emitting.

So I'm going to attach these to the body.

I think we just want them attached to the body.

I'm going to hit control A with the body selected add a new mesh instance 3D.

And I'm going to go to the mesh property and select a box mesh.

I'm going to make this significantly smaller.

I'm going to make it 0.2m on the x axis, 0.2m on the z axis, because that's its depth.

And then its height can be something a bit bigger.

I'm going to go with 0.3m.

So now I'm going to move this arm to the left so we can see it.

I'm going to use this blue arc to control its rotation around the z axis.

Let's go back into a more orthogonal view.

And I'm going to rotate it around the z axis so that it points towards this middle section of the
ship.

I'm going to move it down and to the right.

I want it to be long enough that it juts out, but also so that we can't see the corner cropping out.

So I don't want to leave this harsh edge jutting out, so I'm going to actually need to make it a
bit

longer.

Let's try 0.4m and move it a bit closer to the body.

At about works.
I might need to rotate it a bit more.

There we are.

So we've got an arm jutting out.

If I look around the ship, you can see it's flush with the actual body.

And we can have another booster attached down here.

In fact, it would be nice from my perspective if it was a bit closer to the main thruster.

Let's go back in and let's angle it down a bit more and bring it just a bit closer to the bottom
thruster.

And I think that looks good.

So now I can position my thruster here in that empty space.

So I'm going to rename this to Left Arm.

I know this is the left arm because I remember from earlier that the positive x direction.

So where this red arrow is pointing is to the right from the games perspective.

So I'm going to call this the left arm.

And I'm going to add a capsule as a child of it, and that capsule is going to be the last the
thruster

on the left.

So I'm going to select that left arm, because I want this to be a child of that arm.

So as I move the arm around, the thruster will move with it.

I'm going to select the left arm, hit control A and add a mesh instance 3D.

And this mesh instance is going to be a capsule mesh.

So in the mesh property I'm going to go over and select capsule mesh.

No it's not going to be a capsule mesh mesh.

It's going to be a cylinder mesh.


So I'm going to change that to cylinder mesh.

And I'm going to make it much smaller.

I'm going to make it 0.3m, 0.2m at the top, 0.2m at the bottom, and I'm going to make it 0.3m
tall.

Because this is a radius.

Two meters is actually a lot wider than two meters for the boxes.

So actually I'm going to want it a bit smaller.

That reason is it's a radius.

So two meters is only covering half of the width of the cylinder.

So actually the total width is going to be 0.4m.

So I think I can get away with 0.1.

Point one's a bit small.

Let's try 0.15.

And there we have a thruster of some kind.

So I'm going to go into my Z view.

I'm going to rotate this around and I'm going to move it down a bit.

That looks good, but it's not quite tall enough to reach the top, so let's increase its height a bit.

I'm going to increase the height to 0.4 and then move it up a little.

And I've changed my mind.

I want the bottom to be a constant width, so it is just a cylinder coming out at that point.

Let's rotate it closer to the body.

So now we have the left arm of our ship.

If we want to make this move over to the right, we do need to do one extra step.

So I'm going to select this left arm.


I am going to duplicate it.

I'm going to hit control and D to duplicate.

Or you could have right clicked and selected duplicate.

If I drag it over to the right its orientation is wrong.

We're going to want this to rotate about its y axis so that it's facing the right way.

So I'm going to reset its position.

I'm going to rotate it around the y axis by with this left arm to selected.

Go down to the transform property and set its rotations y value to 180.

So that's about the green arrow.

So if it's rotated around there it is now a mirror reflection around the middle.

From our perspective.

And I can now invert its position if I take its positions x value and I get rid of the minus sign,

it will now be mirrored about the middle of the ship and it will be at the same point the left
arm is,

but this time on the right and with the correct orientation.

But our name is wrong at the moment because it's still called Left Arm.

So I'm going to rename this to Right Arm.

And I'm going to take this opportunity to rename this to thruster.

And the one under the right arm thruster as well.

The last step I wanted to do for this show, because I think that's looking pretty neat at the
moment,

is I wanted to add a little ring around the base.

Way I'm going to do that.

So I'm going to select the body, hit Ctrl A, add a new mesh instance 3D.
And in here I am going to add a new mesh property.

I'm going to select a Taurus mesh, and a Taurus is a shape much like a donut.

So you'll see it's a ring with a hole in the middle.

And I'm going to want this ring to go through each of the thrusters on the outer edge of the
ship.

And I think that's going to be around about 0.4m on the inside and 0.5m on the outside.

That looks about right.

So the two properties we've got here are the distance from the middle to the inside of the ring,
and

the distance from the middle to the outside of the ring.

So with an inner radius of 0.4m, we've gone 0.4m and our donut shape has started.

And then 0.1m later our shape has ended.

So we've ended up with a 0.1m wide donut going around.

I'm going to drag this down to line up with the thrusters and see how that looks.

I am actually quite happy with that.

One last thing I missed there.

Let's rename that to Base Ring.

So one thing we can do at the moment, because my thrusters are a bit up, we can actually
move these

particles so that they emit from within where the thrusters are.

So I'm going to go up in my scene tree and I'm going to find my left booster particles.

And I'm just going to move them up and to the left a bit so that they're inside this left booster.

And I'm actually going to rotate them ever so slightly so that they come out at a bit of an angle
down

to the left.
And then I'm going to do exactly the same thing for the right booster particles.

So I'm going to select the right booster particles, move them up and to the right and use this
blue

arc to rotate them.

So they're coming out to the right.

And with that all said and done, we are finished.

We have constructed a new, much more rocket looking ship out of component mesh instance
3DS and learnt

about some new shapes that we can create with those nodes.

In the next lecture, we are going to go on and start adding colour to our ship and learn how to
use

standard materials in a bit more detail and do things like save them and reuse them.

Coloring the Ship


In this lecture, we will carry on making our ship look much more like a rocket ship by going
ahead

and adding some color.

And in order to do that, we will be learning how to save colors to reuse across a variety of
objects.

So the way I'm going to go about adding colors is I'm going to make it all a uniform red color.

I am going to create that red color on the body to start with, because we're going to need to add
this

color to each of those meshes we've created.

So I'm going to select the body for this ship in the scene tree.

And I'm going to scroll up to find the geometry dropdown under Geometry Instance 3D.

Fold out that geometry menu and we'll have material override.

In the material override property we can add a standard material 3D.


So let's click the drop down to the right of it and add a new standard material 3D.

You'll see it's gone a little bit whiter.

If we expand this material, we can go down to the albedo property, and in the albedo property
we can

set the color for our shape.

I'm going to click on the color property to open the color picker.

Drag this value down a bit so I can see the colors I'm dealing with and find a red.

Bordering on orange that I quite like the color of.

I actually think I found something quite nice rather quickly there.

I might make this a little bit darker, so I'm going to drag that down a bit, but that's quite a nice

ready orange color.

So now I'm happy with this one color.

What I'm going to want to do is I'm going to want to save this material I've got as a resource,
and

then I'm going to apply it to all of the other parts of our ship.

And the way I'm going to do that is I'm going to scroll up to this material override, where this
material

I just made is if I click this drop down to the right of it, you can see there are options for
loading

in materials, making it unique or at the bottom, saving it.

And when we save a material, it gets added to our file system as another resource that we can
drag

and drop.

So I'm going to click save and I'm going to name this ship Red material.

And I'm just going to save that in the root directory along with where the player scene is.

So I'm going to click save.


And if we go down in the file system you will see at the very bottom we have this ship red
material.

And if I double click on that it will open it in the inspector and we can edit it there.

So now we want to apply this red material to our other shapes.

What we could do is we could click on, say, the cockpit of our ship, go to that same geometry
property

and under material override, click the drop down to the right of it and quick quick load.

And if we do that we'd be able to select our one available material we have saved in our file
system.

In fact, I'm going to do that for this one.

And now it's loaded that material in there.

But another neat thing we can do is you can just drag this ship material from down in our file
system

and then drop it on a part of the ship.

I really like that.

It's quick and easy, but I have noticed it has some quirks.

If you drag this material over a body that already has a material on it, it seems to remove the
material

that's there.

I think because it tries to drop the one you've got in and it replaces the old reference or
something.

I assume it's a bug, but it's worth bearing in mind that you need to try and avoid hovering over
a

part of the ship that already has a material.

So I'm just going to drag this material over all the individual parts of this ship.

And let's try that out again to see it in action.


Just like that, we have a much more unique and neat looking player character.

Let's crash it for the sake of it.

So with that all said and done, it's time for a challenge.

You've made a custom ship with custom colors, all in constrained conditions, something a bit
unique

to you and your challenge, should you choose to accept it, is to share what you've created with
the

community.

We have a variety of social media platforms where you can share a picture of what you've
created.

You could go to the Game Dev forum or the Game Dev Discord server, or you can tag game
dev directly

on major social media platforms, for example Twitter, Instagram or Facebook.

This is a great opportunity for you to see what others have created and to show off your own
artistic

talents.

So I'm very excited to see what you've made, and I will see you back here in a few moments.

All right.

Welcome back.

That has been a quick look at using standard materials to set the color of our ship, as well as
some

ways to save and reuse materials, as well as applying them to a variety of mesh instances.

In the next lecture, we are going to be moving on to using CSG shapes to filling out the rest of
our

level and adding some much needed backgrounds.

Building Backgrounds
In this lecture, we will start using shapes to flesh out the backgrounds of our levels.
So to start with, we're going to want to return to levels seen.

And we're going to use CSG shapes very similar to our floor to create a bounding box around
our level

to the left, above and to the right.

So the first thing I'm going to do is I am going to select the floor and I'm going to create a new
node

as a child of it, which is going to be another box.

So I'm going to hit control A to open the Create New Node dialog.

And I'm going to search for box 3D.

I'm going to hit enter to add that and drag it up.

And we can see our box right here.

One important thing we're going to want is we're going to want the material that's on our floor,
because

I want to use the same shade of brown.

So I'm going to select the floor node and its material in its material property.

I'm going to click the drop down to the right and select the copy option.

This will let us copy the resource that we can paste into other slots in inspectors that accept a
material

property.

So I'm going to copy that.

Click on this new box 3D.

And in its material property I am going to click paste.

Now.

One point a convenient thing CSG boxers do is if a parent has some specific properties like
use collision

or children will have the same properties automatically enabled.


So this box doesn't have any collision properties we can enable.

It's just going to use the same value as that floor.

I'm going to rename this node to wall.

And I'm going to give it some dimensions.

I'm going to make it ten meters tall.

I'm going to make it four meters on the x axis and four meters on the z axis.

And now we can move that around as we need.

I'm going to just drag it over to the left to make a left wall and use this blue Z axis rotation to

tilt it away from the ship a bit.

And with it over on the left.

I'm quite happy with that actually.

I'm going to move it down lower a bit.

There we are.

So we have one more, and I'm just going to copy and paste this around until we have an entire
bounding

box.

So I'm going to hit control and D to duplicate this wall.

Now we have another node called wall two in the same place.

I can move that straight up and use this blue Z rotation to rotate it so that after angling to the
left

at the bottom, it's now going to the right and creating an overhang over the head of us.

Let's bring that down a little bit.

And this is fine for a wall on the left side of my play area, I think.

Now I'm going to duplicate it one more time.


And this is going to be a ceiling node.

So I'm going to rotate it around.

So it's horizontal.

And I'm going to rename this one to ceiling.

Let's move that up with the gizmo.

Let's change to full side view with that Z button on the gizmo in the top right.

I'm holding shift and clicking the middle mouse button to move around and scrolling in with
my mouse

wheel, and I'm going to move that over to the right a bit and use this blue Z axis rotation to
angle

it down just a little bit.

I think I can move it a bit higher up, and I think I'm happy with that broad shape.

I'm going to copy it over so that we can start bridging this gap over to where the landing pad
is.

Actually, let's go a little bit higher.

I'm going to hit Ctrl and D to duplicate it.

Move this new one to the right.

And I think I'm okay having a bit of a jutting, jagged shape in the rocky walls of whatever
location

we are flying around.

And so I'm going to duplicate it one more time and move it over further to the right.

And now rotate it downwards using that blue Z axis.

And I'm going to try and line it up just a little bit with the existing wall.

Let's put it there.

A little bit further.


There we go.

So now we want walls to cover this section here.

So I'm going to copy one of my wall nodes so I don't need to rename it.

I'm going to hit Ctrl D on wall to move it below wall three.

So I'm just keeping the.

Whenever we add a new node it gives it a new unique number until it has a unique name.

I just moved wall three below wall two so that all of my numbered walls are ordered
numerically.

I'm going to move this new wall three over to the right hand side of the landing point and drag
this

blue Z axis rotation to angle it away and move it up a bit.

And now I just need to bridge it from here to here.

And we will have a complete bounding area.

So I'm going to hit control and D to duplicate.

Move it up and rotate it around.

And then we are good to go.

So now let's move around.

So one thing we will want to do is see how much of the level we can actually see with our
camera.

So I'm going to collapse this floor and I'm going to select the camera 3D node for this level
and click

the preview to see what we can see.

We're not actually seeing the full picture here.

I'm going to enter distraction free mode so we can see more of that viewport.

And we can see right now this isn't quite doing the trick.
We'd rather see more of the bounding area.

So I'm actually going to go ahead and move the camera back and up a bit.

So I'm going to select that camera 3D in the inspector.

Go to its transform property.

And I'm going to move it further back and its distance away from the play area is this z value.

So let's increase that z value, move it a bit further back, and then let's move it a bit further up

so we can see that jagged roof a bit more and a distraction free mode.

We can now see a bunch of the floor at the bottom, and not very much at the top.

We can actually afford to go a bit higher, so I'm going to move that even higher up.

And then let's just see that in action.

I'm going to play this level.

And there we have all of this new terrain around the edge of our level.

And you can see it has collision enabled.

So if I touch the ceiling, we will indeed crash.

Now I actually think we could use a little bit more vertical space because we're going to have
things

like things to dodge around the top on level three and around the bottom to dodge.

So I actually want to move all of that stuff just up a little bit.

So I'm going to try that.

Now.

I'm going to exit this camera preview mode, close that bottom part, and I'm just going to move
all

of the items at the top up a bit.

So I'm going to go into the floor.


And because we renamed them to ceiling, we know which ones are at the top.

So I'm going to move this item up just a bit higher.

I'm going to need to move this wall up a bit to reach it as well.

So I'm going to just click on that wall on the left and move that up a bit.

And then this area was too high as well.

So I'm going to click on this box, move it up and rotate it a bit.

And I think something like that is good.

Can afford to move the middle one just a little bit higher to.

There we go.

I'll re-enter the camera preview mode.

And that looks great to me.

Let's run it one more time.

There we go.

We have a bunch of area around the edge of the map being contained.

So with that done, we can move on to our challenge.

So given we've added shapes to the sides and top of our level, I want you to go ahead and add
more

shapes behind the stage to fill out the background.

And this is a chance for you to flex your creative muscles and imagine what kind of confined
space you

want your rocket to navigate through.

Are there rounded edges to any of the shapes?

Are there domes?

Are there various spacey buildings?


Whatever you want.

And with that, I will leave you to go ahead and create a background with more shapes.

Welcome back.

So for my background, I want a bunch of jagged blocks looking rather similar to these shapes
we have

jutting out at the top of our screen.

In order to do that, I'm going to exit this preview mode and I am going to go ahead and copy
one of

these wall pieces.

I am going to Ctrl D to duplicate that wall.

We've now got wall five.

I'm going to drag it down below the walls and ceilings of this section, and I'm going to call it
background.

Rock.

And I'm going to move that back into the scene.

So it is now behind everything else, and I'm going to move it to the side and angle it a bit, and

I'm just going to end up with a bunch of jutting out shapes, and I'm going to use whatever
rotation

I want.

So I'm going to rotate this shape around the y axis.

So it's angled backwards a little bit.

And I think I'm just going to have a series of shapes like that.

So I'm going to duplicate this background rock and move it over.

Maybe move it down a bit and then duplicate it again, move it over and move this one up a bit.

And try and change over to the view from the front so they look rather symmetrical at the
moment.

They at least all look lined up.

I'm going to move that one over a bit so that they intersect and move it down.

And we're really just going to populate this shape with anything we think will look interesting.

I might actually want to frame the center a bit more with these shapes.

So I'm going to select both background rock two and three by holding shift and clicking on
them in the

scene tree.

And I'm going to drag them both over to the right.

And then I'm going to select this block on the left and move it over to the left.

Then going to duplicate lock three and move it up to the ceiling and use this y axis to rotate it
around

so that we have another another prism seeming to come about from above.

And it's just going to look like some very cubic blocks, a little bit like bismuth.

I'm going to decrease the dimensions of this.

I'm going to make it three meters wide and three meters tall instead, but the same height.

And I'm just going to have a bunch of sharp, jagged rocks coming from the ceiling at fairly
similar

directions.

I'm going to leave that one going off to the side so that it looks like we're rounding out the
cavern

a bit.

And then I think I need one more down in this space.

So I'm going to duplicate background rock to move it to the right and move it down.

I'm just going to go back to the front view.


Make sure that there's no really empty spots.

There's kind of an empty spot up here where it'd be nice to have a rock.

And there's an empty spot down here where it'd be nice to have a rock.

So I'm going to duplicate background rock seven, move it across to the right and down again.

Now this space is filled out and I'm going to select this block behind us on the left.

I'm going to change my rotation so I can see it.

This one over here.

And I'm going to duplicate it and move it to the right and then up.

So it's out of the way a bit.

And then I'm going to move it back into the view so that it becomes a bit smaller for our
perspective.

So now we have a bunch of blocks in our background.

If I run that, I can see how it looks.

So we just have a bunch of jagged rocks filling up the back of our view that we can explore,
and the

light is passing through all of them in interesting ways.

And I'm going to try and land my ship over here, and that's all fine.

And we're going to encounter our first issue, which is that background isn't applied to all of
our

levels.

So what I'm going to do is I'm going to select this floor node.

So this one that contains all of those backgrounds.

And I am going to save that as a scene.

So I'm going to right click on it.

And I'm going to save branch as scene.


And I'm going to call this background.

And hit enter.

So now that floor scene is saved.

If we go into our other scenes, we can replace the floor node with this new entire background
scene,

and it will get those backgrounds that we've just made.

So let's load level to scene.

We have a floor node here.

I'm going to select the root node.

Right click instantiate a child scene.

And I'm going to search for background.

There it is.

And I will click open and we have the background.

It's called floor though, so we can get rid of the old floor node that is just the base and hit the

delete key with that selected and hit enter.

You can also delete by right clicking and selecting delete nodes at the bottom, and then
clicking confirm.

And then I'm just going to rename that to floor.

And I'm going to repeat that for level three and four.

I'm going to open level three.

This time I'm going to delete the floor node first because I know it's going to rename the other
node

if I don't do it first.

So I'm going to delete the floor.


Right click on the root.

Instantiate a child scene, search for background and instantiate it.

We now have a background here, and in level four we can get rid of the floor.

Right click on the root, instantiate a child scene, select background, click open and we're done.

So now if I run that and as I progress through the level we will have a whole bunch of different
backgrounds.

I've actually just noticed something, and that is that I adjusted the camera for level one, but I

haven't adjusted the camera for those subsequent scenes.

I'm going to show you a neat way you can update a node's properties, and that is by copying a
node's

properties.

So let's close this.

Let's return to the root level.

This one our camera is further back.

So if I click on the camera 3D and scroll down you can see it's it's y position is about 5.8 and
its

z position is about 9.3.

We can copy all of the properties associated with this node and paste them onto other nodes.

What you'll do is you'll click this little screwdriver and spanner in the top right of the camera
3D,

and you will select Copy Properties, and that's going to copy every property this node has.

If I then go onto level two and I select the camera 3D, you can see where it is at the moment.

Right here.

If I click the spanner again and I click Paste Properties, it has now moved back and up because
it's

got that new transform property.


I'm then going to save this.

Go to level three.

Select the camera.

Click on the little spanner and click Paste Properties.

Save.

Click on level four.

Click on the camera, click Paste Properties and save.

And now if we run when we move on to the next level, it will have the same view that we have
here.

So let's land.

And now level two has this new view that's further back and with this background.

And with that, we've set up an interesting background for our levels.

In the next lecture, we are going to handle a bit more of the lighting and the world
environment to

try and unify the appearance of this scene.

Lighting the Scenes


In this lecture, we are going to work on our lighting with the Omni Light 3D node and tweak
both our

existing world environment and directional light.

So way back at the start of our project, we set up a default world environment and directional
light

based on the preview, directional light and world environment that are available in these three
dots

at the top.

Well, now we have a bit more of a world setup.

We can start customizing those a bit to make our game look how we want.
Our world environment is responsible for this background, ground area and sky area we get.

And I'm going to just shift that over to a flat color so that it's not obvious that there's stuff
going

on in the background.

So in order to do that, we're going to want to fiddle with our world environment on one of our
levels.

It doesn't matter which just one where we've set up this background.

Let's go over to the World Environment node in the scene tree and select it.

In this node's environment dropdown, while its environment property, you get access to a ton
of features

for controlling how our scene will look.

You get things like glow options, fog options, ambient occlusion, a bunch of stuff, and the
property

that controls how our background looks is in this background fold out menu.

So at the moment it's set to Sky and you can control how that sky looks.

But you can also just click this mode option.

And in the dropdown to the right of it select the custom color option.

And that will let us just pick a flat color to use as the background for our scene.

So in this environment in the mode property, click the dropdown to the right and select
Custom Color.

This is going to set everything to be black.

Now having a black background is fine, but you'll notice the lighting's also changed.

The reason our lighting's changed is because of this ambient light fold out menu.

At the moment it's using the background color to determine how our ambient light should
look, but we

can make it continue to use the sky as before.


So under ambient light in the source property, click the dropdown to the right and select Sky.

So we use that previous sky for the ambient light, but when it's drawing the background, it will
just

use the color we set.

Now I'm actually going to do a neat trick to blend our color in a bit.

I'm going to go to our camera 3D, and I'm going to go into preview mode so I can see what the
camera

can see.

And now I'm going to select that world environment again.

And I want to pick a color for this background that blends in a bit more with the background
than being

a harsh change to black.

And the way I'm going to do that is in this background out menu for the world environment, it
has a

color property.

If we click on the color picker for that color property, there is this little eyedropper button.

And that lets us pick somewhere in our level to select a color from for this background color.

So I'm going to click on that.

And now you'll see as I move my mouse around the screen it is going to eyedrop whatever
color I'm hovering

over.

So I could set my background to be this red on our ship, or this green on our landing pad, or
this

pink on the collision object.

I'm going to select an area in shadow that's similar to this, an area of shadow on one of the
background
rocks, so that I get a dark brown as my starting point.

And now we have a color that's almost identical to this background.

I'm going to go one step further, though, because I want this to be a bit darker than that area in

shadow is.

And the way I'm going to do that is I'm going to reopen this color.

Now, I've selected that brown baseline, and I'm going to change over to the hue, Saturation
and Value

tab.

This is going to let us alter the saturation and value for this color.

And I'm just going to decrease the value from 14 down to let's say seven.

So let's make it have half the value it does before.

And now it's got the same tone.

The color is the same hue at least, but it's all darker.

And if I try running this level, it should just blend in a bit nicer than it does before.

So it looks almost believably like that's a background Cavan color behind the rest of the level
we've

set up.

So now we've got a background color sorted, we can start fiddling with our lighting.

I'm going to exit the preview mode for this camera, and I'm going to start looking at this
directional

light.

So important thing to know about directional light.

It doesn't matter where it is, it is globally applied in a direction, and that direction is shown

by this white arrow we see in the viewport.

It's just going to, no matter where we are, have light coming down at this angle.
Now at the moment that light is coming from behind our stage.

So if I rotate round, the back of our stage is well lit and this area is in shadow, which doesn't

necessarily look bad because it's dark and cavernous, but I do want to have the front of our
stage

lit.

So we could adjust this by just using the arcs, the rotating arcs on the edge of the gizmo.

And you can see if I select the y axis, the green arc, and rotate it around, we can pan things
until

the until the light is facing the front of this shape.

I actually have a direction.

I want to set this directional light to that I found while messing around earlier.

So I'm going to select my directional light.

And in the transform property I'm going to find its rotation.

And I'm going to set its x value to -40.

And I'm going to set its y value to ten degrees.

And so you can see that that is it's rotated so that the front is lit up.

But it's also angled up a bit higher.

It's not going as steeply downwards.

So a bit more of our background is lit now.

And if I change back to the camera view and preview, you can see more of this as well.

Lit.

One extra step I want to go through here is I actually want to make this directional light give
less

light to our scene, because we're going to add some more lights into our level later on.
So to make this a bit more ambient, I'm going to select the directional light I was just editing.

Its position doesn't matter.

So I'm actually going to put it back where it was.

And I'm going to scroll up to the top and see the properties for this light.

Now you have a bunch of options like setting the color of the light, and the energy of the light
is

how bright it is.

And that's exactly what I want to fiddle with.

I want to make the scene a bit darker.

So I'm going to make this directional light give half the energy it is at the moment.

So I'm going to set the energy property to 0.5.

You'll see it's all a bit darker.

So now we've edited our directional light 3D and our world environment.

We're going to start to want applying these changes that are on these nodes to the other levels.

Now we could go ahead and step through each level and copy and paste our values across.

But we added a node recently that will help us and that is our background scene, this one with
the

floor where we can go ahead and move this directional light 3D into that floor scene, and then
every

scene that's instantiated, this will have a directional light that is pointing in the right direction.

So the way I'm going to move it across is we can either right click on the directional light and
click

cut, which will remove it from this scene.

And we can paste it into the other.

Or if we want to be a bit more diligent and make sure we don't accidentally lose this node
somewhere,
we can copy and paste it.

So I'm going to copy this directional light 3D.

I'm going to open the floor scene and I'm going to select the route.

I'm going to right click and I'm going to click paste.

And that's going to add this directional light 3D as a child of this scene.

So you can see this scene right here has lighting set up in the same orientation as the last one.

So I can hit Ctrl s to save that.

And if I close this scene and go back to level two.

We have a slight issue now, which is now.

This level has two directional lights in it.

One within the floor and that one there.

So now it's got the old brightness it did before we decreased the energy.

So I'm just going to go ahead and get rid of this old directional light 3D.

So with that done, we can start taking a look at our challenge.

So we've just moved our updated directional light into our background scene.

I want you to go ahead and do the same thing, but move the world environment into the
background scene.

So you're going to want to either cut or copy that world environment, put it in the background,
and

then delete the old world environment from the main level scene.

All right, that's the challenge.

I'll see you back here in a few moments.

Welcome back.

So in order to remove this wild environment and add it to the floor, this time I'm going to cut
this

object so I don't have to delete it.

On the way back, I'm going to right click on the world environment and select cut.

So now this level doesn't have that world environment anymore.

But if I go into the floor, click on the floor scene, enter, open it in the editor and I'm going

to select the root node.

And I'm going to paste in that world environment.

So now every scene that adds this background will get that world environment with the nice
shade of

brown for the background.

I can save that and reopen level two.

And it has the new environment.

I am now going to do a bit of cleaning up, and I am going to remove those two unnecessary
lights and

wild environments from all the other levels.

So I'm going to go into level one.

I'm going to select this directional light and world environment.

I hold control to select them both in the scene tree and hit the delete key and hit enter.

And now they're gone.

And it's using that world environment and light from the background.

Same for level three.

Select the directional light.

Select the world environment.

Hit delete.
Hit enter and save.

Level four select the light.

Select the environment.

Hit delete.

Hit enter and save.

So now we have our nice new background.

The last thing I want to do, as far as lighting is concerned, is I want to go straight into this
background

scene.

So I'm going to make my changes in here now so that they're applied to all of those levels at
once.

And that is I'm going to add some new lights.

I'm going to select the root node.

I'm going to hit Ctrl A and search for Omni Light 3D.

So it's saying this is an omnidirectional light, such as a light bulb or candle.

It spreads a light out in all directions, unlike the directional light, which all casts it in one

specific direction.

I'm going to click create and I'm going to move it up.

So you can just about see it's lighting up ever such a little around the back.

The reason I want some omni lights in this scene is because of this big, hard shadow that's cast
on

the background.

I just want to soften those up a bit and make it a bit less obvious that this front, this front area

is casting a shadow on the background.

So I want to make this light bigger.


With this omni light selected.

It has a whole bunch of properties.

If I go over to the inspector and look under the Omni dropdown, we have a range property.

That is how far this light is spreading out.

If I increase that, you will see that the white gizmo is increasing in size.

I'm going to increase that up to 12.

I think that's a nice large range, but you'll see it's having a very little influence on the
background.

And that's because of this attenuation property.

And that controls how quickly the light drops off as we get further away from the center.

So when you have a curve like this, you can either click on it and drag down, and you will
make it

so that it drops off even faster.

Or if you raise it up, you will see very quickly that it is spreading the light much further before

dropping off.

You can already see the scene's a lot lighter if I do that.

There's actually a really nice shortcut for these curves.

And that is if you right click on the curve you get a bunch of preset curve options.

So there's ease in which is that first option where it dropped off faster and ease out where it
dropped

off much closer to the edge.

So I'm going to select this ease out option that set this to 0.5.

And you can see we have a light that is quite distinctly spreading more around the background.

In fact I'm going to move it a bit further back.


And I think I'm quite happy with that.

So now we have one light in the background.

I am simply going to repeat it.

I am going to duplicate this light.

So I'm going to select it in the scene tree and hit control and D.

And I'm going to move this one over to the left to light up the left side of our scene.

And I'm going to duplicate it once more and use the gizmo to drag it all the way over to the
right.

And now I think that looks really nice.

It looks like there is a lot of light in the center of our scene, and less at the edge.

So with that all in place, I'm going to run the scene and see how it looks.

I think that looks good.

Let's fly to the end and see how the next one with objects in the middle look.

And that is how our scene is looking, with all of its new lighting and world environment
options.

In the next lecture, we are going to look into wrapping up this project and learning how to
export

it so that you can provide it for other people to play.

Exporting your game


In this lecture, we are going to learn how to distribute our game files to players so they can
actually

play our project.

So who can play the games we produce?

We can easily export to windows, Linux, Mac, iOS, Android and web.

The export options will drastically increase the file size of the engine.

So we are going to need to download templates for whatever platform we want to distribute to.
So if we want to distribute to windows, we will need to download the windows templates.

And if we want to export to web we will need to download the web templates.

Thankfully, that's all doable from in the export page for the engine.

So let's go back to Godot.

We'll find our export options in the top bar in the project dropdown and under export.

If you click that export button, you will open this export window where we can add presets for
the

different platforms we want to distribute to.

If you click this add button in the top middle, you will see all the available platforms we can
build

for.

I am going to select Windows Desktop because I am on windows, and you will see we get a
bunch of config

options on the right and some warnings at the bottom.

I'm just going to make this full screen green so I can see what's going on.

And you can see it says we have no export templates found at the expected path.

That's what I was saying about we need to download templates for whatever platform we want
to distribute

to.

So if you click this Manage Export Templates button at the bottom, it will give us a prompt
where we

can start downloading whatever templates we need.

So it's already figured out that we want to download templates for the version of the engine
we're using,

which is 4.1.1, and we can just click the download and install button on the right, and it will
download
those from whatever the best available mirror is.

So click the download and install button.

As you can see, this is 700MB.

And that's just because of all the necessary binaries for distributing for that platform.

I'm just going to wait for this to download and see you back here in a moment.

Okay.

It has returned me to that export template manager, and it is telling me in the top right that
export

templates are installed and ready to be used.

So I'm going to close that export template manager.

I'm going to click the project button in the top left again click export.

And now you can see all of those errors are gone.

And I'm able to freely distribute on windows desktop.

Although at this point you may actually see a little message about the RC edit tool at the
bottom.

If you do, that's nothing to worry about.

We'll talk about that a bit more later on.

So there are a bunch of options on the right for how our project should export.

At the top, I'm going to rename this project.

I'm going to call it Project Boost.

There is this embed PAC file option.

At the moment the player will receive an EXE file and a PAC file.

If we embed that PAC file in the exe.

They will just have the one.


Exe file they need in order to run the game.

I'm going to go down a bit further and look at the rest of the options we can pick.

Icons that I'll talk about a little bit more later on.

We can pick product names, company names, all of that stuff.

I'm going to put the game name in the product name option and I'm going to say Project Boost
again.

With that all done, we can start exporting.

There is the export project option or export pack and zip.

They differ a little, but you will typically want to export projects.

So click Export Project in the bottom left.

And that will open a directory viewer so that we can choose where we want to export our
project.

This export with debug toggle.

If you leave that enabled when the game runs, a console will pop up, which can help give you
some

testing information, which is useful if there's an error when or some kind of issue in your
exported

project, but don't need that for the moment, I'm going to disable it, and I'm just going to save

Project Boost in the root of my file system for this project.

So I'm going to click save.

And now we're going to get this error.

And this is what I was mentioning a few moments ago about the icon.

You need to go through a few special steps if you want to customize the icon for an
application on windows.

That's also due to Godot being an open source tool.

It's not something I'm going to worry about at the moment.


We're just going to have the Godot icon as our application X, so this is just a warning.

It's all fine.

We can click okay.

Going to close this export window, and I'm going to open the file from my file system.

So I'm going to right click on the root in the file system.

And I'm going to open it in my file manager.

So now Windows Explorer has this area open which has my audio level folder particles folder
or the rest

of the files that we've been using.

And you can see we've got Project Boost with the Godot icon.

And it's about 67MB.

If I double click on that, the game should run.

You can see it open very fast, and my game is running and I can fly around and land and
progress through

the levels.

So with that exported, you can send that to your friends or whoever you want to try out your
game.

But we can move on to our first challenge.

So for the challenge, I want you to go back to the player script, and I want you to add a check
if

the player is pressing the cancel action.

If they are pressing the cancel action, I want you to call get Dot quit so that the game will
close.

So in short, while the player is playing, they can hit the escape key and when they do, the
application

will close.
After you've done that, I want you to export the game again and check the player can quit the
game

by pressing the escape key.

This is all an exercise to ensure that you've got in your mind how you can export the game.

So I'll leave you to that and I will show you it in a few moments.

Welcome back.

Let's make those changes to the script.

Going to close that explorer and I'm going to open my player script.

I'm going to make this full screen.

And I am going to find the process function.

So the process function is where we check for inputs.

At the moment we are saying if input is action pressed and then checking the action that was
just pressed.

And we want to check if the cancel action was pressed.

So let's go down to the end of this process function, which is around here on line 40 for me,
I'm

going to hit Enter and Backspace so that I'm indented to the same level.

All the rest of these other functions are I'm going to say if input dot is action pressed.

Now actually I'm going to say is in is action just pressed which is a variation of his action
pressed

that won't fire every frame.

It will only fire the first time the key went down.

We should see the same functionality for both, but it's just a little bit more technically correct

to use.

Is action just pressed here?


I then want to say we want to listen for the cancel action.

So I'm going to do double quotes UI underscore cancel.

And select that option.

I'm going to put a colon at the end and hit enter so that we enter this indented part of the if
statement

and we want to call get tree dot quit.

So that should make it so that while we're playing the game, if we ever hit the escape key, the
game

will close.

I'm going to test that out quickly now before I export it, to make sure everything's behaving as
I

expect.

So I'm going to run this project.

I'm going to fly up a bit and I'm going to hit the escape key and it quit.

Perfect.

So now we can get back to trying to re-export this project.

So as before in the top bar we're going to click the project dropdown.

And we are going to select the export option from that dropdown menu.

In here we have all the same settings as last time.

It should have remembered everything from previously.

It's got the same project name.

It should still have embed pack.

The option we want it to click to export was Export Project on the left here.

And then I'm just going to overwrite this old Project Boost file.
I'm just going to click save.

In this Save a File dialog it's going to say do we want to overwrite it.

And we do because it has that new functionality.

And this warning is fine.

So we'll click okay.

And now we can close it and we can try running our game.

So I'm going to open that file system again I'm going to go to the file system open it in the file
manager.

And I'm going to find the game and I am going to run it.

And now I should find if I hit the escape key, it quits.

And that is how you export your projects so that you can have other users try out your games.

In the next and final lecture, we will be doing a bit of a wrap up and talking about various
ways you

can improve this project.

You might also like