Teclas virtuales o virtual keys: ejemplo con botones
En el post anterior, comentamos como añadir un par de botones que podríamos usar en un juego en dispositivos móviles. Por ejemplo, en un juego de plataformas para PC, lo habitual sería que se moviese por el teclado, o en un joystick/gamepad. Si ese mismo juego que estamos desarrollando lo exportamos para un móvil, no hace falta hacer ningún cambio: añadimos los botones para que se visualicen, los relacionamos para que se activen con el teclado y nada más. Pero entonces, si no hay teclado en un móvil o tablet, ¿como se utilizarían estos eventos? Ahora es cuando entramos con las teclas virtuales.
Qué son las teclas virtuales o virtual keys
En Game Maker Studio, no sé si en otros programas o lenguajes también lo hacen de la misma manera, existe un concepto para relacionar un evento de teclado con un trozo de la pantalla (del móbil o tablet). Esto es lo que hace exactamente una virtual key: decimos el área de nuestro dispositivo que cuando se toque reaccione igual que si pulsamos una tecla determinada.
Para los eventos de ratón no es necesario definir nada extra. Si tenemos un evento Left Pressed, se asocia directamente con el tap de la pantalla. Con el botón derecho, Game Maker especifica que lo han relacionado con el doble tap de la pantalla. Con los eventos globales del ratón ocurre lo mismo, no hace falta programar nada para que funcione bien.
En los eventos de teclado, podemos añadir los botones necesarios, y en ellos podemos añadir la tecla virtual. El área que definimos será el mismo que ocupe el botón, así que sabiendo dónde está ubicado sería suficiente, aunque veremos que algún problema nos puede dar.
Funciones GML de virtual keys
Con las acciones que vemos a la derecha, del editor de objetos, no podemos gestionar de ningún modo teclas virtuales, así que toca pasar por escribir código GML (como la mayor parte de cosas avanzadas).
Existen 4 funciones principales para gestionar virtual keys.
virtual_key_add(x, y, w, h, keycode)
Con esta función añadimos una nueva tecla virtual. Vemos que nos piden en los parámetros la posición X/Y, y el tamaño del ancho y alto. El último parámetro es para decir que tecla es la relacionada.
virtual_key_show(index)
Para poder depurar el área y posición de nuestra tecla virtual, podemos usar esta función para que muestre que zona es la afectada. Lo habitual es ver un rectángulo blanco, aunque podemos modificarlo con las funciones de dibujo que tenemos. Para testear nos sirve tal cúal se ve.
En la función nos pide como parámetro index, este parámetro se refiere al índice de la tecla virtual.
Volviendo a nuestros botones creados, si añadimos en nuestro evento Create este código GML
///Virtual Key LEFT v_left = virtual_key_add(x, y, sprite_width, sprite_height, vk_left); virtual_key_show(v_left);
podemos ver al compilar (sí, muestra la tecla virtual cuando lo lanzamos para Windows aunque no la podemos usar) que el área ocupa todo el botón. La variable v_left
tiene el índice que le pasamos luego para mostrar en virtual_key_show()
.
Recordemos de quitar o comentar la última línea cuando tenemos nuestro proyecto definitivo, para que pueda verse el botón. Yo suelo mostrarlo cuando compilo en modo debug, y sustituyo la línea por esto
if debug_mode virtual_key_show(v_left);
De esta manera me olvido cuando creo el fichero definitivo a exportar, usando la variable debug_mode
, que devuelve true
si compilamos con la opción Run in debug mode o pulsamos la tecla <F6>.
virtual_key_hide(index)
Con esta función podemos esconder la tecla virtual mostrada.
virtual_key_delete(index)
Elimina la tecla virtual, eliminando los eventos asociados al área que teníamos adjudicada. Hay un tema importante que hay que tener en cuenta: cuando la room finaliza, se elimina automáticamente la tecla virtual (sin usar la función). Esto es muy útil si tenemos rooms con opciones de menú antes de nuestro juego, ya que Game Maker lo hace automático (y nos olvidamos). Pero tenemos que vigilar en que eventos creamos nuestras virtual keys, ya que si tenemos muchos niveles de un juego en diferentes rooms, debemos crear la virtual key en cada room. Un error común sería hacer que los objetos de botones sean Persistent, para no añadirlos en cada nivel de nuestro juego, pero debemos de cambiar el evento de creación. En el evento Create solo se ejecutaría una sola vez, así que en la siguiente room no funcionaría. Una opción fácil sería cambiarlo al evento Room Start
.
Problemas con virtual keys
Parece muy fácil de usar las virtual keys, ¿verdad? Creas un objeto botón sencillo, añades un par de líneas y ya funcionaría en nuestra tablet o móvil. Pero vamos a ver un problema muy común que vamos a tener, dependiendo del juego que hagamos. Es muy posible que estés usando views en tu juego. Y si estás usando views, es probable que estés usando ports, o lo que es lo mismo, estás haciendo zoom en tu juego (la parte de zooms lo abordaremos en próximos posts para reescalar en dispositivos Android). Empezamos con un ejemplo.
Vamos a activar las views en nuestro juego, poniendo el tamaño total de nuestra room, que en nuestro caso es de 800×480, en las opciones de View in room y Port on screen. Os muestro como queda:
Ahora cambiamos los valores de port incrementado en un 50%, poniendo en W 1600 y H 240. Vemos el área del virtual key:
¿Qué ha pasado? ¿No estábamos cogiendo los valores del botón? Sí, y coincidían mientras no usemos port en vistas, pero ahora son diferentes. ¿Porqué? Porque los parámetros que se pasan en virtual_key_add()
son los parámetros de la pantalla del dispositivo, no los del juego. Para entenderlo, ponemos un ejemplo radical: imagina que hacemos un juego con estética retro, como un tetris, y no necesitamos una room más grande de 320×240. Exportamos nuestro juego en nuestro móvil, que puede tener fácilmente 1920×1080 de resolución. ¿Qué hace Game Maker? Pues lo ampiará hasta el tamaño máximo de pantalla. Si hemos definido una tecla virtual de 64×64 píxeles, eso es lo que hará en el móvil. Así que tenemos un problema para solucionar.
¿Como solucionarlo?
Está claro que debemos definir el tamaño del área de nuestra virtual key, dependiendo de dónde se juegue, y que cambie resultando si estamos usando un iPhone 4S o un iPad 2. Yo he usado una solución estándar que vamos a explicar.
Cuando estamos diseñando nuestra room, podemos crear una grid para ajustar los objetos y que queden alineados. Yo creo los botones ajustándolos en esa grid para que queden bien alineados. En nuestro ejemplo, la grid es de 64 píxeles. Vamos a numerar cada casilla de la grid para ver dónde quedan los botones
Vemos que el primer botón está en la casilla x=1, y = 6. Así que vamos a modificar el código para que quede así:
///Virtual Key LEFT /* Si creamos juegos en pantalla completa, móvil o tablet, mejor utilizar en device_width la función display_get_width(); */ device_width = window_get_width(); grid_size = device_width / 12.5; xx = grid_size * 1; yy = grid_size * 6; v_left = virtual_key_add(xx, yy, grid_size, grid_size, vk_left); virtual_key_show(v_left);
En la variable device_width
guardamos el ancho de nuestro room con window_get_width()
. Usamos esta función porque, tal y como comento en el código, si nuestro juego es una ventana (no está en pantalla completa), o dentro del navegador, si es HTML5, no podríamos usar display_get_width()
, ya que esa función se utiliza para saber el tamaño del ancho de la pantalla completa.
La variable grid_size
calcula el tamaño de la casilla a utilizar. Si no ampliamos nuestro juego con views, o jugándolo en pantalla completa, el tamaño sería el que vemos en la imagen del editor de rooms, 64 píxeles. Si usamos el port o zoom de la vista, entonces este tamaño cambiará y se adaptará a la perfección.
En las variables xx
e yy
, almacenamos la posición que quedaría con el cálculo.
Ahora solo falta modificar la función virtual_key_add()
, añadiendo la posición calculada. Como el tamaño de los botones coincide con la casilla, podemos usar grid_size
para definir el ancho y el alto de nuestra tecla virtual.
Conclusión
Si queréis ver como queda el código, os dejo este proyecto modificado. Un último apunte: los botones se han añadido tal cual en la room, si hacemos una vista que se va moviendo por toda la room, los botones también se desplazarán y pueden ocultarse. Cuando hagamos ejemplos de juegos, ya haremos todas las adaptaciones también para móvil. Queda pendiente para un futuro post como crear un pad de 360 grados para que funcione de una manera similar a un tecla virtual.
¿Que os parece el uso de las virtual keys? ¿Queda suficientemente claro? No dudéis en preguntar en los comentarios.
¡Hola amigo! Muy buen post (y encima en español) sobre la introducción a las virtual keys, me aclaró bastantes dudas, muchas gracias 😀
Pero tengo un problemilla. Mi juego emplea views para seguir al personaje, entonces lo que hago es agregar los botones y las virtual keys. Con las VK no tengo problemas, ya que se quedan quietas en la misma posición todo el rato, pero con los botones (el dibujo basicamente) se mueve arriba, abajo, izquierda, derecha… hacia donde se mueve el jugador antes de regresar a su posición original. El código que les tengo es muy simple, en el evento Step pongo x e y en función de view_xview y view_yview, pero no consigo que se estén quietos en la misma posición como las Virtual Keys. ¿Tú sabrías cómo arreglar esto?
¡Gracias y suerte con tu web!
Buenas Marco,
, no con Draw
. Ese evento funciona de la misma manera que las virtual key, pinta basándose en la pantalla, da igual el tamaño de la room o de la view.
si tienes los botones como si fuesen objetos, lo más fácil es como tú dices, colocarlos con la posición X/Y con view_xview y view_yview.
La otra opción más fiable es usar un objeto controlador que sólo pinte los sprites de lo botones, y pintarlos con el evento Draw GUI
La ventaja es que en el ejemplo ya tienes el X/Y, ancho y alto de la tecla virtual, así que podrías usar esos mismos valores.
¡Ya me dirás si te funciona!
David
Vaya, así que para esto servía Draw GUI… xD ¡Muchísmas gracias, David!
Cuando activo el código y con draw gui , igualmente aparece el rectángulo blanco , no hay manera de desaparecerlo o camuflarlo ? , si la hay podrías explicar el código ?
El rectángulo blanco se utiliza para ver dónde queda la tecla virtual, que se hace con la función
virtual_key_show(index);
No es obligatorio mostrarlo para que funcione, yo solo lo hago cuando ejecuto en modo debug. Igualmente, con la función
virtual_key_hide(index)
puedes esconderlo.Buenas men, buen post! Muestras muy buena info! Tengo una inquietud a ver si podrán ayudarme por aquí… Utilizo el evento Draw_GUI y diseño las teclas virtuales, en eso no hay problema, el detalle está cuando muevo al personaje, ya que lo tengo con una cámara de seguimiento, y al llegar al borde, simplemente el personaje pareciera tomar más velocidad con respecto a la cámara que lo sigue y se pierde de la pantalla. Qué podría estar sucediendo? Gracias de antemano.
Es posible que haya llegado al final de la room y salga fuera de ella, y la vista siempre se queda hasta el límite de la room.
Si, modifiqué y estoy haciéndolo solo con el evento Draw, funciona bien, pero el detalle está cuando cambio de dispositivo y las resoluciones son diferentes, modifica al parecer las coordenadas de los botones y es todo un lío 🙁
SI, al cambiar la resolución tienes que hacer lo que comento en el post: dividir en áreas la pantalla y decir que la tecla virtual es el área (1,6).
Ya lo puedes decir que es un lío hasta que aciertas…
Buenas! toda esta info me vino de lujo, pero me esta surgiendo otro problema con el virtual_key.
Resulta que mi personaje hace un doble salto, en Modo Windows con la BARRA, pulsando una y de nuevo cuando esta en el aire, una como Key_pressed y ya en el aire, key_check
cuando programo mi botón digamos “B” para android le digo que con “vk_space” salta, cuando pruebo el juego, el personaje salta, pero al apretar de nuevo dicho botón de salto, no lo hace… como puedo hacer?
gracias!!!
Entiendo que si pulsas dos veces la barra, deberías de chequear dos veces con key_pressed, entiendo que en el evento Step.
Lo que puedes hacer es crearte una variable
salto = false;
y cuando pulsas una vez
if (salto == false){
salto = true;
//código del salto
}
para la segunda vez añades un else
else {
//codigo del salto en el aire
salto = false;
}
También deberías de desactivar la variable una vez ya no esté en el aire.
creo que no me estoy expresando como es devido, me seria mas facil compartir pantalla y mostrar el problema, no se bien como explicarlo por aca, tejo mi Discord por si alguien puede ayuarme!
PoTTi#8969
Desde ya muchisimas gracias!
No puedo dar soporte individualizado, ¡sino se me va la vida!
como puedo hacer que el virtual key sea invisible
Si has puesto
virtual_key_show()
, puedes ocultarlo convirtual_key_hide()
como ajustar que los virtual keys no se salgan de su posición en una tableta o celurar
En el ejemplo lo explico, no es lo mismo la room que el tamaño de la pantalla, y las virtual keys funcionan con el tamaño de la pantalla.
Es la solución que comento de dividir la pantalla en una grid y usar esos valores.