tag:blogger.com,1999:blog-22610464338849080582024-03-05T02:58:59.551-08:00YellowAfterlifeYellowhttp://www.blogger.com/profile/02048945177006677120noreply@blogger.comBlogger5125tag:blogger.com,1999:blog-2261046433884908058.post-88049268471693196392011-11-27T22:29:00.000-08:002011-12-13T07:01:50.891-08:00GameMaker - multi-dimensional arrays<p>As you may know, GameMaker natively supports only 2-dimensional arrays with size up to 32000x32000.<br>
However, in some cases, you may want to use arrays with 3 (or more) dimensions.<br>
Small comparison table with descriptions below:</p>
<table class="atable">
<tr>
<td width="24%">Stat\Method</td>
<td width="19%">array:offset</td>
<td width="19%">array:instance</td>
<td width="19%">ds_grid's</td>
<td width="19%">ds_map</td>
</tr>
<tr>
<td>Init (fill-up)</td>
<td><span class="word-no">Slow</span></td>
<td><span class="word-no">Slow</span></td>
<td><span class="word-yes">Fast</span></td>
<td><span class="word-no">Slowest</span></td>
</tr>
<tr>
<td>Access (i/o)</td>
<td><span class="word-yes">Fast</span></td>
<td><span class="word-yes">Fast</span></td>
<td>Average</td>
<td>Average</td>
</tr>
<tr>
<td>Size limit</td>
<td><span class="word-no">~10<sup>9</sup> cells</span></td>
<td><span class="word-no">32k/dimension</span></td>
<td><span class="word-other">Resizable</span></td>
<td><span class="word-yes">No</span></td>
</tr>
<tr>
<td>Index</td>
<td><span class="word-yes">Integer</span></td>
<td><span class="word-yes">Integer</span></td>
<td><span class="word-yes">Integer</span></td>
<td><span class="word-other">String</span></td>
</tr>
<tr>
<td>Existance check</td>
<td><span class="word-no">No</span></td>
<td><span class="word-no">No</span></td>
<td><span class="word-other">Not needed</span></td>
<td><span class="word-yes">Yes</span></td>
</tr>
<tr>
<td>Region operations</td>
<td><span class="word-no">No</span></td>
<td><span class="word-no">No</span></td>
<td><span class="word-yes">Yes</span></td>
<td><span class="word-other">Only clearing</span></td>
</tr>
<tr>
<td>References</td>
<td><span class="word-no">No</span></td>
<td><span class="word-other">Partial (layer)</span></td>
<td><span class="word-yes">Yes</span></td>
<td><span class="word-yes">Yes</span></td>
</tr>
</table>
<a name='more'></a>
<h1>Methods:</h1>
<p><h2>array:offset</h2>
Often used in languages that only support one-dimensional arrays, is based on storing several dimensions in a single one.
<div class="gml">cell = array[z * y_size + y][x]</div>So, the primary restrictions that you are going to have with this method are fixed size for all but two dimensions, and lack of error handling. One could note that there is a limit on max cell count, however it is not significant - 10<sup>9</sup> cells are already 2Gb of data (assuming that they are stored next to each-other in double precision floating point format) - if you have a feeling that you may exceed that limit, think again.
</p>
<p><h2>array:instance</h2>
This method is a 'call' to very relative object oriented programming that exists in GameMaker. Concept is simple - you cannot store array in a array, but you can perfectly store instance in a array. So why not just make ones that would serve a single purpose of storing sub-arrays?
<div class="gml"><span class="co1">// Initialization</span><br />
<span class="kw1">for</span> <span class="br0">(</span>k <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> k <span class="sy0"><</span> zsize<span class="sy0">;</span> k <span class="sy0">+=</span> <span class="nu0">1</span><span class="br0">)</span> <span class="br0">{</span><br />
layer <span class="sy0">=</span> <span class="kw3">instance_create</span><span class="br0">(</span><span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> obj_array<span class="br0">)</span><br />
array<span class="br0">[</span>k<span class="br0">]</span> <span class="sy0">=</span> layer<br />
<span class="co1">// Sub-init for layer itself:</span><br />
<span class="kw1">for</span> <span class="br0">(</span>i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0"><</span> xsize<span class="sy0">;</span> i <span class="sy0">+=</span> <span class="nu0">1</span><span class="br0">)</span><br />
<span class="kw1">for</span> <span class="br0">(</span>j <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> j <span class="sy0"><</span> ysize<span class="sy0">;</span> j <span class="sy0">+=</span> <span class="nu0">1</span><span class="br0">)</span><br />
layer.<span class="me1">array</span><span class="br0">[</span>i<span class="sy0">,</span> j<span class="br0">]</span> <span class="sy0">=</span> <span class="nu0">0</span><br />
<span class="br0">}</span></div>Advantages of this method are less strict array limits (32000 per dimension) and ability to pass reference to specific array 'layer'. Disavantage is in having additional dummy instances.
</p>
<p><h2>ds_grid's / ds_list's</h2>
Setting up multi-dimensional array with this method is relatively easy - you create a ds_grid (or ds_list), and store it in other one of these.
<div class="gml"><span class="co1">// read</span><br />
value <span class="sy0">=</span> <span class="kw3">ds_grid_get</span><span class="br0">(</span><span class="kw3">ds_list_find_value</span><span class="br0">(</span>array<span class="sy0">,</span> z<span class="br0">)</span><span class="sy0">,</span> <span class="kw2">x</span><span class="sy0">,</span> <span class="kw2">y</span><span class="br0">)</span><br />
<span class="co1">// write</span><br />
<span class="kw3">ds_grid_set</span><span class="br0">(</span><span class="kw3">ds_list_find_value</span><span class="br0">(</span>array<span class="sy0">,</span> z<span class="br0">)</span><span class="sy0">,</span> <span class="kw2">x</span><span class="sy0">,</span> <span class="kw2">y</span><span class="sy0">,</span> value<span class="br0">)</span></div>
As advantage, list and grid functions become available, which allow faster manipulations over array contents. Primary disadvantage is need for a complex array disposal function.
</p>
<p><h2>ds_map</h2>
String-based key gives ds_map slight advantage over other methods in methods of storing data - you can have a cell at (0, 0, 0) and few thousands points away without filling everything between. As well it grants ability to store negative indexes, which is hard to manage with other data structures. Access to values is done via composed index (normally coordinates with delimeters between them).
<div class="gml"><span class="co1">// read</span><br />
value <span class="sy0">=</span> <span class="kw3">ds_map_find_value</span><span class="br0">(</span>map<span class="sy0">,</span> <span class="kw3">string</span><span class="br0">(</span><span class="kw2">x</span><span class="br0">)</span> <span class="sy0">+</span> <span class="st0">';'</span> <span class="sy0">+</span> <span class="kw3">string</span><span class="br0">(</span><span class="kw2">y</span><span class="br0">)</span> <span class="sy0">+</span> <span class="st0">';'</span> <span class="sy0">+</span> <span class="kw3">string</span><span class="br0">(</span>z<span class="br0">)</span><span class="br0">)</span><br />
<span class="co1">// write</span><br />
adress <span class="sy0">=</span> <span class="kw3">string</span><span class="br0">(</span><span class="kw2">x</span><span class="br0">)</span> <span class="sy0">+</span> <span class="st0">';'</span> <span class="sy0">+</span> <span class="kw3">string</span><span class="br0">(</span><span class="kw2">y</span><span class="br0">)</span> <span class="sy0">+</span> <span class="st0">';'</span> <span class="sy0">+</span> <span class="kw3">string</span><span class="br0">(</span>z<span class="br0">)</span><br />
<span class="kw1">if</span> <span class="br0">(</span><span class="kw3">ds_map_exists</span><span class="br0">(</span>map<span class="sy0">,</span> adress<span class="br0">)</span><span class="br0">)</span><br />
<span class="kw1">then</span> <span class="kw3">ds_map_replace</span><span class="br0">(</span>map<span class="sy0">,</span> adress<span class="sy0">,</span> value<span class="br0">)</span><br />
<span class="kw1">else</span> <span class="kw3">ds_map_add</span><span class="br0">(</span>map<span class="sy0">,</span> adress<span class="sy0">,</span> value<span class="br0">)</span></div>
Advantage of this method is practially no limitation in array size or coordinate spread. Dis-advantages are problematic enumeration (to get all items on specific depth, program must cycle through all items), and slightly slower access speed.
</p>
If I am mistaken somewhere, feel free to leave a comment.Yellowhttp://www.blogger.com/profile/02048945177006677120noreply@blogger.com0tag:blogger.com,1999:blog-2261046433884908058.post-67581030469752552522011-11-22T09:50:00.001-08:002011-11-24T00:39:16.405-08:00GameMaker - INI without an *.ini<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8__zcPi8FnxVDKGHS8M35v2mmkjq0ZdhC3NTS71M-k97AbYQSKI_lhu2Tx-CodBxDQLrEc-v4XWSSZh_O4CiktuC2eaZ4QZFh-uXGgSxbcYMdIYr50jrQCH-d0juFbdCNbl5SoAcCYsU/s1600/temp4.png" imageanchor="1" style="float:right;"><img border="0" height="128" width="128" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8__zcPi8FnxVDKGHS8M35v2mmkjq0ZdhC3NTS71M-k97AbYQSKI_lhu2Tx-CodBxDQLrEc-v4XWSSZh_O4CiktuC2eaZ4QZFh-uXGgSxbcYMdIYr50jrQCH-d0juFbdCNbl5SoAcCYsU/s400/temp4.png" /></a>
<p>So, say, you would like to load data from INI without creating an *.ini file somewhere.<br>
There can be many reasons for doing so, be that security, performance, or simple fact of INI contents being defined inside of game's code.</p>
<p>There are two things to do about it - deciding on presentation of data, and creating a algorithm to load it. Presentation of data is relatively simple with INI - file is split into named sections, which contain named values. Since both use string index, using ds_map (sections) with other ds_map's inside (values) seems like an approriate choice. Below is my implementation.</p>
<a name='more'></a>
<p>Here, I have named main ds_map "fi" (Fake Ini). So, script to read a value from it would be as the following:
<div class="gml"><span class="coMULTI">/* fi_get(section, key, default)<br />
Reads a value from loaded ini. */</span><br />
<span class="kw1">if</span> <span class="br0">(</span><span class="sy0">!</span><span class="kw3">ds_map_exists</span><span class="br0">(</span>fi<span class="sy0">,</span> argument0<span class="br0">)</span><span class="br0">)</span> <span class="kw1">return</span> <span class="kw4">argument2</span><br />
<span class="kw1">local</span>.<span class="me1">map</span> <span class="sy0">=</span> <span class="kw3">ds_map_find_value</span><span class="br0">(</span>fi<span class="sy0">,</span> <span class="kw4">argument0</span><span class="br0">)</span><br />
<span class="kw1">if</span> <span class="br0">(</span><span class="sy0">!</span><span class="kw3">ds_map_exists</span><span class="br0">(</span><span class="kw1">local</span>.<span class="me1">map</span><span class="sy0">,</span> <span class="kw4">argument1</span><span class="br0">)</span><span class="br0">)</span> <span class="kw1">return</span> <span class="kw4">argument2</span><br />
<span class="kw1">return</span> <span class="kw3">ds_map_find_value</span><span class="br0">(</span><span class="kw1">local</span>.<span class="me1">map</span><span class="sy0">,</span><span class="kw4"> argument1</span><span class="br0">)</span></div>
As can be seen, two checks ensure that both section and key exist, and return default value if they do not.</p>
<p>Writing value to "ini" requires a similar procedure, with exception of things being created when they do not exist yet:
<div class="gml"><span class="coMULTI">/* fi_set(section, key, value)<br />
Writes a value to loaded ini. */</span><br />
<span class="kw1">if</span> <span class="br0">(</span><span class="sy0">!</span><span class="kw3">ds_map_exists</span><span class="br0">(</span>fi<span class="sy0">,</span> <span class="kw4">argument0</span><span class="br0">)</span><span class="br0">)</span> <span class="kw3">ds_map_add</span><span class="br0">(</span>fi<span class="sy0">,</span> <span class="kw4">argument0</span><span class="sy0">,</span> <span class="kw3">ds_map_create</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><br />
<span class="kw1">local</span>.<span class="me1">map</span> <span class="sy0">=</span> <span class="kw3">ds_map_find_value</span><span class="br0">(</span>fi<span class="sy0">,</span> <span class="kw4">argument0</span><span class="br0">)</span><br />
<span class="kw1">if</span> <span class="br0">(</span><span class="sy0">!</span><span class="kw3">ds_map_exists</span><span class="br0">(</span><span class="kw1">local</span>.<span class="me1">map</span><span class="sy0">,</span> <span class="kw4">argument1</span><span class="br0">)</span><span class="br0">)</span> <span class="kw3">ds_map_add</span><span class="br0">(</span><span class="kw1">local</span>.<span class="me1">map</span><span class="sy0">,</span> <span class="kw4">argument1</span><span class="sy0">,</span> <span class="kw4">argument2</span><span class="br0">)</span><br />
<span class="kw1">else</span> <span class="kw3">ds_map_replace</span><span class="br0">(</span><span class="kw1">local</span>.<span class="me1">map</span><span class="sy0">,</span> <span class="kw4">argument1</span><span class="sy0">,</span> <span class="kw4">argument2</span><span class="br0">)</span></div>
</p>
<p>Then the most interesting part starts: reading data from "INI" string into such structure.<br>
Without further thought, I have made a small 'parser' for basic INI format. With minor effort you could tell how it works, and maybe even improve it further.
<div class="gml"><span class="coMULTI">/* fi_load(data: string, append: boolean)<br />
Loads data into fi* system<br />
Data must be in INI-like format<br />
[SectionName]<br />
stringVar = Text<br />
numberVar = 0<br />
Append indicates if new sections should be appended to currently<br />
loaded ones (true) or replace them (false).<br />
Script author: YellowAfterlife */</span><br />
<span class="kw1">var</span> i<span class="sy0">,</span> j<span class="sy0">,</span> s<span class="sy0">,</span> c<span class="sy0">,</span> z<span class="sy0">,</span> w<span class="sy0">,</span> m<span class="sy0">,</span> v<span class="sy0">;</span><br />
<span class="co1">// remove existing maps:</span><br />
<span class="kw1">if</span> <span class="br0">(</span><span class="sy0">!</span><span class="kw4">argument1</span><span class="br0">)</span> <span class="kw1">if</span> <span class="br0">(</span><span class="kw3">ds_map_size</span><span class="br0">(</span>fi<span class="br0">)</span> <span class="sy0">!=</span> <span class="nu0">0</span><span class="br0">)</span><br />
<span class="kw1">for</span> <span class="br0">(</span>i <span class="sy0">=</span> <span class="kw3">ds_map_find_first</span><span class="br0">(</span>fi<span class="br0">)</span><span class="sy0">;</span> <span class="kw3">ds_map_exists</span><span class="br0">(</span>fi<span class="sy0">,</span> i<span class="br0">)</span><span class="sy0">;</span> i <span class="sy0">=</span> <span class="kw3">ds_map_find_next</span><span class="br0">(</span>fi<span class="sy0">,</span> i<span class="br0">)</span><span class="br0">)</span> <span class="br0"><span class="kw1">{</span></span><br />
<span class="kw3">ds_map_destroy</span><span class="br0">(</span><span class="kw3">ds_map_find_value</span><span class="br0">(</span>fi<span class="sy0">,</span> i<span class="br0">)</span><span class="br0">)</span><br />
<span class="kw3">ds_map_delete</span><span class="br0">(</span>fi<span class="sy0">,</span> i<span class="br0">)</span><br />
<span class="br0"><span class="kw1">}</span></span><br />
s <span class="sy0">=</span> <span class="st0">''</span><br />
<span class="co1">// parsing below:</span><br />
<span class="kw1">for</span> <span class="br0">(</span>i <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span> i <span class="sy0"><=</span> <span class="kw3">string_length</span><span class="br0">(</span><span class="kw4">argument0</span><span class="br0">)</span><span class="sy0">;</span> i <span class="sy0">+=</span> <span class="nu0">1</span><span class="br0">)</span> <span class="br0"><span class="kw1">{</span></span><br />
c <span class="sy0">=</span> <span class="kw3">string_char_at</span><span class="br0">(</span><span class="kw4">argument0</span><span class="sy0">,</span> i<span class="br0">)</span><br />
v <span class="sy0">=</span> <span class="br0">(</span>c <span class="sy0">==</span> <span class="kw3">chr</span><span class="br0">(</span><span class="nu0">13</span><span class="br0">)</span> <span class="sy0">||</span> c <span class="sy0">==</span> <span class="kw3">chr</span><span class="br0">(</span><span class="nu0">10</span><span class="br0">)</span><span class="br0">)</span><br />
<span class="kw1">if</span> <span class="br0">(</span><span class="sy0">!</span>v<span class="br0">)</span> s <span class="sy0">+=</span> c<br />
<span class="kw1">if</span> <span class="br0">(</span>v <span class="sy0">||</span> i <span class="sy0">==</span> <span class="kw3">string_length</span><span class="br0">(</span><span class="kw4">argument0</span><span class="br0">)</span><span class="br0">)</span> <span class="br0"><span class="kw1">{</span></span><br />
<span class="kw1">if</span> <span class="br0">(</span><span class="kw3">string_length</span><span class="br0">(</span>s<span class="br0">)</span> <span class="sy0">></span> <span class="nu0">0</span><span class="br0">)</span> <span class="br0"><span class="kw1">{</span></span><br />
c <span class="sy0">=</span> <span class="kw3">string_char_at</span><span class="br0">(</span>s<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">)</span><br />
<span class="kw1">if</span> <span class="br0">(</span>c <span class="sy0">==</span> <span class="st0">'['</span><span class="br0">)</span> <span class="br0"><span class="kw1">{</span></span><br />
z <span class="sy0">=</span> <span class="kw3">string_copy</span><span class="br0">(</span>s<span class="sy0">,</span> <span class="nu0">2</span><span class="sy0">,</span> <span class="kw3">string_pos</span><span class="br0">(</span><span class="st0">']'</span><span class="sy0">,</span> s<span class="br0">)</span> <span class="sy0">-</span> <span class="nu0">2</span><span class="br0">)</span><br />
<span class="kw1">if</span> <span class="br0">(</span><span class="kw3">ds_map_exists</span><span class="br0">(</span>fi<span class="sy0">,</span> z<span class="br0">)</span><span class="br0">)</span> <span class="br0"><span class="kw1">{</span></span><br />
m <span class="sy0">=</span> <span class="kw3">ds_map_find_value</span><span class="br0">(</span>fi<span class="sy0">,</span> z<span class="br0">)</span><br />
<span class="br0"><span class="kw1">}</span></span> <span class="kw1">else</span> <span class="br0"><span class="kw1">{</span></span><br />
m <span class="sy0">=</span> <span class="kw3">ds_map_create</span><span class="br0">(</span><span class="br0">)</span><br />
<span class="kw3">ds_map_add</span><span class="br0">(</span>fi<span class="sy0">,</span> z<span class="sy0">,</span> m<span class="br0">)</span><br />
<span class="br0"><span class="kw1">}</span></span><br />
<span class="br0"><span class="kw1">}</span></span> <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">(</span><span class="kw3">string_letters</span><span class="br0">(</span>c<span class="br0">)</span> <span class="sy0">==</span> c<span class="br0">)</span> <span class="br0"><span class="kw1">{</span></span><br />
j <span class="sy0">=</span> <span class="kw3">string_pos</span><span class="br0">(</span><span class="st0">'='</span><span class="sy0">,</span> s<span class="br0">)</span><br />
w <span class="sy0">=</span> <span class="kw3">string_copy</span><span class="br0">(</span>s<span class="sy0">,</span> <span class="nu0">1</span><span class="sy0">,</span> j <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">)</span><br />
z <span class="sy0">=</span> <span class="kw3">string_copy</span><span class="br0">(</span>s<span class="sy0">,</span> j <span class="sy0">+</span> <span class="nu0">1</span><span class="sy0">,</span> <span class="kw3">string_length</span><span class="br0">(</span>s<span class="br0">)</span><span class="br0">)</span><br />
<span class="co1">// delete unneeded spaces:</span><br />
<span class="kw1">while</span> <span class="br0">(</span><span class="kw3">string_char_at</span><span class="br0">(</span>w<span class="sy0">,</span> <span class="kw3">string_length</span><span class="br0">(</span>w<span class="br0">)</span><span class="br0">)</span> <span class="sy0">==</span> <span class="st0">' '</span><span class="br0">)</span><br />
w <span class="sy0">=</span> <span class="kw3">string_copy</span><span class="br0">(</span>w<span class="sy0">,</span> <span class="nu0">1</span><span class="sy0">,</span> <span class="kw3">string_length</span><span class="br0">(</span>w<span class="br0">)</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">)</span><br />
<span class="kw1">while</span> <span class="br0">(</span><span class="kw3">string_char_at</span><span class="br0">(</span>z<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">)</span> <span class="sy0">==</span> <span class="st0">' '</span> <span class="sy0">&&</span> z <span class="sy0">!=</span> <span class="st0">''</span><span class="br0">)</span><br />
z <span class="sy0">=</span> <span class="kw3">string_copy</span><span class="br0">(</span>z<span class="sy0">,</span> <span class="nu0">2</span><span class="sy0">,</span> <span class="kw3">string_length</span><span class="br0">(</span>z<span class="br0">)</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">)</span><br />
<span class="kw1">while</span> <span class="br0">(</span><span class="kw3">string_char_at</span><span class="br0">(</span>z<span class="sy0">,</span> <span class="kw3">string_length</span><span class="br0">(</span>z<span class="br0">)</span><span class="br0">)</span> <span class="sy0">==</span> <span class="st0">' '</span> <span class="sy0">&&</span> z <span class="sy0">!=</span> <span class="st0">''</span><span class="br0">)</span><br />
z <span class="sy0">=</span> <span class="kw3">string_copy</span><span class="br0">(</span>z<span class="sy0">,</span> <span class="nu0">1</span><span class="sy0">,</span> <span class="kw3">string_length</span><span class="br0">(</span>z<span class="br0">)</span> <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">)</span><br />
<span class="co1">// convert to number, if looks like one:</span><br />
c <span class="sy0">=</span> <span class="kw3">string_char_at</span><span class="br0">(</span>z<span class="sy0">,</span> <span class="nu0">1</span><span class="br0">)</span><br />
<span class="kw1">if</span> <span class="br0">(</span><span class="kw3">string_pos</span><span class="br0">(</span>c<span class="sy0">,</span> <span class="st0">'0123456789.-'</span><span class="br0">)</span> <span class="sy0">!=</span> <span class="nu0">0</span><span class="br0">)</span> z <span class="sy0">=</span> <span class="kw3">real</span><span class="br0">(</span>z<span class="br0">)</span><br />
<span class="kw1">if</span> <span class="br0">(</span>c <span class="sy0">==</span> <span class="st0">'\'</span><span class="br0">)</span> z <span class="sy0">=</span> <span class="kw3">string_copy</span><span class="br0">(</span>z<span class="sy0">,</span> <span class="nu0">2</span><span class="sy0">,</span> <span class="kw3">string_length</span><span class="br0">(</span>z<span class="br0">)</span><span class="br0">)</span><br />
<span class="co1">// add to submap:</span><br />
<span class="kw1">if</span> <span class="kw3">ds_map_exists</span><span class="br0">(</span>m<span class="sy0">,</span> w<span class="br0">)</span><br />
<span class="kw1">then</span> <span class="kw3">ds_map_replace</span><span class="br0">(</span>m<span class="sy0">,</span> w<span class="sy0">,</span> z<span class="br0">)</span><br />
<span class="kw1">else</span> <span class="kw3">ds_map_add</span><span class="br0">(</span>m<span class="sy0">,</span> w<span class="sy0">,</span> z<span class="br0">)</span><br />
<span class="br0"><span class="kw1">}</span></span><br />
<span class="br0"><span class="kw1">}</span></span><br />
s <span class="sy0">=</span> <span class="st0">''</span><br />
<span class="br0"><span class="kw1">}</span></span><br />
<span class="br0"><span class="kw1">}</span></span></div>
As can be seen, it even allows some freedom in form of leading\trailing spaces.
</p>
<p>If you'd like to go a bit further and save INI data into a string, you can utilize the following function:
<div class="gml"><span class="coMULTI">/* fi_save(): string<br />
Creates ini code from currently loaded data and returns it */</span><br />
<span class="kw1">var</span> s<span class="sy0">,</span> m<span class="sy0">,</span> i<span class="sy0">,</span> j<span class="sy0">;</span><br />
s <span class="sy0">=</span> <span class="st0">''</span><br />
<span class="kw1">for</span> <span class="br0">(</span>i <span class="sy0">=</span> <span class="kw3">ds_map_find_first</span><span class="br0">(</span>fi<span class="br0">)</span><span class="sy0">;</span> <span class="kw3">ds_map_exists</span><span class="br0">(</span>fi<span class="sy0">,</span> i<span class="br0">)</span><span class="sy0">;</span> i <span class="sy0">=</span> <span class="kw3">ds_map_find_next</span><span class="br0">(</span>fi<span class="sy0">,</span> i<span class="br0">)</span><span class="br0">)</span> <span class="br0"><span class="kw1">{</span></span><br />
m <span class="sy0">=</span> <span class="kw3">ds_map_find_value</span><span class="br0">(</span>fi<span class="sy0">,</span> i<span class="br0">)</span><br />
<span class="kw1">if</span> <span class="br0">(</span>s <span class="sy0">!=</span> <span class="st0">''</span><span class="br0">)</span> s <span class="sy0">+=</span> <span class="kw3">chr</span><span class="br0">(</span><span class="nu0">13</span><span class="br0">)</span> <span class="sy0">+</span> <span class="kw3">chr</span><span class="br0">(</span><span class="nu0">10</span><span class="br0">)</span><br />
s <span class="sy0">+=</span> <span class="st0">'['</span> <span class="sy0">+</span> i <span class="sy0">+</span> <span class="st0">']'</span><br />
<span class="kw1">for</span> <span class="br0">(</span>j <span class="sy0">=</span> <span class="kw3">ds_map_find_first</span><span class="br0">(</span>m<span class="br0">)</span><span class="sy0">;</span> <span class="kw3">ds_map_exists</span><span class="br0">(</span>m<span class="sy0">,</span> j<span class="br0">)</span><span class="sy0">;</span> j <span class="sy0">=</span> <span class="kw3">ds_map_find_next</span><span class="br0">(</span>m<span class="sy0">,</span> j<span class="br0">)</span><span class="br0">)</span> <span class="br0"><span class="kw1">{</span></span><br />
s <span class="sy0">+=</span> <span class="kw3">chr</span><span class="br0">(</span><span class="nu0">13</span><span class="br0">)</span> <span class="sy0">+</span> <span class="kw3">chr</span><span class="br0">(</span><span class="nu0">10</span><span class="br0">)</span> <span class="sy0">+</span> j <span class="sy0">+</span> <span class="st0">' = '</span> <span class="sy0">+</span> <span class="kw3">string</span><span class="br0">(</span><span class="kw3">ds_map_find_value</span><span class="br0">(</span>m<span class="sy0">,</span> j<span class="br0">)</span><span class="br0">)</span><br />
<span class="br0"><span class="kw1">}</span></span><br />
<span class="br0"><span class="kw1">}</span></span><br />
<span class="kw1">return</span> s</div>
</p>
<p>Obviously, ds_map isn't going to magically create itself on game start, so a small 'init' function is needed:
<div class="gml"><span class="coMULTI">/* fi_init()<br />
Initializes system. Call at game start. */</span><br />
<span class="kw1">globalvar</span> fi<span class="sy0">;</span><br />
fi <span class="sy0">=</span> <span class="kw3">ds_map_create</span><span class="br0">(</span><span class="br0">)</span></div>
</p>
<p>That's all. You can either copy & use above code, or download a GMK <a href="http://solidfiles.com/d/1cf1c6bc74/">here</a>.<br>Have a nice day.</p>Yellowhttp://www.blogger.com/profile/02048945177006677120noreply@blogger.com0tag:blogger.com,1999:blog-2261046433884908058.post-59710905547739043872011-11-17T13:23:00.001-08:002011-11-17T13:40:22.236-08:00GameMaker - "sliding" viewsThis example illustrates setup of 'sliding' views, similar to ones seen in older console games (like Legend of Zelda).<br>
In this case game is not paused while view is scrolling, making it slightly different from origins.
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSyNmQ8Si-jm0wJAD3m5x-IpyVt-FbhY6rc2a5rw5ed5wwx8QpyvaY65v8rrM2AJHctnOnizfpqsdHSDo3vNpUjkTOJ8op72PHsjpHdKRRGNCIZw_nlMmYy3bV5vZoF-fBcBYr4_39F1E/s1600/temp2.png" imageanchor="1" style="margin-left:1em; margin-right:1em"><img border="0" height="289" width="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSyNmQ8Si-jm0wJAD3m5x-IpyVt-FbhY6rc2a5rw5ed5wwx8QpyvaY65v8rrM2AJHctnOnizfpqsdHSDo3vNpUjkTOJ8op72PHsjpHdKRRGNCIZw_nlMmYy3bV5vZoF-fBcBYr4_39F1E/s400/temp2.png" /></a></div>
Download: <a href="http://solidfiles.com/d/a76754ffb0/">(link)</a>Yellowhttp://www.blogger.com/profile/02048945177006677120noreply@blogger.com0tag:blogger.com,1999:blog-2261046433884908058.post-29632950622899561572011-11-17T09:43:00.000-08:002011-11-17T10:46:40.918-08:00GameMaker - get sprite's alpha channelIn some cases you may want to retrieve alpha channel of chosen sprite, to either apply it to other sprite, use for drawing, or in some other way.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWIvQ3asECZ1R17ydjMgr8TwmRx94I_46ChO3DZiTnzNPe6IrCCaXtXI2o7KqguCqOcZy60wGq_-DSUn4CIHw64WULXneTaSHoMIp7ZO6OVGISTocpfy59Y3yKV0mX9W9kde739mgP0jg/s1600/temp4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWIvQ3asECZ1R17ydjMgr8TwmRx94I_46ChO3DZiTnzNPe6IrCCaXtXI2o7KqguCqOcZy60wGq_-DSUn4CIHw64WULXneTaSHoMIp7ZO6OVGISTocpfy59Y3yKV0mX9W9kde739mgP0jg/s400/temp4.png" width="384" /></a></div><a name='more'></a><br />
The following script helps this: <br />
<div class="gml"><span class="coMULTI">/*<br />
sprite_get_alpha(sprite): sprite<br />
Returns alpha channel version of specified sprite<br />
Uses: sprites, surfaces, d3d fog settings<br />
Notes: modifies d3d fog settings.<br />
*/</span><br />
<span class="kw1">var</span> w<span class="sy0">,</span> h<span class="sy0">,</span> b<span class="sy0">,</span> t<span class="sy0">,</span> l<span class="sy0">,</span> i<span class="sy0">,</span> s<span class="sy0">,</span> c<span class="sy0">;</span><br />
w <span class="sy0">=</span> <span class="kw3">sprite_get_width</span><span class="br0">(</span><span class="kw4">argument0</span><span class="br0">)</span><br />
h <span class="sy0">=</span> <span class="kw3">sprite_get_height</span><span class="br0">(</span><span class="kw4">argument0</span><span class="br0">)</span><br />
l <span class="sy0">=</span> <span class="kw3">sprite_get_xoffset</span><span class="br0">(</span><span class="kw4">argument0</span><span class="br0">)</span><br />
t <span class="sy0">=</span> <span class="kw3">sprite_get_yoffset</span><span class="br0">(</span><span class="kw4">argument0</span><span class="br0">)</span><br />
b <span class="sy0">=</span> <span class="kw3">surface_create</span><span class="br0">(</span>w<span class="sy0">,</span> h<span class="br0">)</span><br />
c <span class="sy0">=</span> <span class="kw3">sprite_get_number</span><span class="br0">(</span><span class="kw4">argument0</span><span class="br0">)</span><br />
<span class="kw3">surface_set_target</span><span class="br0">(</span>b<span class="br0">)</span><br />
<span class="kw3">d3d_set_fog</span><span class="br0">(</span><span class="kw4">true</span><span class="sy0">,</span> <span class="kw4">c_white</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="br0">)</span><br />
<span class="kw1">for</span> <span class="br0">(</span>i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0"><</span> c<span class="sy0">;</span> i <span class="sy0">+=</span> <span class="nu0">1</span><span class="br0">)</span> <span class="br0">{</span><br />
<span class="kw3">draw_clear</span><span class="br0">(</span><span class="kw4">c_black</span><span class="br0">)</span><br />
<span class="kw3">draw_sprite</span><span class="br0">(</span><span class="kw4">argument0</span><span class="sy0">,</span> i<span class="sy0">,</span> l<span class="sy0">,</span> t<span class="br0">)</span><br />
<span class="kw1">if</span> <span class="br0">(</span>i <span class="sy0">==</span> <span class="nu0">0</span><span class="br0">)</span><br />
<span class="kw1">then</span> s <span class="sy0">=</span> <span class="kw3">sprite_create_from_surface</span><span class="br0">(</span>b<span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> w<span class="sy0">,</span> h<span class="sy0">,</span> <span class="kw4">false</span><span class="sy0">,</span> <span class="kw4">false</span><span class="sy0">,</span> l<span class="sy0">,</span> t<span class="br0">)</span><br />
<span class="kw1">else</span> <span class="kw3">sprite_add_from_surface</span><span class="br0">(</span>s<span class="sy0">,</span> b<span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> w<span class="sy0">,</span> h<span class="sy0">,</span> <span class="kw4">false</span><span class="sy0">,</span> <span class="kw4">false</span><span class="br0">)</span><br />
<span class="br0">}</span><br />
<span class="kw3">d3d_set_fog</span><span class="br0">(</span><span class="kw4">false</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="sy0">,</span> <span class="nu0">0</span><span class="br0">)</span><br />
<span class="kw3">surface_reset_target</span><span class="br0">(</span><span class="br0">)</span><br />
<span class="kw3">surface_free</span><span class="br0">(</span>b<span class="br0">)</span><br />
<span class="kw1">return</span> s</div>Yellowhttp://www.blogger.com/profile/02048945177006677120noreply@blogger.com0tag:blogger.com,1999:blog-2261046433884908058.post-27673651033197520252011-11-16T11:37:00.000-08:002011-11-17T12:30:20.681-08:00GameMaker - shuffling an arrayIn some cases you may want to shuffle contents of array.<br>
Out of those, it may also happen that it can not be easily replaced by ds_list.<br>
The following code can be used to sort an array relatively fast and finely:
<div class="gml"><span class="kw1">var</span> i<span class="sy0">,</span> j<span class="sy0">,</span> k<span class="sy0">;</span><br />
<span class="kw1">for</span> <span class="br0">(</span>i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span> i <span class="sy0"><</span> size<span class="sy0">;</span> i <span class="sy0">+=</span> <span class="nu0">1</span><span class="br0">)</span><br />
<span class="br0">{</span><br />
j <span class="sy0">=</span> irandom_range<span class="br0">(</span>i<span class="sy0">,</span> size <span class="sy0">-</span> <span class="nu0">1</span><span class="br0">)</span><br />
<span class="kw1">if</span> <span class="br0">(</span>i <span class="sy0">!=</span> j<span class="br0">)</span><br />
<span class="br0">{</span><br />
k <span class="sy0">=</span> data<span class="br0">[</span>i<span class="br0">]</span><br />
data<span class="br0">[</span>i<span class="br0">]</span> <span class="sy0">=</span> data<span class="br0">[</span>j<span class="br0">]</span><br />
data<span class="br0">[</span>j<span class="br0">]</span> <span class="sy0">=</span> k<br />
<span class="br0">}</span><br />
<span class="br0">}</span></div>Where <b>data</b> is name of array variable, and <b>size</b> is array length (with elements being stored in indexes from 0 to (size - 1)).Yellowhttp://www.blogger.com/profile/02048945177006677120noreply@blogger.com1