How to program in Godot - GDScript Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
GD script A highlevel object-oriented imperative and gradually typed programming language with syntax a lot like python build specifically for good do I know that sounds like a lot but today we're going to learn it while it's of course impossible to cover everything and entire programming language has to offer in just one video will certainly try in fact we'll cover everything from variables and conditionals to getting input inheritance dictionaries signals and the list goes on and who knows perhaps we'll even figure out what GD stands for candle script Green Day script gadolinium we might never know we'll start with the things that I consider to be most important for beginners and then move on to more abstract programming Concepts as we progress it's not as much a follow along as it is an overview so if you're a beginner lean back and know that you don't have to understand everything the first time also it's totally okay to stop the video and try some of these things out you can always come back to it at a later time we've made sure to split everything into clearly named sections so hopefully you'll be able to use this as a reference manual going forward and if you're a season programmer transitioning to GD script this video should provide you with a nice overview of the tools at your disposal and how to approach doing different things keep in mind that this is a video on GD script not an introduction to gdau so if you've never opened up gdau before I suggest you begin with our video on making your very first game in gdau all right without further Ado let's learn G P script but first this video is sponsored by codec Crafters if you've been writing software for a while and are looking to take your skills to a whole new level code Crafters is the place to be code Crafters allows you to practice writing complex software by challenging yourself with real world projects you get to build your own git implementation your own HTTP server or even your own bit T client along the way you will practice Advanced system design and gain a greater understanding of lower level programming Concepts such as networking OS interaction and performance and when you're done you'll have a really impressive project to add to your portfolio on top of this you get to try new languages like python C C++ and many many more also new challenges are constantly being added I for one voted for the compiler challenge to be next so become a better software engineer today by signing up for code Crafters use the link below to get one week free and 40% off on all membership plans hello world so here we are in an mty kodo project it's really ious in here as it is custom let's begin by making a script and adding some code to print a message to do that we need a test scene so let's go and hit the plus I'll add in a node rename it to Main and let's save this as a scene so I'll hit control s hit save let's add a script by pressing the scroll we'll use the default template and the name of the script should be main as well with a non capital M this creates a script with two functions we'll start by focusing on the top one named ready think of this as the start of our game as it says here this function is called when the node enters the scene tree for the first time which happens right when we play our game so we can put code in here that we want to happen immediately I'll get rid of the other function for now you can zoom in by holding down control while scrolling now right now the only thing in our ready function is the pass keyword pass basically means do nothing and it will appear in functions we haven't filled out yet so let's replace it with some code that our message we'll write print and inside of the parenthesis we'll put our message in quotation marks hello world we can then run the game by pressing this button here or hitting F5 it's going to ask us which scene we are going to run we'll hit select current and while our game isn't very exciting yet we can now see that the console prints our message the output window here or the console is where it will display prints and it's also where we check for errors now to stop our game from running we press the sub button here or press f8 syntax now this might have worked for you and it might not that's because there are a few things to be aware of when writing GD script the first is that statements like print here terminate with a new line there's no need to add a semicolon at the end like in many c-based languages and GD script similar to a language like python uses indentation to determine the structure of your code this means that you use tabs to tell TD script where your code belongs belongs in our example here I'm using a tab to tell kodo that our print line belongs to the ready function if I delete this tab I get an error also GD script is case sensitive so if I write print with a capital P I will also get an error so just a couple of things to look out for there now printing to the console is cool or I mean maybe not as cool as backflips but well I can teach you to do those but I can teach you how to display text in the game window instead to do that we'll need to modify a through script modifying nodes 1.0 first we need a node to modify let's use a label so I'll add a new node choose label I'll zoom in Center it on the screen make some more room let's add a default text this is a label I'll Center it and overwrite the font size now to edit the text of this label through script we need two things we need a reference to the label and we need to access the property in this label that we want to change in this case the text if we hover over text we can see the name of the property through script which is text with a non capital T so in our main script we'll first get a reference and we can actually do this by simply taking the label and dragging it into our ready function then we can access the property by going Dot and we'll type in text and set it equal to hello world and now when we play our label changes to hello world and we can use this exact method to change other things as well such as the color of the text in fact there's a property called modulate which allows us to tint Sprites and UI elements in the inspector you can find it all the way down here under visibility let's change it to Green so again we'll click and drag to create a reference to the label write. modulate and set it equal to color dot here we have a bunch of different colors we'll choose green and voila our label is now green so this is how we can make changes to nodes when our game is running but right now not much is happening during our game so let's see how we can use input to make our game respond to our actions input let's say we want to turn this label red when we press the space bar to do this we first need to set up an input action we'll go project project settings input map here we can add actions actions allow us to bind keys to something that we want to happen common actions would be shoot jump or so on in our case we wanted to change a color I'll just go ahead and call it my action so we can use it later for other things now let's hit add and here is our action let's find the key to it by pressing plus it's now listening for input I'm going to press this space bar and hit okay and now our space bar is bound to my action then in our script we need to create an input function we'll write funk for function underscore input and let's hit enter to autoc complete now just like ready this is one of the build-in functions of gdo but instead of being called at the start of the game it runs every time the game receives any input such as when we press a button event is what we call the information about what triggered the function was it a movement of the mouse or the Press of a key we need to check if the event that triggered the input was our action being pressed so we'll write if event. is action pressed and as you can see our action shows up here my action then we'll put in a colon and if we pressed my action well then we'll change the color so we'll drag in the label write modulate and set it equal to color do red and we can just as easily check if the action was released we'll go if event do is action released this time my action well then we'll take the exact same line and change it back to green so now when we play and I press the space bar it turns red and when I release it it turns back to green that's right we made a party he disco [Music] party now this is just one out of many ways to handle input in gudo but since we're focusing on the GD script language I'm not going to go further into it here I'll make sure to provide a link to where I can learn more about input if you're interested variables 1.0 variables are essentially containers that hold information in the case of a player character we could use variables for information like the player's name Health damage and perhaps if the player is alive or not let's make a health variable at the top here I'll write bar for variable the name of our variable and then we'll set it equal to a default value now we can print this variable inside of our ready function we write print health and if we play you can see that it now prints 100 now we can easily change our variable so before printing let's assign a new number Health equal 40 we can also assign a calculation so Health = 20 + 30 we'll set our health to 50 we can also add Health Plus equals and then 20 we'll add 20 to our health and subtract Health minus equals to multiply we do times equals and to divide we do slash equals so if we run this now it will do all of these calculations from top to bottom and then print out the result which turns out to be 120 let's look at an example where our player takes some damage and we want to subtract the damage from our health let's try decreasing our health variable whenever we press the action we made earlier so in the input function we'll check if the action was pressed and then we'll subtract from our health and we can print the result so now every time I press the space bar bound to my action we can see that I reduced the health really cool but as you can see we can currently reduce our health below zero and nothing happens when we do so if we were making a game we'd probably want our player to die and the game to restart luckily we can make our game react to variables by using IF statements if statements or conditionals if statements are the glue that holds all of our logic together we've actually already used if statements to check if our action was pressed but they can do so much more yet they are really simple an if statement is just a condition that needs to be met in order for the code inside to be run let's add an if statement here to check if our health reaches zero so I'll make some room write if health is less than than or equal to Zer well then we'll set our health to zero and we'll print that we died and now when our health gets to zero it prints you died now here we're using less than and equal to to compare our health to the value zero but there are many more comparisons we can make here are all the comparisons we use such as is equal to is not equal to and so on we can also add more conditions to one if statement we use the and keyword to add another condition where both need to be met and the or keyword to add a condition where only one of them needs to be met now one really useful thing about if statements is that we cannot only Define what happens when the condition is true we can also choose what happens when it's false we do this using the else keyword let's add an else to print that we are still alive if our health hasn't reached zero yet so if our health is less than or equal to zero we died else we print you are healthy and even cooler we can chain together if statements using else if or El if for short so we check if our health reaches zero and if not else if El if our health goes below 50 well then we'll print that we are injured and if neither of these two are true we'll go to else and say that we are healthy and if we play we can see that at 80 we are healthy at 60 we are still healthy then we are injured and at zero we die very cool note that the if statement we made here is nested under another if statement you can easily layer if statements to get more and more specific functionality however try not to overdo it you can quickly get lost in the ifs actually a lot of people don't know this but that's why programmers and philosophers have so much in common we both tend to spend a lot of time with the ifs and the wh ifs so if you get frustrated along the way remember that so was Play-Doh anyway that's it for if statements comments we use comments to help explain and remember the what and the why of our code adding a comment is simple and can be done above or after a line so if we have some code we can make a comment above the line and this is a comment about the code that follows or we could make one right after and this is a comment about this line only we can also use comments to temporarily remove parts of our code from being executed here we simp simply put a hashtag in front of the code and it's good practice to emit the space here to indicate that what follows is code we can also select multiple lines of code right click and toggle comment just remember that you can't have a completely empty function we need to add the pass keyword to avoid an error variables 2.0 when creating or declaring a variable we need to think about where we do so if we declare a variable inside of an if statement for example we can only use that variable inside of the if statement M this is called scope and it's something that beginners often make mistakes with if we want to use a variable in many different places in our script we make sure to put it at the top outside of any functions so this is a script wide variable this can be accessed anywhere in your script if you were to declare it inside of a function you would only be able to use it in that function so this is a variable we can only use in ready now a really cool thing about variables in GD script is that you can declare them without thinking about what type of data is inside them here's a variable that is either true or false and here's a variable that stores a number as you can see they're created in the exact same way in fact we can even change the type of data that they hold just by reassigning them so we can actually set our coolness to true and this runs completely fine that being said we still need to be aware of what type of data we're working with because some parts of our game will expect a specific type of data and we will get an error if we try to use another type without converting now in GD script we have the four classic data types Boolean or bull for true and false integer or int for whole numbers float for numbers with decimals and string for text converting from one type to another is called casting for example we can cast an integer into a string so if we have a number that is equal to 42 and we have some text which is a string well then we can add add the number to this text but we convert it into a string by writing Str Str for string and then the variable inside of the parentheses and if we print this it works fine we can do a similar thing to say convert a float into an integer so if we have a variable called Pi that is equal to 3.14 then we can convert this into an integer by going int pi and let's print this and it prints three a whole number note however that this automatically truncates the number it does not round it simply gets rid of the decimals so 3.9 also results in three some other data structures that are really common in GD script are Vector 2 and three Vector 2 stores two floats X and Y and Vector 3 stores three floats X Y and Z these are most commonly used for positions so I can create a variable called position with some coordinates I can then modify one of the components so position X plus = 2 adds 2 to the X component and then we can print the whole thing and this gives a vector 3 of 5 - 10 5 Now by default gdscript is what we call dynamically typed this means that we don't Define what type of data a variable can hold when we declare it which we've been using so far this makes it fast to create variables and flexible because we can reassign data of another type at will however it is also more prone to error and less performant than static typing luckily GD script allows us to statically type any variables we want we can pick and choose totally based on preference to statically type a variable we simply add the type when declaring it so here if we have a damage variable we can specify the type and then set the value so now this variable will always stay an integer we can even have gdo automatically determine the data type by simply writing colon equals and then the default value this is called invert typing and the result is exactly the same the type is still static kdo simply recognizes that 15 is a whole number and sets the variable to a type of in this also means that the variable cannot change to another type if we try to set it to a string we get an error now adding export in front of a variable will allow us to set it using the inspector the value that we set in the script will just be a default value so if we save this and select our node we can set a value in the inspector if we print our damage we can see that this updates in our game and we can always press the circular Arrow to revert back to the default now sometimes you want to Define a variable that cannot change for this we use constants so I'll write const for constant we'll call it gravity as you can see it's standard practice to name constants with capital letters and we'll set it equal to 9.81 now we can use this like any other variable but we cannot change it if we try to do that it throws an error and that's it for variables great job functions functions are the bread and B of programming they allow you to bundle up your code in small reusable packages so far we've been using some of gau's build-in functions like ready and input notice how these are prefixed with an underscore this is to show that they are not activated or called by us but by the engine itself but we can actually make our own functions and use them to do really cool things common functions to making games are things like jump die shoot and respawn and making a function is actually really easy let's make a function for jumping so we'll write [Music] Funk then the name of our function open and close parenthesis and a colon then in here we'll put all of our code for jumping so we could add an upwards Force play a funny sound and a jump animation for now we'll just print jump but nothing is currently triggering or calling our function let's call it whenever we press the action we made earlier so Funk input event and if our action was pressed then we call our jump function by writing jump followed by open and close parenthesis and now when I press space it displays jump and at this point I encourage you to add the sound effect [Music] yourself a lot of fun to be had here now this already makes our code more readable and reusable but right now our function is just a simple command we call call it and it does some things however we can actually use functions for much more than this they can have inputs and outputs let me explain I like to think of functions as machines take for example this coffee maker just like the name implies it performs a function to make coffee to do this however it needs some input some water a filter and some ground coffee with this it performs its function and then spills out an output delicious coffee in code we call the input we give our function parameters and the output is called returns so let's make a function that adds together two numbers Funk add and then inside of our parentheses we add the parameters so number one we'll call num one and the second number will call num two then inside our function we can add these together and store them in a result variable so we'll set that equal to num 1 + num 2 and for now let's just print the result then in ready let's try calling this function so we'll call add we'll give it the first number three and the second one let's do eight and let's actually call it again so let's do a harder one let's add 245 with 111 and indeed it prints 3 + 8 which is 11 and 356 which is the result of our second calculation so here we've created a function with two parameters the numbers we want to add together but the function actually doesn't return the result it just prints it this means that we can't actually access the result where we are calling the function up here and ready to return the result we replace print with return so we'll do return result and now up here we can store the result in a variable set it equal to add and we'll add together three and five and we can print that and the result is eight and because we have access to it up here we can do more things I add more numbers to it so we can say result equal to add and pass in the result from before and add 10 and then print it and there you go we now get 18 because 3 + 5 + 10 is 18 really cool and just like when declaring variables we can also statically type parameters and return types to make it clear that the function is made to work with numbers so after num one we'll specify that this is an integer we'll do the same thing with num two and here we can set the return type using an arrow and this is also an integer so now this function will only work with numbers 3 4 6 8 2 1 one and a half random numbers getting random numbers is very easy the function Rand F gives a random number between 0 and one it's great for assigning probabilities to your code say we are deciding what loot to give the player and we want to make some loot more rare than other well in this case we could create a ro variable and set it equal to randf then we could check if the roll is less than or equal to 0.8 which means there's an 80% chance that we print you found a common item and if not well then there's a 20% chance that you found a rare item and if we play this most of the time it's going to display that we found a common item but if we keep playing if we keep playing keep playing eventually there's a 20% chance so at some point we'll eventually this is we'll eventually find a rare item that was crazy we can also use Rand F range and Rand I range to get a random float or integer between a minimum and maximum value say to assign a random height to a character so bar character height equals Rand I range for a random integer between 140 and let's doe 210 and we'll print that your character is then we'll insert the height remember to convert to a string cm tall and we'll roll a character and apparently I am a giant basketball here I come documentation GD script is actually pretty well documented and one of the really cool things about it is that the documentation is linked with the editor if we hold down control and click on something we would like to know more about such as the randai range function it opens up the documentation right here in the editor this is a really quick and easy way to check if you're using a function correctly it also works for classes which we'll learn about later arrays sometimes you want a variable that can hold more than one thing in fact sometimes you might want to store a whole list of elements for this we use arrays defining an array is very easy let's make one to hold items in an inventory so we'll create a normal variable and set it equal to open and close square brackets this creates an empty array we can then add elements inside the square brackets I'll add a potion string the number three and the number six notice how unlike many other languages GD script has no problem mixing data types within an array but if you want to constrain an array to a specific type we can of course statically type it so here we simply add the type this is an array and the elements inside it are going to be strings so that's the Syntax for that and now we get an error because three is not a string so we'll replace this with feather and six is also not a string we'll replace that with stolen heart now the way that we access elements in an array is by using an index when you add an element to an array it is automatically assigned a number based on its position in the array in this case the first element potion has an index of zero feather has an index of one and the stolen harp has an index of two so to access and print the first element in our array we write print items and then we access the first element which has an index of zero and This spells out potion pretty cool we can just as easily change elements this changes the second element to smelly sck and the third element to staff and arrays also have functions for finding removing or adding new elements so to remove at an index we write remove add and then the index one this removes the smelly sock and to add a new elements we write do append and we'll append an overpowered sword to the end of the array now arrays can quickly become long and difficult to manually go over luckily we can use something called Loops to help out loops loops loops loops allow us to repeat code a number of times with small variations they are perfect for iterating through all the elements in an array if for example we wanted to print out all the items in our array here we can do that easily by using a for Loop so we write four then the name of the item that we're currently looking at we'll just name that it item in the array so in items we will print out the current item we're looking at so print item and as you can see it prints potion feather and stolen harp this is cool because we can have any number of items in our array the code will work just fine we can also add more functionality say to only print items that are more than 6 letter long if item. length so the amount of characters in item is greater than let's say six then we're going to print that item and now it only prints feather and stolen harp because potion is exactly six letters we can also create Loops that run a certain amount of times if we write 4 n in 8 it creates a for Loop where the variable n starts at zero then goes all the way to seven so if we print n we can see that it runs eight times and N starts at zero and ends at 7even we say that n is the current iteration of the loop another type of loop is the while loop this repeats as long as a certain condition is met now I think most people who know me would say that I'm a glass half full kind of person and to those who disagree let me go ahead and prove it by using a while loop to fill up a glass halfway so I'll create a glass variable and default it to 0.0 the glass is currently empty no arguing about that then we'll create a while loop that continues while glass is less than 0.5 so we have haven't filled it up halfway yet in which case we will add a certain amount to our glass we could do a constant amount like this or in real life when I try to pour something into a glass I'm not that precise so let's add a random number instead so we'll add a random float between 0.01 and 0.2 and then we'll print out how much is in the glass at the current time then when the loop is done we get to continue down here in our code and we'll print that the glass is now half full and if we run this we can see that the glass slowly becomes more full with a random amount each time and then it says that the glass is now half full as you can also see it overshoots a bit because we're adding a random amount each time and not claming the value just like when trying to hit exactly half a glass in real life my wife says that I add too much milk when I make her coffee I think I'll refer her to this going forward now we actually have to be really careful when using while Loops that we don't create an infinite Loop these can be tricky to avoid and can very easily crash our program say if I were to remove this line that adds a little bit to our glass every time well then our glass would actually never become half full and we would be stuck in this Loop forever now I don't think this will actually crash Gau indeed it didn't but we get a lot of overflow errors and as you can see our game is definitely not responding not good finally in both for and while Loops we can use the break and continue keywords break as the name suggests breaks out of the loop and moves on to the code after while continue immediately skips to the next iteration of the loop so if we were to write if glass is greater than 0.2 and then break we can see that our while loop ends way early because we exit out of the loop before we even get to print that the glass reached 0.2 dictionaries they sound really boring but they're really cool while arrays are great for storing lists of elements it's sometimes confusing to access each element with an index sometimes it makes more sense to use a dictionary dictionaries hold what we call key value pairs let me explain in real life we use a dictionary to look up the definition of words in a language the key in this instance is the word we're looking up and the value is the definition dictionaries and TD script work the exact same way creating an empty dictionary is really easy we write VAR I'll call this one my dict and set it equal to some curly brackets this is an empty dictionary we can then add key value pairs inside the curly brackets say for example that we have multiple players in our game we can use a dictionary to keep track of them each player has a username this will be the key and a level this will be the value so I'll create a player called Crook and this level is going to be one I'll create a another player villain with a level of 35 and finally a player with the username boss with a level of 100 if defining on one line becomes too much you can split it up like this and it's good practice to add a comma to the last entry so you're ready for a new one and let's name this dictionary players then to get the level of a player we simply type in the username let's print the level of our villain so print and we'll write players type in villain and this should print 35 and you can just as easily assign a new value or add another entry so we can reassign the villain here to say 50 and add a new entry called Dwayne with a whooping level of 999 and just like with arrays we can Loop over a dictionary with a for Loop when we do this we are actually looping over all the keys in our dictionary so all the usernames and for each username in players we will go ahead and print out the username I'll add a string to separate and then the level so here we access our players dictionary and input the username we're currently looking on to get the value and remember to convert this into a string so Str Str to cast to a string there you go it prints our entire dictionary now just like with arrays you can have multiple data types of keys and values in the same dictionary and even cooler you can actually have arrays or dictionaries inside another dictionary this might sound really abstract but it's actually pretty cool and often comes in handy say for example we don't just want to store the level of each player but also other info like their health well then we simply replace this value with another dictionary so open and close some curly brackets here we'll add a key called level with a value of one and another key called Health with a value of 80 and at this point it's a good idea to use tabs to keep our code clean duplicate this I'll assign some values and now we can access a value by using two keys let's print the health of our boss so print players we go into our boss and we access the health and this prints 500 which is correct so this way we can start to think of ways we can structure data about what's going on in our game such as player stats inventory Buffs and so on enums enom are a convenient way to define tags or states in our game say we're making a game with a bunch of units and we want a way to Mark each one as either hostile neutral or Ally in this case we could create an enum that defines these tags so at the top here I'll write enum to create a new enum and then in the curly brackets I'll write Ally neutral and enemy and now we can use these states in our game for example we can create a variable called Unit alignment and set it equal to any one of these states I'll just set it to Ally and this makes it really quick and easy to then check in our code if our unit has a certain alignment Also let's just give our enum a name here to stay organized so I'm going to call this alignment and now whenever we are accessing a state we have to go inside of alignment Dot and here you can see our state so I'll go alignment. Ali by default and then inside of ready we can check if unit alignment is equal to alignment dot let's check for enemy and if it is we will print you are not welcome here and if it's not so it's not an enemy we'll just write welcome and now if we run we can see that our console displays welcome because our unit alignment is currently Ally this is much safer than using say a string or an integer to represent States because K will throw an error if we misspell a state if for example I misspell enemy we can see that Gau throws an error but I think one of the real powers of enums is that we can use them for exported variables to do this we Mark our variable here with export and then set the type to alignment and now we can actually set our unit alignment in the inspector so I'm going to set mine to enemy here and now when we play it prints you are not welcome here really cool now what is actually happening happening behind the scenes here is that Gau is creating a constant for each state in our enum so this code here is actually completely identical to our first line and as you can see the value here increases from 0 to 1 to two kind of like an index so an enum is essentially just a bunch of constants with an increasing value which means that if we try to print one of these states say you print alignment do enemy the console simply shows the value of that con which is two because it's the third state this is rarely something you need to take into account but it's nice to know what our code is actually doing and we can even overwrite the default value if we want so we could set Alli equal to 1 neutral equal to0 and enemy equal to minus1 and now our console displays minus one because that's now the value of our enemy constant now something that pairs really nicely with enums are match statements because they allow us to quickly add function it for each state match match is the Gau equivalent of the switch statement from other languages and allows us to execute different code depending on the value of a variable in this case here we can use a match statement to add some code for the different values of our enum so I'll write match then the variable we are matching based on which is my alignment colon and now we add code for each value so in case my alignment is alignment. Ali I'll print hello friend if it is neutral I'll print a common piece if it is enemy taste my wrath and a cool thing here is that we can actually add a default response as well to do that we do underscore colon and so if it isn't any of the cases above we'll print who art thou and if we set my alignment to say enemy taste my wrath modifying nodes 2.0 so far when we need to access a node we've done so by simply dragging it into our script which creates a dollar sign followed by the path to the Noe I've created a few empty noes here to demonstrate a play a note with a graphics and weapon node and an enemy node so if I drag in the weapon node it creates a path that goes into the player and finds the weapon and we can actually store this reference in a variable to do this we simply drag it to the top and hold down scol while releasing this automatically creates a variable with the name of the node and the correct path and as you can see it uses the on ready keyword this is because gdau has a very strict order in which nodes are created and if we open the game and try to find the weapon node before it exists we will get an error on ready simply make sure that Gau Waits until all child nodes have been created so we don't get any issues and just a quick note the doll sign here is actually just shorthand for using the G node function so this is actually identical also you might have noticed that the path is relative our script is on the main node so it starts right after that Noe we can print the absolute path through script we'll print weapon. get path this prints the absolute path starting from the root of our game all the way to weapon now paths are great for many things but sometimes they can be a bit inflexible they break if we rename any of the nodes in the path and it's best to only use paths when the node we want to access is at of the node we're working on we'll talk more about parent child relationships later luckily we can also use the export keyword to reference other nodes so if we write export and create a variable called my node we can set the type to node and then in the inspector we can assign whatever node we want or simply click and drag I'll drag in the player we can also check if the node is a certain type by using the is keyword so in ready we'll check if my node is of type node 2D in which case we'll print is 2D and it is we can even be specific about what type of note we want to be able to reference if for example we only want to reference Sprite nodes we just change the type to Sprite so Sprite 2D I'll reset the variable here and now we can only assign Sprites which in this case are the graphics and weapon nodes now if we play it still prints that this node is a 2d node even though Sprite 2D and no node 2D are two different nodes this is because Sprite 2D inherits from node 2D but we'll get into that in the inheritance chapter signals signals are messages that nodes can send to each other we use them to notify that a certain event occurred it's probably easiest to look at an example gdau has many built-in signals take this UI button if we select it and go to node we can see a list of all the signals on this node I'm going to connect the Pressed signal to our main script so double click it I'm going to select Main and hit connect as you can see this creates a function called on button pressed and over here there's a green arrow pointing to it this means that a signal is currently connected to this function if I click on it we can see the source which is our button let's just add a Quick Print line here and now if we play and press the button it prints money get it now this is because whenever we press the button it emits the Pressed signal and everything connected to it gets called in this case our on button pressed function which indeed prints money we can connect as many functions as we want to a signal they will all be called when it gets emitted this is really cool because it allows us to link together nodes in a way where they don't have to be aware of each other the button has no idea which functions are connected to the signal it just tells it to emit this makes signals great for separating different parts of our game or decoupling say we're playing a character that can level up by getting enough XP whenever we level up there are probably many game systems that need to update the UI our player stats perhaps we have spells or achievements that unlock and updating all of these from the player can quickly become a mess instead we create a leveled up signal that all these systems can connect to then all we need to do is have the player emit the signal when we level up let's try it out instead of a button here I'll create a timer so I'll add a timer node and set it to auto start this will count down from one and when it reaches zero it emits a signal called timeout let's connect that to our script and make it increase our XP so we'll create an XP variable default it to zero then in our function we increase our XP and let's also print it if our XP then reaches say 20 we'll set it back to zero we leveled up and we can start over for the new level and if we then play it's going to increment our XP every second and when we reach 20 it's going to go back to zero now let's create a signal that other nodes can connect to so at the top we'll write signal leveled up and if we save this and select our main node we can actually see that signal we can connect it to other nodes but just for this example we'll connect it back to our main node this creates an unleveled up function which is called when the signal is emitted let's print a message that says ding now we simply have to emit the signal let's do that when we reach 20 XP here we'll write leveled up emit now when we reach 20 XP it emits the signal and we print ding awesome we can also connect signals through code I'll disconnect the signal in the editor and instead in a ready function I'll write leveled up. connect and the name of the function we're connecting to on leveled up careful here this will probably autocomplete with parentheses we don't need those we just want the name of the function and disconnecting is just as easy disconnect we can also pass parameters through signals this could be used to pass the level red or other useful information I'll just add a quick message that we can print so on a signal We'll add a parameter we'll make sure that our function supports this as well and instead of printing ding we'll print whatever message was input and then when we emit the signal we can put in a message let's put in grats and voila it displays is grats and that is signals get set go or just get set Getters and Setters allow us to add code for when a variable is changed this means that we can do things like clamp a value within a certain range or emit a signal letting other parts of our code know that the variable changed the example that is always used for this is health so we'll add a health variable default it to a 100 and then we'll use a colon to go and Define a Setter in the parenthesis we name the value that was passed in so this is the value that we are trying to change our variable to and now we can decide what to do we could for example set our health equal to not the value directly but clamp it first between 0 and 100 so this makes sure that our health does never exceed 100 or go below zero we could also emit a signal here so we can create a signal Health chain and we can actually input the new health as a parameter and then in our Setter we can go Health changed. Emit and put in the new health of course we need to make sure to connect this signal we can do that through the editor and let's just print the value so we'll print the new health then in ready let's try this out by assigning a value to health let's try assigning -150 and now if we play we can see that it prints zero this is because we put in - 150 it clamps this to zero and then it emits the signal the signal then calls the onhealth changed function and we print the new health which is zero so that's a good example of adding a Setter Getters are more commonly use to convert values so let's add two variables we'll have a chance that is equal to2 and then we can have another one which is our chance in percent we'll make this of type int and we will add a getter here whenever we try to get the chance percentage we'll simply return the chance variable times 100 and now if we try to print this variable print chance percentage or change our chance to Let's say6 and print it again we can see that our chance percentage is completely based on whatever our chance is currently equal to and so it starts at 20% and then goes to 60% and for good measure sake We'll add a Setter also so if we set to a new value we will modify our chance and set it equal to the new value divided by 100 and since our chance is a float we'll make sure to cast that value so now instead of changing the chance we can directly change the change percentage to say 40 there we go classes this is a good one GD script is an objectoriented programming language this means that we gener try to structure our code inside of contained objects that interact with each other we primarily do this using classes for now try to think of a class as a blueprint say for example we are making an RPG and we need to populate it with a bunch of characters that the player can interact with so we create a character class that has some variables and logic that all characters in the game should have so for variables we could add things like name health and a line of dialogue for when you interact with them for logic we could could add functions like talk and die then we take this class and create instances instances are specific versions of the class so we could create an instance named potion seller that has a health of 50 and a line that says you can't handle my strongest potions and a bunch more instances all of which have the same variables but different values and all of which can talk I used to be an adventurer like you and die so that's the idea of classes in you've actually already encountered a bunch of classes that's because all the built-in noes in Gau are classes which actually makes a lot of sense if you think about it all the nodes are self-contained objects with a bunch of variables and logic that we can create instances of if we add a Sprite node we're instancing the Sprite class so when we create a script we are actually also creating a class I have to put a disclaimer here that we're technically not creating a class but for all intents and purposes it works just like one so let's forget all about that for now so let's abandon our main script here for now and instead create a new node so search for node and let's name this node character and add a script to it now to make it more clear that our script is a class that defines a character let's set the class name to character so right at the top here we'll go class name character with a Capital C and we can now add some variables we'll mark these with export so that we can set them in in the inspector for each character instance so export VAR let's add a profession of type string and give each character a health as well of type integer and so now we can see that our character here has these two properties in the inspector and we can go ahead and fill out the profession this is going to be the potion seller who is going to have a health of let's say 40 and now we can create more instances by duplicating this node so let's duplicate it a few times the second character here will name X Adventurer with a health of 30 and the last character will be our Knight and we'll give him a health of say 150 so now we have these three instances with different properties and we can also give them a function so let's add a die function so I'll write Funk die and this function is going to set our health to zero as well as print our profession and the fact that we died and that's it for our character class but currently nothing is triggering this function so let's go into our main script now and here we can get a reference to one of our characters and call the die function we could simply drag and drop one of these nodes to get a reference but because we have named our class we can actually use an export variable for this instead this way we can set the connection in the editor and we don't have to worry about the path changing so we'll write export VAR and here we'll have a character to kill of type character and now if we save that we can see that our main node now has a slot here for the character to kill and we can either drag in one of these characters or hit assign and select one I'm going to choose character three and now in our ready method we simply go to our character to kill and call the die function and if we run this indeed the die function fun is called on our character three which is our Knight so it says Knight died and if we choose another character say the first one we are instead killing the potion seller really cool inner classes these are classes that exist inside of another class you mostly use these for bundling together variables and maybe add a function or two they can be a good alternative to dictionaries because they are sometimes a bit more safe to use say we have this character class here and we would like to add some equipment we could create an inner class called equipment so I'll write class equipment and then we can give it a couple of variables I'll create an armor variable set it to 10 by default and a weight of five now we can use this class around our script so we could create some variables using it I'll create a chest that is equal to equipment. new calling. new will create an instance of the equipment class so now we have one piece of equipment one instance which is a chest we'll also create legs and again we'll call equipment. new then in the ready function we can access these classes so we can go into our chest and change the armor and set it equal to 20 we then print chest. armor or maybe print legs. weight and this is also where you can see that this is sometimes safer than using a dictionary because GD script will recognize that there is a weight variable inside of the equipment class and if we try to access something that isn't there we'll get an error before playing the game not only when we reach this point in our code this is called being type safe and now if we run this we can see that each of the instances of our character will print these two pieces of equipment and the armor of the chest is 20 and the weight of the legs is five inheritance so we know that all notes in Gau are classes and we can effectively make our own using scripts but there's one more important thing we need to know to understand how Kau is structured inheritance inheritance refers to the ability to derive one class from another we've actually already been doing this notice how our script says extends node so our script deres from the node class this means that all the functions and variables of the node class are also available in rscript gdo actually has a very nice way of visualizing this when adding a new node we can see all the nodes available to us but some of these are organized under other nodes that's because these nodes inherit from the top ones for example both animated Sprite 2D and Camera 2D inherit from note 2D this is because node 2D is a base class for all things that exist in 2D space so since both a camera and a Sprite needs a position in our world they both inherit from it and even cooler we can actually find our character class on this list as well that's because when we create a character class we're essentially defining a new node type and we can see that it inherits from node really cool now all of this Probably sounds a bit abstract because it is but what it means in most cases is simply that we need to make sure we inherit from or extend the right class for what we're working with if for example we are making a script that moves around our player we would create a character body node and add a script to that node we could name it say player and as you can see the script then automatically extends character body 2D and we now have access to all the functionality in it such as the velocity and the move and slide function which moves the node around composition now even though gdau uses inheritance for its nodes there are often better ways to structure your code gdo actually leans itself really well to another way called composition I'm not going to explain that here since there's already a really good video on the subject by a channel called bit liic but I definitely recommend you check that out call down signal up when writing GD script there are of course many best practices that we can choose to adhere to going over all of them is a video on its own but one that is particularly important is call down signal up which we use as a rule of thumb when communicating between nodes every scening Gau is a tree of notes and the beginning of the tree is called the root node which is the highest in the hierarchy when looking at two nodes where one is right above the other we say that they have a parent child relationship the node that is above is the parent and the node that is below is the child and that child might also have a child and so on call down signal up means that notes are fine to call functions on the nodes below them in the hierarchy but not vice versa instead notes below should use signals to communicate that something has happened the notes above can then connect to these signals as they choose and act accordingly think of it like real life parents are allowed to tell their children what to do but children shouldn't directly command their parents to do things instead children signal their needs to the parents and the parents decide the next step now keep in mind that this is a way to remember a good coding practice it is definitely not parenting advice but what if we need to communicate between two nodes that are on the same level you guess that these are called siblings well here the common parent is in charge of connecting the signal from one sibling to the function on the other this is most often done in the ready function right at the beginning so that's the idea of the rule but of course always implementing this concept correctly requires some practice I'll have a link to a good article with some nice examples style during this video I've tried my best to adhere to the official GD script style guide these are the conventions we use for naming and order to keep our code elegant and readable for others I won't go into further detail here but I'll have a link to the official guide that was a lot of code for one video [Laughter] of course I haven't covered everything you are ever going to need in GD script but I hope this served as a nice overview of the most important aspects also don't forget to check out Cod Crafters become a better software engineer today by using the link below and get a free week and 40% off on your code Crafters membership so this is the last video we've prepared for now if you liked our new videos on Gau and have a topic that you would like to see covered please let us know while we don't know what the future holds we've had a blast making these videos and I hope you've enjoyed watching them so until next time stay awesome and funky [Music]
Info
Channel: Brackeys
Views: 445,982
Rating: undefined out of 5
Keywords: game, development, dev, game dev, video game, games, how to, tutorial, tutorials, godot, programming, new video, beginner, lesson, get started, make a game, course, gdscript, input, script, brackeys, brackets, functions, if-statements, classes, dictionaries, arrays, loops, learn
Id: e1zJS31tr88
Channel Id: undefined
Length: 58min 9sec (3489 seconds)
Published: Sun May 12 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.