3. Reto 3. Interacciones

3.6. p5.js en los dispositivos móviles

Podemos usar nuestra aplicación en dispositivos móviles. p5.js se encarga de traducir los eventos de pantalla a eventos de teclado, con lo que un toque en la pantalla equivaldrá a un clic del ratón.

Los ejemplos 5-20 y 5-21 están pensados para usarlos con dispositivos móviles.

Funciones específicas para dispositivos móviles

Aunque podemos usar las funciones y variables de ratón para interaccionar con la pantalla de un dispositivo móvil, p5.js nos proporciona algunas opciones interesantes para hacerlo.

Para que los programas que hacemos funcionen bien para dispositivos móviles, hará falta también una pequeña modificación del archivo HTML que usamos como base y que es el que habríais de usar siempre.

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
  <style>
    body {margin: 0; padding: 0;}
  </style>
  <script src="js/p5.min.js"></script>
  <script src="js/sketch.js"></script>
 </head>
 <body>
 </body>
</html>

touches

touches es una variable del sistema que nos guarda información de las posiciones donde se ha tocado la pantalla. Las pantallas de nuestros dispositivos móviles son multitáctiles, lo que quiere decir que pueden detectar más de un toque a la vez. La variable touches almacena todas las posiciones de la pantalla que se están tocando. Es lo que llamamos array y, a pesar de que lo veremos explicado con más detalle en el siguiente reto, vamos a ver ahora cómo funciona.

Los arrays son una estructura de datos que nos permite guardar más de un dato a la vez. En la variable touches podemos guardar todos los toques simultáneos en la pantalla. Para poder consultar los diferentes valores que puede guardar una variable de tipo array, usamos esta notación:

touches[n];

Donde n es la posición que queremos consultar. En el caso de touches, además tendremos un valor para la posición x y otro para la posición y; así que para consultar la posición x e y del primer toque que se haga en la pantalla, haremos esta consulta:

var posX = touches[0].x
var posY = touches[0].y

Si hay dos dedos tocando la pantalla, ¿cómo accederemos a la posición del segundo dedo? Fácil, si la primera posición era 0, la segunda es 1:

var posX = touches[1].x
var posY = touches[1].y

Vamos a ver un primer ejemplo con la variable touches. Queremos que al hacer un toque en la pantalla, se dibuje en la posición donde se ha hecho el toque un círculo.

// En el setup creamos el canvas. Lo haremos de la anchura y la altura
// máxima de la pantalla.

function setup() {
 createCanvas(windowWidth, windowHeight);
 background("white");
 fill(255);
}
function draw() {
 if (touches.length>0) {
   ellipse(touches[0].x, touches[0].y, 50, 50);
 }
}

Si probáis este ejemplo, os daréis cuenta de que la pantalla del móvil se mueve al mover el dedo. Es un efecto extraño y feo de cara al usuario, pero arreglarlo es muy fácil. Tenemos que añadir esta función al final (la explicaremos mejor más adelante):

function touchMoved() {
  return false;
}

Ahora, con todo el código, si probamos el ejemplo funcionará mejor.

Ejercicios

  1. Modificar el código para hacer que, en vez de pintar un círculo, pinte un punto negro.
  2. Modificar el código para que dibuje dos círculos si se está tocando la pantalla con dos dedos.
  3. Modificar el código para que el primer dedo haga dibujar un círculo y el segundo dedo haga que cambie el color (negro si no hay un segundo dedo, rojo en caso contrario).
  4. Modificar el código para que el color de fondo cambie según el número de dedos (hasta 4) que tocan la pantalla.

touchStarted()

La función touchStarted(), por defecto no tiene ningún código asociado a p5.js, así que tendremos que escribir nosotros el código si la queremos usar. Esta función es llamada en el momento en que se detecta un toque en la pantalla o un clic en el ratón. Si esta función no existe, es decir, si no la hemos escrito nosotros, entonces se busca la variable mouseIsPressed. El funcionamiento, sin embargo, es diferente y, por lo tanto, la programación será también diferente si se usa la función o la variable.

Veremos ahora un par de ejemplos extraídos del manual de referencia de p5.js:

Ejemplo 1

var value = 0;
function setup() {
 createCanvas(windowWidth, windowHeight);
 background("white");
}
function draw() {
 fill(value);
 rect(25, 25, 50, 50);
}
function touchStarted() {
 if (value === 0) {
  value = 255;
 } else {
  value = 0;
 }
}

Como podemos ver, cuando se hace un toque en la pantalla, se cambia el color del cuadro. Veréis que con el ratón funciona muy bien, pero en el móvil solo funciona bien si mantenemos tocando con el dedo al menos un segundo.

El segundo código es este:

function setup() {
 createCanvas(windowWidth, windowHeight);
 background(124);
 fill(255);
}

function touchStarted() {
 ellipse(mouseX, mouseY, 5, 5);
 // prevent default
 return false;
}

En este caso, cada vez que hacemos un clic con el ratón o tocamos la pantalla, se dibujará un círculo. Probad el ejemplo y comprobad qué pasa cuando, manteniendo un dedo tocando la pantalla, hacéis un toque con otro dedo.

touchMoved()

La función definible touchMoved(), se llama cuando movemos el dedo por encima de la pantalla. Si no está definida, se llama a la función mouseDragged(). Sin duda, la mejor manera de entender el funcionamiento de esta función es con un ejemplo, que será el segundo que hemos usado para la función touchStarted(), pero cambiando la función definida:

function setup() {
 createCanvas(windowWidth, windowHeight);
 background(124);
 fill(255);
}

function touchMoved() {
 ellipse(mouseX, mouseY, 5, 5);
 // prevent default
 return false;
}

Añadimos una función touchStarted() para borrar el contenido:

function setup() {
 createCanvas(windowWidth, windowHeight);
 background(124);
 fill(255);
}

function touchMoved() {
 ellipse(mouseX, mouseY, 5, 5);
 // prevent default
 return false;
}

function touchStarted() {
 background(124);
}

touchEnded()

La función touchEnded() se llama cuando un toque finaliza. De nuevo usaremos un ejemplo para ver mejor su funcionamiento:

var xIni, yIni = 0;
var xFin, yFin = 0;

function setup() {
 createCanvas(windowWidth, windowHeight);
 background(124);
 fill(255);
}

function touchStarted() {
 background(124);
  xIni = mouseX;
  yIni = mouseY;
         print(xIni);
}

function touchMoved() {
 ellipse(mouseX, mouseY, 5, 5);
    xFin = mouseX;
    yFin = mouseY;
 return false;
}

function touchEnded() {
  line (xIni, yIni, xFin, yFin);
}

Fijaos en que hemos usado mouseX mouseY para conocer la posición del dedo en la pantalla en cada momento. Hay que decir que este código funcionará tanto en un dispositivo móvil como en un ordenador; en el dispositivo móvil reaccionará a los toques de pantalla, y en el ordenador a los clics y movimientos del ratón.

La función map()

La función map()se usa para cambiar la escala de un valor. Para explicarlo, en el libro se pone un ejemplo (el 5-22) que no utiliza esta función pero hace algo parecido.

Pero el ejemplo 5-23, que sí usa la función map()es más claro. Tenemos dos rayas: una, la blanca, que hacemos que llegue desde la posición 0 hasta la posición máxima del canvas; y una segunda, negra, que solo queremos que se mueva entre el rango de 60 a 180. Así, lo que haremos será pasar el valor de x, que puede estar entre 0 y 240 a un número que irá entre 60 y 180.