Make Your First 2D Game with Godot: Menus, Pause, and Score (beginner tutorial part 3)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
this is the third and the last plant to our free beginner-friendly calls to make your first game with the good game engine and this one you are going to learn about user interface creating a menu for your game adding some score as well an end screen I'll help you make sense of good O's powerful it's a little complex user interface system now before we get started I want to remind you that this course is made possible and sponsored by our premium courses you can find an extended edition for ten bucks that's going to give you some bonus content link in the description below you also have the table of contents in the description and the links to the previous two parts but that said enjoy the tutorial see you at the end in this first part we're going to create our title screen one that kind of resizes fluidly depending on the screen that the player is playing with then we'll create reusable UI components so buttons that allow you to start the game to change scene to be precise and to quit you're good at game your applications let's get started so here I am starting where we left off in the previous part of chapter the level might look a bit different because this is the level from the final project and not the one I created live for the tutorials but while starting with our level here and we want to create our title screen for that let's go to scene new scene and we're going to create user interface so in Godot when you add a node all the nodes under control the green icons our user interface nodes all of these have special properties that they share if you select your control node and go to the inspector you will see that quite a few of them actually the anchor margin grow direction the rectangle which is the rectangle that you can see in the viewport right now hint focus Mouse etc we're not going to see all of them because the system is quite complex it's designed to allow you to make interfaces like we go to editor itself with tabs with resizable columns etc can use them to create your tools and plugins the Godot itself all the user interface is made with this system with these control nodes for an example of what you can achieve here is RPG in a box a tool to create 3d voxel based RPGs made entirely in Godot so everything you can see in the video right now is made with this UI system now going back to our user interface the first node is going to serve a bit as a container that will be the main base flower screen that we can easily resize with the selection tool by clicking and dragging on one of the handles so everything will fluidly rearrange inside of it based on the parentage we'll give to the control nodes we'll call that our main screen now we're going to start by adding the background so expand the assets folder and you have background at PNG for that click and drag it on the view and you can keep the Alt key down as you can see in the top left to change the node type we don't want a sprite here instead we want the texture rectangle texture rectangle is a resizable texture that you can use for user interface and so the texture will appear where you dropped it where your mouse cursor was when you release the mouse click now we want to have it fit our main screen our user interface here so select the background node and that's why we're going to start using the layout menu that appears in the toolbar when you select one of these green nodes layout contains a number of options to scale anchor and move your UI nodes so go to the layout menu and select for rectangle this is going to move and resize your background texture so that it fits the full rectangle of its parent let me select the expand option here that will allow us to resize the texture on crop some of it with the background node selected I'm going to resize it to make it much smaller and again go to layout full rectangle and you can see that it scales to fit the main screen here now if you select the main screen and you resize it you will get the background to resize alongside it so select the background node again and in the inspector you have a stretch mode that you want to change so that it does not get scaled but the texture gets cropped instead so you can choose tall and when you choose that and you start to resize the background you will see that the texture will only get cropped but if you expand it on the x-axis it will get expanded next up we are going to add some text to our title screen so select the main screen node press ctrl a and you want to look for label label is a basic text box if you want very simple so you're going to see it added in the top left of our view and the node is very small with the label selected the first thing you want to change is the text in the inspector so let's call it my first game something like that my first good game while going to place it at the center of the screen so go to layout or the node selected and Center top this will make the nodes position relative to that Center top anchor so press the W key to select the move tool and click shift and drag it down to make the node live at an offset vertical offset from the top left corner the text a bit small well going to change it in the next video but for now we are going to work with that so selecting the main screen again I'm going to resize it and you will see that the text stays centered horizontally and it stays at a fixed relative offset from the top corner here now we are going to add the buttons so let's add a button you want to press ctrl-a again look for the button node and add that again it gets added to the top left of the screen we want to resize it a bit with the select tool active and we can add some text to the button as well so you can call this one play or the play button and we're going to duplicate it so select the button scene control D to duplicate it W shift click and drag down with the shift key down to move it down and the second button will be quit now the thing is you want to use these anchor system and the layout to make sure that the position of your own control nodes is relative to the parents in this case the main screen node so select the two buttons and just to show you I'm going to move them manually to the screen center in which case when I resize the parent the main screen the buttons will not follow right now only thing is we also want these buttons to stay aligned to be contained in some kind of box together for that you have a special type of nodes in Godot though containers so select the main screen and let's add a new node not button this time we're going to look for the container node and when you look for that the main container the container class is designed to allow you to create custom containers via code but you have a number of nodes that you can use by default especially the box containers here each box container is going to be a set of columns if you want and VBox container is going to give you a set of rows so let's add a V box container with that V box container selected or going to go to layout Center so it's going to Center the note and then we just have to select our two buttons in the inspector click and drag them inside the V box container and they will magically align and resize to fit the V box container so then you want to chain the size that VBox contain a node you can click on one of the corners with ctrl + alt held down so you're going to resize the box so that it gives a bit more space for the buttons and then you will see that the buttons have some kind of minimum vertical size here which is actually based on the text size we want to force the buttons to expand to take all the available space in the V box container so select the two buttons and when you select several similar nodes like these and you change properties in the inspector you're going to change the value on all of the notes all of the children so we're going to go to the size flags category expand it and then you will see you have horizontal and vertical flags these trigger some special modes or behaviors on the control nodes expand vertically means that the nodes will resize vertically to take all the available space and they will compete full space for example if I remove the expense size flag on just one button look at what happens the other button expands to take as much space as possible respecting the minimum size of the other button if both of them have the expand flag on they will share the space half in half and then you have a stretch ratio value that can change to make one node take more space than the other with that we have our base menu so I'm just going to move the label a little bit and we're going to do a few more things first we're going to rename some of the nodes to keep our work clean so label or rename to title because it's the game title for V box container we can say menu that contains the buttons then for the buttons we're going to the first one play button and the second one is going to be the quit button we're also going to do one more thing we're going to save these nodes to separate scenes so that they become reusable UI components so right-click on title say branches scene and go to source we're going to create a new folder we'll call it user interface okay and inside that folder will save our title as a scene right click on play button save the branches scene same thing it will be in your user interface folder by default so save there and finally same thing for the quit button because we will reuse these nodes the title will be for any text that should have a title font in our game and the buttons to play and quit are going to be reusable buttons but will that save your main scene we're going to save the main screen here in a new folder once again that will call screens these are going to be entire separate screens from our game levels the main screen save you can do one last thing it's to go to project project settings the run category and our main scene the one that loads when we press the f5 key was our level one until now press the folder icon click it and let's use our main screen instead so go to the screen folder double-click on main screen to make it so when you press f5 it will launch your main screen and you can see that you can already interact with the buttons and you will see your text and all but for now nothing's happening because of course we haven't coded anything anyway in the next part we're going to add the font to make our text readable okay so we want to make the text readable and to do so we have to change the font used by the text we can't just resize the box and have the text scale right now and go to 3.1 3.2 is the same so we're going to see how to do it the right way quote endquote if you go to the file system and you look at the assets folder you have two fonts prepared for you from default font title these are reusable resources that you can plug in any node so for example on the title here you can go down the inspector to the custom fonts category and drag and drop your font default there you might have seen that done in other tutorials but this is not the correct way to set a default font actually you don't want to use the custom fonts for that so I'm going to go back and deactivate the custom font instead we are going to use a UI theme so here I am in a more advanced version of the project to show you what themes are and what they do I can apply a theme to any control node using the theme property so a theme is a resource that you create in Guto and when you apply it to one node all the children the entire tree of UI nodes inherits from the properties of that theme so you can then edit that theme to modify how the entire UI looks for example you can set a default font and this is what we are going to do now it's coming back to our project let's in the inspector use the add resource button it's in the top left corner click that and you want first to add a font we are going to see how to create a text font so you type font and we want to use dynamic font create that so this is the type of resource you use if you want to use a font like a OTF on TTF file the kind of fonts that can find on your system here all these fonts that you have installed on your computer you will need to go find the file it depends on the operating system you are using and put it in your good folder or you can go download them from the internet in here for example we have mon sarah from google and then with your dynamic font resource open in the inspector you want to expand the font category and click and drag your oth TTF file either is fine on the font beta here with that done you can then change the size of the text by changing the size setting or property it's in pixels by the way so if you do 24 pixels it means that the letters will be 24 pixels high with that done you want to save your resource so at the top of the inspector you go to the Save icon and click save as and we can then save it in our assets folder at the root of the project and call that your dynamic font you don't have to create it I just wanted to show you what the process is like I'll save this one as our new dynamic font from there you want to create a theme a theme is also a resource so we're going to use the button in the inspector click on it look for theme and you should have only one resource to create that create that and our theme by default displays at the bottom of the screen here and it has only one slot to set the default font for our user interface so you can then drag and drop your dynamic phone's dot T res file and place it in the default font slot and you should see the text updates in the bottom panel this button panel the theme panel is just here to give you preview of your UI theme then we'll see in the extended edition that can use the edit theme menu to add more items to then start to change the style of the buttons the distance between elements in your UI so you can use that a bit like CSS in the web development world to style your user interface anyway we're going to save that theme as our UI underscore theme dot t res in our assets folder here click Save and then select your main screen node go to the theme at the bottom and you want to click and drag your UI theme that T res into the theme slot you should see the fonts change instantly now the title itself went a little off to the right we want to fix that but as we saved our title like button and quit button as separate scenes we want to open these things to go change the default property of our title here so open it in the editor and for our title I want to make sure that it is aligned Center so the text is centered inside the box that you can see here then we want to create a new font or rather use the form title that we created for you the same way I showed you moments ago and go down to custom fonts and click and drag the font title into the slot I'm going to change the default text to title here and again go to layout Center or rather we're going to do a layout Center top so that the text position is relative to the top center of the screen all of the parent node save go back to your main screen and you should see the font changed then we want to do the same again layout cent top to reset the position of the node and you can move it down by clicking and dragging with the move tool selected or select all then shift to constrain to the y-axis and with that we have our UI setup we can move on to the code ok so now we're going to code I would play and quit buttons that are currently not doing anything to do so we're going to open our play button scene so click the button to open it in the editor next to the node and we want to add a script to our play button note click add script by default should go in the right spot user interface slash play button da GT note that I'm using the empty template once again click load or save the script to open the script editor we're going to make the button do something change the scene when we click it or rather when we release pressing the button to do so we have to use a signal select the play button go to the node tab next to the inspector and you can see that you have a base button category with a few button related signal button down is going to trigger when you press or start pressing the button down when it is down button up will trigger when you release the button so releasing the button is when see when I click the button changes shade it's when I release the click that very moment this is button up this is what we're going to use here so select button up click connect and you're going to connect to the play button I'm going to change at the bottom the method in node 2 on button up because this is happening on this node on it's attached crypt already so we don't need to have a more complicated name click connect to go to the script editor and have the on button up function created for you there we will change the scene so that is how our play button is going to work we're going to do that by getting the node tree the node tree is what you see in the scene tree but we want to get the one the games who go get tree dot change scene and then you have to give Goodell a path to a new scene so a path would be anything you will get if you drag and drop a scene from the file system here into the code editor I'm going to go to the levels folder for example and click and drag the file into the script editor as you can see this writes the absolute path to the file itself relative to the resource folder which is the main the root folder of your good or project now we don't want to have a hard-coded paths in here we want to make our button reusable actually we're not going to call it play button in this scene that we'll call it the change scene button for example and we might want to rename the scene as well on the file system so go to the user interface folder play button right click we want to rename it to change scene button so go back to the script editor now and I'm going to add an exported variable so we are going to do export variable next scene path and it's going to be empty by default I'm going to add a colon to automatically set the variable to a string and in the change scene call that can see in there I'm going to change the string influences and use next scene path instead alright now we can do a little better than that because if you go to your change scene button in the inspector you should have that next scene slot but it would be nice if we could directly select a file from there it turns out that we can so let's go back to the script editor and after the export keyword in parenthesis we can give some parameters to tell Godot what this string is going to be exactly and in this case is going to be a file path so add parentheses after export and we're going to first tell the dough that this exported variable is going to be a string and then we want that string to use a file browser slot so you have a few keywords you can use here constants you have file and you have multi-line for example if you want to have a large text field but in our case holding to use file save go to your change scene button again and you should see the folder icon next to the next scene path now you can click that folder icon to go find a scene file in your project ok well I'm not going to do that here because our button is going to have a different path in every scene where it will be used so while creating a smart reusable component let's say we're going to do a little more than that we're going to see how to add a warning if we forget to set the next scene path because if you forget to set it you're going to get nothing as the path is empty right you just click the button nothing happens so we're going to go back to the script and first at the top of the script we're going to add the tool keyword tool allows you to run any code inside of the editor so this is the keyword you would use to create plugins in Godot for example then there is a built in feature to give warnings to the user this is the warning you get for example when you add and carry a 2d node right that warning icon here to add that we need a function called get configuration warning you should get auto completion for it now we'll add the string return type it's going to return a warning string if a certain condition is not met so let's return next same path must be set for the button to work and we're going to do that so let me expand the view here if the next seen path is an empty string like so else we return the empty string so the warning will show in case we'll return a string with something inside of it and that will happen if next seen path is not set which is the default value here so save that and you will see the warning sign appear in the note tab that is until we put something in next in five sometimes you have to reload the scene or save for the warning sign to go away but well we have that set up with that now if you save and go to the main screen we're going to set up our play button so the next scene path here is going to be the path of our first level in the file system tab navigate to level o one dot t SC n right click can copy the path and paste it in the inspector then we want to code the quit button it's going to be a lot faster and simpler so open the quit button in the editor while going to change the layout say it's going to be centered by default or we can say top left just to have a clean scene to work with and we are going to attach a script to it create a new script with quit button selected it's going to be saved in the user interface folder and for this one we're going to do the same when we release the button when it's up while I'm going to quit the game so go to the note tab double click the button up signal or connecting it to the quit button and I'm going to rename the function to on button up of that when the button is up while going to call the quit function which is on the tree the scene tree object so we call get tree to get that tree object and we call its method and that is it with that you can play the main screen click the quit button it'll quit the game click the play button and it will launch the first level next up we are going to work on the games and screen that is going to be quite similar to our main screen but we'll see how we can reuse our buttons that way so let's create a new scene and wanting to make it a user interface singing called and screen let's save that to our screens folder as our end screen so end screen is going to have some title it's going to have some message about the score and two buttons like we saw with the main screen so let's create that right now we're going to start by placing the background so one thing we can do here is grab that texture rectangle that background from our main screen scene back to the end screen right click on the node and select the merge from scene option you want to select your main screen scene a good screen main screen t sen and you want to select the branch of the tree that you are going to integrate so we want to get the texture rect here press ok you can use that to get entire sub trees of nodes as is copied to your new scene we could also save our background as a scene to reuse it but I wanted to show you that other functionality we're going to do the same merge from scene go get the main screen to merge our menu here because we're going to have a very similar menu in the end to restart the game from scratch or quit it let's click OK and you'll see that because we are not using our UI theme yet the text is really small so select the end screen node expand the theme category and we're going to drag and drop our UI theme dot t res into the theme slot now for the play button we want to change the next scene we don't want it to restart from level one I want to restart from the main screen so let's open our main screen seen in here to get the full path to it when you'll click Play from the end screen it will go back to the title screen and so we can change the text on the play button to play again the quit button can stay the same so we can reuse our UI component as is and all we are left with is the text from the text we're going to first search for a title seen the title component that we stalled and drag and drop it on to our scene here click to select it and we're going to change it to a message in screen message so congratulations you finish the game then we want to reset with the title selected it's layout - we're going to align it with Santa top click shift and drag to move it down and enter the title select the n-screen node press ctrl-a to add a label we'll write the score in that label so it appears in the top left we're going to use layout sent it up set it to your final scroll is well put the score there you died x times now we're going to expand that property so you can click the expand icon in the inspector to have a large text field to edit your text and we're going to use some placeholders for the text that we can replace later via code you can use the modulo sign followed by s to say replace that by a string later when we use the format function ng D script so we're just going to have these placeholders for now and later via code we'll be able to insert a numeric value here your final score will be let's say 1000 and you died three times we'll keep track of that a bit later but for that for now we're going to have it that way um use so layouts I'm going to set it up again to reset that you could align the text centered horizontally like so and shift click and drag to place it under the title so again because these two nodes are attached to the top of our UI means that when we are going to resize it because these two text nodes are attached to the top of the UI here means that when we resize the UI they are going to stay at the same offset from the top you might want to attach them to the center instead so you don't get that collapse between the buttons and the labels going to select the menu label title we're going to Center them on-screen and then manually up set the title and the label place them above the buttons finally you can select the menu label and title together W to use the Move tool and shift click and drag to Center them visually on the screen and once you've done that there will be relative to the center of the parent container you shouldn't be worried about the text getting too large for example in some cases because when you are creating games you're optimizing them for either portrait if you're going to make a mobile game or landscape mode the ratio of the supported screens will go from something around like that for the very white screens to something a little smaller 4/3 for example these are the main ratios you should want to support in which case the text is always fine it's always going to fit in the center of the UI and as you might have gotten by now this is in part why we have all these layout options this is so on different displays that have different ratios or sizes you will have the UI elements centered or aligned and resized relative to some anchor points next up we're going to add a system to count the score in a way that's persistent when we change the scene so that we can show the players score at the end of the game to do so we're going to use a feature called Auto loads that relies on creating a node that will always be AXA ball and that we can use anywhere in our projects from the code so let's go to scene new scene to create that new node we're going to use the custom node button here to create a basic note let's call this one player data it's going to store data related to the player save it we're going to put it in the source folder create a new Auto load folder and save it as player data the TSC n now let's create a new script where we'll manage the score the thing to understand about the code we're going to put here is that any of the script in our project will be able to access it this node is going to count the score and the deaths of the player so let's create two variables to store these values variable score is going to start at 0 and we're going to create a variable deaths that's going to start at 0 as well two integers and what I'm going to do something there to be able to notify the rest of the game that we updated that node so that the user interface will be able to react to it so we're going to use signals for that at the top of the script let's create two signal signal updated and a signal current player died so updated you could say values updated something like that for example or we're going to call it score updated to be a bit more precise we're going to create two functions so that every time we change the score so if in some script you write score plus equals one like so it's going to go through a function that will increase the score variable and call the signal here for that you can use a feature in G script called set get the set get keyword allows you to define a function that every time you're going to change that variable it will send the new value to that function that will process it so set get set score this is called setting up a setter function and after the said get keyword you first write the name of the set of function the one that will update the variable and optionally you can add a comma and add a getter function one that will return the score value to the user of the variable now we're only going to use a setter so a function that is going to be called every time we change the score itself let's copy this function name and create it to clear the error in the script so function set score every time you have a setter it's going to get the value that you want to assign to the variable want to make sure that this value is an integer in that case that is to say a whole number because that is what our school is and this function will not return any value I'll just put the recent keyword so we don't have any error here but to explain imagine that one another script coin player data that score plus equals one add one to the score going to commend that out what's going to happen is gutter is going to call that set score function with the new value of the score so the current score 0 plus 1 so 1 then it does not modify the score variable this is up to you to do it so every time you create a set of function the first thing to do is to say score is equal to the new value passed by the function and then you can add extra instructions that Godot can follow in our case m8 signal and we want to omit the score updated signal so that way the user interface will be able to listen to that signal and get the new score value at that point from our player data or optionally you could make your signal pass the score value so you could pass score or in that case value both variables at this point will hold the same value but in our example we chose to not add to not pass the information through the signal as anyway everything's going to use that player data directly we're going to do the same for the Deaf's so at this point you should be able to replicate what we did for the score using the player died signal instead of score updated I'll let you pause the video and do that and so it looks like that so I'm going to copy the set get keyword set deaths note that the convention for setter and getter functions is to call them set underscore followed by the name of the variable and forget --is get underscore name of the variables so I'm going to copy and paste the set score function and rename score to death in here one thing we can do that is use the control on shortcut to replace in the selection only that should be automatically checked if you made a selection before calling the shortcut and you can replace score with deaths and click replace all and finally after you've done that you want to change the signal name to play a died now we're going to register that scene that node as an o2 loaded note because right now if I go let's say I'm going to open my player script if I try to type player data there's not going to find it it's not globally registered yet so we want to go to project project settings and there is a tab dedicated to the o2 loads click on that then in the path you want to go find your file player data TS yen so go to source o to load player data and RTS yen note that we don't actually need to make a scene as long as your script inherits from node it is enough but let's do that now and it will give that note a name this is the name you will use to call the node to access that new player data class in your script files the default player data is fine let's add this and close here now we have that autoload registered from anywhere in our script for example when the character dies we can say player data dot deaths plus equals 1 so now we're going to code the death a little bit differently we're going to create a die function on our player the reason being that you if you want to add new ways for your player to die you don't want to hard code the death in every block in every signal callback like when the enemy touches you so instead we're going to create a new function called die so you can write that here it's going to give you an error and go to the bottom of the script why you will create a new function called die it's not going to return any information and we're going to increase the number of deaths so player data the deaths plus equals 1 and we're going to q3 the player and with that it should clear the error and we have the player death coded we don't have much more to do well automatically later on show the user interface when the player data singleton or Oh to load Emmett's that player died signal now I'm going to work on the score so the score will increase when you stomp an enemy or you collect a coin let's go to the enemy scene to control shift Oh to open the enemy scene and will automatically open the enemy script we had a die function already there so now when the enemy dies want to increase the score and to do so well I'm going to create a new variable so an exported variable called score which is the score value of the enemy so let's say it's a 100 points here then in the die function at the bottom of the script we are going to increase player data but score by the enemy's score value we finally have the coin to take care of so let's open the coin scene and when the coin is picked we also had a function for that because we're going to increase player data at score plus equals let's call the value score as well while we had it already on the coin and so we're going to increase the score by 100 when the coin is picked and that is it for the school system that is all you need to make it work the score and the death count will be persistent between different scenes now going back to the player data scene and script we're going to add one last thing we're going to add a function to reset the score and the deaths when the player restarts the game at the very end so let's create a new reset function it's not going to take any parameters and it's not going to return anything all it does is reset the call to zero and the deaths to zero and there I have to add a little precision regarding the way Santa's work setters set a function so sets go on set deaths are going to be called every time you change the skull from the outside so if we go to play energy D we do player data the best plus equals one it's going to go through that setre sete deaths but when you write score equals zero deaths equals zero inside the class like so it's directly going to modify the variable without going through that function this is there for flexibility so that internally inside your class you can make changes to the variable when you need to like in our case we don't want to omit the player died signal that later on will trigger showing some bit of interface saying you died restart the game etc we just want to reset the values so that's what we are doing but with that let me show you one thing we're going to play the game so press at five we shouldn't have any errors and then in the top left you have a remote tab in the scene tray that appears and that remote tab is going to show you the state of the game scene tree in real time so you can see one thing we are in the main screen scene and we can see our notes our UI knows player data is also there automatically loaded for us this is why these nodes and this feature is called auto load then if I click play the nodes change in the scene tree so we have the player and on the level the tile map etc but the player data did not change and this is what these outlets do furthermore if you look on the right I've selected the player data and you can see live its values so you can see that as I move the player around and I collect coins the score value of my player increases now I'm going to die and death counts increased as well with that in the next video we can add the game user interface including the pause menu in this video we're going to add the user interface in game so the text that will display the score and the pause menu and the corresponding overlay it's going to look something like that in the end with three buttons that allow you to say quit the game if you want to so back from our main screen we are going to create a new scene for our user interface once again so we're going to start by calling the scene user interface and saving it to the disk in our user interface folder let's start by adding the theme so that our UI looks consistent with the main menu in the end screen so we'll put it just on the top level user interface node and everything else will inherit from our theme then let's create our score that way score is going to be a label that will anchor and the top right of the screen so go to the layout menu and top right this means that when you click and drag on the know to move it it will be relative to the top right of the screen you can align the text to the right and the label and let's type our template text scroll comment and modulo s remember this module S is a template that we will then replace from the code I'm going to move the node a little bit again so it stays in the top right of the interface alright with that we have our score label really we're going to create the bars overlay straight and we're going to create it inside that scene so we're going to start by making some color rectangle that's going to cover the entire screen so let's add a new node and look for color rectangle or color wrecked then with that new node selected go to layout for rectangle so as you can see it's just a colored rectangle we can change the color in the inspector we're going to go for a transparent black overlay so click to open the color picker drag to get some black color and then we have to change the full channel so we have RGB for red green and blue components of the color and to change the transparency you want to drag the a for alpha so go down to something like 60 a light overlay then we're going to create our pause menu so we're going to have a title and then a list of three buttons let's go to our source folder a user interface and we have title but we can click and drag inside our color rectangle that will rename to fuzz menu or Parrs overlay because this node is just the overlay it's not the menu itself so we're going to have our title go fast like so we're going to Center it and move it up a little bit then select the plus' overlay node to add a new node as a child of it of ctrl a and we want to look for the box container again so a vertical box go to layout Center to Center it and we're going to use the Alt key and click and drag on the corners to resize it around its center let's make it something like that a box that has enough space for the three buttons we'll put inside I'll move the title up a bit I rename the V box container to pause menu and then we want to add our quit and scene change buttons inside so you can go to the file system and select the two scenes and click and drag them inside the scene and you can see the blue bar and the pause menu which means that there will be added as a child of the pause menu then if your buttons are properly set to expand they should take all the available space here let's take the scene change button in the scene tree and there's a shortcut to move it up and down the hierarchy control up arrow to move it up control down arrow to move it down and look in the view how the order of the buttons change this is really the magic of these UI containers now we're going to have our scene change button right down main screen it's gonna go back to the main screen and form the scene path we want to go so in our file system to the screens main screen you can right click to copy the path here and right click to paste the path inside the next scene path slot and that way our button is set up now we need to add one new type of button a button to retry the current level so we're going to create a reusable scene once again we're going to get either button quit all scenes scene change button right click duplicate the scene in the file system tab and let's call this retry button press ENTER to create it and double-click to open the scene there now I'm going to rename the note retry button and we want to change the script on it so I'm going to click your remove script icon and click again to add a new script it should save automatically to the right path user interface slash retry button the GD click create and then we're going to have a similar setup to what we had before so note that the signal connection is still there and still on button up going to call an underscore on button up function so I'm going to type shine on button up it's not going to take any parameter and it's going to not return anything either when we want to retry the level here's what we want to do first want is set the scroll back down to zero going to update the score in the user interface but we don't want to reset the deaths this is why we don't do player data of deaths equals zero or we don't call player data reset right we just want to set the score back to zero then we're going to reload the current scene so get tree because this function is on the scene tree node so we have to call the guitry function to get that node dot reload the current scene and finally we'll do one more thing ahead of time while going to add a pass system and the pass system is built into Godot so you can call get tree to get the scene tree again and this century has a property called paused so you can say buzz is equal to false so what's going to happen is because that button is in the pause menu you know that if you are clicking that button it's that the game is currently paused so when you click it you're going to unpause the game so that when we reload the current scene you can play instantly and that is it we can save close the scene press f1 to go back to the 2d workspace and click and drag the retry button and I will pause menu oh I forgot one thing so let me reopen the retry button scene to set the bottom text to retry go back to the user interface and voila we have our full pause menu in the next video we are going to code our pass system on the user interface node back to our pause menu wanting to code the pause so first I wanted to set the default state of our menu we don't want the overlay to show in-game by default so we're going to toggle the visibility off then select the user interface node and let's create our user interface script there we are going to manage the bars state of the game and a little more will see that afterwards like put some label when the player died etc anyway we're going to create a variable called paused to manage the paused state of the game and of the interface as well and while going to use the setter function the set of feature of Godot to go through a function whenever we pause the game so let's create that function the reason for that is that when you pause the game you not only want to change the past state of the scene tree but you want to toggle this menu on and off so we're going to create a set post function again it always takes a value a boolean in that case so true or false and it does not return anything now first thing to do with a setter is to assign the value to the variable that you want to set to change then we're going to set the scene tree to be the same state as I will pass value here and to do so we're going to cache the scene tree we're going to get the scene tree node and store it in a variable and we can do that using an unready variable so the unready keyword remember triggers right before the underscore ready function in Godot and allows you to get nodes and to store that in memory because getting nodes all the time if you have a very large game you can start to use quite a bit of CPU to use quite a bit of performances so can be nice to do him it's ahead of time sorry so sentry we're going to call the get tree function here at the start and that way within this script we can use the scene tree variable to refer to the scene tree node so in our set past function we're going to write sin tree not pause and you'll see you get followed to completion thanks to the type hints here we're going to set it to our value here but that's not all while also going to change the visibility of the pause overlay and so this is a convention we use a GE quest where we cache what we call the dependencies the other nodes in the scene or outside the scene that we use inside a given script I'm going to create a new unready variable for my bars overlay and we're going to get the node called pause overlay here right and for the type it won't give you an error if you use the automatic type like that but you can say that this is actually a color rectangle here to go to-- and because by default if you only have the common the type that good it will use here is the return type of this function you see when we write the arrow after a function we tell Godot which type this function is going to return and get node returns the type node but if you want to be more specific and get better Auto completion you can tell Google what is the exact type of the node that you are getting in this case call it wrecked so we are going to do then pause overlay that's visible equals value okay so next up we want to pause the game to use that pass variable we're going to do that with input so let's add a new pause input event go to project project settings input map and let's create a new action called pause press ENTER to create it I'm going to click the plus button here to add a new key and we'll use escape to pause and unpause the game now in our user interface script around the top we're going to add a new unhandled input function it's one of the built-in callbacks that we've used for input right and we're going to check if the event only input event parameter that we get corresponds to the action bars being pressed in which case we will toggle the paused variable so I told you that if you say just pause it equals two well we can use not paused or the exclamation mark to negate the value so it means if you have a boolean like that if it's false set it to true if it's true set it to false in other words toggle the value of my boolean variable here I like to write using the not keyword because it's plain English right buzz becomes the opposite of the current state of the variable now if I do that it's going to change the variable directly because well within that class and not go through the center there are two ways to go through the setup the first one is to directly call the function inside the class the other one is to use the self keyword which is what we generally use IG requests so self dot past will ensure that the variable goes through the set of function this is because when you call the variable from another script say from my retry button or whatever you are implicitly going through that self you are go to is going to say I want to change the pause variable of this instance of the user interface while getting a bit more technical what we have to understand that is that in many programming languages you have to explicitly write that self dot all this dot in your classes to refer to a variable that you created inside that class and in Gd script it's not the case most of the time it is implicit but in this one case we need to make it explicit for godot to go through the setter here finally whenever you go through that and handle the input function we don't want anything else to intercept that event if we already pass the game so one thing you can do here is on the scene tree call the set input as handled function whenever you press a key on the keyboard all the nodes in the game that have unhandled input or a similar function will receive that event and if you have two bits of your game like your user interface and your player that reacted the same events for example pressing the arrow keys you can use set inputs as handle to not propagate the event right so it will stop here only this function will process the pars input event now at this stage we can test the bars system in our game so let's save and go to our level here the first level while going to add the user interface there but if you directly add it you will see that it gets collapsed to the top left corner of the screen and so the score label shows at an offset of that we want to use a new layer like we did for our background to separate the UI from the rest of the game so select level o 1 press ctrl-a and create a new canvas layer that layer is going to be let's call it user interface and wanting to place it around the top level here make sure with the note selected that we sent the layer to a high number so it shows in front of everything else and then click and drag user interface of T SCN under that note and you'll see that now it resets it takes the entire screen with that you can press f6 to try the current level press escape and you will see the game pause so the enemy stops moving magically now if you try to click the nodes here you trying to click the buttons or press escape you will see there's a little issue I told you the paws system is built into Godot and by default when you set the game to paused all the nodes in the game like the enemy in the background it stops moving it stops processing it stops reacting to clicks and to signal callbacks so I'm going to quit the game here to stop it with f8 go back to the user interface and with the user interface node selected you want to go down to the bars category and the mode by default is inherit so it will inherit from its parent which in this case is the user interface which inherits from level o one and the default mode for the top-level node is stop when you pause the game everything stops as a result going back to the user interface scene while going to set the mode here to process which means that whenever we pause the game the user interface will not pause we will still be able to use it so let's go back press f6 and so I press escape to pause the game now I should be able to retry the game as you can see escape to pause and I can quit so that way you can test your user interface and see that it works that the pause works in just a few lines of code here next up we are going to connect the player data node which is o2 loaded in our projects are accessible from everywhere to this user interface while going to do that in the ready function because we need all the nodes to be loaded in memory but me via the game just to show you the remote sentry so the ready function gets called on every node from top to bottom so let's say the root node but then play a data and when it hits main screen it's gone not called ready on main screen is going to start with its children so text erect title when it hits menu it's gonna jump to the children play button quit button then menu and finally main screen so it goes in the tree alter from top to bottom but then it starts from the deepest children to the parent for each branch in the tree this is why the auto loaded nodes will be available in the ready function that will be loaded before everything else in the game that is why we can directly call player data dot connect and we're going to connect the score updated signal to this node so we have to use self as the second parameter and we're going to call a new function that will call update and the score interface as a callback for that I'm going to expend the view as well here so every time that the score gets updated we're going to change our score label here then we are going to connect the dyed signal to another function let's let's do that let's do the two connections so I'm going to duplicate this line with control B and instead of score updated we're going to connect player died yeah and while going to connect it to an on player data lower case player and score died and finally at this point so we're going to use that update interface function to update the score and we'll call updates interface here which is going to give us an error because we have to create that function so copy this update interface and we're going to place it above our setter down there function update interface it's not going to return anything and in this one we're just going to update the score label so the score label is our label here and I'm going to create a new variable on top of the script to store it so unready horrible school calling label it's of type label and we can get the node label yeah again if we are doing that at the top of every script it's for code readability anyone opening our user interface can look at the first lines with our convention and understand that this node depends on the scene tree on the bars overlay that you can see here and on the score label and this helps a lot when your game grows so that's why even if we could directly call get nodes inside our functions we are trying to give you good practices for your future projects here okay so long going to do school label dot text is going to be equal no I called it school it's called a text is equal to and we're going to use the same template as in our score label so school Colin the modulo s and then you can use the modulo sign followed by a value that will come and replace your modulo s here in our case play a data dot school and well automatically when we play the game replace the modulo s so you can play level one where we added our user interface already and you can see that the score is set to zero at the start and as you hit the coins it goes up on the UI already we have one last bit to do it's to react to the player dying and the thing what I'm going to do there is we're going to pause the game so it's going to show our pause menu and we'll change just the title of the pause menu instead of writing paused because the death menu will have the same options retry main screen and quit we're going to have a different text you died or something like that so let's copy the callback function we have in ready when we connect to the player died signal and right under the ready function we're going to place that function player data player died or I need to add an on here need to select the text press control all to search and replace and I'm going to replace the text by on underscore player data player died replace all okay so this function same thing it's a void function it does not return any value and there well going to bars the game so self dot past equals true and we're going to update the title label in our pause menu pause overlay so for that again we go back to the top of the script we duplicate the score here we are going to call it buzz label or pause title it's going to be of type label and we're going to get started type buzz and you should find bars overlay slash title Oh to complete it for you and so now going back to our on player data player died we're going to get our bars title dot text is going to be equal to he died there you go so um I know that that mechanic of jumping back to the top of the script adding these unready variables and jumping back down and the way we alter the code sometimes can seem a bit messy at first but again the goal is to make the code as easy to read as possible for your future self to understand the code you wrote months ago all for your teammates it's exactly the same thing and the conventions that we use as a request we've worked a lot on that to optimize them so that for example when we connect to signals we generally do it in the ready function of our notes so it makes sense to have the callbacks like on player data player died as close as possible to your ready function that way you can see the connection and you can see the result really quickly the exception to that rule is when you are using a method that other nodes of the parts of your game make all independently from the signal like wandering with update interface anyway with that we have our pause menu you have to make sure that the pause overlay his head by default and then you will need one more thing in this project it's to copy that user interface bit the layer and the user interface scene to the different levels so I'll open level Oh - in my game I'm going to right click merge from scene and I'll go find my level one where I created my UI setup so I'm going to go to levels a1 and I want to copy the user interface okay it will probably be added to the bottom of the tree going to put it back at the top and voila we have our score in the second level you can do that as well in the level template so I'm going to ctrl shift o open level template here and in my level template I'll do the same right-click much from scene go to level 1 double-click user interface and place the user interface at the top with that you have your in-game UI we have one thing left to do to change the end screen of the game so let's open it ctrl shift o to open the and screen scene and remember we have the text your final score is something you died x times well we have to replace that with a bit of code so select the N screen node let's add a script and we're going to create it in the end screen folder now we're going to first get that label that we need to change the one that has these template strings so going back to the script editor f3 I'm going to type unready variable we're going to call it label oh yeah label it subtype label and it's the label note I'm going to use the get node function for inconsistency in our project note that's what I was doing here was typing the dollar sign which is a shorthand for that I think I've mentioned it in the course but just in case we don't really need a function to change the text when we arrive on the end screen we are going to change seen from the second level to that end screen seen so we will get the ready function of the N screen node called let's create that ready function and this is where we're going to change the labels text so label that text is equal to label dot text so we already have the template here with the modulo s for the score and the deaths so now all we have to do is to use our module sign which is the symbol to format a string to replace the templates that we have and then we have to pass in first the score and second the number of deaths the deaths count and we have to pass it inside an array so we are going to create an array like so using the square brackets and first we pass play that's cool and second we're going to pass player data dot vests so now if we go back to the scene and would play this scene with f6 should get 0 for the both of them if now I play level Oh - I'm going to double check that our portal to D here the next scene is let's see level 2 is not linking to the end screen so now we have to go find the end screen in our file system tab and click and drag it on to the next scene slot of our portal for testing purposes only I'm going to place the player closer to my portal here and press f6 to play so all I want is to check that the score is working I have a score of 300 I pass the portal and I get to the end screen the final score is 300 let's do another test I'm going to fall down die retry and then jump to the portal and the death count works we died one time I have a score three hundreds which corresponds to getting or grabbing three coins now let's test the final game so if you have set up all your portals right in level one level two should be able to play the game and have all the connections work I'm going to make the gale game fullscreen so go to project project settings for that and in the search bar search for fullscreen it's in the display window category check the fullscreen Trank box and when you press f5 the game will be fullscreen as you'd expect so let's play it and there I want to thank you very much for watching the course or this video to the end if you were just interested in the UI part of the course now you have an extra lesson in the extended version of the course in this chapter as well the balance creating you I theme but you can pat yourself in the back for getting there and with that I want to thank you kindly for watching be creative have fun and let's see one another in the next one which can be another tutorial another course thank you very much see you soon there is a bug that happens in the game when you die that that someone who played the game reported so when you are dead you can press escape to unpause the game in which case you have to know that you have to press escape to open that menu again who might not want that I'm not saying that the you died is also a bit upset here that we have to recenter it but first things first we want to prevent the player from and pausing when they are dead so for that let's open the user interface scene and the pause menu is controlled in the user interface script let's open that so when you die the player died signal is emitted you pass through that callback function the game is paused opening the menu and the title is set to you died this just pauses the game but then if you press the pause action escape in our case it's going to just unpause the game so here we could add a new property to say that the player is dead and just if it's dead you don't unpassed another option is to use the past titles text to check if well on the died menu or not so we can say if the action in pause is pressed and the unhandled input function and vice titles text is not equal to you died then we can unpause the game look at the result while going to die here if I press escape it's not going to do anything in that case I can only click the buttons retry retries the game etc bug fixed this might seem strange to some of you because you'll see that a lot of people will use boolean will add extra variables to handle those kinds of problems it's actually something you should avoid the fewer properties you create in your code the fewer bugs you will create this is not necessarily the best way to solve the bug while really patching the game here you might want to move that message to some constant for instance you have a constant at the top of the script I'd message and you could say you died that way you can't make a typo if you replace the hard written message by the died message constant and that is it for this issue when it comes to you the text title it's already said to be center-aligned and I think that the align problem comes from the text box that when you change the text we can try here you died yeah it's going to push a text box to the right so the issue is that there is not enough space in the text box to make room for the you died text message so we have to alt click on the handles with you move tool selected as usual to make a little more horizontal space for the you Dyke text another option to fix that bug would be to have a completely different pause menu and you died menu with possibly different options that would probably be more flexible because in a full game you might want to differentiate the two menus to have an inventory to have something in the pause menu but when you died to only have returned retry main screen and quit for example with that if you find any bug you can find a link to the code repository below the video i invite you to report issues there congratulations for guess to thee and the course and thank you for watching it until the end I hope it was helpful please tell me in the comments below if this was helpful for one what you liked in the course and if you have anything you'd like to see us improve moving forward I don't have a lot of experience making big enough friendly content so that would be most valuable now you should subscribe to the channel because there's going to be more moving forward want to keep creating free content like that we have our 3d mannequin that's open-source now it's not necessarily a big enough friendly thing but it's a professional-grade game character that you can use to prototype your games and we have James who's working on a beginner friendly first-person shooter tutorial series but that said I want to thank you kindly for watching be creative have fun and let's see one another in the next one bye bye you
Info
Channel: GDQuest
Views: 72,921
Rating: undefined out of 5
Keywords: godot user interface, godot main menu, make your first 2d game, godot beginner, godot pause, godot score, godot 2d platformer tutorial, godot 2d tutorial for beginners, godot tutorial 2d, godot platformer 2d, godot platformer, make a video game in godot, how to make a 2d game in godot 3.1, godot tutorial for beginners, make your first game, godot engine getting started, godot 3, godot 3.1, godot game development, godot engine
Id: mjWwWIEyib8
Channel Id: undefined
Length: 89min 52sec (5392 seconds)
Published: Thu Dec 05 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.