GameMaker - Better Saving & Loading (JSON)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody today I'm going to be teaching you how to create a save and load system in gaming studio one or two so as you can see we have the spike box where I can click and play some very interesting things and then I can press s to save and it came up there in the output window game saved I can restart pressing more things and then press Cal to reload our previous game stain okay as a system that involves using JSON to save and load data and it's super scalable and will work very well even with the most complex types of games allows you to save and load a or basically any kind in any structure it's really really useful so there are lots of different ways in game maker to save data you can use text files and any files which is what I've shown in tutorials previously and those do work for very simple games but as some of you might have noticed they can break under the pressure of trying to save much more complex kinds of data so what we're going to be using today is JSON combining des maps and des lists this system is based on a talk by juju Adams which you should definitely go and watch he explains it in way more detail than I'm going to but the basics that you're going to need to know for this video are the JSON files in a game maker context at least can be thought of as an arrangement of dius lists and the S Maps which can be nested and arranged in any way we want more or less we can have lists of maps and maps of lists and lists of maps of lists of maps of maps and basically store and retrieve almost any kind of data structure we could feasibly need this can be used for savegames level editors I used in my recent deck building game for storing info about cards you name it being able to arrange these in any way we want a super powerful because we can create huge nested data structures and save and load those structures in a very small amount of code that's super powerful and super flexible now I'm skimming over a lot of stuff in a lot of details but you should seriously just watched yuju's talk it's not very long it's very clear it goes over all the uses and advantages of this system in a lot of detail I'm just here to show you how to set it up so let's get to it so we have this very exciting game right how are we going to store information about all of these instances how many there are where each one of them is what color each one of them is what Spri each one of them is using how fast they're rotating and so on how do we store all that information about all these instances in a very simple easy to manage way well what we can do is we can take each one of those instances and for it create a DS map that DS map can then contain all of the information about it that we want to store so it's x coordinate swine corn its rotation speed its image index its image blend the name of the object type itself me we've got multiple types of objects and so on and so forth the great thing about this is we can just keep adding and removing these there's an unordered list of elements so we can store anything we want to about this object and we don't have to worry about what all do we store it in around adding and removing things later and someone okay it's really good what we can then do is for each one of these is we store every single one of these DS maps inside an overall DS list okay and then that DS list is what we can save into our JSON and it will store every single one of these DS Maps properly nested inside it that's the awesome power of this system you can go further than this so each one of these maps could then contain further lists and those lists could contain further maps maps can contain more maps and lists can contain more lists and so on which allows you to do all kinds of crazy fun things but as I said what we're going to do for this video is we're going to have every instance stored as a DS map inside a grey add es list so one basic setup for this is pretty straightforward I'm gonna have an object called Oh save and load when we press the S key we're going to do everything we wanted to saving the game and when we press L we're gonna do everything we want for loading the game okay so let's start with saving the game that makes the most sense cuz without saving the game there's nothing to actually load right so the first thing I'm gonna want to do is create that route list that we want okay so create a route list I'm gonna call bar underscore route list equals D s list it creates okay that's gonna be this variable is going to store our list which is going to contain all of our DS maps for all of our instances okay so for every instance create a man that's what we're gonna do I'm gonna do with not a capital Inc with he saved me okay because that's what I've done here if I go to object hierarchy we can see in here I've got a parent object called P save me and the only child that I'll get this oath thing which is what's been creating are cats and dogs that we've been placing throughout the game world okay there you add to it this way is because we could have more different types of objects that we want to save and some ones have both but if we just make them all children of parents save me we can just access them all at once by doing with P save me your system might be more complex than that but hopefully you'll see how this works and you'll see how you can extend and change it to match more or less any cell you can imagine okay but either way with each one of those instances what we're gonna do is create a map for that instance and crawl up bar map equal vs we'll call underscore map we'll just be consistent in calls D s and that creates open bracket close bracket semicolon okay as simple as that for creating IDs mattress to the same as creating a DS lists nothing in it yet what you always have to do as well when you create data structures like these is remember to destroy them when you're done but luckily because we're working with JSON there's something very cool we can do in order to manage all that very automatically at the end and you'll see what that is as we go on before we want to add stuff to this D s map we want to actually add this to the list so I'm going to say D s list and underscore route list and what we're going to add for that list is this very map okay now that hasn't actually added the map to the list in the strictest most technical the census what because this variable doesn't actually contain this list and this variable doesn't actually contain this map what they contain are pointers or ID numbers very similar like instance IDs for example which tell game maker when this ID is referenced where that map lives for example so map underscore map at this point might have the number two and it all something like that and route list might have the number one and or something like that okay they don't actually store the list themselves they just store a reference in game maker to where those deers listen the estimates are so what we need to do for when we actually come to saving out this file and saving as a JSON is we need to actually mark it as mark this map as a DS map within the list so I can write D s list say are operating on IDs list mark has map underscore route list yes us size underscore route less -1 okay what that does is we're going to take the lot the last entry that we just put into the DS list which is just this map okay we're getting that entry with this because we're taking the size of the DS list minus one so I'll give us um whatever the latest entry is so on our first one the first entry will be position zero so that's size of the list which is one at this point we've got one entry minus one zero okay so every time it gets the right one and it takes that element of that list and it marks it as a DF map so that when we save the map we're so sorry when we save this list instead of just saving like the number two or whatever that's referring to where that map is in game maker we actually save all that data that we're going to put in the DES map okay very important this is the only context in which you should use these commands they're not designed for any any other kind of mechanism whether in game maker it's just for when you're saving things as JSON files okay okay so once we've done that and then type bar underscore obj equals object again name object index okay and that's going to literally return the name of the object itself so alvaro thing is going to find a string that literally contains the text oh thing okay so that will be useful when we load it back so we can check that and check to make sure that each object is the object but we want it to be it's a nice thing to be able to store and I type this map add in the score map the key will be the string obj comma and the data will be underscore obj okay so we're going to take that name that string that probably that contains oath thing will only do that in this case because that's the end the object we're saving and it's going to add that to the list under the key obj now we're gonna add some more data about that object okay that's yes map underscore map why my caps lock semicolon okay and that's gonna add our y-coordinate under position Y and again I say it doesn't matter what order you do these in because the DS map is totally unordered copy and paste that and put in X and I'm gonna copy paste this a few more times and just fill in the rest of the data that we're gonna want to store about this object okay so there you have it I'm just going ahead and added the speed which is the speed at which the object is rotating the image index and the image blend of this object okay so here we've stored everything we need to know about every instance of thing to know what objective was what it's excellent y position was what its rotation speed was what as image index wasn't understand which blinds was okay we can go on with this okay we can store we keep adding whatever we want to store about this instance okay and then we can just recover it from load and it doesn't matter what order we do it in or anything like that okay and that's that's everything that's added every instance to this D s list and in the form of um map okay cool stuff now what we need to do before we save this is we actually going to wrap our route D s list inside a DS map with only one entry and one key okay you might be wondering why why are we doing that why don't we just save the route list jaison's don't well the way JSON to interact with game maker they don't seem to like very much starting with a DS list they seem to prefer starting with a DS map so and also doing this allows us to get rid of all the data in a very clean nice way as well so then I say wrap the route list oh and I'm Mac and var underscore rapper an equal DF map create and then D s map add list underscore rapper as the map we're adding to root is the key that we're going to put this in and underscore root from the score list is the name of the DS list itself that we're gonna add okay you'll notice I've not used es map ad here I've used es map ad list and this is very similar to the DS list market map command and that it's actually adding the information in the list to this entry or it's marking it to tell it to actually save when when we save as a JSON to actually save the data in the list and not just the internal GameMaker reference for where the list is okay I don't know why it works slightly differently to the s list because of the dias list you have to add the thing then mark the thing whereas the DS Maps you can just you you can add it and market at the same time with one function I don't know why why there's a difference there but that's just game maker for you but that will do the same thing as that okay so we've created a ramp amount we've added that to it and now all we need to do is actually save all of that okay now I have a script here for doing this and I'll show you it in a second save all of this to a string the first thing we want to do though is do var underscore string I'm gonna work out the string of text that we want to say because that's all it actually gets output as to the JSON file it's just a string of text it's just arranged in such a way I think like square brackets represent a list and curly braces represent abs map when you actually see the data structure but it's all just one long stream and it just gets encoded into a format that's understood as JSON okay so all we need to do is type JSON and code underscore wrapper okay we pass through the map the DES map that we want to encode as it's a only takes TS mapping you can't do it with a list so that's what we need to wrap it and that will turn that into literally just one long text string that contains all of this information okay which is really cool cuz then we just save out that one string very much the same way as we save a save a text file just as we've done before like when we saved a dot txt to save games or dot ini' file and we're just gonna save out this one string and this one string contains all of our data which is awesome we're gonna do that with a script called save string to file and pass through the file name of save game dot south for example and now just made that extension up and the string is underscore strength the one we've just encoded okay so let's take a look at what this this script does okay I'll just leave it on screen here so you can pause and you could write this script in yourself as it stands I'm not gonna go over into much detail but it creates a buffer answer strings buffer and it saves that book to a file I stole this completely from Judy Adams talk it was in his slides and I asked him also afterwards like why did we decide to save the string with a buffer why not why do something that complicated and I'm not gonna explain that in this video you can go look into it another video but this is how it works if you want to use it why do that why not just create a text file and basically the answer was that saving as a buffer is more widely comparable across different platforms and also if you want to use net code because you can send buffer packs over a network whereas saving to text files is a little bit less flexible and it's less useful across different platforms especially consoles like ps4 and so on ok so that's the only reason but this is a really really simple script it's only six lines long that uses a buffer to save any string that you give it to a file that's really useful so go ahead and copy that down and that's what we're gonna use okay so back to our save script we only have to do one more thing now that we've saved all this data and it's been saved to a file we want to get rid of it nuke the data now you might think oh man we've got to go through every one of these des Mattson over and the DSM the list and the wrapper and destroy all of them we've created so many DS Maps how do we take care of all of them actually all we have to do is do D s map destroy and score wrapper and by destroying the wrapper we actually create a cascading effect and destroy all of the lists and maps and all of that data that we've added to it because we've used the DF markers map and because we've used the DSM map ad list functions and mark those as being you know a part of a nested structure by using the S map in this fashion we actually just nuke all of that day at once and we don't have to go through each individual wants to clear it from memory it's very important that you do this as well otherwise you can create memory leaks if you don't get rid of your desk maps but one of the best things about working with JSON in the system is that you can just do this one line and that clears up all the data for you beautiful stuff okay that's our save scripts done actually no I'm gonna do one one tiny thing should I types show debug message game and saved okay so we can see their name per window the bottle that this is all worked okay okay now that's all safe script done let's come over to key press l and get started on our load game script okay so now that we've got all of our data in place and we know how its structured actually loading it back in actually really straightforward so first of all if we're loading in the game let's just get rid of any objects that we already have so I'm gonna do with P save me instance okay I should get rid of all those so soon we're restarting the game and that's all there is in the game start is the same thing right so if file exists savegame dotsub gonna make straw as well dive name that are the same savegame door snap savegame that's happy a cool make sure that's named the same as what how you saved it otherwise obviously won't work bar underscore rapper equals load Jayce load JSON wrong file saved game sad now you won't have this script again you'll have to create a script yourself and here it is I'll leave it on screen for you for a moment you can pause it copy this down I'm just gets the buffering loads loads in that one string just the same and just at the end here we importantly does JSON decode okay so remember when we press key s we needed JSON encode to save to turn that string into JSON format we then take that JSON format that we got back from the file and we decode it so it turns it back into DS map D s list DS maps okay so it brings it back into the data that we can work with in game maker so that's come back to UK SL key press sorry so I learned that and that means once we've done that we've got that string and we've decoded it back into that wrapper so that we've got in this wrapper a DS map the contains in route the route list which contains all of our instance data okay so if i underscore list can equal wrapper open square bracket question mark routes okay now what on earth have I done here okay this is one thing I need to explain by doing this this is what's called an accessor and it's a quick way of getting information out of a data structure so rather than using the S map is it find Ivanova okay finally I don't even know the regular one so rather than doing D s map find value our wrapper root which would also work you could do that does the exist is the exact same thing and takes way less time to write okay I think you just type the name of the DS map open square bracket just like you would with an array question mark and then in a string the name of the key that you're looking to find and that will get the data just the same you can do the same thing with all the types of data structures so for a list actually we're gonna do that in a second so I won't bother demonstrating it but there's different kinds of accesses you can use for different data structures the one for the s maps is a question mark so now that we've got that list that is the same list that we created here root listing s let's create so every entry in that list is one of these ts maps so for VAR i equals 0 I less than es list size underscore list I plus plus ok think I've written that right so variable I staying at 0 and for every entry of the list ok so we're going to go through one by one by one I increasing by one each time if I'm just going map equals underscore list open square bracket and then I don't actually know the name of this symbol but for me on my keyboard it's the one that you get for pressing a shift and backslash I don't actually know the thing of it but it's a straight vertical line okay that's the symbol and that's the access of 4ds lists okay so you want that if you're struggling to find that on your keyboard you can really very simple just those with DSM oh it's just a it's a shortcut so you could just write instead yes list find value underscore list name in the list and position i okay and again that would do exactly the same thing as this is just a quick away alright so either way that map now contains one of our instances okay so the Deus map that represents our instance it's got the object name the speed X Y all that kind of stuff so to get the object name back out for example I can do bar underscore obj equals map question mark in quotation marks obj quotation mark closed square bracket okay again just that simple oh wait sorry underscore map there we go okay so then that gets the object name back out of that map and what we can do is now use that object name to create an instance of that object so what I can do is with instance create layer 0 0 for now we'll move the XY coordinate in a second layer I could do it there but it's you know make the line really long so let's just leave it whatever layer you it's another thing you might want to store you might want to store the layer in there as well and get that back out so you know which layer it needs to go on asset get index underscore obj and close okay so what asset get index does is you take the take the name of the object which is just a string okay pass it into here and then it returns the index oh it's like object to or whatever which is over thing right okay so knows what object to make and it's just made it at 0 0 that's position it correctly so x equals underscore on map nice remark X let's get that data back out and I'm just going to do the exact same thing and get all of my data back out okay there you have it all done so that's all the data back out of the DDS map for this instance and that instance created in the actual game world okay so after we've done all that what we'd want to do is just get rid of that wrapper again yes map destroy underscore wrapper and show debug message game loaded okay you might also want to do like an else down here that handles like show some sort of error message if you can't find the save file etc but I'll leave that up to you okay and just the same again by destroying the wrapper because it's all loaded from the JSON as JSON to code back into this rapper this rapper actually contained the lists and the lists am truly contain those maps so by destroying the overall map that wrapped everything else up you destroy the DS list and you destroy each map before each one of these instances okay and that's absolutely everything so if I run the game now we should be able to place a bunch of on dudes let's get rid of one let's place one over here's specific arrangement press s games saved and then I can just place some more press l we get that same arrangement back or I can restart the game press more press L I can close the game down I can run it again and you know spoiler alert I'm going to press L and we get what we we had before Bank again straight from that file okay there you have it that's saving and loading using JSON super flexible system you can do all sorts of cool stuff with it I hope you enjoyed this one guys I'll catch you guys next time a huge shout out to Julien Adams who's awesome talk is linked in the description and was the basis for this video a huge shout out also as always to my amazing patreon supporters without whom none of these videos would be possible a shout out in particular but in no particular order to mark links Louis R Pereira don't act Ben Dan Chris maja gummy Taemin James grimly mark de Rove and darlin Harold Guidry matte coat disk McTaggart it's Nick's lavish Steven Hagen Michael Ward Jason McMillan Jonathan crispy Robert churches oh and Morgan Zinn unmei boughs of the dog TJ and Patrick goofy thank you all very much for your support
Info
Channel: Shaun Spalding
Views: 40,171
Rating: undefined out of 5
Keywords: Game Maker (Video Game Engine), Tutorial, GameMaker Tutorial, GameMaker, Game Development, Game Maker Studio, GameMaker Studio 2, GMS, GMS2, saved game, save game, load game, saving and loading, saving, loading, json, data
Id: QmxQb1BFQRE
Channel Id: undefined
Length: 25min 49sec (1549 seconds)
Published: Fri Apr 27 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.