Buffer Examples

This page has two examples of using buffers to help understand how to use them.

Making Checkpoints With A Buffer

A simple example of how a buffer can be used in any GameMaker: Studio game for any platform, is the function game_save_buffer. This function will take a "snapshot" of the current game state and save it to a pre-defined buffer, which can then be read from to load the game at that point again.

NOTE: This function is very limited and it is designed for the beginner to get a checkpoint system up and running quickly, but more advanced users may prefer to code their own system using the File functions, due to the fact that the game will not save any of the dynamic resources that you can create at run-time like data structures, surfaces, added backgrounds and sprites etc...

The first thing we need to do is create a new object to control the saving and loading, so you would make one and give it a Create Event. In this event, you could place the following code:

SaveBuffer = buffer_create(1024, buffer_grow, 1);
StateSaved = false;

The first line creates a grow buffer (since we don't know the final size of the saved data) of 1024 bytes and aligned to 1 byte. A variable is then created to check against and see if the game has been saved or not (this will be used for loading).

Next we would add a Keypress Event (for example) in which we will save the current game state to the created buffer:

StateSaved = true;
buffer_seek(SaveBuffer, buffer_seek_start, 0);
game_save_buffer(SaveBuffer);

The above will first set the control variable to true (so that this is saved when we save the game to the buffer) and then seek to the start of the buffer before writing the current save state into it. Why do we use buffer_seek? Well, as mentioned on the Using Buffers page, you read and write to a buffer from the last position that data was added to. This means that if you don't set the buffer tell back to the start then when you save you will be adding the data into the buffer at the current buffer read/write position, so we use the function buffer_seek to move the tell to the buffer start.

We have now saved the current game state to a buffer. The next step would be to code how to load it, probably in another Keypress Event:

if StateSaved
   {
   buffer_seek(SaveBuffer, buffer_seek_start, 0);
   game_load_buffer(SaveBuffer);
   }

The game will then be loaded at the end of the event in which you place the above code.

NOTE: This is only for use in the same room, and not for generating complete saved games for after your game has been closed or restarted!

The final thing to add to the controller object is a "clean up" code. Buffers are stored in memory and as such if you do not clean up when you are finished with them, you can get memory leaks that will eventually lag and crash your game. So you would probably add a Room End Event (from the Other event category) with:

buffer_delete(SaveBuffer);

This object can now be placed into a room and on a key press save and load the room state from a buffer.

Networking Buffers

When working with the GameMaker: Studio networking functions, you have to use buffers to create the datapacket that is being sent over the network connection. This example intends to show how this is done, but due to the scope of the networking possibilities, it is only designed to show how to use the buffers themselves, and not the full networking system (there is a Demo file included with GameMaker: Studio that shows this).

The first thing we will show is the creation and use of a buffer for the client side of the network connection. This buffer will be used to create small data packets that can then be sent to the server, so in the Create Event of an instance we would assign a buffer like this:

send_buff = buffer_create(256, buffer_grow, 1);

We make the buffer small (256bytes) as it is not intended for holding large amounts of data, we make it a grow buffer to ensure no errors should we need to add more data to be sent at any time, and the alignment is set to one for convenience.

Now, let's say that we want our client to send data to the server. For that we need to create a buffer "packet", and in this example we are going to send a Key Press Event, like when the player presses Left Arrow to move around the game. To do this we write the necessary data to the buffer first then send it off:

buffer_seek(buff, buffer_seek_start, 0);
buffer_write(buff, buffer_u8, 1);
buffer_write(buff, buffer_s16, vk_left);
buffer_write(buff, buffer_bool, true);
network_send_packet(client, buff, buffer_tell(buff));

Before writing to the buffer we have set the "tell" to the start of the buffer as networking always takes the data from the start of a buffer. We then write the check value (this will be used by the server to determine the type of event to be processed), then the key being used, and then the state of the key (in this case true for pressed). This buffer is then sent as a data packet by the network function. Note that we do not send the whole buffer! We only send the data written, using the buffer_tell function to return the current read/write position of the buffer (remember that writing to the buffer moves the "tell" to the end of what has been written).

What about receiving the data on the server? The received data packet that must be written into the buffer on the server and then used to update the game. For that we would use the Networking Asynchronous Event in the network controller object of the server, as this simplified code below shows:

var buff = ds_map_find_value(async_load, "buffer");
if cmd == buffer_read(buff, buffer_u8);
   {
   key = buffer_read(buff, buffer_s16 );
   key_state = buffer_read(buff, buffer_bool);
   }

The asynchronous event will contain a special temporary ds_map (it is removed at the end of the event automatically) which contains different information depending on the type of incoming data from the network. In this case, we are assuming that the map has been checked and found to be a buffer data packet sent from a client. We now check the first piece of data that is in the buffer to see what kind of event has been sent - in this case the value "1" represents a key event, however when coding these things you should define constants to hold these values to simplify things - and then store the key being pressed and its state (true = pressed, false = released). This information would then be used to update all the clients with the new status of the sending client player.

NOTE: The buffer that is created from the ds_map is automatically removed at the end of the Network Asynchronous Event so there is no need to use buffer_delete here.


Back: Buffers
Next: Using Buffers
© Copyright YoYo Games Ltd. 2018 All Rights Reserved