The GameMaker Language (GML) also permits you to access certain
Data Structures
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
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:
list_index[| index]
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;
repeat(10)
{
ds[| index++] = irandom(9);
}
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. 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, as well as initialise all the positions in the list up to the given index as 0.
The syntax for maps is:
map_index[? key]
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";
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:
value = ds[? "Name"];
The above will get the value from the key "Name" and store it in a variable. 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.
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();
ds_grid_clear(ds, 0);
var gw = ds_grid_width(ds) - 1;
var gh = ds_grid_height(ds) - 1;
repeat(10)
{
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).
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]
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[99] = 0;
scr_Array_Populate(array);
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.