Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more

Tech

Accessors For Data Structures and Arrays

Posted on 24 January 2014

The next update to GameMaker: Studio, Early Access added an interesting extra functionality for some data structures and normal arrays called "Accessors". These accessors are simple logical expressions that permit you to add or change values within the structure, and they are written in a similar way as you would for working with arrays, only we use a special identifier symbol before the first argument to tell GameMaker: Studio that you are working on a (previously created) data structure or with directly with an underlying array. 

You can add, replace and get values and keys for the following data structure types: ds_maps, ds_lists, and ds_grids, and each one has been given its own symbol for accessing, changing or setting values, as shown below. For arrays, this functionality permits you to get direct access to a given array from a script, preventing the standard "copy on write" behaviour that you would normally expect (this is explained at the end of the article).

Also note that the symbols chosen to designate an accessor have been chosen specifically for their mnemonic nature (for example # is the ds_grid identifier) which makes them easier to identify and remember.

ds_list [| ]

The syntax for lists is:

list_index[| index]

So when you have used ds_list_ceate() 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 0:

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.

ds_map [? ]

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.

ds_grid [# ]

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" size in the room to get the correct location). 

Arrays

The normal GameMaker: Studio way of working with arrays is "copy on write", meaning that if you pass an array (for example) into a script, the original array is referenced until you change any of the array values, at which point it is copied. This means that to get the new values you have set, you must return the array from the script and re-assign it to the original array variable. For example:

//CREATE EVENT
a[9] = 0; //initialise a 10 value array 

//CALL A SCRIPT WITH THE ARRAY
a = scr_Set_Array(a);

//SCRIPT
var temp_a = argument0;
temp_a[3] = 500;
return temp_a;

However this can be limiting and is also very slow, especially when you have a very large array and it's being copied every time you run the script. However, there is now an accessor for working with arrays too, with the syntax:

array[@ val]; //1D array
array[@ val, val]; //2D array

What this does is write directly to the underlying array, meaning that it is no longer copied into the script itself. Using the example code above as a reference, you would change it to this:

//CREATE EVENT 
a[9] = 0; //initialise an array to have 10 indices, each index assigned the value 0

//CALL A SCRIPT WITH THE ARRAY 
scr_Set_Array(a);

//SCRIPT 
var temp_a = argument0; 
temp_a[@ 3] = 500;

Notice that we now have no need to return the array as it hasn't been copied, but rather you have written the new value directly into the appropriate place in the base array.

Back to Top