Aleatoriedad en nuestros juegos
Cuando hacemos un juego, es muy posible que necesitemos usar la aleatoriedad, menudo palabrejo, para simular el azar: tirar un dado, lanzar una moneda, posibilidades en % de golpear o no, IA de un enemigo que puede elegir entre varios caminos, poder elegir entre varios enemigos que atacan…
Las posibilidades de uso son muchas y variadas, así que es bueno saber cuatro cosas a la hora de programar.
Para empezar, ningún ordenador hace una aleatoriedad total, pero el algoritmo que lo genera lo hace bastante bien. Por eso se llama pseudo-aleatoriedad. En Game Maker: Studio encontramos varias funciones que nos sirven para generar este algoritmo. Vamos a verlas en detalle.
Función choose()
La función choose()
permite añadir varios parámetros, hasta 15, dónde devuelve uno de ellos al azar. Me gusta esta función porque en los parámetros podemos poner cualquier cosa, no solo números: objetos, sprites, textos, etc. Por ejemplo, si tengo que elegir que salga uno de tres enemigos, pondría
enemy = choose(obj_enemy1, obj_enemy2, obj_enemy3);
Si nos interesa números aleatorios, podemos elegir alguna de las distintas funciones random()
que hay en el sistema.
Función random()
La función random()
devuelve un número aleatorio, entre 0 y el parámetro que le pasamos. Por ejemplo, random(1000)
devuelve un número CON DECIMALES entre 0 y 999. Si no nos interesa números con decimales, tenemos la función irandom()
. La función irandom es la más usada en Game Maker.
Veamos un pequeño ejemplo. En un proyecto nuevo, creamos un objeto nuevo llamado obj_random. Como nos interesa tener varios valores, lo meteremos todo en una array de 20 posiciones. En el evento Create inicializamos la variable a. Usamos el evento Global Left Released para generar los números. El código es el siguiente:
///RANDOM A for (i=0; i<20; i++) { a[i] = random(1000); }
Para ver los datos, usamos el evento Draw con este código:
///DRAW A if is_array(a) { for (i=0; i<20; i++) { draw_text(x, y + (i * 20), a[i]); } }
Hacemos la comprobación de is_array(),
sino dará error nada más empezar, porque aún no le hemos dado al botón en la room.
Al añadir el objeto en la room y ejecutar obtenemos esto:
Tiene buena pinta, ¿verdad?
Función irandom()
Si no queremos decimales, sólo hay que cambiar la función random()
por irandom()
, como hemos comentado
///RANDOM A for (i=0; i<20; i++) { a[i] = irandom(1000); }
Yo lo he hecho en un objeto nuevo. Miremos el resultado:
Función irandom_range()
Si nos interesa un rango de números, por ejemplo, entre 10 y 50, tenemos las funciones random_range()
para usar el azar entre dos números. Un ejemplo:
///RANDOM A for (i=0; i<20; i++) { a[i] = irandom_range(0, 100); }
Y su resultado:
Pero si os fijáis en las tres imágenes, vemos que ocurre algo raro. La primera columna, o todas, siempre salen con los mismos números cuando lo ejecutamos por primera vez. Da igual si lo ejecutamos hoy o mañana ¿Porqué ocurre esto?
Para facilitar la depuración del código. Diría que todos los lenguajes de programación, incluído GML, cuando llamamos a una función que genera aleatoriedad siempre devuelve el mismo número cuando se ejecuta, así podemos controlar y corregir mejor nuestro código. ¿Y como hacemos verdadera pseudoaleatoriedad? Con la función randomize()
.
Función randomize()
Cuando llamamos a randomize()
, es suficiente hacerlo una vez al principio del juego, le decimos a Game Maker: Studio que forzamos el azar y siempre devolverá números diferentes. Si queremos, podemos decir que eso sólo ocurre cuando creamos el ejecutable de nuestro juego.
if !debug_mode randomize();
Así ya sabemos que todas las funciones de azar que llamamos en nuestro juego se ejecutarán correctamente.
Función random_set_seed()
¿Y si nos interesa forzar que esos números aleatorios tengan la misma secuencia?
Existe una manera en GML de hacerlo. Game Maker: Studio nos ofrece la función random_set_seed()
, dónde le pasamos un parámetro, normalmente un número fijo, y sabemos que después la secuencia de números siempre será la misma, al igual que si no tenemos randomize()
.
¿Para que puede servir?
Por ejemplo, tenemos un enemigo que queremos que siempre pegue de la misma manera, izquierda, izquierda, derecha, centro. Podemos forzar eso en código, o podemos usar un random()
4 veces con la misma secuencia.
Recordemos de llamar luego a randomize() si queremos volver a forzar el azar en nuestro código.
En el ejemplo del final, he creado una room separada para que podáis ver que aunque llamamos al randomize()
, si después tenemos random_get_seed()
siempre saldrán los mismos números. Con el botón derecho podemos volver a usar randomize()
.
Proyecto de ejemplo
Os dejo un proyecto, para que podáis ver todo esto que he explicado. Si teneis dudas, podéis escribirlo en los comentarios.
No sabes si hay valores aleatorios “Perlin noise” o “noise”? es lo mas util que puedes usar en aleatorio en muchas cosas jaja
Buenas Nacho!
La gran mayoría de lenguajes utlizan el método de Knuth para generar números pseudoaleatorios. Pongo aquí enlaces de .NET y Android como curiosidad.
Random en .NET
Random Android
Por lo que tengo entendido, corrígeme si me equivoco, el método Knuth se utiliza normalmente para usar valores aleatorios, porque se suelen usar un valor detrás de otro, y en Perlin Noise se usa más en efectos gráficos, para simular humo, fuego, etc…
Lo importante del post es saber utilizar las funciones de
random()
y resolver las dudas de para que sirverandomize()
, que pasa cuando los números siempre salen los mismos, etc…¿Cómo hago que salga un Room aleatorio? No entiendo bien esto…
Puedes poner
rm = choose(roo1, room2, room3, room4)
room_goto(rm);
preciso ayuda para mi juego de rpg. Mi player esta sentado en una silla, pero cuando se baja lo hace siempre en una misma posición (x.y) y trae inconvenientes cuando hay un objeto posado en dicha coordenada. No doy con el codigo correcto. (Una coordenada aleatoria libre de colision, a 32 pixeles de la silla.)
if keyboard_check_pressed(vk_anykey) and global.sit_down=1
{
if !place_free(x,y)
{
x=other.x+20;
y=other.y+20;
}
Quizás en vez de usar if !place_free(x,y), deberías de hacer un bucle para comprobarlo. por ejemplo
xx = other.x;
yy = other.y;
while !place_free(xx,yy) {
xx += 20;
yy += 20;
}
x = xx;
y = yy;
Todo esto sin saber tu código!!! Es una sugerencia.
Hola qué tal uso game maker estudio 1.4 y estoy haciendo un ciclo día noche y todo bien, pero ahora quiero poner un obj rain y quiero que salga al azar cómo se vería el código puesto y dónde tendría que poner el objetivo.rain? Muy buen aporte un saludo!
Para efectos comunes como el de lluvia, yo usaría los efectos que ya tiene por defecto Game Maker. Si lo que quieres es que salga aleatoriamente, yo escribiría esto:
Y para eliminar todos los efectos (por ejemplo al salir de la room o cuando quieras:
Ante todo, muchas gracias por enseñarnos. Yo estoy empezando y para probar estoy haciendo el típico juego de marcianitos vertical. La pregunta es ¿Si tengo, por ejemplo, 20 naves enemigas, creadas del mismo objeto, como puedo hacer que disparen aleatoriamente, es decir, que varias de arriba y varias de abajo disparen. Muchas gracias.
Lo que haría yo…
Imaginemos que disparan cada 5 segundos, y entiendo que tienes una alarma configurada que
alarm[0] = 150;
oalarm[0] = 5 * room_speed;
)En el evento Create pondria este codigo:
alarm[0] = choose(30, 60, 90, 120);
Así empezaría a disparar en el primer segundo, o en el segundo, o en el tercero o en el cuarto. Así cada marciano tendría un número inicial diferente (algunos repetirían).
Si quieres que el tiempo entre disparos también sea aleatorio, puedes cambiar el dentro de la alarma.
Perfecto! Muchas gracias David por tu pronta y funcional respuesta. Un saludo.
y para que no se repitan los números?
Pon
randomize()
al principio del juego y ya está.y si en dado caso de quiera que genere letras en vez de numeros,como podria programarse?
Una opción sería utilizar chhose() de la siguiente manera:
choose(‘a’,’b’,’c’,’d’,’e’);//y así con todas las letras que te interese.
como le otorgo un valor aleatorio a una posicion determinada de un grid
¿Quieres una posición aleatoria de una grid o quieres un número aleatorio en un lugar de la grid?
Buenas, soy muy novato, y lo que quiero intentar hacer es que en una room se generen enemigos de forma aleatoria y constantemente, ¿como lo podría escribir en código y donde?
Deberías de usar una alarma, y en el evento de la alarma ya puedes hacer un instance_create(), dónde la posición x, y si que debe ser aleatoria. Un ejemplo sería:
instance_create(irandom_range(0, room_width), irandom_range(0, room_height), obj_enemigo);
Luego está si te interesa que el objeto dónde se coloque esté en una posición libre.
Hola, soy novato en game maker, esto me servira por ejemplo, mi juego sera de sumas, y en ella aparecera una leyenda que mostrara 10, entonces tengo que tocar a los objetos uno que valga 5 y otro 5 para que avance al siguiente nivel, esto me servira en game maker 2 studio?
Puedes hacerlo perfectamente en cualquier versión de Game Maker Studio 🙂
Hola yo quiero hacer un fan madera de fnaf y quiero que mi animatronico se mueva por unas cámaras limitadas, como hago para que el animatronico se mueva?
Hola,
¿a qué te refieres a que se mueva por unas cámaras limitadas? ¿Te refieres a qué siga una camino?
Que se mueva por ciertas cámaras aleatoriamente por ejemplo
Que se mueva por las cámaras 1,2,3 y 4 pero que no siga un orden predeterminado para pasar por ellas.
Si a cámaras te refieres a rooms (aunque también te servirá para cualquier recurso, números, etc.) lo mejor es usar la función
choose()
. Por ejemplo:camara_elegida = choose(cam1, cam2, cam3, cam4);
Y luego tienes la variable que ya puedes usar con la opción que haya elegido el programa.
Hola, quisiera saber si me podrias ayudar:
1. Una manera de generar mazmorras (para actionRPG) de forma aleatoria.
2. Generar enemigos en cualquier lugar de la mazmorra, siempre y cuando el lugar este libre (osea que no salga encima de otro enemigo, de un bloque o un muro, etc).
Gracias de antemano.
Para el primer punto, no existe una solución o un código específico para hacerlo, depende mucho de como será tu juego final. Te recomiendo un vídeo que vi hace poco que hablaba del tema:
Y sobre el segundo, la respuesta es casi la misma :(.
Depende de si tu juego usa cuadrícula o no, si hay objetos que pueden superponerse, como elementos del fondo, etc.
En esta entrada creaba yo objetos en posiciones aleatorias sin que se solapasen entre ellos, quizás te puedo servir:
Crear instancias aleatorias
Ey bro, no se si seguirás activo o no pero bue, aquí va mi pregunta:
Estoy creando un juego tipo pong, y lo que quiero es que la Ball vaya aleatoriamente al iniciar el juego (Una dirección aleatoria). Lo que he hecho es crear una variable Movimiento y usar la función “random (170)” y que la ball tome la dirección de Movimiento. El problema es que, por alguna razón, SIEMPRE empieza hacia el mismo sitio. Intente usar “Randomize” pero entonces no me toma la condicion “170” y se me dispara a donde se le da la gana,
Has dicho dos cosas contrarias, que siempre empieza hacia el mismo sitio y que se dispara donde le da la gana 🙂
Con que se ejecute una vez
Randomize()
al principio del juego es suficiente para que la semilla del azar lo haga como queremos.Hola, muy buenas noches desde México, no se si estás activo, pero aquí va mi pregunta…
Estoy haciendo un proyecto escolar sobre ecuaciones, el caso es que en la pantalla donde corre el personaje en la parte inferior aparece una ecuación ( 2×2 o 3×3) aleatoria y cuando se encuentre a los 3 enemigos aleatorios delante suyo en la parte de abajo aparesca la solución correcta de un solo enemigo, pero que sea aleatorio.
• ¿Cúal sería el código correcto?
• ¿Se puede?
Gracias de antemano… espero su respuesta
Poder se puede, pero es complicado explicarlo en un comentario.
Podrías meter todas las ecuaciones en una lista (o leerlo de un fichero), mezclas la lista y eliges el primero. Luego dependiendo de lo que elijas ya muestras el enemigo o las soluciones que quieras.
Por favor se que esto es de hace unos años pero nesesito de tu ayuda, no se sí yo no lo haya notado pero en el texto no dice lo de las probabilidades 🙁
no hay una función tipo:
(variable.x (25%), variable.x (25%), variable.x (50%))
?????? me refiero a una función que use chances
yo haria algo parecido a esto
switch (irandom_range(1,4))
{
case 1:
variable.x;
break;
case 2:
variable.x;
break;
case 3:
case 4:
variable.x;
break;
}
Se conseguiría lo mismo.
oye amigo estoy haciendo un juego de conquistar planetas mas o menos el de ruthles warfare y quisiera saber como hago para que la ia de las naves eliga aleatoriamente entre un planeta vacio y uno mio o de otro enemigo lo eh intentado pero siempre sigue el mismo patron
Si siempre sigue el mismo patrón, seguramente tengas que llamar a la función Randomize() antes de nada (con una sola vez al inicio del juego es suficiente)
Buen día disculpa, llevo una semana intentando pero no puedo,
quiero hacer un sistema de supongamos de cartas,
puedo hacer que el sistema elija las cartas, lo que no puedo hacer o no sé cómo sería el código o arreglo de array, para que después de que el sistema elija una de las cartas, en la siguiente selección aleatoria, no me repita la carta, gracias de antemano.
No quisiera confundirte, por eso hago otro comentario, me refiero a que si el sistema eligió aleatoriamente la carta número 4, en la próxima selección el sistema pueda elegir entre la carta 1, la carta 2, la carta 3, y la carta 5, porque la carta 4 ya la tengo en mi mano ya que la seleccionó el sistema anteriormente.
Tal y como te he dicho 😉
Yo lo meteria en una lista, lo mezclaria con la función shuffle(), y luego lo eliminaría de la lista. Piensa que al eliminar de la lista no se elimina el objeto, sólo su lugar en la lista.
Hola llevo tiempo intentando programar un sistema de seleccion de personajes de forma aleatoria y lo consegui pero quisiera que los personajes no se repitan, osea que un jugador no pueda tener el mismo personaje que el otro, me puedes ayudar?
Yo los añadiría en una lista, los mezclaría con ds_list_shuffle() y una vez uno elige a un personaje, lo eliminaría de la lista. Si vuelve a cambiar se añade.
hola esto es muy importante estoy haciendo un juego y estoy haciendo el jefe pero necesito que elija 3 tipos de disparos pero una ves que elije el juego que disparo hacer se interponen uno con otros creando algo inesquivable
prueba con la función choose(), por ejemplo:
choose(disparo1, disparo2, disparo3);
Luego ya debes de ver como hacer la distinción de cada disparo, por ejemplo con la sentencia
switch
.Hola, David tengo una pregunta Estoy creando un TD y tengo a mis enemigos siguiendo un path que tambien atacan a unos soldados el caso esta en que todos los enemys atacan a un solo soldado, como puedo hacer que si un objeto ya es el target (osea que ya esta siendo atacado por un enemigo )los demas obj lo ignoren y sigan su camino ? Gracias de antemano tus toturiales me ayudan un monton
Necesitarás meter en algún sitio (una lista por ejemplo) todos los soldados que están siendo atacados, y comparar que no esté en la lista.
Entiendo que los enemigos detectan los soldados mediante un área, y ahora puedes tener tener una lista de todos los que estén e colisión con ese área, por ejemplo con
collision_circle_list()
.Gracias me ayudara mucho para la app que estoy haciendo
(⌐■_■)