Multitouch GM:S

Como se vio en el tutorial de barridos, GMS automáticamente interpreta una pulsación en pantalla como un evento de ratón, sin embargo, dependiendo del juego y la jugabilidad, es posible que se requiera detectar simultaneamente más de una pulsación en un dispositivo táctil. Game Maker Studio ofrece la posibilidad de detectar y procesar hasta 5 pulsaciones distintas. Al parecer, algunos usuarios en comunidadgm.org han enfrentado problemas al implementar la característica multitouch, como por ejemplo, que la pulsación en el segundo dispositivo falla si no se está ejecutando una pulsación en el primer dispositivo. Este pequeño ejemplo resuelve el problema y muestra una forma de implementar el arrastre de dos objetos mediante multitouch.

Las funciones para procesar multitouch utilizan las mismas constantes que las funciones normales de lectura del ratón y la idea principal es que funcionan como si un equipo tuviera conectado multiples ratones a la vez y cada uno de estos ratones tuviera asignado un número (del 0 al 4). La principal función a usar en este caso será cualquiera de las funciones device_mouse_check_ (para más detalles, consultar el manual de GMS). El primer argumento de estas funciones es un número que indica qué dispositivo se pretende revisar. Generalmente el chequeo del dispositivo se realiza dentro de un ciclo for para aprovechar la variable del ciclo como medio de revisar uno a uno todos los dispositivos sin reescribir 5 veces la misma función. Según lo visto en comunidadgm.org, esta parte del código probablemente sea la misma o la mayoría la usa de la misma manera.

Lo que por lo general falla es que no se realiza una revisión de cuántos dedos (dispositivos) se están usando. Es decir, revisar uno a uno los dispositivos en el ciclo no es sufuciente, también se debe preguntar si el dispositivo actual no se ha asignado previamente a otro dedo, y sólo en el caso de no ser así, asignar un dedo al dispositivo actual. Si acaso esto pareciera confuso, en realidad no lo es y al ver el código se entenderá la idea de manera más clara. En este ejemplo, uso un objeto controlador porque esta es mi costumbre, pero no es necesario y el código se puede implementar sin objeto controlador. En dicho controlador he declarado un arreglo (global) para llevar un control de qué dedos se están utilizando. Este arreglo tampoco es necesario declararlo ni como variable global ni en el controlador; si se desea, la declaración se puede hacer en otro objeto y como una variable nomal. En mi caso sólo estoy siguiendo costumbres o mañas que uno desarrolla a la hora de programar. Ten en cuenta que este código está pensado para detectar dos dedos simultáneamente ya que la petición en el foro requería precisamente dos dedos, pero al entender la lógica del código el ejemplo se puede expandir hasta los 5 dedos.

Este es el código del objeto controlador [CREATE]:

globalvar finger;
finger[0] = -1        //Primer dedo
finger[1] = -1        //Segundo dedo

La soliciitud original pretendía mover dos objetos mediante multitouch. Todo el código necesario va en [STEP] de cada uno de esos dos objetos. De tal manera, en el objeto A o primer objeto:

if (finger[0] < 0)
{
    for (i = 0; i < 5; i++)
    {
        if device_mouse_check_button(i, mb_left)
        {
            if point_distance(x, y, device_mouse_x(i), device_mouse_y(i) ) < 40
            {
                if (finger[1] != i)
                {
                    finger[0] = i
                    break;
                }
            }
            else
                finger[0] = -1
        }
    }
}

if device_mouse_check_button(finger[0], mb_left)
{
    x = device_mouse_x(finger[0])
    y = device_mouse_y(finger[0])
}
else
     finger[0] = -1

Ya que se está trabajando con múltiples dispositivos (ratones), no debemos usar las variables mouse_x /mouse_y como lo haríamos en el caso normal, sino que habrá que recurrir a las funciones device_mouse_x()/device_mouse_y() para leer la posición de cada dispositivo. El código del segundo objeto es prácticamente el mismo, sólo cambia, como es lógico, la revisión de un dedo por otro: Si para usar el primer dedo nos aseguramos que el dispositivo actualno está asignado al segundo dedo, debemos hacer lo propio para el segundo dedo). Por tal motivo no colocaré el código del segundo objeto.

Otra cosa que es importante para lograr un correcto funcionamiento y que al parecer algunos usuarios han omitido es validar la pulsación considerando la distancia de dicha pulsación al objeto. Dependiendo del tamaño de los objetos a mover, es probable que necesites aumentar la magnitud de la distancia en el if anidado. Si no se considera una manera de validar la pulsación, entonces cualquier toque en cualquier zona de la pantalla podría arrastrar al objeto, comportamiento seguramente erróneo en la mayoría de los casos.

Como puedes ver, la solución al final es bastante sencilla. Este fue el minitutorial sobre multitouch, espero que te sirva. Gracias por pasar y hasta la próxima Estupidez Artificial!

Penumbra.