The GameMaker Language (GML) also permits you to access certain
Structures and Buffers through the use
of logical expressions called accessors. This is done in a
similar way as you would for working with arrays only we use an identifier symbol before
the first argument to tell GameMaker Studio 2 that you are
working on a (previously created) data structure.
You can add, replace and get values and keys for the following data structure types: ds_maps, ds_lists, and ds_grids. Each one has been given its own symbol and method for accessing, changing or setting values, as shown below.
The syntax for lists is:
So when you have used ds_list_create() to create your list, you would use the list index (that you have stored in a variable) to reference it, with the "index" value being the position in the list to set or add. For example, the following code creates a list and then adds 10 entries, setting each entry to random number from 0 to 9:
ds = ds_list_create();
var index = 0;
ds[| index++] = irandom(9);
Note that if you are using an expression to add a reference to an index that already has a value, the previous value will be replaced rather than have a further index added to the list. To add further entries you would need to know the ds_list size and add them to the end. It is also worth noting that you can set a list index that is greater than the size of the list being referenced, and this will set that value, expanding the list at the same time and initialising all the positions in the list up to the given index as 0.
Once you have created your list structure and filled it with data, to get values from the list you would have something like:
value = ds[| 5];
The above will get the value from position 5 (the sixth index, since lists start at 0) and store it in a variable. If you supply a position that is outside of the list size then the value undefined will be returned, which you can check for using the function is_undefined().
The syntax for maps is:
After creating your map with ds_map_create(), you would use the map index that you have stored in a variable to reference it, with the "key" value being the map key to set or get. For example, the following code creates a map and then adds a few entries to it using this syntax:
ds = ds_map_create();
ds[? "Name"] = "Hamish";
ds[? "Company"] = "MacSeweeny Games";
ds[? "Game"] = "Catch The Haggis";
Note that if the map already contains the same key value as you are trying to add, it will not create a duplicate key with the new value, but rather the previous value will be replaced.
Once you have created your map structure and filled it with data, to get values from a specific map key you would have something like this:
value = ds[? "Name"];
The above will get the value from the key "Name" and store it in a variable, but be aware that if the given key does not exist in the DS map, then the value returned will be undefined. This can be checked for using the function is_undefined().
The syntax for grids is:
grid_index[# xpos, ypos]
After creating your grid with the ds_grid_create() function, you would use the grid index that you have stored in a variable to reference it, with the "xpos" and "ypos" being the position within the grid to get or set a value. For example, the following code creates a grid, clears it to 0, then and then adds a few entries to it:
ds = ds_grid_create();
var gw = ds_grid_width(ds) - 1;
var gh = ds_grid_height(ds) - 1;
var xx = irandom(gw);
var yy = irandom(gh);
if ds[# xx, yy] == 0 ds[# xx, yy] = 1;
Once you have created your grid structure and filled it with data, to get values from a specific grid position you would have something like:
value = ds[# mouse_x div 16, mouse_y div 16];
The above will get the value from the given ds_grid based on the mouse position (divided by the "cell" width in the room to get the correct location). If you supply a position that is outside of the grid boundaries then the value undefined will be returned, which you can check for using the function is_undefined().
Arrays also have their own accessors which works in a similar way as those listed above for data structures. however array accessors have an interesting property and that is to permit you to modify an array from a script without having to copy it. When you pass an array into a script, it is passed by reference, meaning that the array itself isn't being copied into the script but rather it is simply being referenced to get the data. Normally if you then need to change the array, it would be copied to the script and then you would need to pass back the copied array for the original array to be updated. This can have costly processing overheads, and you can use the accessor instead, as that will change the original array directly without the need for it to be copied. You can see how this works in the examples below.
The syntax for arrays is:
array[@ xpos, ypos]
After you have created your array in an instance, you can then
pass it to a script by reference and use the accessor @ to
change it directly. For example you would create the array and call
the script like this:
array = 0;
The script itself would have something like this:
var a = argument0; var i = 0; repeat(25)
i = irandom(99);
while (a[i] != 0)
i = irandom(99);
a[@ i] = 100;
All this script is doing is selecting 25 random positions in the array and setting the value of the chosen array position to 100.