Items and Autoload Scripts (Godot Retro Text Adventure Tutorial #10)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video you're going to learn how to use auto loads in godot to make singletons and shared type files that you can use across your game and how to responsibly manage using singletons in godot you're also going to implement items so you'll look here and see we now have an items key line here it's saying what items are in a room and if you go to a room where there are no items like if i go east you'll see no items to pick up and you're going to learn how to make this text and customize it as needed let's get started alrighty so the first thing we need to do is actually create our items before we do that though just because we're starting to get a lot of different files scenes scripts etc in our file system here for our project i want to do a little bit of reorganizing to make this a little bit nicer so i'm not going to do anything super deep or complicated but i'm just going to make a new folder and i'm going to call this rooms again remember in godot if you can it's best to keep your file names or your folder names excuse me lowercase i think it's especially with linux it preserves some compatibility with just um naming schemes so just keeping things lowercase is the best all around all os if you can so within our room rooms folder i'm going to drag a room gd room.tc our room manager gd and our exit.gd so basically anything that deals with rooms or exits i'm going to put in here and this might crash this okay hold on sometimes you get an error so if i save it looks like things worked sometimes when you move things around godot can get a little finicky make sure you do it within the editor though and not within your file system itself within an os window like finder um on mac or explore on windows because good o will handle renaming and moving things around the way it needs to okay and now that we have that i'm going to make one more folder and i'm going to call this input and this is where i'm going to put any of our ui input elements as well as our code that's handling some of our input i won't put our command processor in there yet but just to kind of separate some of our ui elements so i'll just make folder call it input and then basically input input history input response response etc all these that are ui elements that show our input or just handle the actual entering of the input not the processing but the entering i'm going to drag all of these into input and there we go now i can save and i'm just going to run our game just to make sure everything is working as expected and so okay you realize we've got a there's some paths i've got to update here so i'll just do input slash that and then input slash that and i'm going to go through and make sure all the paths are updated you might have to do this on your own if you are also refactoring which you don't have to but i'll come back in just a second when i've got all the errors fixed okay so our game is working i can run it and it will pop up and we can play it and everything is good go so now we're ready to start working on items and so the reason i wanted to do that is because in order to just start making things a little bit nicer i'm going to add a new folder called items and now we've already got a bit of this similar folder structure set up so when i add items it's just a continuation there and so to make items we're going to do a similar thing that we did with exits we're going to make them a resource and the reason why is because at least at this point there's not really any visual representation we need for items even if we did show them in our map or 2b mapper in our developer interface we could just output as part of the room description or another thing just list all the names of items in the room we don't actually need the item itself to have any visual any nodes there's no visual component to it and so we're going to start it as resources and that means that again like we talked about in the last video you know is going to automatically handle reference counting those resources it'll handle making sure they load in correctly and if we do want to modify items and save them in their modified state it'll be really easy to do that because items are serializable by default in godot so there's not really any reason not to use resources instead of just a reference so we'll just use a resource for our items okay so let's make a new script here i'm going to right click on the items folder and hit new script and i'm going to say item.gd and if i open this one up we'll see all this default boilerplate stuff and we're going to change this to not extend node but to extend you guessed it resource all right now that we have our item resource we are good to start making our items or adding the properties to it if you remember with our exit really it was just kind of a data container exits right now don't do much on their own besides some common functionality like getting the other room from you know whichever room is calling it and so we'll add some similar things to our item probably just an item name and item type right now and then it'll be a good foundation later on for us to extend as needed okay so if i go back to item let's start adding some properties on here and really there's two properties that i want to add right away one is the item name and another is the item type so my vision for items at least at the beginning you can really go overboard with items and trying to make them easily customizable my favorite way of making making something able to be customized but without adding all these ridiculous rules a nice balance so that you can make them quickly while also giving a nice amount of flexibility is to define strict types or some define some variants and then allow allow customization beneath that once you've got those in place and so really what i mean by that is we can define a rule set of item types so an item must be either a key or a potion or a consumable even and so you define these broad item types and then it allows you to customize specific to which type it is and so you're kind of developing this rule set for items anyway that'll make a little bit more sense as we get going but what i want to do is add an item type property to our item now the way i want to define those item types is by using an enum i think we've covered enums before but as a brief refresher enums are basically dictionaries where you define set constant values and so you can get those constant values and use them kind of as a type almost across your code and so what we can do is just define a set of constant values that define the possible item types we have one thing i want to do which i'll show you in just a second is use an autoload script in a singleton a global singleton to define those enums so first let's start um let's start adding our properties here so we're going to have and these will be export variables and we'll see why in a second so we'll do export and we're going to do string this is going to be our item name so export string var item name and we can just default this to be a string that just says item name item name there we go and we're going to have an export and right now we'll just say integer we'll come back to this export variable item type and right now we'll just default this to negative one and we'll come back to this in just a second so now we've got our item type but rather than just having integers or strings or just values that are mutable and you can't really be sure of like what you should expect to get let's make an enum so first what i want to do is create a new autoload script if you're unfamiliar with those auto loads are godot's way of creating scripts that are global that you can access from anywhere in your code base what it does is you attac you create an all load script and you tell godot it should be an auto load and then when your game runs godot will create a node at the root of your scene tree that has that script attached that is globally accessible to any other node any other script in your game now as a software developer by trade and someone who really loves software architecture singletons and especially global you know global singletons get a bad rap and rightfully so i think because they're easy to abuse because when you're storing a bunch of data in a global singleton you it can be a crutch where it's super easy to just keep adding more and more data because it can be accessed anywhere it means you don't have to set up a really nice data flow between your code and because that because it's easy like that and convenient there's a temptation to just keep building it and throwing things in there that shouldn't be in there and it can lead to a lot of weird bugs and hard to follow code because you're just every script in your game is basically just accessing and changing these global values and it's it's kind of a mess it's not what you want to do that said though there are tons of really useful and important things you can do with global scripts with with singletons with autoload scripts and godot and so i do want to use them and one thing i do in a lot of games is create a types global script that types auto load and all it contains is enums and maybe some functions to get like you know the string names of imnums etc stuff that doesn't store any data but it provides types that any script in our code can use without having to worry about cyclical dependencies because our autoload scripts never pull any types in themselves so if that didn't make any sense don't worry we're going to go through all of that in just a second here and so i'll show you how to make an autoload script so what we want to do is come to our file system and i'm going to make a new folder and i'm going to call this globals the reason i do this is because it's immediately clear that any script within this globals folder is auto loaded into my game so i only put scripts in here that become an auto load so we'll call it globals this is another reason we did our refactor of our file system because now we've got this pattern that's easy to follow so i'll right click on globals and i'll hit new script and i'm just going to call this types because it's a script that's going to contain our types our enums that we can pull in across many places and if you're kind of catching a width of a typescript in here uh that would be because i do love typescript it is my preferred language and so it's hard for me not to pull some some typescript ways into into my code anyway so we've got this typescript right if i come in here you'll see it's got all these things we want to create an enum here right and i'm going to say enum item types now if you're not familiar with enums again it's really just a dictionary of static values so we give the enumerate name then we use brackets and then we basically just give a list of values and you want to make these capitalized because these are constant values they do not change and so this is where we're going to have all of our item types like a key or a potion or whatever other item you want to have in your game you can customize as necessary for us right now for this video just for our first item we only want a key so we're gonna write capital key and that's all we have to do and what this is gonna be set to under the hood is the value zero so it's like item types of zero is key if we added another it'd be one two three etcetera so by default by default godot assigns integer values starting at zero to an enum and this is helpful because it means that whenever we get itemtypes.key we're really just passing an integer around so it's a nice way that it's compatible with the rest of your code and now so we've got our item types here right but we need to actually make it in auto load so it's accessible to the rest of our project in order to do that i'm going to come up to our project setting or our project button up here hit project settings and then auto load and here i just need to find the path of the script that i want to turn into an auto load so i'll hit this button here at the little file button and you'll see i'm already in res globals and then types.gd so if i hit open and then hit add all of a sudden i've got a new all loads auto load script excuse me with the name of types this is the path to it and it's it is enabled to be a singleton with auto loads in godot they don't have to be singletons so you could theoretically from code instance multiple of them generally you don't really want to do that i'm not sure at least i can't think of a case where you wouldn't want it to be a singleton but we do want it to be a singleton in this and so now we've got it so if i close this and save it all of a sudden our types.gd script will be accessible anywhere in our game because godot will realize that every time our game starts it's going to add a no a node to the top of our scene tree to the root with this types script attached and we can access that from any other script in our game so to see that in action now we can come to our item.gd file and here we can actually change this exported value not just to be an integer but if i start typing types watch this you'll see how it auto-completes it's because godot realizes this is an autoload so we can use this for completion so i hit types and now watch if i hit the dot here we'll start getting options of what we can use and there's a ton of stuff on here so i'm not going to go through this but if i start typing item types which is the name of our the enum we created you'll see that also pops up and so godot has this really cool functionality this or this really cool feature where you can use an enum as an export variable type and it'll only let you choose from the editor the values that are actually part of that enum which is exactly what we want we only want our items to be an actual item type so rather than sending it to be any integer we can limit it only to the values that are part of our item types enum okay and remember how i said that enums are really just integers under the hood well that's why we can still set this variable to be negative one by default but now we can actually change this to be types.itemtypes.key and you'll see we get autumn completion the whole way and so we're just setting our item type to be a key by default you know you could add like a null or undefined item type too if you wanted a better default but that was a lot i hope it makes sense i hope you're kind of starting to see why auto loads are helpful so we've created this nice types file where we can add any enums or other types that we want in our game and be able to pull them in again there's no data access here we're not manipulating or modifying anything we're just creating data or structural types basically that we can use across our game and we're going to use that to limit the options of item types that we have to the actual item types that we want to deal with okay so let's actually start adding items to our game one thing we're going to want to do is add a line under extends we'll do class name item and i'll show you why we're doing this it's so that we can actually create item resources now by giving it this class name we've identified it to godot as a named custom resource and so what i can do is if i come to our items folder i can right click on it and you'll see there's a new resource button in godot now we didn't use this for our exits or other resources because we were creating them strictly via code and i think ultimately at least for now for this tutorial that's how we'll create our items but i want to show you how you can create and modify resources that you custom make from the editor so if i hit new resource you'll see we've got a ton of items here but if i type in item we'll see there's item.gd there's a lot of other things called item or that have item in it canvas item material etc but you'll notice that now that we've given our item script a class name there is this item custom resource we can create and so if i hit create here i can say let's just say key item we give it a better name than i do now godot also lets you define a custom icon which is what you would see here instead of this little folded page button but now if i double click on item remember this is not a node in our scene so we can't click around and find it that way but if i click double click on this resource this key item resource in our items folder you'll see that all of a sudden on the right side in our inspector we um we get these values here so we can actually edit it from our inspector and here's the really cool thing watch what happens if i change this to be a key so i change our item name to be that and we could change our item type we only have one value in our enum but look how it's re it's a bulleted list it's restricting us to the values in that enum now if i click on something else and come away from this notice i save too but if i click on something else and you know we change inspector if i double click our key item again the values stay because like i said godot serializes resources by default so if you edit a resource in your file system from the editor like we just did and save it godot will save that to disk and so you can edit your items from within godot itself which is super super cool and i'm not saying this is the best way to do items like if you've got a complex rpg it's still probably going to be easier to have some sort of a spreadsheet that gets loaded in and manually converted to items you know you'll have to find a system that works for you but for our game a simple text adventure and for a lot of use cases being able to edit items or being able to edit resources within the godot editor and to have them automatically serialize is a huge huge boost okay so that's really cool that's why i wanted to show you that and that's why we made our item let me open our item script that's why we made these export variables so that if we do want to create items via the editor via our file system we can edit them too from the editor we'll keep these as export variables because it doesn't matter if they are not but i think what i'm going to do is delete our key item resource here and i'm actually going to add our items via code which is how we're doing it for our exits which are also resources and the reason i want to do that at least for now is not because it's necessarily better you know you can do either way but i think just because we're handling all of the initialization of our rooms um and our exits within our room manager i wanna also do our items here so we've got one place where we know we're setting up our game state and i think this will be it'll be a little bit more clear why i want to do this when we have a bunch of rooms which i'm hoping in the next couple videos we can actually take some time to create new rooms we've been doing so much functionality that we've only got two rooms right now so i hope on your own you've been extending the game a little bit because it's kind of boring right now but um yeah i think i want to create our items within our room manager just to keep things consistent again i wanted to show how you can create resources within the editor so that you can pick which way works best for you but we'll do the code for now okay now so to add items if we go to our room script you'll notice that when we add exits because we gave our exits a class name we don't actually have to use preload or load or anything godot is able to pick up what an exit is it's able to pick up that it's resource and we can just say exit.new here and so we're going to actually be able to do the same thing for items because we have given a class name to our items so what we actually need to do is add a new function to our room and i'm going to call this add item so i'll say function add item and what this is going to take is an item and we can type this as an item because we know that that is a class name we've defined and so what we can do is call this add item function both at the beginning when we're setting up our game and creating items and theoretically later down the road if a player drops an item for example we can call this same add item function to add that item to our room now before we can finish this we actually need to create some kind of an array or dictionary whatever to store our items because now our room doesn't have a way to store items for our exits we use the dictionary and that's because we wanted to have pretty explicit directional names associated with it but for our items the items will have names themselves we don't actually need to associate an item name in the dictionary or anything so we can actually just use an array and we might change it later on but for now i think having an items array is totally fine and so what i'll do is just type pass in our add item function for now and then under our variable exits i'm going to say variable items and this is going to be an array again i don't have to explicitly type that but i will and this is going to be an empty array and what we can do in add item now is say items dot add or append sorry item and that's all it's going to do it's just going to append this item to our array okay so now we have an items array and the ability to add items now you'll notice that this add item function the way we've defined it requires an existing item we're not passing in you know a name and a type and then constructing the item but we are just passing in an existing item so that means our room manager right now is going to be responsible for creating those items which is fine we can again change this later on but just a bit of an explanation why we won't create our items in the function itself like we did here it'll let us use the same add item function again while our game is running as well if the player in the future we add a drop command or something so we can go back to our room manager now and this is where we'll actually be able to start adding items to our game okay so let's add a key item and right now i think all we're going to do is have eventually we'll lock the door from our house to the outside and we'll have to use this key so we'll make a key so you'll have to do it to unlock it in this video we're only going to get to actually creating the item and then i think the next video will probably do player inventory so you can pick up the key and then after that we'll get to unlocking rooms but unlocking rooms is going to be really easy to do so it should be a pretty short video but in this video let's just focus on creating our key so what i can do is say variable key and i can say item and you'll notice it'll pick it up and i can do new and we're just going to create a new item and now right now as it stands we have to manually edit our our item properties so i have to do key dot you know item name and you see both of its properties here um let's kind of follow a pattern we've done before and add a function to our item that lets you set these these things from the get go okay and so you already know where this is going we'll say function initialize and here we're going to say item name underscore this will be a string and we'll say item type now when i try and give our item type here a type a parameter type notice if i start typing types dot item types oops sorry item types and actually make this our function and hit pass here you'll notice we get an error saying the identifier item types is not a valid type so here's one downfall of using enums and godot right now which i think is going to be fixing godot 4. here's hoping please please god but you can't use custom enums you can't use ty or enums as custom types and so what we have to do is actually change this our item type to be an integer so this is a big bummer because we can't limit you know the uh what's coming into an as an item type to a specific set of integers we have to open it up to any type of integer but we can just assume that whenever we're calling this function hopefully that we're going to be passing in an integer that falls into our item types enum that we've defined so this will be change eventually in good04 but right now we have to just set whenever you want to pass in an enum value you're just setting this to be of type integer unfortunately but that's totally fine and so now we've got this initialize function and we need to do self.itemname and again if you're not familiar with self the reason we have to do this is because we're calling item name our parameter the same as our item name field and so if you don't include this self it's going to try and change the parameter value which is not what we want so we want to say item name equals item name the parameter parameters always take precedence over fields or properties and so if you have a parameter the same name as a field or a property whenever you use that name without the self keyword it will always refer to a parameter within the scope of a function so we're saying self.itemname equals itemname and then we can say self.itemtype because again remember itemtype is the same name for the parameter and our property up here self.item type equals item type and just like that all of a sudden we have this initialize function that we can use from our room manager to kind of initialize an item stats once we create it so again this isn't maybe the way we want to do all of our items but it is a way we can at least do it for now so we can say var key equals item.new like we already have so we're going to create a new item and now we can see key dot initialize and here we can pass in a key uh yeah i don't know i guess we can make more creative names for this later you might have multiple keys but for now we'll just have one key and then remember the second parameter is the item type and so what we can do is types item types dot key now it's already going to be set to key because that's our default for now but we just want to be explicit about setting what it is okay cool so now we have items that are being created now we need to actually add it to our game so let's put this in our house room so you know you can organize this function however you want i'm probably going to do all the things for one room at a time so we'll connect the exits for the house room and then add the items so remember that we did a we um had an ad item function which you'll see in our autocomplete here and here all we need to do is pass our item in which is key so now we are creating a key and we're adding it to our room now there's one last thing we want to tackle in this video and that is there's a key that is in this room but the player has no idea that it's there we're not displaying any text that would hint to the player that there's a key there but what we really want to do is provide some text or something that can indicate to the player that there is an item in this room okay so if we go to our command processor you'll remember it's within our change room function where we're actually building up the strings that we display to the user and what i want to do is actually take this exit string and the strings array that we're doing and move these to our room class our room script and actually have functions that return these here so now our command process won't be responsible for building any of these strings it'll just get them from the room so what i'm going to do is copy our line 48 through 52 the exit string and strings variables that we have i'm just going to copy them i'll keep them here for now but come to back to our room and what i'm going to do is create a new function i'll add mine after add item but you can put ever and i'm just going to say function get full description here and what this is going to do is it's going to return a string okay and so i'm just going to paste in the code that we had previously and i'm going to return a full description here which i'll make is a new variable so variable full description okay so what we need to do is build up this string array and then also add our items to it so we want the player to be able to see what items we have now i'm gonna we need to rename this a little bit because we don't need this new room variable anymore that our command processor had we're just looking at our current room so room name room description just get rid of all the new rooms okay so we're going to modify this function so that we just return a string we do all of the building up of the string array within our room script so in order to do that i'm going to kind of take what we have here on line 29 where we were building up our strings variable and make that our full description so i'm gonna just copy and paste this or i'll do command x and just set it equal to our full description i'll just copy it in there get rid of strings here because we don't need that variable and now all of a sudden we've got this full description so we're just returning this here what i want to do though is break have this one big function here that will return all this into one string but i also want to have individual functions that will do each of these lines on its own so for example i'll add a new one function get exit description i don't know if description is the right word here but we'll use it for now and so what i'm going to do here is just copy this exit string that we're making get rid of that and copy this into this new function and i'm actually just going to return what we're doing here so return this join pool string array and now for exits instead what i'm going to do an in get full description so in this function instead of using this exit string i'm just going to say get exit description um and so maybe what we actually want to do here is drag out our exits and move this down below so we're just returning our get exit description let me grab this string right here and i'll copy this so all we're going to return is get exit description and then what i'm going to do is concatenate that with this pool string array that gets joined and then we can do the same thing with our room description itself so this our room name and room description so i can make another function called function get room description and i know this is kind of confusing saying get room description and get full description that doesn't really make sense so we'll rename this in a second but what i'm going to do is just again command x this line or cut and paste it down here and get rid of that the comma at the end and i'm just going to return this string there we go and now what i can do within our get full description within the full description array here i can just say get room description and the reason i want to do this the reason we're refactoring here is so that if at any point we need to just get this line in and of itself like just get the room description or just get the exits or just get the items for example the player can just do that and it'll make it really easy going forward and we're still able to join them together in this nice full description array here so now what we want to do now that we have the room and exit description is add one for items as well so what i'm going to do is add a new function i'll put it in between the two because i think we want items to come before exits you can change the order as needed i'll say get item description this will be the exact same format we've done so far which will just return a string here and we're just going to return similar to our exits we'll say items colon and a space and then oh whoops okay and then we'll do we'll concatenate a new pool string array pool string array and here we will go through items and just kind of add them all into are into this pool string array now there are better ways to do this than this for example you might not just want to say items a key a potion etc you might want to make it more subtle or make it like you know in a lot of the old text adventure games you'll have text like something shiny in the corner like you're not sure what it is and you're kind of making the player do some of the work to guess or figure out what items are available so you can refactor this as needed maybe you add a hidden description to an item so when the item is not in the inventory of the player it uses the hidden description which is a little cryptic so for example you could add that you know you can do all kinds of customization to this if you want but for now just for the sake of getting this tutorial done we are just going to explicitly say here are the items you can pick up in this room and i think that's okay for now and so to actually start adding our items to this array and actually i don't even think we'll need a pool string array come back to that first what we want to do is make sure that we actually have items in this room so we can say if items dot size equals zero so if there's no items we can just return no items to pick up you can make that text whatever you want i'll just do something simple and then we can do is say variable item string we'll make this an empty string and we're just going to concatenate all of our item names and add them to this string we'll just build it up so this is why we want to actually need an array and just to be sure if we go back to the item script or remember that item name is the name of the item that's the variable that we want to get so if i come back to our room here what we're going to do is just do a for loop we'll do 4 item in items and again we're sure that we have items in here now because our items.size is greater than zero and we'll just say item string and we'll do plus equal so we'll concatenate item item name so we're gonna add all the names and then we'll also add a space in here just so that they're spaced out and then we don't even need this pool string array anymore we can juice items and then plus or concatenate item string just like that and all of a sudden we've got this get item description function and i can add this up here to our get full description so say get item description just like that add a little comma there and all of a sudden we've got this really nice get full description function that's going to get all this together for us and just return this full description at the same time we can get the individual items and exits and whatever if we need to so now that we have this get full description function we can come back to our command processor and instead of doing exit string and strings all we need to do is actually just return new room dot get full description and it's gonna handle all of it for us and you see how much nicer this is now that we've moved all of the building of these strings and handling of it to our room itself so our command processor is only responsible now for processing commands and it's our room itself that's getting all the descriptions and handling keeping track of which items and exits it has so this is a really nice change that's going to clean up our command processor a bit we've still got a fair amount of exit and working with rooms in our go command that's fine we might get to changing some of that later but i think for now we've already done a good job of making this better and now we can start to see when we go to certain rooms we should be able to see whether there's items so now if i run our game we should see all of a sudden look look at that we've got the same description we had before you're in the house random house etc and look at that we've now got an items line here which says that there's a key there and if i go east we'll see no items to pick up which is exactly what we want and so we've got this really awesome easy to implement item system now if i go back west we'll see our key is still there now we didn't actually do the take command so it won't be recognized and i think i'll save that for the next video but we have our item system in place now we're ready to implement player inventory and then after that actually get to locking and unlocking doors thanks so much for watching everyone i really appreciate it and hope you've enjoyed this video if you have a like and subscribe to help support the channel are always appreciated we'd love to have you in the discord server the link to that is in the description below and if you do find my work helpful donating me a coffee on buy me a coffee helps me to continue making great videos link to that also in the description thanks so much for watching see you in the next video
Info
Channel: jmbiv
Views: 1,022
Rating: undefined out of 5
Keywords: godot, godot engine, godot 3.2, godot tutorial, godot 2d, how to make a game in godot, game development, godot for beginners, game dev, how to godot, godot game engine, godot text adventure, godot text adventure tutorial, godot text, godot input, godot user interface, godot control node, first godot game, godot beginner tutorial, godot resources, godot resource tutorial, gdscript, godot items, godot autoload, godot singleton, godot beginner tutorial 2d, gamedev
Id: YyIpug_xD1E
Channel Id: undefined
Length: 33min 37sec (2017 seconds)
Published: Mon Apr 19 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.