Como usar grids en nuestro juego
Una grid en Game Maker Studio es como una array de dos dimensiones, pero que tiene funciones especiales que podemos aprovechar para situaciones específicas.
A diferencia de las arrays, cuando se crea la grid hay que darle una altura y una anchura determinada, y dentro podemos almacenar cualquier número o cadena (o mezclar ambos).
Tal y como hemos comentado en cada estructura de datos, una grid también tiene un accesor para poder acceder a los datos sin tener que usar las funciones de sistema. Se escribiría así
nombre_grid[# xpos, ypos];
Veamos algún ejemplo para usar grids.
Ejemplos de uso de grids
Las grids se utilizan casi siempre para dividir la room en zonas, de manera que podamos usar cada zona para saber que está ocurriendo en cada momento.
Un ejemplo sería en cualquier juego de puzzles, tipo Tetris, Candy Crush Saga, etc, dónde tenemos unas casillas definidas y necesitamos saber que objeto hay en cada casillas, para calcular sus movimientos, posibles objetos a mostrar, etc.
En la web de YoYoGames explican un ejemplo, podéis verlo aquí.
Otro tipo de uso de las grids sería en juegos de tableto, como puede ser un ajedrez, Go, etc.
También se utiliza para la creación de escenarios, ya que permite explotar una de las funciones más importante del uso de grids: la posibilidad de crear rutas.
Un ejemplo que considero brutal de creación de escenarios tio roguelike, aunque no use grids, es la explicación de Spelunky.
Funciones útiles de grids
Las grids tienen muchas más funciones que cualquier otra estructura de datos, así que vamos a comentar las más importantes.
Como siempre, necesitamos crear la grid
mapa = ds_grid_create(20, 20);
Recuerda que una estructura de datos hay que borrarla con su función específica, que es éstA:
ds_grid_destroy(mapa);
Para controlar y saber el tamaño de la grid, tenemos las siguientes funciones:
ds_grid_width(mapa); //ancho de la grid ds_grid_height(mapa); //altura de la grid ds_grid_resize(mapa, 40, 40); //cambiar tamaño de la grid
Gestión de datos de una grid
Para gestionar datos de una grid, podemos limpiar la grid
ds_grid_clear(mapa);
Dar un valor concreto a una celda
ds_grid_set(mapa, x, y, valor);
Aquí ya empieza las funciones específicas. Podemos rellenar de valores un área circular de una grid. Por ejemplo, desde un punto concreto, un edificio, podemos rodear de enemigos usando
ds_grid_set_disk (mapa, x_edificio, y_edificio, radio, valor);
¿Os acordáis de cuando comentamos el movimiento de un personaje de una grid? Pues una manera más efectiva sería con esta función, aunque también hay que controlar si una casilla está ocupada y se puede hacer ese movimiento.
Seguimos. Imaginamos que queremos copiar un área, cuadrada o rectangular, de una grid en otro punto (de la misma grid o no). Se podría hacer con un par de bucles, pero existe una función específica para poder hacerlo
ds_grid_set_grid_region (mapa_origen, mapa_destino, x1, y1, x2, y2, x_nuevo, y_nuevo);
Si queremos seguir olvidándonos de bucles, podemos rellenar un área rectangular de un valor concreto
ds_grid_set_region(mapa, x1, y1, x2, y2, valor);
Si una vez rellenada la grid queremos mezclar todos sus valores, podemos hacerlo con
ds_grid_shuffle(mapa);
Recuerda que cuando hablamos de aleatoriedad, usamos la función randomize() para que los datos se mezclen de manera diferente cada vez.
También podemos ordenar una parte de la grid, concretamente una columna
ds_grid_sort (mapa, columna, true);
el último parámetro es para decidir si quieres la ordenación ascendiente o descendiente.
Si queremos recuperar un valor, tenemos la función
ds_grid_get (mapa, x, y);
Cálculo de datos de una grid
Podemos también podemos buscar un valor en un área. Si queremos buscar el valor más grande en toda la grid o una zona concreta
ds_grid_get_max (mapa, x1, y1, x2, y2);
y el valor más pequeño
ds_grid_get_min (mapa, x1, y1, x2, y2);
También podemos calcular la media de todos los valores numéricos de un área. Se me ocurre que esto puede ser útil si tenemos enemigos con un valor de nivel (nivel 1, nivel 2, nivel 3) y queremos saber si con una media nos podríamos enfrentar
ds_grid_get_mean (mapa, x1, y1, x2, y2);
También podríamos sumar los valores de una zona
ds_grid_get_sum (mapa, x1, y1, x2, y2);
Todas estas funciones son para un área rectangular, pero también existen su equivalente para un áre circular
//el valor más alto de un área circular ds_grid_get_disk_max (mapa, x, y, radio); //el valor más bajo de un área circular ds_grid_get_disk_min (mapa, x, y, radio); //Cálculo de la media de un área circular ds_grid_get_disk_mean (mapa, x, y, radio); //suma de valores de un área circular ds_grid_get_disk_sum (mapa, x, y, radio);
Incremento de valores de una grid
Imaginamos que tenemos controlados unos enemigos que están colocados en una grid. Por alguna acción, venga ¡que sea un hechizo!, queremos que el nivel del enemigo aumente en 1. Si queremos arrinconar la gestión de bucles, podemos usar funciones que aumenta el valor de una grid.
Si queremos aumentar el valor de una celda
ds_grid_add (mapa, x, y, valor_incremento);
De un área cuadrada
ds_grid_add_region (mapa, x1, y1, x2, y2, valor_incremento);
Un área circular
ds_grid_add_disk (mapa, x, y, radio, valor_incremento);
También podemos sumar entre dos áreas. Imaginemos que tenemos un área cuadrada, la que comprende las coordenadas (3,2)(6,5) y queremos sumar sus valores en otra zona , coordenadas (7,7).
Podemos sumar los valores de la cuadrícula que tenemos, así que el área afectada sería en (7,7)(10,10).
ds_grid_add_grid_region (mapa_origen, mapa_destino, 3, 2, 6, 5, 7, 7);
Si en vez de sumar queremos multiplicar el valor, tenemos sus funciones equivalentes
ds_grid_multiply (mapa, x, y, valor_incremento); ds_grid_multiply_region (mapa, x1, y1, x2, y2, valor_incremento); ds_grid_multiply_disk (mapa, x, y, radio, valor_incremento); ds_grid_multiply_grid_region (mapa_origen, mapa_destino, 3, 2, 6, 5, 7, 7);
Búsqueda de valores de una grid
Podemos buscar un valor concreto en un área de una grid. Por ejemplo, para buscar en un área rectangular usamos el método
if ds_grid_value_exists (mapa, x1, y1, x2, y2, valor) == true { //código }
También tenemos una función para un área circular
if ds_grid_value_disk_exists (mapa, x, y, radio, valor) == true { //código }
También podemos buscar una coordenada concreta. Vamos a imaginar que queremos saber en que posición hay una pócima dentro de un área. Para saber las coordenadas X/Y
xpos = ds_grid_value_x ((mapa, x1, y1, x2, y2, valor); ypos = ds_grid_value_y ((mapa, x1, y1, x2, y2, valor);
Y para buscar en un área circular
xpos = ds_grid_value_disk_x ((mapa, x1, y1, x2, y2, valor); ypos = ds_grid_value_disk_y ((mapa, x1, y1, x2, y2, valor);
Gestión entre grids
Como en todas las estructuras de datos de Game Maker Studio, es posible copiar una grid con datos a otra
ds_grid_copy (mapa_destino, mapa_origen);
También podemos guardar los datos en un fichero. Por ejemplo, para guardarlo dentro de una clave de un fichero ini
ini_open("config.ini"); ini_write_string("config", "mapa", ds_grid_write(mapa)); ini_close();
Y para recuperar esos datos
//Siempre hay que crearla!! grid = ds_grid_create(room_width div 32, room_height div 32); ini_open("config.ini"); ds_grid_read(grid, ini_read_string("config", "mapa", 0)); ini_close();
Conclusión
Hemos visto todas las opciones y funciones para poder gestionar grids. Sé que falta un ejemplo concreto, pero al menos espero haber aclarado todas las dudas que puedan surgir.
¡Nos vemos!
Muy útil! Gracias!
Un detalle: el link de los arrays de la sección “¿Nuevo? empieza aquí” se ha perdido.
¡Gracias por el aviso!
¡Ya está corregido!
Buenas, soy nuevo en esto de Game Maker y realmente no tengo conocimientos en programación, pero me he estado esforzando por entender un poco como funciona y he estado trabajando en una idea, sin embargo me quedo atorado por mi falta de conocimiento.
Quería preguntar si me podrían orientar como hacer para seleccionar un personaje o dos y asignarles una acción sólo a los que selecciono.
Por ejemplo Tengo al Personaje A y Personaje B y Personaje C, yo doy click en Personaje A y Personaje B y luego doy click en un punto cualquiera de la room y quiero que ambos vayan a ese punto. Cómo podría hacerlo?
De antemano las gracias, y muy bueno este espacio para aprender Game Maker!
Saludos
Buenas Alex,
yo lo que haría es ponerlo en una array global, cuando haces click a un personaje añades a la array, y cuando haces click en la grid, que se muevan las instancias de la grid.
Una vez están allí, limpiar la array. Espero haberte ayudado.
David
Estoy intentando hacer un juego donde puedes colocar objetos en las grid para que quede alineado, ¿pero como debería usar las grid en ese caso?
Estamos hablando de cosas diferentes. Una cosa es el tipo de fichero llamado grid, y otra es la rejilla o grid que quieres hacer en tu juego alineado.
Busca información de la función
move_snap
para que quede alineado.