Los eventos de Game Maker Studio 2
Ahora que ya hemos hablado de objetos, el siguiente paso es hablar de los eventos en Game Maker Studio 2. Ya podemos imaginarnos que es un evento: es cuando sucede algo en un momento concreto de nuestro juego. ¿Cuando? Depende: cuando empieza el juego, cuando se crea un objeto, cuando se pinta un sprite, etc…
Una vez que ya sabemos cuando, nos interesa saber el qué hará el objeto en el juego en ese momento. Para eso arrastraremos acciones o escribiremos código en GML, pero de eso hablaremos en próximos posts. Recordemos otra vez todos los eventos genéricos que puede tener un objeto.
Tenemos alguna novedad con respecto a versiones anteriores de Game Maker Studio, así que lo mejor es empezar a detallar cada uno de ellos para ver en que momento es mejor usarlos.
Evento Create
Este evento ocurre cuando se crea una instancia del objeto, y es lo primero que ocurre en la instancia colocada en la room, a través del editor, cuando se abre en el juego. Es el lugar ideal para inicializar variables, iniciar timelines, paths, etc. También es útil si queremos que se ejecuten cosas sólo una vez, o solo cuando se crea una instancia por primera vez en la room.
Recuerda que también puedes modificar cualquier cosa en el código de creación de la instancia, botón derecho en el editor de rooms encima de un objeto, la opción de menú Instance Creation Code, y se ejecuta justo después del evento Create que estamos comentando.
Evento Destroy
Este es el evento que se ejecuta cuando se destruye la instancia. No siempre utilizamos este evento cuando los objetos se eliminan, pero lo podemos usar para crear efectos de explosión o de partículas cuando se destruye un enemigo, o para volver a generar una nueva instancia del objeto en otra parte de la room, o añadir puntos al score global…
Evento Clean Up
Este es nuevo en la versión Game Maker Studio 2. Se llamará después de cualquier evento que elimine una instancia del objeto de la room, por lo tanto, se activará si la instancia se destruye, es decir la destruyes tú, o si la room termina, o si el juego acaba. Está pensada para que podamos limpiar todos los recursos dinámicos que puedas tener en tu juego (sobretodo estructuras de datos) o para realizar cualquier tarea que necesites una vez se elimina la instancia. Ten en cuenta que este evento se llamará solo después de que se haya llamado a cualquier otro evento, por lo que siempre será el último que se ejecutará de cualquier instancia.
Evento Alarm
El evento de alarma se divide en 12 subeventos, uno para cada una de las posibles alarmas que podemos configurar en una instancia. Por lo tanto, al hacer click en el botón agregar alarma se presenta una ventana que va desde la alarma Alarm 0 hasta la Alarm 11. Recuerda que las alarmas sólo se activan si la hemos configurado previamente con su propia acción, dándole un valor numérico. Ese valor irá disminuyendo en cada paso/step del juego, y cuando llegue a 0 se ejecutará el código o acciones que hayamos configurado. Una vez que se ha ejecutado el código, la alarma tendrá valor -1, dónde permanece así hasta que se vuelve a activar. Así si su valor es superior a -1, podemos saber si la alarma está funcionando o no.
Poner una alarma a 0 no hará que se ejecute su código, ya que lo único que hace es poner su valor a -1 en el paso siguiente, debemos ponerlo a 1 para que pase a 0, ejecute su código y luego pase a -1. Si queremos usar las alarmas con segundos, podemos usar la variable room_speed para saber cuantos pasos ejecuta en un segundo. Por ejemplo 3 * room_speed serían 3 segundos.
Otra cosa a tener en cuenta es que una alarma sin acciones no se ejecutará, es decir, no hará la cuenta atrás. Sin embargo, sólo con poner un comentario, sin acciones ni código, la alarma se activará y contará hacia abajo como nos interesa.
Evento Step
Game Maker Studio 2 divide el tiempo en pasos o step, que es como se define la velocidad en la room. Estos pasos que definimos son los que se ejecutan en un segundo. Un paso es básicamente el bucle que se ejecuta constantemente con todos los eventos que se controlan y se activan según sea necesario mientras el juego se ejecuta, así que el evento step se comprueba en cada paso mientras la instancia existe.
El evento se subdivide además en Step, Begin Step y End Step. Lo habitual es usar el primero de ellos, pero a veces quieres tener un poco más de control sobre el código que se ejecuta y en que momento, por lo que se proporcionan los otros dos. Los tres se comprueban en cada step y el orden siempre es el mismo.
Evento Collision
En un juego es muy importante detectar cuando dos o más instancias de un objeto han colisionado, y para esos sirve este evento. En este evento que colocamos en un objeto le decimos contra que otro objeto debe comprobar la colisión.
Si no hemos activado las físicas, estas colisiones se calcularán en función de la máscara de los objetos (por defecto el sprite que tiene asignado en ese momento, pero puedes asignar una máscara diferente en las propiedades del objeto), que comprueban si se superponen o no.
Hay que tener en cuenta que si una de las instancias de la colisión no tiene máscara asignada no se detectará la colisión (no saltará el evento). Con las físicas activadas las colisiones funcionan de manera diferente, pero al menos en el evento tendrá que tener un comentario si quieres que sea detectada.
Eventos Keyboard , Keyboard Press y Keyboard Release
Uno de los aspectos más importantes de un juego es dejar que el jugador pueda controlarlo mediante inputs de entrada. Los más comunes pueden ser el teclado, el ratón o un pad. Para el teclado, existen una serie de eventos, con una lista super completa de subeventos, para saber en todo momento que pasa con las teclas del teclado.
Tenemos tres principales eventos: uno que se ejecuta una sola vez cuando se pulsa una tecla, otro que detecta en todo momento si la tecla está pulsada, y por último el que detecta cuando la tecla se ha dejado de pulsar. En cada uno de estos eventos tendremos una lista de subeventos con cada una de las teclas que tiene el teclado: letras, números, teclas especiales, teclado numérico de la derecha, incluso si pulsas cualquier tecla o ninguna (si queremos saber si no lo están pulsando).
Evento Mouse
El evento contiene una serie de subeventos que nos permite tener un control más parecido de lo que está sucediendo en nuestro juego. Tenemos subeventos relacionados con los diferentes botones que podemos hacer click: el botón izquierdo, el derecho y el botón central. También lo tenemos separado al igual que con el teclado, cuando se pulsa un botón (cualquiera de los tres), si se mantiene pulsado o cuando se deja de pulsar. Todos estos eventos funcionan con la máscara de la instancia que tiene el evento, así que podemos decir que se gestionan como si fuera una colisión. Si el objeto no tiene máscara asociada no funcionará.
También tenemos los eventos Mouse Enter y Mouse Leave, que son parecidos a los que hemos comentado anteriormente porque depende de una máscara, que detecta cuando el cursor del atón toca la instancia o cuando lo deja. Pero estos eventos no son continuos y solo se activan una vez para cada vez que el cursor entra o sale del objeto. Es ideal si estamos creando botones.
Finalmente, tenemos otra sección para las opciones globales. Aquí detecta cunado un botón del mouse se pulsa, pero no en el objeto de la room sino en cualquier punto de ella. Así que tenemos este evento global en varias instancias se generará para todas ellas, independientemente de la posición del ratón en la room.
En dispositivos móviles o con pantalla táctil, el botón izquierdo del ratón se puede usar como si ha hecho un tap en la pantalla, y el botón derecho como si se ha hecho doble tap.
Evento Gesture
Este evento detecta diferentes opciones en la pantalla del juego, relacionado principalmente como un evento de pantalla táctil (aunque también tiene su equivalencia con el mouse). Tenemos varios subeventos: tap, doble tap, inicio al arrastrar, mientras arrastramos, taps globales…
Cuando se lanza el evento, se genera un mapa especial en la variable event_data
, dónde tendremos una serie de datos para saber que está ocurriendo en ese momento.
Aquí tienes en detalle para ver los diferentes ejemplos de cada subevento.
Evento Other
Hay una serie de eventos especiales que podemos usar cuando hacemos nuestros proyectos, y que en su mayoría se agrupan en en este evento. Vamos a ver el detalle de cada uno de ellos:
Outside Room
Se desencadena cuando una instancia sale de la room, y se realiza basándose en el sprite asignado, cuando ha salido totalmente de la room. Si la instancia no tiene sprite, entonces se usa la posición de la instancia y se activa cuando su X/Y está fuera de la room.
Este evento se suele usar para liberar memoria una vez han salido de la room, como pueden ser las balas.
Intersect Boundary
Este evento se desencadena cuando una instancia toca el borde interior de la room, y también se basa en el sprite que tiene, da igual si el sprite tiene sus propiedades modificadas (como puede ser su tamaño mediante escalado). Si la instancia no tiene sprite, lo mismo.
Se suele usar para que rebote en la pared de la room.
Views
Las vistas se definen normalmente en el editor de rooms, y se utilizan para mostrar solo una pequeña área de una gran room. Este evento tiene su propia lista de subeventos que se divide en dos categorías: outside view y intersect boundary, con 8 eventos diferentes correspondiente a todas las vistas que podemos tener. Estas dos categorías funcionan igual a las que hemos comentado arriba, sólo que funcionen en el límite de la view con la instancia.
Game Start
Este evento especial se activa solo una vez en todo el juego y sólo para aquellas instancias con acciones o código colocadas en el evento. Las instancias deben estar colocadas en la primera room del juego, desde el editor de rooms y no creadas dinámicamente. Este evento ocurre después del evento Create de todas las instancias, así que puede haber acciones, como variables, que se crean previamente antes del evento.
Este evento suele definirse solo en un objeto, que solemos llamar controller, y suele usarse para inicializar variables globales, empezar música o leer archivos de datos.
Game End
Al igual que el evento anterior, este evento se activa una vez en todo el juego y justo antes que la ventana del juego se cierre. Recuerda que hay dispositivos móviles que no cierran el juego, así que este evento puede que no se ejecute.
Suele usarse este evento para guardar datos.
Room Start
Este evento ocurre para todas las instancias en una room cuando empieza. Ocurre después del evento de creación y por lo tanto depende de las variables y cosas que hemos definido previamente.
Room End
Este evento ocurre en todas las instancias cuando una room termina. Es muy útil para limpiar cosas después que un nivel haya terminado, como recursos cargados, partículas, memoria de datos creados, etc.
Animation End
Sabemos que los sprites no son estáticos, que contienen subimágenes que pueden ser animadas a diferentes velocidades. Cada frame de la animación tiene su propio número, empezando por 0, que podemos comprobar en todo momento por código, pero a veces nos interesa saber cuando una animación ha terminado. Para eso se desencadena este evento, justo al final de la animación cuando el índice de la subimagen muestra el último fotograma.
Suele ser útil para configurar que una instancia se destruya cuando acaba la animación, como puede ser una explosión.
Animation Update
Este evento solo se usa cuando usamos las funciones de animación de esqueleto (con Spine). Es un evento especial que se activa en cada step en una instancia que usa este tipo de animación, y sirve para interceptar los datos del esqueleto justo después que la orientación se ha calculado para la animación actual.
Animation Event
Este evento también es para funciones de esqueleto. Se utiliza para capturar y transmitir datos de la animación del sprite tal y como se han definido en el editor. En el evento se crea un mapa llamado event_data, que contiene la siguiente información:
- name: el nombre del evento (como se define en el programa de animación).
- track: el índice del track de animación que está reproduciéndose (por defecto a 0).
- integer: un valor entero asociado al evento.
- float: un valor flotante asociado.
- string: un valor de cadena asociado.
Path Ended
Los paths o rutas son una parte importante de cualquier juego, ya sea en un juego de tipo tower defense, un shotem’up, y es interesante saber cuando llega al final de su ruta. Este evento detecta esto y se dispara cuando sucede, por lo que podemos añadir código o acciones, por ejemplo para destruir la instancia o disminuir la salud de nuestro objeto principal.
User Events
Estos son eventos especiales que no se activan por Game Maker Studio 2, pero pueden ser llamados desde código mientras el juego se ejecuta. De esta manera podemos crear nuestros propios eventos que suceden cuando decidamos.
Evento Draw
Este evento se rige por lo que vemos en pantalla cuando se ejecuta el juego, y tenemos varios subeventos para controlar como queremos pintar las cosas. Por defecto suele usarse el evento Draw , que siempre se llama para cada instancia, independientemente de si tiene sprite o no (pero si marcamos el objeto como invisible el evento no se activará). Si el objeto tiene un sprite por defecto, el sprite se pinta sin tener que escribir nada en este evento.
Los eventos de Draw se ejecutan antes que Draw GUI, y entre los eventos Pre Draw y Post Draw, así que todo lo que se dibuja se hace por debajo de lo que ponemos en Draw GUI, independientemente de la capa de cada instancia o la que tiene el evento.
Evento Asynchronous
Este evento es especial, porque no se activa de forma predeterminada por GMS 2, sino más bien al final de alguna otra acción, como la carga de un fichero o la respuesta de un servidor web.
Por lo tanto, si queremos añadir un fichero de imagen a un objeto, podemos mostrar una barra de carga hasta que finaliza (se lanza el evento asíncrono), y así sabemos que se ha cargado.
Ya hablaremos en detalle de todos los eventos asíncronos de los que disponemos en Game Maker Studio 2.
Descripción en los eventos
Ahora que hemos descrito cada evento, volvemos a recordar que los eventos puedes ponerles una breve descripción que se mostrará junto a ellos en el editor de eventos. Simplemente añadiendo en la primera línea del editor de código algo parecido a esto
/// @description Aquí la descripción
en la ventana de eventos se verá así:
Orden de los eventos
Debemos de pensar que los eventos suelen tener un orden exacto, porque depende del funcionamiento de GMS 2. Así que es interesante saber ese orden para saber como y dónde colocar ciertas partes del código. El orden de creación es:
- Evento Create de cada instancia.
- Instance Creation Code, si está definido en la instancia de la room-
- Evento Game Start, que se activa solo la primera vez que se inicia el juego.
- Room Creation Code de la room, si lo hemos definido.
- Evento Room Start, de todas las instancias definidas.
Recuerda que las instancias tienen un orden establecido en la room, así que podemos cambiar el orden del evento Create de cada instancia en el editor de rooms.
También tenemos un orden en los tres eventos de step y los diferentes eventos de draw.
- Evento Begin Step.
- Evento Step.
- Evento End Step.
- Evento Pre Draw.
- Evento Draw Begin.
- Evento Draw.
- Evento Draw End.
- Evento Post Draw.
- Evento Draw GUI Begin.
- Evento Draw GUI.
- Evento Draw GUI End.
Y hasta aquí llega el listado de eventos que nos encontramos en Game Maker Studio 2. La gran mayoría ya los conocemos, y funcionan de la misma manera, aunque tenemos un par de nuevos que veremos en detalle en próximos posts.
Pues vaya molestia que primero se ejecute el evento create y despues game_start.
Digamos que quiero crear una macro llamada maxPS, con el maximo de salud del jugador.
Esta variable solo se crea una vez al comenzar el juego. En el evento create del jugador tengo PS=maxPS. Pero al hacerse esto primero, el juego se cuelga.
¿Hay algun modo de darle la vuelta al orden de los eventos?
No puedes cambiar el orden de los eventos, debes buscar otra manera de hacerlo.
Entiendo que la variable
maxPS
es global, así que se debería llamarglobal.maxPS
. Es posible que tengas el error por ahí.Yo suelo tener un objeto controlador llamado
obj_controller
, y ahí pongo todo lo que sería global, por ejemplo el número de vidas del player, si se escucha o no música, etc. Ahí yo pondría la variableglobal.maxPS
para que se use en otros objetos. También es posible que te interese que sea Persistente, para que esté en todas las rooms.Solo tienes que asegurarte que está en la primera room y que es la primera instancia que se crea de todos (mira el orden en el diseño de la room.
Qué diferencia hay entre CREATE y DRAW para una instancia?
Tal y como lo entiendo, solo se diferencian en que CREATE se ejecuta primero, y en qué DRAW no se ejecutará si el objeto no tiene sprite o es invisible.
Create se ejecuta cuando se crea el objeto, ya sea porque lo has colocado en la room (y se inicia), o lo creas mediante Drag&Drop o con
instance_create()
.Draw se ejecuta varias veces por segundo cuando tiene que dibujar algo, ya sea un sprite asociado o porque tiene código en su evento (para dibujar texto, otros sprites, etc). Si tienes código en el evento y el objeto es invisible, no se ejecutará.