Introducción a Processing 1



Descargar 1,94 Mb.
Página9/11
Fecha de conversión04.03.2017
Tamaño1,94 Mb.
1   2   3   4   5   6   7   8   9   10   11

Ejercicio 13

  • EJ13: Crear una forma animada autónoma que comunique la idea de "orden".
  • Utilizar funciones de usuario.
  • Comentar todas las instrucciones.

Ejercicio 14

  • EJ14: Crear una forma animada autónoma que comunique la idea de "caos".
  • Utilizar funciones de usuario.
  • Comentar todas las instrucciones.

Ejercicio 15

  • EJ15: Crear una forma interactiva que comunique la idea de "orden y caos".
  • Utilizar funciones de usuario.
  • Comentar todas las instrucciones.
  • Parte 13 Otras funciones matemáticas
  • Para calcular el cuadrado de un número usamos la función sq(). La misma nos regresa el resultado, el cual será siempre un número positivo aunque usemos un valor negativo.
  • sq(valor)
    • float x = sq(1); // Asigna 1.0 a x: equivalente a 1 * 1
    • float y = sq(-5); // Asigna 25.0 a y: equivalente a -5 * -5
    • float z = sq(9); // Asigna 81.0 a z: equivalente a 9 * 9
  • Función sqrt() – Raíz cuadrada
  • La función sqrt() es usada para calcular la raíz cuadrada de un número. La misma regresa el resultado.
  • sqrt(valor)
  • Recordemos que también lo podemos expresar de la siguiente manera: (√a) == (a1/2 )
    • float r = sqrt(6561); // Asigna 81.0 a r
    • float s = sqrt(625); // Asigna 25.0 a s
    • float t = sqrt(1); // Asigna 1.0 a t
  • Función pow() – Potenciación
  • La función pow() calcula la potencia en función de dos términos: base y exponente. La misma regresa el resultado.
  • pow(base, exponente)
  • Recordemos que, cuando el exponente es una fracción irreducible, también lo podemos expresar de la siguiente manera:
  • (m√an) == (an/m )
    • float d = pow(1, 3); // Asigna 1.0 a d: equivalente a 1*1*1
    • float e = pow(3, 4); // Asigna 81.0 a e: equivalente a 3*3*3*3
    • float f = pow(3, -2); // Asigna 0.11 a f: equivalente a 1 / (3*3)
    • float g = pow(-3, 3); // Asigna -27.0 a g: equivalente a -3*-3*-3
  • Función norm() – Normalización 1/2
  • Muchas veces se vuelve conveniente convertir un rango de números dados al rango 0.0 a 1.0. A este procedimiento se lo llama normalización.
  • Cuando multiplicamos números entre 0.0 y 1.0, el resultado nunca será menor a 0.0 ni mayor a 1.0. Esto permite no salir de un rango determinado.
  • Desde luego que todas las operaciones de normalización deben ser realizadas con el tipo de dato float.
  • Para normalizar un número debemos dividirlo por el valor máximo que este represente. Por ejemplo: para normalizar una serie de valores entre 0.0 y 255.0, divida cada uno por 255.0:
  • Valor inicial Cálculo Valor normalizado
  • 0.0 0.0 / 255.0 0.0
  • 102.0 102.0 / 255.0 0.4
  • 255.0 255.0 / 255.0 1.0
  • Función norm() – Normalización 2/2
  • Para simplificar esta tarea podemos utilizar la función norm():
  • norm(valor_a_convertir, valor_mínimo, valor_máximo)
  • Si el valor a convertir se encuentra fuera del rango, el resultado podrá ser menor a 0.0 o mayor a 1.0 de acuerdo al caso.
    • float x = norm(0.0, 0.0, 255.0); // Asigna 0.0 a x
    • float y = norm(102.0, 0.0, 255.0); // Asigna 0.4 a y
    • float z = norm(255.0, 0.0, 255.0); // Asigna 1.0 a z
  • Función lerp() – Interpolación lineal 1/2
  • Luego de la normalización, podemos convertir el número a otro rango mediante operaciones aritméticas.
  • Por ejemplo, para convertir desde un rango entre 0.0 y 1.0 al rango entre 0.0 y 500.0, simplemente los multiplicamos por 500.0. Para convertir números entre 0.0 y 1.0 al rango que se extiende entre 200.0 y 500.0, multiplicamos por 300 y luego sumamos 200.
  • Veamos a continuación algunos ejemplos de conversión:
  • Rango inicial de x Rango de destino de x Conversión
  • 0.0 a 1.0 0.0 a 255.0 x * 255.0
  • 0.0 a 1.0 -1.0 a 1.0 (x * 2.0) - 1.0
  • 0.0 a 1.0 -20.0 a 60.0 (x * 80.0) - 20.0
  • Función lerp() – Interpolación lineal 2/2
  • Nuevamente, para simplificar esta tarea podemos utilizar la función lerp(). La misma presenta tres parámetros
  • lerp(valor_mínimo_del_rango_a_interpolar, valor_máximo_del_rango_a_interpolar, valor_a_interpolar)
  • El tercer parámetro (valor a interpolar) debe ser siempre un valor entre 0.0 y 1.0. Veamos algunos ejemplos:
    • float r = lerp(-20.0, 60.0, 0.0); // Asigna -20.0 a r
    • float s = lerp(-20.0, 60.0, 0.5); // Asigna 20.0 a s
    • float t = lerp(-20.0, 60.0, 1.0); // Asigna 60.0 a t
  • Función map() – Mapeo 1/2
  • Existe otra función que nos permite aplicar las operaciones de normalización e interpolación lineal en una: hablamos de la función map().
  • Con dicha función podemos convertir directamente un valor correspondiente a un rango de números a otro correspondiente a otro rango de números.
  • Posee cinco parámetros:
  • map(valor, mínimo1, máximo1, mínimo2, máximo2)
  • Donde valor corresponde al número de origen a mapear, mínimo1 y máximo1 a los números del rango origen, y mínimo2 y máximo2 a los números del rango de destino.
  • Función map() – Mapeo 2/2
  • El próximo ejemplo muestra el uso de map() para convertir valores del rango de origen 0 a 255 al rango de destino -1 a 1. Este proceso equivale a, primero, normalizar el valor, y luego a multiplicar y sumar para desplazar el rango de 0 a 1 al rango -1 a 1:
    • float x = map(20.0, 0.0, 255.0, -1.0, 1.0); // Asigna -0.84 a x
    • float y = map(0.0, 0.0, 255.0, -1.0, 1.0); // Asigna -1.0 a y
    • float z = map(255.0, 0.0, 255.0, -1.0, 1.0); // Asigna 1.0 a z
  • Función constrain() – Limitación de rangos 1/2
  • La función constrain() permite limitar un número a un rango determinado. Trabaja con enteros o decimales.
  • Posee tres parámetros:
  • constrain(valor, mínimo, máximo)
  • Donde valor corresponde al número a limitar, mínimo al valor mínimo posible y máximo al valor máximo posible. Esta función regresa el número mínimo si el parámetro valor es menor o equivalente al antedicho, regresa el número máximo si el mismo es mayor o equivalente, y regresa valor si se encuentra en el rango previsto.
  • int x = constrain(35, 15, 90); // Asigna 35 a x
  • int y = constrain(10, 15, 90); // Asigna 15 a y
  • int z = constrain(91, 15, 90); // Asigna 90 a z
  • Función constrain() – Limitación de rangos 2/2
  • // Limitar la posición de una elipse a una región determinada
  • void setup() {
  • size(100, 100);
  • smooth();
  • noStroke();
  • }
  • void draw() {
  • background(0);
  • // Limita mx entre 35 y 65
  • float mx = constrain(mouseX, 35, 65);
  • // Limita 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);
  • }
  • Función dist() – Distancia entre coordenadas 1/3
  • La función dist() calcula la distancia entre dos coordenadas. Trabaja con enteros o decimales, pero regresa decimales.
  • Posee cuatro parámetros:
  • dist(x1, y1, x2, y2)
  • El primer par de parámetros corresponde a la primera coordenada y el segundo par a la segunda.
  • float r = dist(0, 0, 50, 0); // Asigna 50.0 a r
  • float s = dist(50, 0, 50, 90); // Asigna 90.0 a s
  • float t = dist(30, 20, 80, 90); // Asigna 86.023254 a t
  • Función dist() – Distancia entre coordenadas 2/3
  • // La distancia entre el centro de la ventana de representación
  • // y el puntero determina el díametro del círculo
  • void setup() {
  • size(100, 100);
  • smooth();
  • }
  • void draw() {
  • background(0);
  • float d = dist(width/2, height/2, mouseX, mouseY);
  • ellipse(width/2, height/2, d*2, d*2);
  • }
  • Función dist() – Distancia entre coordenadas 3/3
  • // Dibujo de una grilla de círculos y cálculo de la
  • // distancia de cada uno de ellos para determinar el tamaño
  • float distanciaMax;
  • void setup() {
  • size(100, 100);
  • noStroke();
  • smooth();
  • fill(0);
  • distanciaMax = 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 distanciaMouse = dist(mouseX, mouseY, i, j);
  • float diametro = (distanciaMouse / distanciaMax) * 66.0;
  • ellipse(i, j, diametro, diametro);
  • }
  • }
  • }
  • Técnica Easing – Aligeramiento 1/7
  • La técnica de animación llamada Easing, es en realidad una técnica de interpolación entre dos puntos. Al mover en cada cuadro una fracción de la distancia total de una figura, el movimiento de esta parece desacelerarse (o acelerarse) al acercarse a la ubicación de destino.
  • El siguiente diagrama muestra qué ocurre cuando un punto siempre se mueve la mitad del recorrido entre su posición actual y la posición de destino:
  • A medida que la figura se acerca a la posición de destino, la distancia recorrida disminuye en cada fotograma, por lo tanto el movimiento de la misma parece ralentizarse.
  • Técnica Easing – Aligeramiento 2/7
  • En el siguiente ejemplo la variable x corresponde a la posición horizontal actual del círculo y la varible destinoX corresponde a la posición de destino.
  • La variable easing dispone la fracción de la distancia entre la posición actual del círculo y la posición del ratón que el círculo se mueve en cada cuadro. El valor de esta variable cambia la rapidez con que el círculo llega al destino.
  • El valor de easing debe estar siempre entre 0.0 y 1.0, y los números cercanos a 0.0 causan que el movimiento se ralentice más.
  • Un valor de easing de 0.5 hará que el círculo se mueva la mitad de la distancia en cada cuadro, mientras que un valor de 0.01 hará que el círculo se mueva una centésima de la distancia en cada cuadro.
  • El círculo superior es dibujado de acuerdo a la posición destinoX, mientras que el círculo inferior es dibujado de acuerdo a la posición interpolada.
  • Ahora sí veamos el ejemplo:
  • Técnica Easing – Aligeramiento 3/7
  • float x = 0.0; // Distancia actual en x
  • float easing = 0.05; // Números 0.0 a 1.0
  • void setup() {
  • size(100, 100);
  • smooth();
  • }
  • void draw() {
  • background(0);
  • float destinoX = mouseX;
  • x += (destinoX - x) * easing;
  • ellipse(mouseX, 30, 40, 40);
  • ellipse(x, 70, 40, 40);
  • }
  • Técnica Easing – Aligeramiento 4/7
  • En el siguiente ejemplo utilizamos dos variables para controlar la técnica easing en las dos dimensiones. Observe que estructuralmente es igual al anterior. El ejemplo se encuentra en la siguiente página:
  • Técnica Easing – Aligeramiento 5/7
  • float x = 0; // Distancia actual en x
  • float y = 0; // Distancia actual en y
  • float easing = 0.05; // Números 0.0 a 1.0
  • void setup() {
  • size(100, 100);
  • smooth();
  • noStroke();
  • }
  • void draw() {
  • background(0);
  • float destinoX = mouseX;
  • float destinoY = mouseY;
  • x += (destinoX - x) * easing;
  • y += (destinoY - y) * easing;
  • fill(255);
  • ellipse(x, y, 40, 40); //Círculo blanco grande interpolado
  • fill(153);
  • ellipse(mouseX, mouseY, 20, 20); //Círculo gris pequeño destino
  • }
  • Técnica Easing – Aligeramiento 6/7
  • Los dos ejemplo previos continúan realizando el cálculo para la posición del círculo incluso luego de haber alcanzado su destino. Desde el punto de vista informático resulta ineficiente, y si hubieran cientos de círculos todos aligerando las posiciones, esto ralentizaría el programa en general.
  • Para detener los cálculos cuando estos no son necesarios, evalúe que la posición de destino y la posición actual sean equivalentes y detenga el cálculo si esta condición resulta verdadera.
  • El siguiente ejemplo presenta el uso de la función abs() la cual devuelve el valor absoluto de un número.
  • Esta es necesaria ya que los valores resultantes de la técnica Easing pueden ser tanto negativos como positivos dependiendo de si la posición se encuentra a la izquierda o a la derecha del destino.
  • Técnica Easing – Aligeramiento 7/7
  • float x = 0.0; // Distancia actual en x
  • float easing = 0.05; // Números 0.0 a 1.0
  • void setup() {
  • size(100, 100);
  • smooth();
  • }
  • void draw() {
  • background(0);
  • float destinoX = mouseX;
  • // Distancia desde l posición hasta el destino
  • float dx = destinoX - x;
  • // Si la distancia entre la posición actual y el destino
  • // es mayor a 1.0, actualizo la posición
  • if (abs(dx) > 1.0) {
  • x += dx * easing;
  • println(dx);
  • }
  • ellipse(mouseX, 30, 40, 40);
  • ellipse(x, 70, 40, 40);
  • }
  • Cálculo de velocidad 1/3
  • A continuación calcularemos la velocidad del ratón mediante la comparación de la posición actual con la posición anterior.
  • Esto lo haremos usando la función dist() con los valores de parámetros de las variables mouseX, mouseY, pmouseX y pmouseY.
  • Entonces, el siguiente ejemplo calcula la velocidad del ratón y convierte este valor en el diámetro de una elipse:
    • void setup() {
    • size(100, 100);
    • noStroke();
    • smooth();
    • }
    • void draw() {
    • background(0);
    • float velocidad = dist(mouseX, mouseY, pmouseX, pmouseY);
    • float diametro = velocidad * 3.0;
    • ellipse(50, 50, diametro, diametro);
    • }
  • Cálculo de velocidad 2/3
  • El ejemplo previo muestra la velocidad instanténea del ratón. Los números producidos son extremos –saltan constantemente entre cero y otros valores más grandes de un cuadro al otro.
  • Se puede utilizar la técnica Easing para incrementar o mermar la velocidad de forma suavizada.
  • El siguiente ejemplo muestra cómo aplicar la técnica Easing en dicho contexto. La barra superior representa la velocidad instantánea mientras que la inferior representa la velocidad aligerada:
  • Cálculo de velocidad 3/3
    • float velocidad = 0.0;
    • float easing = 0.05; // Números 0.0 al 1.0
    • void setup() {
    • size(400, 400);
    • noStroke();
    • smooth();
    • }
    • void draw() {
    • background(0);
    • float destino = dist(mouseX, mouseY, pmouseX, pmouseY);
    • velocidad += (destino - velocidad) * easing;
    • rect(0, 33, destino, 17);
    • rect(0, 50, velocidad, 17);
    • }
  • Orientación 1/4
  • La función atan2() es usada para calcular el ángulo desde cualquier punto del área de representación a la coordenada de origen (0, 0). Tiene dos parámetros:
  • atan2(y, x)
  • Donde los parámetro x e y corresponden a la coordenada de interés. Note que la posición de ambos parámetros se presentan en reverso comparado a cómo las usa otras funciones tales como point().
  • Los valores de ángulo son regresados en radianes dentro del rango π a –π.
  • Recordemos que un circulo mide 2*π radianes, lo cual equivale en grados a 360º. Por lo tanto, un ángulo de 90º corresponde a π/2 (1.5707964). Para convertir una medida de radianes a grados utilizamos la función degrees().
  • Veamos un ejemplo donde aplicamos estas dos funciones:
  • Orientación 2/4
    • // El ángulo se incrementa a medida de que el ratón
    • // se mueve desde la esquina superior-derecha de la
    • // pantalla a la esquina inferior-izquierda
    • void setup() {
    • size(100, 100);
    • frameRate(15);
    • fill(0);
    • }
    • void draw() {
    • float angulo = atan2(mouseY, mouseX);
    • float grados = degrees(angulo);
    • println(grados + "º");
    • background(204);
    • ellipse(mouseX, mouseY, 8, 8);
    • rotate(angulo);
    • line(0, 0, 150, 0);
    • }
  • Orientación 3/4
  • Por último, para calcular la orientación relativa a otro punto de referencia que no sea la coordenada de origen (0, 0), utilizamos la función atan2() cuyos parámetros son substraídos por los valores correspondientes al otro punto de referencia que se desea fijar.
  • Veamos lo antedicho en el siguiente ejemplo:
  • Orientación 4/4
    • // Rota el triángulo apuntando siempre
    • // a la posición del puntero
    • float x = 50;
    • float y = 50;
    • void setup() {
    • size(100, 100);
    • noStroke();
    • smooth();
    • }
    • void draw() {
    • background(0);
    • float angulo = atan2(mouseY - y, mouseX - x);
    • pushMatrix();
    • translate(x, y);
    • rotate(angulo);
    • triangle(-20, -8, 20, 0, -20, 8);
    • popMatrix();
    • }
  • Lectura recomendada
  • Capítulo “Shape 2: Vertices” (pag. 69).
  • Capítulo “Math 2: Curves” (pag. 79).
  • Capítulo “Math 3: Trigonometry” (pag. 117).
  • Capítulo “Transform 1: Translate, Matrices ” (pag. 133).
  • Capítulo “Transform 2: Rotate, Scale” (pag. 137).
  • Capítulo “Shape 3: Parameters, Recursion” (pag. 197).
  • Capítulo “Input 4: Mouse II” (pag. 237).
  • Información complementaria
  • Reducción de rango
    • Disponemos de cinco funciones básicas:
      • ceil()
      • floor()
      • round()
      • min()
      • max().
  • ceil() - techo
    • Calcula el valor entero más cercano que el valor más grande o igual del de su parámetro.
        • int w = ceil(2.0); // Asigna 2 a w
        • int x = ceil(2.1); // Asigna 3 a x
        • int y = ceil(2.5); // Asigna 3 a y
        • int z = ceil(2.9); // Asigna 3 a z
  • floor() - piso
    • Calcula el valor entero más cercano que el valor más pequeño o igual del de su parámetro.
        • int w = floor(2.0); // Asigna 2 a w
        • int x = floor(2.1); // Asigna 2 a x
        • int y = floor(2.5); // Asigna 2 a y
        • int z = floor(2.9); // Asigna 2 a z
  • round() - redondeo
    • Calcula el valor entero más cercano al valor de la media de su parámetro.
        • int w = round(2.0); // Asigna 2 a w
        • int x = round(2.1); // Asigna 2 a x
        • int y = round(2.5); // Asigna 3 a y
        • int z = round(2.9); // Asigna 3 a z
  • min() - mínimo
        • int u = min(5, 9); // Asigna 5 a u
        • int v = min(-4, -12, -9); // Asigna -12 a v
        • float w = min(12.3, 230.24); // Asigna 12.3 a w
  • max() - máximo
        • int x = max(5, 9); // Asigna 9 a x
        • int y = max(-4, -12, -9); // Asigna -4 a y
        • float z = max(12.3, 230.24); // Asigna 230.24 a z
  • Parte 14 Movimientos simples
  • Movimiento
  • En esta sección revisaremos tres clases de movimiento:
    • Movimiento implícito
    • Movimiento explícito
    • Movimiento mediante transformación
  • Movimiento implícito en una dirección 1/2
  • Para poner en movimiento una figura, necesitamos al menos usar una variable para cambiar un atributo.
  • El siguiente ejemplo presenta un movimiento implícito, es decir un movimiento rectilíneo uniforme que no contempla posición de origen ni de destino:
  • Movimiento implícito en una dirección 2/2
    • float y = 50.0;
    • float velocidad = 1.0;
    • float radio = 15.0;
    • void setup() {
    • size(100, 100);
    • smooth();
    • noStroke();
    • ellipseMode(RADIUS);
    • }
    • void draw() {
    • background(0);
    • ellipse(33, y, radio, radio);
    • y = y + velocidad;
    • if (y > height+radio) {
    • y = -radio;
    • }
    • }
  • Efecto de desenfoque 1/2
  • Puede crear un efecto de desenfoque utilizando un rectángulo semitransparente dentro del bloque draw().
  • La cantidad de desenfoque es controlado por el valor del parámetro de transparencia usado para pintar el relleno del rectángulo (la función fill()).
  • Los números cercanos a 255 refrescarán rápidamente la pantalla, mientras que los cercanos a 0 crearán un fundido lento.
  • Veamos su aplicación en el siguiente ejemplo:
  • Efecto de desenfoque 2/2
    • float y = 50.0;
    • float velocidad = 1.0;
    • float radio = 15.0;
    • int direccion = 1;
    • void setup() {
    • size(100, 100);
    • smooth();
    • noStroke();
    • ellipseMode(RADIUS);
    • }
    • void draw() {
    • fill(0, 12); // Valores funcionales entre 10 y 100
    • rect(0, 0, width, height);
    • fill(255);
    • ellipse(33, y, radio, radio);
    • y += velocidad * direccion;
    • if ((y > height-radio) || (y < radio)) {
    • direccion = -direccion;
    • }
    • }
  • Movimiento implícito en dos direcciones 1/2
  • También podemos utilizar un segundo conjunto de variables para aprovechar el movimiento en el eje X:
    • float x = 50.0; // coordenada en X
    • float y = 50.0; // coordenada en Y
    • float radio = 15.0; // Radio del círculo
    • float velocidadX = 1.0; // Velocidad de mov. en eje X
    • float velocidadY = 0.4; // Velocidad de mov. en eje Y
    • int direccionX = 1; // Dirección de mov. en eje X
    • int direccionY = -1; // Dirección de mov. en eje X
    • void setup() {
    • size(100, 100);
    • smooth();
    • noStroke();
    • ellipseMode(RADIUS);
    • }
    • // ***continúa***
  • Movimiento implícito en dos direcciones 2/2
    • void draw() {
    • fill(0, 12);
    • rect(0, 0, width, height);
    • fill(255);
    • ellipse(x, y, radio, radio);
    • x += velocidadX * direccionX;
    • if ((x > width-radio) || (x < radio)) {
    • direccionX = -direccionX; // Cambia direccion
    • }
    • y += velocidadY * direccionY;
    • if ((y > height-radio) || (y < radio)) {
    • direccionY = -direccionY; // Cambia direccion
    • }
    • }
  • Movimiento explícito en dos direcciones 1/2
  • Si deseamos mover una figura desde y hasta una posición específica, debemos incorporar algunas variables de control más:
    • float origenX = 20.0; // Coordenada de origen en X
    • float origenY = 10.0; // Coordenada de origen en Y
    • float destinoX = 70.0; // Coordenada de destino en X
    • float destinoY = 80.0; // Coordenada de destino en Y
    • float distX; // Distancia a mover en eje-X
    • float distY; // Distancia a mover en eje-Y
    • float x = 0.0; // Coordenada actual en X
    • float y = 0.0; // Coordenada actual en Y
    • float paso = 0.02; // Tamaño de cada paso (0.0 a 0.4)
    • float pct = 0.0; // Porcentaje recorrido (0.0 a 1.0)
    • // ***continúa***
  • Movimiento explícito en dos direcciones 2/2
    • void setup() {
    • size(100, 100);
    • noStroke();
    • smooth();
    • distX = destinoX - origenX;
    • distY = destinoY - origenY;
    • }
    • void draw() {
    • fill(0, 12);
    • rect(0, 0, width, height);
    • pct += paso;
    • if (pct < 1.0) {
    • x = origenX + (pct * distX);
    • y = origenY + (pct * distY);
    • }
    • fill(255);
    • ellipse(x, y, 20, 20);
    • }
  • Movimiento explícito + easing + desenfoque
    • float origenX = 20.0; // Coordenada de origen en X
    • float origenY = 10.0; // Coordenada de origen en Y
    • float destinoX = 70.0; // Coordenada de destino en X
    • float destinoY = 80.0; // Coordenada de destino en Y
    • float easing = 0.05; // Tamaño de cada para a lo largo del recorrido
    • void setup() {
    • size(100, 100);
    • noStroke();
    • smooth();
    • }
    • void draw() {
    • fill(0, 12);
    • rect(0, 0, width, height);
    • float d = dist(origenX, origenY, destinoX, destinoY);
    • if (d > 1.0) {
    • origenX += (destinoX - origenX) * easing;
    • origenY += (destinoY - origenY) * easing;
    • }
    • fill(255);
    • ellipse(origenX, origenY, 20, 20);
    • }
  • Curvas simples 1/5
  • Las funciones exponenciales son muy útiles a la hora de crear curvas simples.
  • En general se utilizan valores normalizados en conjunción con la función pow() para producir incrementos y decrementos exponenciales de números que nunca exceden el rango de 0.0 a 1.0.
  • Estas ecuaciones tienen la siguiente forma:
    • y = xe
  • donde x (base) corresponde a un valor decimal entre 0.0 y 1.0 y e (exponente) corresponde a un valor entero o decimal.
  • Curvas simples 2/5
  • Ejemplo 1:
    • for (int x = 0; x < 100; x++) {
    • float n = norm(x, 0.0, 100.0); // Rango 0.0 a 1.0
    • float y = pow(n, 4); // Cálculo de curva
    • y *= 100; // Rango 0.0 a 100.0
    • point(x, y);
    • }
  • Ejemplo 2:
    • for (int x = 0; x < 100; x++) {
    • float n = norm(x, 0.0, 100.0); // Rango 0.0 a 1.0
    • float y = pow(n, 0.4); // Cálculo de curva
    • y *= 100; // Rango 0.0 a 100.0
    • point(x, y);
    • }
  • Curvas simples 3/5
  • Curvas simples 4/5
  • Curvas simples 5/5
  • Movimiento explícito curvo 1/5
  • Entonces podemos utilizar ecuaciones exponenciales para generar recorridos curvos en vez de rectilíneos:
    • float origenX = 20.0; // Coordenada de origen en X
    • float origenY = 10.0; // Coordenada de origen en Y
    • float destinoX = 70.0; // Coordenada de destino en X
    • float destinoY = 80.0; // Coordenada de destino en Y
    • float distX; // Distancia a mover en eje-X
    • float distY; // Distancia a mover en eje-X
    • float exponente = 0.5; // Determina el tipo de curva
    • float x = 0.0; // Coordenada actual en X
    • float y = 0.0; // Coordenada actual en Y
    • float paso = 0.01; // Tamaño de cada paso (0.0 a 1.0)
    • float pct = 0.0; // Porcentaje recorrido (0.0 a 1.0)
    • // *** continúa ***
  • Movimiento explícito curvo 2/5
    • void setup() {
    • size(100, 100);
    • noStroke();
    • smooth();
    • distX = destinoX - origenX;
    • distY = destinoY - origenY;
    • }
    • void draw() {
    • fill(0, 2);
    • rect(0, 0, width, height);
    • pct += paso;
    • if (pct < 1.0) {
    • x = origenX + (pct * distX);
    • y = origenY + (pow(pct, exponente) * distY);
    • }
    • fill(255);
    • ellipse(x, y, 20, 20);
    • }
  • Movimiento explícito curvo 3/5
  • Todas las curvas simples presentadas anteriormente pueden ser escaladas y combinadas para generar recorridos únicos de movimiento. Una vez que se haya calculado un paso de una curva, el programa puede calcular otras posiciones basadas en una curva diferente:
    • float origenX = 20.0; // Coordenada de origen en X
    • float origenY = 10.0; // Coordenada de origen en Y
    • float destinoX = 70.0; // Coordenada de destino en X
    • float destinoY = 80.0; // Coordenada de destino en Y
    • float distX; // Distancia a mover en eje-X
    • float distY; // Distancia a mover en eje-X
    • float exponente = 3.0; // Determina el tipo de curva
    • float x = 0.0; // Coordenada actual en X
    • float y = 0.0; // Coordenada actual en Y
    • float paso = 0.01; // Tamaño de cada paso (0.0 a 1.0)
    • float pct = 0.0; // Porcentaje recorrido (0.0 a 1.0)
    • int direccion = 1;
    • // *** continúa ***
  • Movimiento explícito curvo 4/5
    • void setup() {
    • size(100, 100);
    • noStroke();
    • smooth();
    • distX = destinoX - origenX;
    • distY = destinoY - origenY;
    • }
    • void draw() {
    • fill(0, 2);
    • rect(0, 0, width, height);
    • pct += paso * direccion;
    • if ((pct > 1.0) || (pct < 0.0)) {
    • direccion = direccion * -1;
    • }
    • // *** continúa ***
  • Movimiento explícito curvo 5/5
    • if (direccion == 1) {
    • x = origenX + (pct * distX);
    • float e = pow(pct, exponente);
    • y = origenY + (e * distY);
    • }
    • else {
    • x = origenX + (pct * distX);
    • float e = pow(1.0-pct, exponente*2);
    • y = origenY + (e * -distY) + distY;
    • }
    • fill(255);
    • ellipse(x, y, 20, 20);
    • }
  • Cambio de velocidad mediante ecuación exponencial 1/3
  • El siguiente ejemplo muestra el cambio de velocidad del movimiento de una figura mediante una ecuación exponencial. El círculo comienza a moverse muy lentamente y luego se detiene en el márgen inferior del área de representación. La variable exponente describe la pendiente de la curva, la cual cambia la velocidad del movimiento. Utilice el botón del ratón para seleccionar un nuevo punto de origen:
    • float origenX = 20.0; // Coordenada de origen en X
    • float origenY = 10.0; // Coordenada de origen en Y
    • float destinoX = 70.0; // Coordenada de destino en X
    • float destinoY = 80.0; // Coordenada de destino en Y
    • float distX; // Distancia a mover en eje-X
    • float distY; // Distancia a mover en eje-X
    • float exponente = 3.0; // Determina el tipo de curva
    • float x = 0.0; // Coordenada actual en X
    • float y = 0.0; // Coordenada actual en Y
    • float paso = 0.01; // Tamaño de cada paso (0.0 a 1.0)
    • float pct = 0.0; // Porcentaje recorrido (0.0 a 1.0)
    • // *** continúa ***
  • Cambio de velocidad mediante ecuación exponencial 2/3
    • void setup() {
    • size(100, 100);
    • noStroke();
    • smooth();
    • distX = destinoX - origenX;
    • distY = destinoY - origenY;
    • }
    • // *** continúa ***
  • Cambio de velocidad mediante ecuación exponencial 3/3
    • void draw() {
    • fill(0, 2);
    • rect(0, 0, width, height);
    • if (pct < 1.0) {
    • pct = pct + paso;
    • float velocidad = pow(pct, exponente);
    • x = origenX + (velocidad * distX);
    • y = origenY + (velocidad * distY);
    • }
    • fill(255);
    • ellipse(x, y, 20, 20);
    • }
    • void mousePressed() {
    • pct = 0.0;
    • origenX = x;
    • origenY = y;
    • distX = mouseX - x;
    • distY = mouseY - y;
    • }
  • Movimiento mediante transformación 1/3
  • Las funciones de transformación (translate(), rotate(), y scale()) también pueden crear movimiento al cambiar los valores de sus parámetros. Antes de usar las transformaciones para el movimiento, es importante remarcar que las transformaciones se reinicializan al comienzo de cada bloque draw().
  • Por lo tanto, cuando se ejecuta translate(50, 0)dentro del bloque draw(), el sistema de coordenadas se ajusta 50 pixeles a la derecha por única vez hasta que se detenga el programa.
    • void setup() {
    • size(100, 100);
    • smooth();
    • }
    • void draw() {
    • background(0);
    • translate(50, 0); // Se reinicia a 50 px cada vez que entra en draw
    • ellipse(0, 50, 60, 60);
    • }
  • Movimiento mediante transformación 2/3
  • Del mismo modo, las translaciones dentro del bloque setup() no tienen efecto en las figuras producidas en el bloque draw().
    • void setup() {
    • size(100, 100);
    • smooth();
    • translate(50, 0); // No tiene efecto
    • }
    • void draw() {
    • background(0);
    • ellipse(0, 50, 60, 60);
    • }
  • Movimiento mediante transformación 3/3
  • Las funciones de transformación pueden ser utilizadas para generar movimiento, sin embargo su uso puede ser un poco engorroso.
    • float angulo = 0.0;
    • void setup() {
    • size(100, 100);
    • smooth();
    • noStroke();
    • }
    • void draw() {
    • fill(0, 12);
    • rect(0, 0, width, height);
    • fill(255);
    • angulo = angulo + 0.02;
    • translate(70, 40);
    • rotate(angulo);
    • rect(-30, -30, 60, 60);
    • }
  • Lectura recomendada
  • Capítulo “Motion 1: Lines, Curves” (pag. 279).
1   2   3   4   5   6   7   8   9   10   11


La base de datos está protegida por derechos de autor ©absta.info 2019
enviar mensaje

    Página principal