Como usar listas en nuestro juego
En su momento, hablamos en general que en Game Maker Studio podemos usar estructuras de datos, que nos facilita la tarea de almacenar y recorrer los datos que almacenamos en memoria. Sabemos que existen los arreglos o arrays, pero a veces necesitamos hacer operaciones como acceder a uno, ordenar, eliminar, desordenar, etc. y con una array, además de tener que programarlo todo nosotros, sería bastante complicardo gestionarlo.
Así que ahora vamos a hablar de una de las estructuras de datos más utilizadas en Game Maker: las listas.
¿Qué es una lista en Game Maker?
Una lista es como una array de una dimensión: es un grupo de elementos enlazados uno a uno secuencialmente. Si estás dudando entre usar una array de una dimensión o una lista, deberías de ver si en tu caso te conviene una o la otra.
Recordemos que en Game Maker los arrays pueden ir creciendo conforme le damos valores (en la mayoría de otros lenguajes de programación, los arrays tienen un tamaño fijo que decides en diseño). Pero conforme va creciendo una array, no podemos disminuir su tamaño, a no ser que la eliminemos totalmente.
Una lista funciona de una manera muy parecida, pero podemos usar métodos avanzados. Para acceder a un elemento, tenemos un índice, un número entero, para saber que hay en esa posición. Pero en una lista podemos añadir elementos en cualquier posición, al principio, en medio o al final, podemos recuperarlos con su posición, o buscar si existen (nos devolvería su posición).
Para ello tenemos una serie de funciones de sistema para manejar listas. Vamos a verlo en detalle.
Funciones para el manejo de listas
Como ejemplo, vamos a hacer un inventario simple para un personaje, dónde almacenamos todos los objetos que vamos recopilando.
Antes de nada, debemos de crear una lista. Para ello, lo hacemos de la manera siguiente:
inventario = ds_list_create();
En la variable lista almacenaremos todos los valores.
Recordemos que al final, cuando queramos eliminar los datos, debemos de llamar a
ds_list_destroy(inventario);
Para saber el tamaño total de la lista
ds_list_size(inventario);
Para saber si está vacía
ds_list_empty(inventario);
Y para vaciar (no destruir) la lista entera
ds_list_clear(inventario);
Ahora añadiremos un elemento a nuestro inventario
ds_list_add(inventario, obj_casco);
Con esta función podemos añadir hasta 15 valores
ds_list_add( inventario, obj_armadura, obj_escudo, obj_espada_basica);
Para eliminar un elemento, necesitamos saber su posición
ds_list_delete(inventario, 0);
Si no la sabemos, podemos buscar elementos por su posición (muy útil para listar todos los objetos del inventario)
for (var i = 0; i < ds_list_size(inventario); i++) { var objeto = ds_list_find_value(inventario, i); }
o buscar si existe sin recorrerla, devolviéndonos su posición (esta función es útil si necesitamos saber la posición para eliminarlo.
ds_list_find_index(inventario, obj_casco);
Si nos interesa añadir un elemento en una posición concreta, tenemos esta función
ds_list_insert (inventario, 3, obj_pocion);
Aunque también podemos reemplazar un objeto de una posición
var pos = ds_list_find_pos(inventario, obj_espada_basica); if (pos != -1) { ds_list_replace(inventario, pos, obj_espada_fuerte); }
También podemos ordenar una lista, de manera ascendete o descedente. El criterio será el tipo de dato almacenado, si e sun número o un texto. Recordemos que todos los sprites, objetos, etc, su referencia es un número.
ds_list_sort(inventario);
También podemos desordenar una lista. En el caso del inventario quizás no tenga sentido, pero yo lo uso para usar aleatoriedad en las instancias. Por ejemplo, imaginemos que aparecen tres tipos de enemigos diferentes en nuestro juego, y puede atacar uno u otro. ¿Cuál elegimos? Conforme creamos un enemigo, lo añadimos en una lista, luego la desordenamos y elegimos el primero de la lista.
ds_list_shuffle(lista_enemigos); ataca = ds_list_find_value(lista_enemigos, 0);
Y así lo puedo usar en cada ataque. Si se elimina un enemigo, ¡también hay que eliminarlo de la lista! Estamos almacenando su referencia, pero al acceder a la instancia no existirá (y nos puede dar un error).
En algunos casos nos puede interesar hacer una copia de la lista (para manejar datos temporalmente). Para ello la variable de copia debemos de crearla y tratarla de la misma manera que hemos visto
if (ds_list_empty (inventario) == false) { old_inventario = ds_list_create (); ds_list_copy (old_inventario, inventario); }
¡Y lo mismo para eliminarla!
Por último, recordar que podemos leer y guardar los datos de la lista para ficheros, con ds_list_read()
y ds_list_write()
ini_open ( "save.ini"); var str = ini_read_string ( "jugador", "inventario", ""); if str != "" { ds_list_read (inventario, str); } ini_close ();
Si mirasemos el valor de str
, seguramente no se podría leer/entender. Aunque sea una cadena, los datos son interpretados, pero al almacenarlo en la lista todo queda tal y como se guardó.
Os voy a dejar unos deberes: si en la lista no estamos almacenando tipos de datos simples, números o textos, sino objetos, ¿estará en su fichero ini todas las variables de sistema (x
, y
, sprite_index
)? ¿Y las que hemos creado nosotros? Probadlo y me contáis 😉
Accesors en listas
Los accesors o descriptores es una manera de escribir abreviada el acceso a los datos de una lista. Para crear la lista, tienes que llamar igualmente a ds_list_create()
, pero si te parece un engorro tener que llamar todo el rato a ds_list_find_value()
, existe una manera más corta y que funciona igual. Al igual que una array escribimos así:
objeto = a[10];
el accesor de una lista sería
objeto = inventario[| 0];
La diferencia es el carácter |. El código equivalente al de arriba es
objeto = ds_list_find_value(inventario, 0);
¿Como preferis escribirlo? Yo prefiero no memorizarme los accessores, ya que también existen para mapas y grids.
Resumen final
Hemos hecho un repaso de todas las funciones para usar en listas, con un ejemplo que podemos usar. Seguiremos con más ejemplo de otras estructuras de datos que pueden sernos útiles.
Genial ayuda tu web amigo! sigue así xDDD
Gracias!
Hice lo q dices pero no pude crear mi inventario no se…………..
Creo que tendré que hacer un tutorial para que se vea mejor. ¡Nos vemos!
oye amigo soy youtuber “no famoso”de creacion de juegos se hacer muchas cosas pero a la hora de hacer un inventario soy la mrd te recomiendo q te crees un canal y subas como hacerlo tendrias muchas vistas
A ver si este año puedo crearlo 🙂
Tengo una pregunta, este uso de inventario se puede hacer para soltar objetos en vez de borrarlos? y tendria memoria en rooms el objeto caido?
Es decir, añado un objeto con add al inventario… pero en otra room quiero soltarlo en el suelo… y me voy de esa room… al volver a esa room, recuerda que aun esta ese item en el suelo para poderlo coger mas adelante cuando tenga espacio por ejemplo?
O de que manera se podria conseguir esto con este inventario?
Muchas gracias
Para que ese objeto se mantenga en la room que dejas, tienes que marcar la room como Persistent, así siempre estará en memoria (cuidado con el espacio).
Aunque si quieres que esa configuración se mantenga en otra partida, debes guardarlo en un fichero.