<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<script type="text/javascript" language="JavaScript">
//<![CDATA[
function reDo() {
if (innerWidth != origWidth || innerHeight != origHeight)
location.reload();
}
if ((parseInt(navigator.appVersion) == 4) && (navigator.appName == "Netscape")) {
origWidth = innerWidth;
origHeight = innerHeight;
onresize = reDo;
}
onerror = null;
//]]>
</script>
<style type="text/css">/*<![CDATA[*/
< !-- div.WebHelpPopupMenu {
position: absolute;
left: 0px;
top: 0px;
z-index: 4;
visibility: hidden;
}
p.WebHelpNavBar {
text-align: right;
}
-->
/*]]>*/</style>
<script type="text/javascript">//<![CDATA[
gRootRelPath = "../..";
gCommonRootRelPath = "../..";
gTopicId = "9.1.1_7";
//]]></script>
<script type="text/javascript" src="../../template/scripts/rh.min.js"></script>
<script type="text/javascript" src="../../template/scripts/common.min.js"></script>
<script type="text/javascript" src="../../template/scripts/topic.min.js"></script>
<script type="text/javascript" src="../../template/scripts/topicwidgets.min.js"></script>
<script type="text/javascript" src="../../whxdata/projectsettings.js"></script>
<link rel="stylesheet" type="text/css" href="../../template/styles/topic.min.css"/>
<link rel="stylesheet" type="text/css" href="../../template/Charcoal_Grey/topicheader.css"/>
<meta name="topic-status" content="Draft"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Accessors</title>
<meta name="generator" content="Adobe RoboHelp 2019"/>
<link rel="stylesheet" href="../../assets/css/default.css" type="text/css"/>
<meta name="rh-authors" content="Mark Alexander"/>
<meta name="topic-comment" content="Page outlining the different Accessors"/>
<meta name="rh-index-keywords" content="Accessors"/>
<meta name="search-keywords" content="Accessors,@,[| ],[@ ],[# ],[? ],grid accessor,list accessor,map accessor,array accessor"/>
</head>
<body>
<div class="topic-header rh-hide" id="rh-topic-header" onclick="rh._.goToFullLayout()">
<div class="logo">
</div>
<div class="nav">
<div class="title" title="Accessors">
<span>Accessors</span>
</div>
<div class="gotohome" title="Click here to see this page in full context">
<span>Click here to see this page in full context</span>
</div>
</div>
</div>
<div class="topic-header-shadow rh-hide" id="rh-topic-header-shadow"></div>
<!--<div class="body-scroll" style="top: 150px;">-->
<h1>Accessors</h1>
<p>The GameMaker Language (GML) also permits you to access certain <a href="../GML_Reference/Data_Structures/Data_Structures.htm">Data Structures</a> and <a href="Arrays.htm">Arrays</a> through the use of logical expressions called <b>accessors</b>. This
is structured in a similar way as when you are normally working with an array, only we use an <em>identifier symbol</em> before the first argument to tell GameMaker Studio 2 that you are working on a (previously created) data structure or the array
literal.</p>
<p> </p>
<p><a class="dropspot" data-rhwidget="DropSpot" data-target="drop-down10" href="#"><span data-open-text="true">DS Lists [| ]</span><span data-close-text="true">DS Lists [| ]</span></a></p>
<div class="droptext" data-targetname="drop-down10">
<p class="dropspot">The syntax for <a href="../GML_Reference/Data_Structures/DS_Lists/DS_Lists.htm">DS lists</a> is:</p>
<p class="code">list_index[| index]</p>
<p class="dropspot">So when you have used <tt>ds_list_create()</tt> 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:</p>
<p class="code">ds = ds_list_create();<br/> var index = 0;<br/> repeat(10)
<br/> {
<br/> ds[| index++] = irandom(9);<br/> }
</p>
<p class="dropspot">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 <i>greater</i> 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.</p>
<p class="dropspot">Once you have created your list structure and filled it with data, to get values from the list you would have something like:</p>
<p class="code">value = ds[| 5];</p>
<p class="dropspot">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 <tt>undefined</tt> will be returned, which you can check for
using the function <a href="../GML_Reference/Variable_Functions/is_undefined.htm"><tt>is_undefined()</tt></a>.</p>
<p class="dropspot"> </p>
</div>
<p><a class="dropspot" data-rhwidget="DropSpot" data-target="drop-down13" href="#"><span data-open-text="true">DS Maps [? ]</span><span data-close-text="true">DS Maps [? ]</span></a></p>
<div class="droptext" data-targetname="drop-down13">
<p class="dropspot">The syntax for <a href="../GML_Reference/Data_Structures/DS_Maps/DS_Maps.htm">DS maps</a> is:</p>
<p class="code">map_index[? key]</p>
<p class="dropspot">After creating your map with <tt>ds_map_create()</tt>, 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:</p>
<p class="code">ds = ds_map_create();<br/> ds[? "Name"] = "Hamish";<br/> ds[? "Company"] = "MacSeweeny Games";<br/> ds[? "Game"] = "Catch The Haggis";</p>
<p class="dropspot">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.</p>
<p class="dropspot">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:</p>
<p class="code">value = ds[? "Name"];</p>
<p class="dropspot">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 <tt>undefined</tt>. This can be checked for using the function
<a href="../GML_Reference/Variable_Functions/is_undefined.htm"><tt>is_undefined()</tt></a>.</p>
<p class="dropspot"> </p>
</div>
<p><a class="dropspot" data-rhwidget="DropSpot" data-target="drop-down14" href="#"><span data-open-text="true">DS Grids [# ]</span><span data-close-text="true">DS Grids [# ]</span></a></p>
<div class="droptext" data-targetname="drop-down14">
<p class="dropspot">The syntax for <a href="../GML_Reference/Data_Structures/DS_Grids/DS_Grids.htm">DS grid</a> is:</p>
<p class="code">grid_index[# xpos, ypos]</p>
<p class="dropspot">After creating your grid with the <tt>ds_grid_create()</tt> 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:</p>
<p class="code">ds = ds_grid_create();<br/> ds_grid_clear(ds, 0);<br/> var gw = ds_grid_width(ds) - 1;<br/> var gh = ds_grid_height(ds) - 1;<br/> repeat(10)
<br/> {
<br/> var xx = irandom(gw);<br/> var yy = irandom(gh);<br/> if (ds[# xx, yy] == 0)<br/> {
<br/> ds[# xx, yy] = 1;<br/> }
<br/> }
</p>
<p class="dropspot">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:</p>
<p class="code">value = ds[# mouse_x div 16, mouse_y div 16];</p>
<p class="dropspot">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 <tt>undefined</tt> will be returned, which you can check for using the function <a href="../GML_Reference/Variable_Functions/is_undefined.htm"><tt>is_undefined()</tt></a>.</p>
<p class="dropspot"> </p>
</div>
<p><a class="dropspot" data-rhwidget="DropSpot" data-target="drop-down15" href="#"><span data-open-text="true">Arrays [@ ]</span><span data-close-text="true">Arrays [@ ]</span></a></p>
<div class="droptext" data-targetname="drop-down15">
<p class="dropspot">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 <a href="Script_Functions.htm">script function</a> or <a href="Method_Variables.htm">method</a> without having to copy it. When you pass an array into a function, it is <strong>passed by reference</strong>, meaning that the array itself isn't being given 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 <em>copied </em>to the script and then you would need to pass back (return) the copied array for the original array to be updated. This can have costly
processing overheads, and so you can use the accessor instead, as that will change the original array <em>directly </em>without the need for it to be copied. You can see how this works in the examples below.</p>
<p class="dropspot">The syntax for arrays is:</p>
<p class="code">array[@ xpos]</p>
<p class="dropspot">After you have created your array in an instance, you can then pass it to a script by reference and use the accessor <span class="inline">@</span> to change it directly. For example you would create the array and call the funtion like this:</p>
<p class="code">array[99] = 0;<br/> array_populate(array);
</p>
<p class="dropspot">The function itself would have something like this:</p>
<p class="code">function array_populate(_array)<br/> {<br/> var a = _array; var i = 0; repeat(25)<br/> {<br/> i = irandom(99);<br/> while (a[i] != 0)<br/> {<br/> i = irandom(99);<br/> }<br/>
a[@ i] = 100;<br/> }<br/> }</p>
<p class="dropspot">All this function is doing is selecting 25 random positions in the array and setting the value of the chosen array position to 100.</p>
<p class="note">NOTE: You cannot use the array accessor <span class="inline">@</span> when working with the <span class="inline">argument[n]</span> array in script functions.</p>
<p class="dropspot"> </p>
<p class="dropspot"> </p>
</div>
<p>An important feature of accessors is the fact that they can be <i>chained</i> together. This means that if you have several nested data structures and/or arrays, there is no longer the need to use a variety of functions to get access to a value that
is deep within the nested structure. For example, say you have an array, and each item in the array is a DS list, like this:</p>
<p class="code">array = array_create(3);<br/> for (var i = 0; i < 3; ++i;)<br/> {
<br/> array[i] = ds_list_create();<br/> switch(i)
<br/> {
<br/> case 0:<br/> with (obj_Wall) ds_list_add(array[i], id);<br/> break;
<br/> case 1:<br/> with (obj_Door) ds_list_add(array[i], id);<br/> break;
<br/> case 2:<br/> with (obj_Chest) ds_list_add(array[i], id);<br/> break;
<br/> }
<br/> }
</p>
<p>In the above code we've created a 3 item array and assigned a DS list to each of them, and then we've populated the different lists with the instance IDs of various objects in the game. Now, to access an ID in one of the lists we can do the
following:</p>
<p class="code">var _list = array[0];<br/> var _id = ds_list_find_value(_list, 0);</p>
<p>However, you can do the same thing using chained accessors in a much cleaner way that uses less code:</p>
<p class="code">var _id = array[0][| 0];</p>
<p>You can chain multiple accessors together in this way and they can be of multiple types to get access to the information stored in each part of the nested structure. Here are some more examples:</p>
<p class="code">// Access a grid that has been added to a list that is part of a map:<br/> var _a = data[? "lists"][| 0][# 0, 0];<br/>
<br/> // Access an array nested in a list from a script and modify it:<br/> data[| 0][@ 10] = 100;<br/>
<br/> // Access a map nested in a grid nested in a list nested in an array:<br/> data[0][| 10][# 3, 4][? "key"] = "hello world";</p>
<p>Using chained accessors for things not only means you can write more compact code, it will also permit you to use iteration (for example, using a <a href="Language_Features/for.htm"><tt>for</tt></a> loop) and other techniques to access your data in
a cleaner and more intuitive manner.</p>
<p>It is worth noting that when using accessors in this way, you should always use the <span class="inline">@</span> accessor for arrays, as otherwise you will be adding extra overhead to any actions being performed. As mentioned above, by default arrays
are passed by reference into functions and then use the "copy on write" behavior when modified. However, if the array is part of a chain, then the previous item in the chain will be updated with the copied array and the "original"
will be deleted. For example, doing something like this:</p>
<p class="code">// In an object event<br/> data[| 0][0] = 100;<br/>
<br/> // In a function<br/> data[| 0][0] = 200;</p>
<p>achieves the same results as doing this:</p>
<p class="code">// In an object event<br/> data[| 0][0] = 100;<br/>
<br/> // In a function<br/> data[| 0][@ 0] = 200;</p>
<p>However, the second example is better as it works without the unnecessary overhead of copying the entire array first.</p>
<p> </p>
<p> </p>
<p> </p>
<div class="footer">
<div class="buttons">
<div class="clear">
<div style="float:left">Back: <a href="GML_Overview.htm">GML Overview</a></div>
<div style="float:right">Next: <a href="Script_Functions.htm">Script Functions And Variables</a></div>
</div>
</div>
<h5>© Copyright YoYo Games Ltd. 2020 All Rights Reserved</h5>
</div>
<!-- KEYWORDS
div
mod
bitwise operators
bitshift
and
or
xor
&&
||
^^
%
|
&
^
<<
>>
bitwise or
bitwise and
bitwise xor
bitshift left
bitshift right
<
<=
==
!=
>
>=
++
$
hexadecimal
-->
<!-- TAGS
expressions_operators
-->
</body></html>