Processing/JS

Ratón II

constrain(), dist(), abs(), atan2()

La posición del cursor es un punto que actualizado cada frame. Este punto puede ser modificado y analizado y en relación a otros elementos calcular nuevos valores.

Es posible restrigir los valores del ratón a un rango específico, calcula la distancia entre el ratón y otra posición. Interpola entre los dos valores, determina la velocidad del movimiento del ratón y calcula el ángulo del ratón en relación a otra posición.

Restricciones

La función constrain() limita un número a un rango, tiene tres parámetros:
constrain(value, min, max)

El parámetro value es el número que limitamos  con el parámetro min y el max. La función devuelve el valor mínimo si el parámetro valor es menor o equivalente al mínimo y devuelve el valor máximo si el parámetro es menor o equivalente al máximo. Devuelve el valor sin cambios si estan entre el mínimo y el máximo.

void draw()
{
background(204);
float mx = constrain(mouseX, 10, 70);
rect(mx, 40, 20, 20);
}

Cuando las variables mouseX o mouseY, esta función devuelve siempre los valores del rango entre el mínimo y máximo.

Ratón

// Restringe el movimiento del círculo a una región
void setup() {
size(100, 100);
smooth();
noStroke();
}
void draw() {
background(0);
// Limites de mx entre 35 y 65
float mx = constrain(mouseX, 35, 65);
// Limites de my entre 40 y 60
float my = constrain(mouseY, 40, 60);
fill(102);
rect(20, 25, 60, 50);
fill(255);
ellipse(mx, my, 30, 30);
}

Distancia

La función dist() calcula la distancia entre dos coordenadas. Este valor se usa para determinar la distancia del cursor y un punto de la pantalla.

La función dist() tiene cuatro parámetros:

dist(x1, y1, x2, y2)

Los parámetros x1 e y1 son las coordenadas del primer punto y x2 e y2 segundo. La distancia entre los dos puntos esta calculada como float.

float x = dist(0, 0, 50, 0); // Asigna 50.0 a x
float y = dist(50, 0, 50, 90); // Asigna 90.0 a y
float z = dist(30, 20, 80, 90); // Asigna 86.023254 a z

El valor devuelto por dist() puede ser usado en las propiedades de las superficies:

Ratón

void setup() {
size(200, 200);
smooth();
}
void draw() {
background(0);
float d = dist(width/2, height/2, mouseX, mouseY);
ellipse(width/2, height/2, d*2, d*2);
}

Ratón

// Dibuja un grid de círculos y calcula la distancia entre el ratón y el centro de cada uno de los círculos
float maxDistance;
void setup() {
size(200, 200);
noStroke();
smooth();
fill(0);
maxDistance = dist(0, 0, width, height);
}
void draw() {
background(204);
for (int i = 0; i <= width; i += 20) {
for (int j = 0; j <= height; j += 20) {
float mouseDist = dist(mouseX, mouseY, i, j);
float diameter = (mouseDist / maxDistance) * 66.0;
ellipse(i, j, diameter, diameter);
}
}
}

Easing

Easing, se llama también interpolación, es una técnica para controlar el movimiento entre dos puntos.

float x = 0;
float y = 0;
float easing = 0.05; // Numero nentre 0.0 y 1.0
void setup() {
size(100, 100);
smooth();
noStroke();
}
void draw() {
background(0);
float targetX = mouseX;
float targetY = mouseY;
x += (targetX - x) * easing;
y += (targetY - y) * easing;
fill(153);
ellipse(mouseX, mouseY, 20, 20);
fill(255);
ellipse(x, y, 40, 40);
}

En los ejemplos anteriores el círculo sigue haciendo el cálculo aunque la posición del cursor ya se haya alcanzado, esto es poco eficiente, si hay miles de círculos puede ralentizarse el programa.

En el siguiente ejemplo se introduce la función abs() para tomar el valor absoluto del número. Esto es necesario para impedir el cálculo cuando la diferencia entre el valo del objeto y del cursor es menor de un píxel.

float x = 0;
float y = 0;
float easing = 0.05; // Numero nentre 0.0 y 1.0
void setup() {
size(100, 100);
smooth();
noStroke();
}
void draw() {
background(0);
float targetX = mouseX;
float dx = targetX - x;
float targetY = mouseY;
float dy = targetY - y;
if (abs(dx) > 1.0) {
x += (targetX - x) * easing;
}
if (abs(dy) > 1.0) {
y += (targetY - y) * easing;
}
fill(153);
ellipse(mouseX, mouseY, 20, 20);
fill(255);
ellipse(x, y, 40, 40);
}

Velocidad

Calcular la velocidad del ratón por comparación de su posición con su posición anterior.

Usamos la función dist() con los valores mouseX, mouseY, pmouseX, y pmouseY como parámetros.
En el siguiente ejemplo calculamos la velocidad del ratón y la convertimos en tamaño de la elipse.

void setup() {
size(100, 100);
noStroke();
smooth();
}
void draw() {
background(0);
float speed = dist(mouseX, mouseY, pmouseX, pmouseY);
float diameter = speed * 3.0;
ellipse(50, 50, diameter, diameter);
}

En el siguiente ejemplo añadimos al movimiento el suavizado easing en el movimiento de una de las barras.

float speed = 0.0;
float easing = 0.05;
void setup() {
size(100, 100);
noStroke();
smooth();
}
void draw() {
background(0);
float target = dist(mouseX, mouseY, pmouseX, pmouseY);
speed += (target - speed) * easing;
rect(0, 33, target, 17);
rect(0, 50, speed, 17);
}

Orientation

La función atan2() es el arco tangente se usa para calcular el ángulo de un punto con las coordenadas (0,0). Tiene dos parámetros:

atan2(y, x)

El parámetro y es la coordenada y, la x es la coordenada x del punto con el que vamos  a calcular el ángulo. El ángulo se develve en radianes en un rango entre π/2 a -π/2 .

Ratón atan

void setup() {
size(200, 200);
frameRate(15);
fill(0);
}
void draw() {
float angle = atan2(mouseY, mouseX);
float deg = degrees(angle);
println(deg);
background(204);
ellipse(mouseX, mouseY, 8, 8);
rotate(angle);
line(0, 0, 200, 0);
}

Calcular atan2() relativo a un punto distinto de (0,0), Usamos la función translate() function para posicionar el elemento en la pantalla y posteriormente lo rotamos usando el resultado de atan2(), y usamos pushMatrix() y popMatrix() para aislar las trasformaciones.

float x = 50;
float y1 = 33;
float y2 = 66;
void setup() {
size(100, 100);
noStroke();
smooth();
}
void draw() {
background(0);
float angle = atan2(mouseY-y1, mouseX-x);
pushMatrix();
translate(x, y1);
rotate(angle);
triangle(-20, -8, 20, 0, -20, 8);
popMatrix();
}