Uso de arrays en Game Maker
Ya hemos visto cómo usamos las variables y que podemos almacenar en ellas. Hagamos un pequeño refresco de memoria: almacenados principalmente números o texto. Estos números también pueden ser una referencia a los recursos del proyecto, ya que internamente se almacenan así, pudiendo utilizar una variable para guardar y usar sprites, sonidos, objetos, etc.
Ahora vamos a ver un tipo de variable que podemos almacenar una array o matriz: una lista de valores de cualquier tipo. Entramos ahora en detalle.
¿Qué es una array?
Como hemos dicho, dentro de una variable tendremos una lista de números o de cadenas de texto. Para acceder a cada elemento de esa lista usaremos un índice, que no deja de ser una referencia. Por ejemplo:
inventario[0] = ‘hacha’;
Tenemos una variable, inventario, y sabemos que es una array porque tiene el número cero entre corchetes. Este número indica la posición dentro de la lista, en este caso la primera. En programación es muy habitual que la lista de cosas, por decirlo de alguna manera, vaya desde el número 0 hasta el número total – 1. Por ejemplo, si abrimos un sprite con varias imágenes vemos que la primera es la 0.
Así que, ¡en programación el 0 cuenta!
Cómo creamos arrays en GML
Ya hemos visto la nomenclatura (como se escribe) una array. Para crear una array, simplemente le vamos dando valores a las distintas posiciones que nos interesa. Destacar que no podemos poner posiciones con valores negativos (a estas posiciones también se le llama índices).
inventario[0] = 0; inventario[1] = 0; inventario[2] = 0;
Aquí estamos creando la matriz, o como hemos dicho a veces, inicializándola (dándole un valor inicial). ¿Por qué? Porque al igual que las variables, debemos crearlas antes de poder usarlas. Aunque se puede hacer fácilmente con un bucle de repetición.
for (i = 0; i < 10; i++) { inventario[i] = 0; }
Otra manera de hacerlo
var i = 0; repeat(10) { array[i] = 0; i++; }
Hemos inicializado la array partiendo de 0 hacia arriba. En otros lenguajes de programación las arrays son fijas, es decir, se define su tamaño en el código y no se puede aumentar o disminuir. En Game Maker podemos ir ampliando su tamaño aumentando su índice. ¿Pero qué pasa si hacemos esto?
inventario[2] = 0;
inventario[0] = 0;
inventario[1] = 0;
Si ponemos el índice 2 primero al crear/inicializar la variable, Game Maker ya reserva el espacio para 0 y para 1. En Game Maker las arrays son dinámicas, es decir, no tienen tamaño fijo. Si vamos dando valor al índice 0, luego al 1, al 2… va aumentando su tamaño de memoria, pero si damos valor al índice 2, Game Maker da un valor por defecto (el 0) para el índice 0 y el 1. De esta manera no se aumenta dinámicamente y es más óptimo en gestión de memoria. Conclusión: si tenéis claro el tamaño, ponedlo desde el principio y luego le damos los valores. Así:
inventario[9] = 0; for (i = 0; i < 10; i++) { inventario[i] = 0; }
Como se borra un array
Si queremos borrar los datos de una array para liberar memoria, Game Maker ofrece una manera muy sencilla de hacerlo: simplemente le asignamos el valor 0 a la variable
//crear array for (var i = 9; i > -1; i--;) { a[i] = i; } //Eliminar array a = 0;
Así eliminamos todos sus elementos sin tener que hacer nada especial.
Arrays de dos dimensiones
Ahora que hemos visto cómo funcionan las arrays, aprenderemos cómo podemos ampliarlas, no aumentar el número de elementos de una lista, sino añadir una dimensión más. Lo que hemos visto hasta ahora es una sola dimensión de la array, como una lista de valores. Pero es posible tener dos dimensiones. Sería algo así
Array de dos dimensiones | |||||
---|---|---|---|---|---|
(0,0) | (0,1) | (0,2) | (0,3) | … | (0,n) |
(1,0) | (1,1) | (1,2) | (1,3) | … | (1,n) |
(2,0) | (2,1) | (2,2) | (2,3) | … | (2,n) |
… | … | … | … | … | … |
(n,0) | (n,1) | (n,2) | (n,3) | … | (n,n) |
Como veis, aunque sea de dos dimensiones no tienen que tener un tamaño fijo en “cada dimensión” (eso solo pasa con Game Maker, en otros lenguajes las arrays suelen ser de tamaño fijo, es decir, son cuadradas).
Se me ocurren infinidad de utilidades para tener una array de dos dimensiones: controlar en todo momento que ocurre en la room (si os fijais, sería como la grid o rejilla que vemos en el editor), almacenar mapas, o aprovechar para tener una lista de objetos con todas sus propiedades. Vamos a detallar esto último.
Aprovechando que en una array podemos tener tipos de datos diferentes, mezclar números y texto, podemos almacenar instancias y sus variables. Pero antes de nada, veamos como se usan estas arrays.
Para una array de una dimensión vimos que las creamos así:
a[0] = 5;
Para una array de dos dimensiones se utilizan así
a[0,1] = 20;
Dentro de los corchetes ponemos las dos dimensiones, que corresponden a dos índices.
De vuelta al ejemplo, podemos usar el primer índice para indicar el objeto o instancia en cuestión y el segundo para controlar cada elemento. Por ejemplo, almacenamos el objeto, un sprite, un nombre y la posición X/Y.
enemies[0,0] = obj_orc; enemies[0,1] = ‘ROAARHG’; enemies[0,2] = spr_dark_orc; enemies[0,3] = 32; enemies[0,4] = 32; enemies[1,0] = obj_skeleton; enemies[1,1] = ‘SKULL’; enemies[1,2] = spr_light_skeleton; enemies[1,3] = 282; enemies[1,4] = 128; …
Como vemos, podemos almacenar una serie de datos que puede ser mucho más práctico de usar que si usamos variables sueltas. Ahora creamos una instancia con un enemigo aleatorio con los datos que tenemos
var i = irandom(1); //número aleatorio entre 0 y uno enemy = instance_create(enemies[i,1], enemies[i,3], enemies[i,4]); enemy.sprite index = enemies[i, 2];
Para finalizar, comentar una característica importante: cuando tenemos arrays de dos dimensiones no son de tamaño fijo. Un ejemplo, si creamos una array así
a[9] = 0;
Implica que se crea la a[0], a[1],...,a[9]
, porque hemos comentado más arriba que al crear un índice más grande que cero reserva memoria para el resto. Eso no implica que no puede crecer más creando un a[10].
Pero si creamos una variable de dos dimensiones así
a[3,3] = 0;
no está creando la a[0,0], a[0,1]...
Solo crea la a[0,3],a[1,3],a[2,3] y a[3,3]
. ¡Debemos tenerlo en cuenta para evitar errores! Recordemos, una vez más, que las arrays en Game Maker son dinámicas.
Uso de arrays con scripts
Podemos pasar una array como parámetro/argumento en un script, pero tenemos que tener en cuenta una serie de cosas.
Si tenemos un script llamado scr_rand_array()
, si le pasamos por ejemplo a[0]
, le estamos pasando ese valor (que se puede modificar). Si queremos pasar la array entera, habría que poner (en un script que se llamase scr_rand_array
)
scr_rand_array(a);
No hace falta poner los corchetes ni nada. Pero aquí viene el problema: como la array es un dato un poco complejo, Game Maker ha decidido crear una copia temporal de esa matriz para pasar en parámetros. Si el script hace esto:
for (var i = 9; i > -1; i--;) { a [i] = random(100); }
pensaremos que al salir del script aparecerán los nuevos valores. ¡Pero no! Al crearse una copia, debemos de devolver su valor. Así que cuando llamamos a ese script en vez de poner
scr_rand_array(a);
habrá que poner
a = scr_rand_array(a);
Y modificar el código del script. Aprovecho la palabra especial del primer argumento argument0
para referirme al array a
.
for (var i = 9; i > -1; i--;) { argument0[i] = random(100); } return argument0;
Funciones útiles relacionadas con arrays
Existe una serie de funciones relacionadas con arrays que pueden ser muy útiles cuando las usemos. Son las siguientes
is_array
Esta función comprueba si una variable es una array o no. Devuelve un valor booleano (true/false
).
array_length_1d
Devuelve el tamaño de la dimensión de una array de una dimensión. Muy útil para recorrer arrays sin saber cual es su tamaño. Se le pasa por parámetro la variable que almacena la array.
for (var i = array_length_1d(a); a > -1; i--;) { a[i] = -1; }
array_length_2d y array_height_2d
Para arrays de dos dimensiones, podemos saber el largo y ancho con estas funciones. Por ejemplo:
for (var i = array_height_2d(a); i > -1; i--;) { for (var j = array_length_2d(a, i); j > -1; j--;) { a[i, j] = -1; } }
Si nos fijamos, array_length_2d
tiene dos parámetros. Eso significa que nos devuelve el total de cada índice, ya que hemos visto que partiendo del primer índice, la segunda dimensión puede tener una longitud total de elementos diferente.
Existe la forma de almacenar las id de objetos en Arrays?
Si puedes. Tienes que tener claro si quieres usar las instancias del juego, es suficiente usando la variable id, o el objeto en sí, que puedes usar el nombre del objeto.