Sie sind auf Seite 1von 24

7/Movimiento

Como un libro animado, la animacin en la pantalla in creada dibujando una imagen, luego dibujando una imagen ligeramente diferente, luego otra, y as sucesivamente. La ilusin de movimiento uido se crea por la persistencia de la visin. Cuando un set de imgenes similares es presentado a un ritmo lo sucientemente rpido, nuestros cerebros traducen esas imgenes en movimiento.
Ejemplo 7-1: Velocidad de los fotogramas Para crear un movimiento suave, Processing trata de ejecutar el cdigo dentro de draw() a 6 fotogramas por segundo. Para conrmar la velocidad de los fotogramas, ejecuta el programa y mira los valores que se imprimen en la consola. Las variables del frameRate mantienen un registro de la velocidad del programa. void draw() { println(frameRate); }

Ejemplo 7-2: Setea el frameRate La funcin frameRate() cambia la velocidad a la que se ejecuta el programa. Para ver el resultado, descomenta diferente versiones del frameRate() en este ejemplo: void setup() { frameRate(30); // Thirty frames each second //frameRate(12); // Twelve frames each second //frameRate(2); // Two frames each second //frameRate(0.5); // One frame every two seconds } void draw() { println(frameRate); }

------------------------------------------------------------------------------------------------NOTA: Processing trata de ejecutar el cdigo a 60 fotogramas por segundo, pero si toma ms que 1/60th de segundo ejecutar el mtodo draw(), entonces los fotogramas disminuirn.La funcin frameRate() solamente especica la cantidad mxima de fotogramas, y la cantidad actual de fotogramas para cualquier programa depende del computador en el cual se esta ejecutando el cdigo. --------------------------------------------------------------------------------------------------

Velocidad y Direccin:
Para crear ejemplo de movimiento uido, nosotros usamos un tipo de dato llamado oat (decimal). Este tipo de variable almacena los nmeros con decimal, lo que provee mas resolucin para trabajar con movimiento. Por ejemplo, cuando se utilizan enteros, lo ms lento que puedes mover cada fotograma es de uno en uno (un pixel y un pixel) (1,2,3,4,.....), pero con decimales, puedes mover tan lento como quieras (1.01, 1.02, 1.03, 1.04,......). Ejemplo 7-3: Mover una gura: El siguiente ejemplo mueve una gura de izquierda a derecha mediante la actualizacin de la variable x:

int radius = 40; oat x = -radius; oat speed = 0.5; void setup() { size(240, 120); smooth(); ellipseMode(RADIUS); } void draw() { background(0); x += speed; // Increase the value of x arc(x, 60, radius, radius, 0.52, 5.76); }

Cuando ejecutas este cdigo, notaras que la gura desaparece en la parte derecha de la pantalla cuando el valor de la variable x es mayor que el ancho de la pantalla. El valor de x continua incrementandose, pero la gura ya no es visible.

Ejemplo 7-4: Example 7-4: Volver


Existe muchas alternativas a este comportamiento, que puedes elegir de acuerdo a tus preferencias. Primero, vamos a ampliar el cdigo para mostrar como mover la gura de nuevo al borde izquierdo de la pantalla despus de que desapareciera en el borde derecho. En este caso, la imagen en la pantalla como cilindro aplanado, con la gura se mover hasta el borde derecho de la pantalla y luego volver al principio (borde izquierdo):

int radius = 40; oat x = -radius; oat speed = 0.5; void setup() { size(240, 120); smooth(); ellipseMode(RADIUS); } void draw() { background(0); x += speed; // Increase the value of x if (x > width+radius) { // If the shape is off screen, x = -radius; // move to the left edge } arc(x, 60, radius, radius, 0.52, 5.76); }

En cada viaje a travs de draw(), el cdigo prueba para ver si el valor de x a aumentado ms all del ancho de la pantalla (ms el radio de la gura). S i lo ha hecho, seteamos el valor de x a un valor negativo, de modo que a medida que contina aumentando, entrara la pantalla por la derecha. ver gura 7-1 para una diagrama de como funciona.

Figura 7-1. Figure 7-1. La pruebas para el borde izquierdo de la pantalla.

Example 7-5: Rebotan en la pared.


En este ejemplo, extenderemos el ejemplo 7-3 para tener una gura que cambia de direccin cuando golpee el borde, en vez de volver a la izquierda. Para hacer que esto pase, aadimos una nueva variable para almacenar la direccin de la gura. Un valor de direccin de 1 mueve la gura hacia la derecha, y un valor de -1 mueve la gura haca la izquierda:

int radius = 40; oat x = 110; oat speed = 0.5; int direction = 1; void setup() { size(240, 120); smooth(); ellipseMode(RADIUS); } void draw() { background(0); x += speed * direction; if ((x > width-radius) || (x < radius)) { direction = -direction; // Flip direction } if (direction == 1) { arc(x, 60, radius, radius, 0.52, 5.76); // Face right } else { arc(x, 60, radius, radius, 3.67, 8.9); // Face left } } Cuando la gura alcanza un borde, este cdigo da vuelta la direccin de la gura cambiando el signo de la variable de direccin . Por ejemplo, si la variable de direccin es positiva cuando la gura alcanza el borde, el cdigo da vuelta el valor a negativo.

Interpolacin:
A veces quieres animar una gura para que valla de un punto de la pantalla hasta otro. Con un poco ms de lineas de cdigo, puedes setear la posicin de inicio y la posicin de termino, luego calcular las posiciones que estn entre medio del inicio y termino de cada fotograma.

Ejemplo 7-6: Calcular las posicin entremedias


Para que este ejemplo de cdigo sea modular, creamos un grupo de variables en la parte superior. Ejecuta el cdigo un par de veces y cambia los valores para ver como este cdigo puede mover una gura desde cualquier lugar a cualquier otro en un rango de velocidades. Cambia la variable de paso (step) para cambiar la velocidad: int startX = 20; // Initial x-coordinate int stopX = 160; // Final x-coordinate int startY = 30; // Initial y-coordinate int stopY = 80; // Final y-coordinate oat x = startX; // Current x-coordinate oat y = startY; // Current y-coordinate oat step = 0.005; // Size of each step (0.0 to 1.0) oat pct = 0.0; // Percentage traveled (0.0 to 1.0) void setup() { size(240, 120); smooth(); } void draw() { background(0); if (pct < 1.0) { x = startX + ((stopX-startX) * pct); y = startY + ((stopY-startX) * pct); pct += step; } ellipse(x, y, 20, 20); }

AZAR
A diferencia del movimiento suave y lineal que es comn de grcas de computador, el movimiento en el mundo fsico es usualmente idiosincrsico. Por ejemplo, piensa en un hoja otando en el suelo, o una hormiga caminando sobre el terreno duro. Podemos simular las cualidades impredecibles del mundo mediante la generacin aleatoria de nmeros. La funcin random() calcula esos valores; podemos establecer un rango para optimizar la cantidad de desorden en un programa. Ejemplo 7.7: Generando valores aleatorios El siguiente ejemplo imprime valores aleatorios en la consola, con un rango limitado por la posicin del mouse. La funcin random() siempre devuelve un valor de punto otante, entonces, hay que asegurarse de que la variable a la izquierda del operador de asignacin es un decimal (oat) como es aqu: void draw() { oat r = random(0, mouseX); println(r); } Ejempli 7-8: Example 7-8: Dibujar al azar El siguiente ejemplo construido en el ejemplo 7-7, usa los valores de random() para cambiar la posicin de las lineas en la pantalla. Cuando el mouse esta en la izquierda de la pantalla, el cambio es pequeo, cuando se mueve hacia la derecha, lo valores de random() aumentan y el movimiento se hace mas exagerado. Debido a que la funcin random() esta dentro del loop, un nuevo valor es calculado por cada punto de cada linea:

void setup() { size(240, 120); smooth(); } void draw() { background(204); for (int x = 20; x < width; x += 20) { oat mx = mouseX / 10; oat offsetA = random(-mx, mx); oat offsetB = random(-mx, mx); line(x + offsetA, 20, x - offsetB, 100); } }

Ejemplo 7-9: Mover las guras al azar.


Cuando se utiliza para mover guras alrededor de la pantalla, valores aleatorios puede generar imgenes que son ms natural en apariencia. En el siguiente ejemplo, la posicin del crculo es modicada por valores aleatorios en cada viaje a travs de draw(). Dado que la funcin de background() no se utiliza, los lugares por donde pas la gura se mantienen en la pantalla.

oat speed = 2.5; int diameter = 20; oat x; oat y; void setup() { size(240, 120); smooth(); x = width/2; y = height/2; } void draw() { x += random(-speed, speed); y += random(-speed, speed); ellipse(x, y, diameter, diameter); }

Si ves este ejemplo por suciente tiempo, probablemente veas un circulo dejando la pantalla y volviendo. Esto se deja al azar, pero podramos aadir un par de estructuras o usar la funcin constrain() para mantener el circulo en la pantalla. La funcin constrain() limita el valor de un rango especco, el cual puede ser usado para mantener x e y dentro de los lmites de la pantalla. Remplazando draw() en el cdigo anterior por lo siguiente,se asegurar de que la elipse permanecer en la pantalla: void draw() { x += random(-speed, speed); y += random(-speed, speed); x = constrain(x, 0, width); y = constrain(y, 0, height); ellipse(x, y, diameter, diameter); } ---------------------------------------------------------------------------------------------------NOTA: La funcin randomSeed() puede ser usada para forzar random() a producir la misma secuencia de nmeros cada vez que el programa se ejecute. Esto se describe con ms detalle en las referencias de Procesing. ---------------------------------------------------------------------------------------------------

Temporizadores:
Cada programa de Processing cuenta la cantidad de tiempo que ha pasado desde que el programa ha empezado. Se cuenta en milisegundos ( milsimas de segundo), entonces despus de 1 segundo, el contador esta a 1,000; despus de 5 segundos, esta a 5,000, y despus de 1 minuto, esta a 60,000. Podemos usar este contador para disparar animaciones en momentos especcos. La funcin millis () devuelve el valor del contador.

Ejemplo 7-10: El tiempo pasa


Puedes ver el tiempo pasar cuando ejecutas el programa: void draw() { int timer = millis(); println(timer); }

Ejemplo 7-11: Provocando eventos de tiempo Triggering Timed Events


Cuando se combina un bloque if (si es A ocurre b), el valor de millis() puede ser usado para una secuencia de animacin y eventos dentro de un programa. Por ejemplo, despus de dos segundos transcurridos, el cdigo dentro del bloque if puede provocar un cambio. En este ejemplo, las variables llamadas tiempo 1 y tiempo 2 determinan cuando cambiar el valor de la variable x: int time1 = 2000; int time2 = 4000; oat x = 0; void setup() { size(480, 120); smooth(); } void draw() { int currentTime = millis(); background(204); if (currentTime > time2) { x -= 0.5; } else if (currentTime > time1) { x += 2; } ellipse(x, 60, 90, 90); }

Circular
Si eres un as de la trigonometra, ya sabes lo asombrosas que son las funciones seno y coseno. Si no lo eres, esperamos que los siguientes ejemplos llamen tu atencin. No discutiremos el detalle matemtico aqu, pero mostraremos algunas aplicaciones para generar un movimiento uido. Figura 7-2 muestra una visualizacin de los valores de una onda sinusoidal y como se relacionan con los ngulos. En la parte superior e inferior de la onda. Observa como el rango de cambio (el cambio del eje vertical) se hace ms lento, para, y luego cambia de direccin. Es esta cualidad en la curva que genera un movimiento interesante.

Las funciones sin() y cos() en Processing devuelven los valores entre -1 y 1 para el seno y coseno del ngulo especicado. Como arc(), el valor los angulos deben ser dados radianes ( ver ejemplo 3-7 y 3-8 para recordar como trabajar con radianes). Para que sean tiles para dibujar, los valores decimales (oat) retornados por sin() y cos() son generalmente multiplicados por un nmero ms grande.

Figura 7-2. Figure 7-2. Valores de seno y coseno.

Ejemplo 7.12: Example 7-12: Valores de onda sinusoidal


Este ejemplo muestra como los valores para sin() van desde -1 a 1 mientras el ngulo aumenta. Con la funcin map(), With the map() function, la variable sinval es convertida desde este rango a valores desde 0 a 255. Este nuevo valor es usado para establecer el color del fondo de la pantalla (ventana): oat angle = 0.0; void draw() { oat sinval = sin(angle); println(sinval); oat gray = map(sinval, -1, 1, 0, 255); background(gray); angle += 0.1; }

Ejemplo 7-13: Movimiento de onda sinusoidal


Este ejemplo muestra como estos valores pueden ser convertidos en movimiento:

oat angle = 0.0; oat offset = 60; oat scalar = 40; oat speed = 0.05; void setup() { size(240, 120); smooth(); } void draw() { background(0); oat y1 = offset + sin(angle) * scalar; oat y2 = offset + sin(angle + 0.4) * scalar; oat y3 = offset + sin(angle + 0.8) * scalar; ellipse( 80, y1, 40, 40); ellipse(120, y2, 40, 40); ellipse(160, y3, 40, 40); angle += speed; }

Ejemplo 7-14: Movimiento circular Cuando sin() y cos() son usados juntos, pueden provocar movimiento circular. El valor de cos() proveen las coordenadas x, y el valor de sin() las coordenadas y. Ambas son multiplicadas por una variable llamada scalar para cambiar el radio del movimiento y se suma con un valor de desplazamiento para establecer el centro del movimiento circular:

oat angle = 0.0; oat offset = 60; oat scalar = 30; oat speed = 0.05; void setup() { size(120, 120); smooth(); } void draw() { oat x = offset + cos(angle) * scalar; oat y = offset + sin(angle) * scalar; ellipse( x, y, 40, 40); angle += speed; }

Ejemplo 7-15: Espirales


Un ligero cambio hecho para incrementar el valor scalar de cada cuadro produce un espiral, en lugar de un crculo:

oat angle = 0.0; oat offset = 60; oat scalar = 2; oat speed = 0.05; void setup() { size(120, 120); ll(0); smooth(); } void draw() { oat x = offset + cos(angle) * scalar; oat y = offset + sin(angle) * scalar; ellipse( x, y, 2, 2); angle += speed; scalar += speed; }

Trasladar, rotar, ampliar


Cambiar las coordenadas de la pantalla es una tcnica alternativa para crear movimiento. Por ejemplo, puedes mover una gura 50 pixeles a la derecha, o puedes mover la locacin de la coordenada(0,0) 50 pixeles a la derecha el resultado visual en la pantalla ser el mismo. Mediante la modicacin del sistema de coordenadas predeterminado, podemos crear diferente transformaciones incluyendo traslacin, rotacin, y ampliacin. La gura 7-3 demuestra esto grcamente.

Figura 7-3. Trasladando, rotando y ampliando las coordenadas.

Trabajar con transformaciones puede ser difcil, pero la funcin translate(), es la ms sencilla, entonces empezaremos con ella. Esta funcin puede cambiar el sistema de coordenadas de izquierda, derecha, arriba y abajo con sus dos parmetro. Ejemplo 7-16: Trasladando la locacin En este ejemplo, tenga en cuanta que cada rectngulo es dibujado en la coordenada (0,0), pero son movidos alrededor de la pantalla, porque estn siendo afectados por translate():

void setup() { size(120, 120); } void draw() { translate(mouseX, mouseY); rect(0, 0, 30, 30); } La funcin translate() establece la coordenada (0,0) de la pantalla a la ubicacin del mouse.En la siguiente linea, rect() dibuja a la nueva coordenada (0,0) que es en realidad dibujada en la ubicacin del mouse. Ejemplo 7-17: Mltiples traslacin Despus que una transformacin es hecha, es aplicada a todas las funciones de dibujos posteriores. Tenga en cuenta lo que pasa cuando un segundo comando de traslacin es adherido para controlar un segundo rectngulo:

void setup() { size(120, 120); } void draw() { translate(mouseX, mouseY); rect(0, 0, 30, 30); translate(35, 10); rect(0, 0, 15, 15); } El rectngulo ms pequeo tradujo la cantidad de mouseX+35 y mouseY+10.

Ejemplo 7.18: Aislando transformaciones


Para aislar los efectos de una transformacin as no afectaran despus los comandos, usa las funciones pushMatrix() y popMatrix().Cuando la funcin pushMatrix() es ejecutada, guarda una copia de las coordenadas actuales del sistema y luego restaura el sistema despus de popMatrix(): void setup() { size(120, 120); } void draw() { pushMatrix(); translate(mouseX, mouseY); rect(0, 0, 30, 30); popMatrix(); translate(35, 10); rect(0, 0, 15, 15); }

En este ejemplo, el rectngulo ms pequeo siempre es dibujado en la esquia superior izquierda porque la translacin (mouseX, mouseY) es cancelada por popMatrix(). ----------------------------------------------------------------------------------------------NOTA: Las funciones pushMatrix() y popMatrix() son siempre usadas en pares. Por cada pushMatrix(), tienes que tener un popMatrix(). -----------------------------------------------------------------------------------------------

Ejemplo 7-19: Rotacin


La funcin rotate() rota (gira) el sistema de coordenadas. Tiene un parmetro, el cual es el ngulo (en radianes) para rotar (girar). Siempre rota (gira) en relacin con (0,0) que es conocido como la rotacin en torno al origen. Para girar una gura alrededor de su centro, primero usa translate() para mover la locacin donde quieres la gura, luego llama a rotate(), y dibuja la gura con su centro en la coordenada (0,0):

oat angle = 0.0; void setup() { size(120, 120); smooth(); } void draw() { translate(mouseX, mouseY); rotate(angle); rect(-15, -15, 30, 30); angle += 0.1; }

Ejemplo 7-20: Combinando transformaciones Cuando translate() rotate() son combinados, el orden en el cual aparecen afecta el resultado. El siguiente ejemploes identico al ejemplo 7-19, excepto que translate() y rotate() estn are invertidos. Ahora la gura gira alrededor de la esquina superior izquierda de la pantalla, con la distancia desde la esquina establecida por translate(): oat angle = 0.0; void setup() { size(120, 120); smooth(); } void draw() { rotate(angle); translate(mouseX, mouseY); rect(-15, -15, 30, 30); angle += 0.1; } --------------------------------------------------------------------------------------------------------------NOTA: Tambien puedes usar las funciones rectMode(), ellipseMode(), imageMode (), y shapeMode() para dibujar ms facil las formas desde su centro. ---------------------------------------------------------------------------------------------------------------

Ejemplo 7-21: Ajustando (traduccin: escala) La funcin scale() extiende las coordenadas en la pantalla. Como rotate(), transforma desde el origen. Por lo tanto, al igual que rotate(), para ajustar una forma desde su centro,trasladada desde su locacin, escale, y luego dibuja con el centro en la coordenada (0,0):

oat angle = 0.0; void setup() { size(120, 120); smooth(); } void draw() { translate(mouseX, mouseY); scale(sin(angle) + 2); rect(-15, -15, 30, 30); angle += 0.1; }

Ejemplo 7-22: Manteniendo las lineas (trazos) consistentes: Desde las lneas gruesas en el ejemplo 7-21, puedes ver como la funcin scale() afecta el grosor de la linea (stroke weight).Para mantener un grosor de la linea consistente (stroke weight) como las escalas de la gura, divide as a shape scales, divide el grosor de la linea deseado por el valor escalar: oat angle = 0.0; void setup() { size(120, 120); smooth(); } void draw() { translate(mouseX, mouseY); oat scalar = sin(angle) + 2; scale(scalar); strokeWeight(1.0 / scalar); rect(-15, -15, 30, 30); angle += 0.1; } Ejemplo 7-23: Un brazo articulado En este ultimo y largo ejemplo de transformacin, pondremos juntos una serie de funciones translate() y rotate() para un brazo que le mueve hacia adelante y hacia atrs. Cada translate() mueve la posicin de la lineas, y cada rotate() se suma a la rotacin anterior para doblar ms el brazo:

oat angle = 0.0;

oat angleDirection = 1; oat speed = 0.005; void setup() { size(120, 120); smooth(); } void draw() { background(204); translate(20, 25); // Move to start position rotate(angle); strokeWeight(12); line(0, 0, 40, 0); translate(40, 0); // Move to next joint rotate(angle * 2.0); strokeWeight(6); line(0, 0, 30, 0); translate(30, 0); // Move to next joint rotate(angle * 2.5); strokeWeight(3); line(0, 0, 20, 0); angle += speed * angleDirection; if ((angle > QUARTER_PI) || (angle < 0)) { angleDirection *= -1; } } Aqu, no usamos un pushMatrix() o popMatrix(),porque queremos que las transformaciones se propaguenpor cada transformacin para construir la ltima. El sistema de coordenadas es automticamente reseteado al valor original cuando draw() comienza cada fotograma.

Robot 5: Movimiento

En ente ejemplo, las tcnicas de movimiento aleatorio y circular son aplicadas al robot. El fondo background() fue removido para ver ms fcil como la posicin y el cuerpo del robot cambian. En cada cuadro, un nmero aleatorio entre -4 y 4 es adherido a la coordenada x, y un nmero aleatorio entre -1 y 1 es adherido a las coordenada y. Esto causa que el robot se mueva ms de izquierda a derecha que de arriba a abajo. Nmeros calculados desde la funcin sin() cambian la altura del cuello que oscila entre 50 y 110 pixles high (arriba o de alto): oat x = 180; // X-coordinate oat y = 400; // Y-coordinate oat bodyHeight = 153; // Body height oat neckHeight = 56; // Neck height oat radius = 45; // Head radius oat angle = 0.0; // Angle for motion void setup() { size(360, 480); smooth(); ellipseMode(RADIUS); background(204); }

void draw() {

// Change position by a small random amount x += random(-4, 4); y += random(-1, 1); // Change height of neck neckHeight = 80 + sin(angle) * 30; angle += 0.05; // Adjust the height of the head oat ny = y - bodyHeight - neckHeight - radius; // Neck stroke(102); line(x+2, y-bodyHeight, x+2, ny); line(x+12, y-bodyHeight, x+12, ny); line(x+22, y-bodyHeight, x+22, ny); // Antennae line(x+12, ny, x-18, ny-43); line(x+12, ny, x+42, ny-99); line(x+12, ny, x+78, ny+15); // Body noStroke(); ll(102); ellipse(x, y-33, 33, 33); ll(0); rect(x-45, y-bodyHeight, 90, bodyHeight-33); ll(102); rect(x-45, y-bodyHeight+17, 90, 6); // Head ll(0); ellipse(x+12, ny, radius, radius); ll(255); ellipse(x+24, ny-6, 14, 14); ll(0); ellipse(x+24, ny-6, 3, 3); }

Das könnte Ihnen auch gefallen