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.
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.