Using Buffers In Game Maker Studio 2

After the 2.3 update launched for Game Maker Studio 2, I was very excited to get started with the new functionality given to the overhauled script system, however before that I needed to implement saving and loading into Lunar Void.

Initially I had game maker write to an ini file, using some very basic code, but I was unhappy with its performance and wanted more control over my saving and loading, with the help of some friendly developers I was able to understand and implement it into Lunar Void.

Lets start off with explaining what buffers are and what they do:

Buffers are (in the case of GMS2) a space on the systems memory (RAM) that can store packet data, which can be basically anything so in this case we used it to save some variables to a save file. There are quite a few different types of buffers so lets go over them;

  • buffer_fixed
  • buffer_grow
  • buffer_wrap
  • buffer_fast

So the four types available to us are pretty easy to distinguish from one another, buffer_fixed is a buffer with a fixed size, that can not be changed once the buffer is created,

buffer_grow is the same as a fixed buffer, but the buffer will automatically grow its size to a larger one to accommodate the extra data. buffer_wrap “wraps” the data so that new data will overwrite the oldest data once the buffer begins to reach its capacity.

Finally we have buffer_fast and as the name suggestions this is the fastest buffer, but it comes with some limitations. Mostly that it can only be used with the “buffer_u8” (You can consult the GMS2 user manual by pressing F1 in the program, or by clicking on the blue link above).

In the case of Lunar Void I needed a way for the device to remember if the player had disabled the audio in the game or not. This is dictated by a single variable (global.music) which can be either in an on or off state. The code used to achieve this was kindly explained to me, and I will break it down further below. First we’ll cover saving.

Saving

function scr_savegame(){
buffer = buffer_create(1024,buffer_grow,1)

buffer_write( buffer, buffer_bool, global.music);

buffer_save( buffer, working_directory + "/lunarsav.dat")
buffer_delete(buffer)
}

Ok so a few things to note about the code above, firstly, I did not need to define this buffer as a buffer_grow but I do know there will be more variables being saved as time goes on developing the project, so I allowed myself room for error. Secondly is that the buffer I used is a buffer_bool because the music is a True/False or Yes/No statement, it can only ever be on or off. For saving other things you will have to use different buffers, stick around at the end and we’ll go over the most common ones, or refer above to the GMS2 documentation.

How does this work? Firstly the function is defined in the script, I called mine scr_savegame. Then we create the buffer, as stated it’s a grow type. We are allocating 1kb of space for now. Next we write to a buffer using buffer_write and then choose where and what to write. In this case we are writing to our buffer we defined in the second line, it’s a bool because its a True/False statement and the variable I want to save the value of is global.music. Next we save the buffer using buffer_save and again, our defined buffer, and then we tell it what to call our save file. This code will save your buffer in the working directory under the project name then call the file lunarsav.dat. I can confirm this is working on both Windows and Android versions.

Last but not least we delete our buffer, this is very important and should never be forgotten or you can create crashes and memory leaks in your game.

Loading

Moving onto loading next, this will be much quicker as its basically the same script but in reverse. One important note is to load the buffers in the exact same order you saved them. So if they first thing you save is the players name, the first thing you load is the players name, and so on.

function scr_loadgame(){
buffer = buffer_load(working_directory + "/lunarsav.dat");

global.music = buffer_read( buffer, buffer_bool);

buffer_delete( buffer);
}

So first we name the function, in this case its scr_loadgame, then we point our buffer to our save file. Afterwards we begin loading all the variables again, so we make global.music = “Whatever is stored on this buffer_bool” and as long as you load the variables in the correct order it will adjust all the variables, as if you were loading your game. Finally, it’s incredibly important to delete your buffer, even after loading.

When To Call

Having the scripts is one thing, but you should know how to call the the functions. You place your scr_savegame whenever you want to save your game, and the same for loading, however if you have any preferences or settings saved then those have to be loaded at the start of the game, however it can cause errors if the variables have not been initialised yet, to get round this we suggest placing an object in the first room of the game called whatever you like, and in its Game Start event you first define all your defaults, in my case it looks like this;

global.music = 1
scr_loadgame();

All this code does is set the music to its on state when the game begins, then it runs the loadgame script, which in turn will check if a save file exists, and if it does, it will update the global variable to be set to the players saved settings.

More Buffer Types & Tips

Finally there a few hints and tricks I was taught I’d love to share, but before that let me quickly show a table with the most useful buffers. I still advice checking out the documentation though!

buffer_S8This can be a value from -128 to 127 (0 is classed as positive).
buffer_s16This can be a value from -32,768 to 32,767
buffer_s32This can be a value from -2,147,483,648 to 2,147,483,647
buffer_boolA boolean value. Can only be either 1 or 0
buffer_stringThis can store a gml string, use it to save names and text.

Some other notes I have are on creating a delete save file script (For allowing players to manually delete their saved data). The code is very simple;

function scr_deletesave(){
if (file_exists (working_directory + "/lunarsav.dat")){
file_delete(global.save_fname)
game_restart()
 }
}

This code simply looks for our file and deletes it, it then restarts the game to reinitialise all the variables. This handy if you want to give players the option to restart, clear save files or just generally good practise to have the option there even if just for debugging.

Next up I want to quickly touch on how this code was shown to me, to try and make it more comprehensive I excluded the variable that controlled the file name, in this is post I wrote the entire name out for each script, and would have to go in and edit them for each project. In your projects I advise to create a variable (which is loaded first in your game start) like such

global.save_fname = working_directory + "/lunarsav.dat"

Now you have your global save file name, replace the directory in the previous code with global.save_fname and you can use these scripts in all your projects by simply setting the global.save_fname to be called whatever you wish.