Arrays

This section deals with arrays, special variables that can hold more than one value.

Arrays may seem confusing at first, but they can be extremely useful and are an essential part of making games. Why? Well, here are just a few things that would be impossible without arrays -

That's just the tip of the iceberg as arrays are one of the most fundamental and useful programming tools you can use, and you'd be surprised at the applications they can have! Let's find out a bit more about them then...

1D Arrays

Okay, we can use an array for those things mentioned above, but what is an array? What does it look like? Well, something like this...

array[0] = 1.25;


This is a 1D (one dimensional) array which we are now going to break down the parts of to see what it means:

array


This is the array's name. Just like any other variable, it can be anything you want from simply "a" to "mymumscow".

[0]


This is the position within the array that we are checking or changing. You see, an array is basically a container with a number of spaces to store values, and each position in the container has a specific number to identify it, which is what we put in the []. It's worth noting that an array always starts at 0 and can never be negative! Now let's expand our array to include different positions...

array[2] = 0;
array[1] = 0;
array[0] = 0;


Our array now contains three positions (0, 1 and 2) and we have initialized our array to 0. What does that mean? Well, an array has to be initialized before we can use it or GameMaker: Studio will give us an error. Initializing an array just means that we give each position of the array an initial value in preparation for it to be used elsewhere in the object or code. This is important to remember as it means that you have to do a certain amount of planning before using arrays, but it is easy enough to initialize one using a repeat loop like this...

var i;
i = 9;
repeat(10)
   {
   array[i] = 0;
   i -= 1;
   }


This simple code will initialize a ten position array (0-9) to 0, in that each position in the array contains the value 0. You will notice that the array has been initialised backwards, with the last value being defined first. This is not strictly necessary but is the optimal way to do it as it will reserve a space in memory that is the exact size of the array, whereas if you initialize an array from 0 upwards, the memory has to be re-allocated for every additional value added. The speed difference is negligible for smaller arrays, but larger ones should be optimised as much as possible in this way.

But what if we want to initialize the array with different values for each position? Well for that we have to manually type each and every position ourselves, but there is a nice trick to help us keep track of things there too!

count = 3;
array[count] = "you?"
count -= 1;
array[count] = "are "
count -= 1;
array[count] = "How "
count -= 1;
array[count] = "Hello!"
count -= 1;


As you can see, we haven't used any numbers in the actual array, rather a variable to count down through the values. This has two benefits - One, we don't have to worry about typos or errors when writing out the array positions, and two, we have in the variable "count" the number of positions that the array contains, which can then be used elsewhere in the object. Very useful!

With that done how do we use an array for practical things? Exactly the same as we would use a normal variable, as shown by the following examples:

total = array[0] + array[5]; //Add two array values together

if (array[9]) == 10 //Check an array value
   {
   //do something
   }

draw_text(32, 32, array[3]); //draw an array value


Since arrays are numbered consecutively, this means you can loop through them to perform extra actions too, like we did to initialize it:

var total = 0;
for (var i = 0; i < 10; i++;)
   {
   total += array[i];
   draw_text(32, 32 + (i * 32), array[i]);
   }
draw_text(32, 32 + (i * 32), total);


The above code will add up all the values in our array, draw each of them and draw the total value at the end.

2D Arrays

Now that we know what a normal array looks like, let's look at a 2D (two dimensional) array.

array[0, 0] = 5;


As before, each number points to a position within the array, only this time each position has an "a" and "b" coordinate. Think of it as an extra dimension to our container, as it now has height and width whereas the 1D array only has height. Here is an extended example:

array[1, 2] = 1;
array[1, 1] = "hello";
array[1, 0] = 55.5;
array[0, 2] = sprite_index;
array[0, 1] = "world";
array[0, 0] = -67.89;


A 2D array needs to be initialised before use, the same as a 1D array, and can hold real numbers, strings and constants, just like any other variable, making them ideal candidates for any game that needs to store large amounts of data in an easily accessible way (remember, you can loop through an array easily). Here is one final example of how this may be used in an actual game... Say you want to spawn four different enemies at four different points in your game depending on a random value. Well, we can use a 2D array to do this and save writing out a load of code.

First we should initialize the array we are going to use in the create event of our "controller" object:

enemy[3, 2] = 448; //y position
enemy[3, 1] = 32; //x position
enemy[3, 0] = obj_Slime; //Object
enemy[2, 2] = 448;
enemy[2, 1] = 608;
enemy[2, 0] = obj_Skeleton;
enemy[1, 2] = 32;
enemy[1, 1] = 608;
enemy[1, 0] = obj_Knight;
enemy[0, 2] = 32;
enemy[0, 1] = 32;
enemy[0, 0] = obj_Ogre;


We now have the objects to spawn instances of and their corresponding x and y spawn coordinates within the room all stored in our array. This can now be used as follows in another event of the controller object (an alarm for example, or a key press event):

var i;
i = irandom(3); //get a random number from 0 to 4
instance_create(enemy[i, 1], enemy[i, 2], enemy[i, 0]); //Use the array to create the object


That short code will now spawn a random enemy in the game room, and it uses far less code than an "if / then / else" structure or even a "switch", and as the array is initialized all together in the create event it is MUCH easier to edit and change any of those values as they are not hard-coded into the rest of the object codes. It is also worth noting that the length of each 2D array can be different, so you can have an array with a height of 2, but entry 0 could be 2 in length, entry 1 could be 4 in length and entry 2 could be 3 in length:

array[0, 0] = 1;
array[0, 1] = 2;
array[1, 0] = "one";
array[1, 1] = "two";
array[1, 2] = "three";
array[1, 3] = "four";
array[2, 0] = "1";
array[2, 1] = "2";
array[2, 2] = "3";

Advanced Array Functionality

Just like normal variables, you can pass arrays through to scripts to be used and then returned to the instance that called the script. To do this, you simply have to specify the array variable (no need for each of the individual entries, nor the [] brackets) and the array will be passed by reference into the script. However, should you change any of the array values, the array will be copied into a temporary array just for the script. Note the use of the word temporary here! You are not actually passing the array itself into the script (as you would a variable), but instead you are requesting that the script create a copy of this array, which you will change in the script. This means that you must always return the array from the script if you wish to change any array values.

NOTE: Due to the way that this works internally, passing arrays to scripts may affect performance, especially if the array is very large. So use this functionality with care!

As an example, consider the following code. First we create the array we want to use, and then we pass that array to the script:

for (var i = 9; i > -1; i--;)
   {
   a[i] = i;
   }

scr_Return_Array(a);


The script itself is something simple like:

for (var i = 9; i > -1; i--;)
   {
   a[i] = i * 100;
   }


Now you would expect the final array to hold the values 900, 800, 700, etc... BUT this will not be the case, since we did not return the array from the script, so all we changed was the temporary copy that was created when we passed the array as an argument into the script. To rectify this we should have formatted the code as follows:

for (var i = 9; i > -1; i--;)
   {
   a[i] = i;
   }

a = scr_Return_Array(a);


And the script should now look like this:

for (var i = 9; i > -1; i--;)
   {
   argument0[i] = i * 100;
   }

return argument0;

NOTE: The above is not necessary if you are not changing any of the array values, but rather simply referencing them. Referencing an array will not copy it and be faster to parse.

You can also delete an array simply by "re-assigning" the variable that defines it to a single value. This will free up the memory associated with all the entries and values for that array. For example:

//Create the array for (var i = 9; i > -1; i--;)
   {
   a[i] = i;
   }
//Delete the array a = 0;

It is also worth noting that you can use the accessor @ to reference an array from a script and change its values directly, which saves the CPU overhead of having it copied into the script. You can find out more information on accessors and how they work, along with an example for arrays, from the following page:

  1. Accessors

Array Functions

There are a few functions associated with the use of arrays too. These are designed to give you flexibility in your code, and will permit you to create more functional and dynamic arrays when making your games. These functions are:

  1. is_array
  2. array_create
  3. array_copy
  4. array_equals
  5. array_length_1D
  6. array_length_2D
  7. array_height_2D


Back: GML Overview
Next: Functions
© Copyright YoYo Games Ltd. 2018 All Rights Reserved