Processing
Índice
- Introducción
- 1.Estructura básica de un programa
- 1.1.“Hola mundo”
- 1.2.Elementos básicos
- 1.2.1.Inserción de comentarios
- 1.2.2.Declaración de variables
- 1.2.3.Función setup
- 1.2.4.Función draw
- 2.Tipo de datos básicos
- 3.Tipos de datos gráficos
- 3.1.Formas básicas
- 3.1.1.Líneas
- 3.1.2.Elipses
- 3.1.3.Rectángulos
- 3.1.4.Triángulos
- 3.2.Gestión del color de las formas
- 3.2.1.Relleno de las formas
- 3.2.2.Contorno de las formas
- 3.1.Formas básicas
- 4.Animación básica
- 5.Interacción básica: capturar el ratón
- 6.Organización del código
- 7.Trabajar con imágenes
- 8.Transformaciones básicas
- 9.Bibliotecas
Introducción
-
http://mosaic.uoc.edu/2013/02/19/cursor-animado-con-lenguaje-de-programacion-Processing/
-
http://mosaic.uoc.edu/2013/02/27/caleidoscopio-con-lenguaje-de-programacion-Processing/
-
http://mosaic.uoc.edu/2013/02/27/sistema-de-particulas-con-lenguaje-de-programacion-Processing/
-
http://mosaic.uoc.edu/2013/02/27/colisiones-y-particulas-con-lenguaje-de-programacion-Processing
-
http://mosaic.uoc.edu/2013/03/26/Processing-practico-parte-2-de-3/
-
http://mosaic.uoc.edu/2013/04/24/Processing-practico-parte-3-de-3/
-
http://mosaic.uoc.edu/2013/03/25/carga-de-un-modelo-3d-con-lenguaje-de-programacion-Processing/
-
http://mosaic.uoc.edu/2013/03/25/imagenes-y-luts-en-programacion-Processing/
-
http://mosaic.uoc.edu/2013/03/25/sonido-con-lenguaje-de-programacion-Processing-primer-ejemplo/
-
http://mosaic.uoc.edu/2013/03/25/sonido-con-lenguaje-de-programacion-Processing-segundo-ejemplo/
-
http://mosaic.uoc.edu/2013/04/24/realidad-aumentada-con-lenguaje-de-programacion-Processing/
-
http://mosaic.uoc.edu/2013/04/24/deteccion-de-colisiones-con-lenguaje-de-programacion-Processing/
-
http://mosaic.uoc.edu/2013/04/24/acceso-a-webcam-y-luts-en-programacion-Processing/
-
http://mosaic.uoc.edu/2013/04/24/acceso-a-webcam-y-procesado-en-programacion-Processing/
-
http://mosaic.uoc.edu/2013/04/24/operaciones-con-imagenes-en-programacion-Processing/
-
Vamos al apartado de descargas, donde podemos decidir hacer una donación para apoyar el desarrollo de este proyecto de código abierto.
-
Seleccionamos download y accederemos a la página donde podremos seleccionar el sistema operativo de nuestro ordenador y la versión de Processing que queremos descargar.
-
Una vez finalizada la descarga, solo habrá que descomprimir el fichero y aparecerá el directorio donde está el programa.
-
Para ejecutarlo, solo habrá que entrar dentro del directorio creado y ejecutar el fichero processing.exe en el caso de utilizar el Windows o el equivalente de cada sistema operativo, y ya nos aparecerá el entorno de desarrollo que utilizaremos para hacer las actividades.
1.Estructura básica de un programa
1.1.“Hola mundo”
void setup() { size(200, 100); } void draw() { text ("Hello world", 10, 10); }
1.2.Elementos básicos
1.2.1.Inserción de comentarios
/* * Hello world with comments * Version: 2 */ // Main initialization function void setup() { size(200, 100); //Window size } void draw() { text ("Hello world", 10, 10); }
1.2.2.Declaración de variables
String message; void setup() { size(200, 100); message = "Hello world"; } void draw() { text (message, 10, 10); }
1.2.3.Función setup
void setup() { size(200, 100); .... .... }
size(displayWidth, displayHeight);
background (255, 0, 0);
stroke (0, 255, 0);
line (0, 0, 200, 100);
1.2.4.Función draw
Repetición infinita
int index; void setup() { size(200, 100); index = 0; } void draw() { println (index); index = index + 1; }
-
Escribimos el valor de la variable.
-
Incrementamos el valor de la variable.
frameRate (1);
Importancia del orden de los elementos
void setup() { size(200, 100); } void draw() { stroke (255, 0, 0); rect (10, 10, 50, 50); stroke (0, 255, 0); rect (30, 30, 70, 70); }
void draw() { stroke (0, 255, 0); rect (30, 30, 70, 70); stroke (255, 0, 0); rect (10, 10, 50, 50); }
int index; void setup() { size(200, 150); frameRate (1); index = 0; } void draw() { println (index); text (index, 0, 10); index = index + 1; }
void draw() { background (128, 128, 128); println (index); text (index, 0, 10); index = index + 1; }
textSize (30);
2.Tipo de datos básicos
2.1.Definición e inicialización de variables
tipus_de_variable nom_de_variable; void setup() { nom_de_variable = valor_inicial; } void draw() { }
2.2.Variables: booleanas
boolean a; void setup() { a = true; a = false; }
2.3.Variables: números enteros
int index; void setup() { index = 0; }
int index; int doble; void setup() { index = 0; doble = 0; } void draw() { println ("index: "+ index +" valor doble: " + doble); index = index + 1; doble = index * 2; }
println ("index: "+ index +" valor doble: " + doble);
2.4.Variables: números decimales
float decimal; void setup() { decimal = 0.0; }
int a; int b; float result; void setup() { a = 11; b = 2; result = a / b; println ("a/b = " + result); result = 11 / 2; println ("a/2 = " + result); result = a / 2.0; println ("a/2 = " + result); }
a/b = 5.0 a/2 = 5.0 a/2 = 5.5
2.5.Variables: conjuntos
int[] int_array;
2.5.1.Inicialización con todos los valores conocidos
int[] int_array = { 10, 20, 30 }; void setup() { }
2.5.2.Inicialización sin valores
int[] int_array; void setup() { int_array = new int [3]; }
2.5.3.Acceso a los datos del array
int_array[1]=444;
println (int_array[1]);
int[] int_array = { 10, 20, 30 }; void setup() { println (int_array[0]); println (int_array[1]); println (int_array[2]); }
println (int_array.length);
2.6.Variables: cadenas de texto
String text; void setup() { text = new String ("Hello"); println (text); }
void setup() { text = new String ("Hello"); text = "bye!"; println (text); }
2.7.Variables: color
color c; void setup() { c = color (255, 0, 0); } void draw() { background (c); }
color c; void setup() { c = color (255, 120, 60); println ("Direct value: " + c); println ("Hexadecimal value: " + hex(c)); }
Direct value: -34756 Hexadecimal value: FFFF783C
-
AA: Valores entre 00 y FF (0 a 255 en decimal), definen el canal alfa, o lo que es el mismo, la transparencia del color.
-
RR: Valores entre 00 y FF (0 a 255 en decimal), definen el canal rojo.
-
GG: Valores entre 00 y FF (0 a 255 en decimal), definen el canal verde.
-
BB: Valores entre 00 y FF (0 a 255 en decimal), definen el canal azul.
2.8.Ejemplo: “Hola mundo” utilizando variables
void setup() { size(300, 200); } void draw() { textSize (30); text ("Hello world", 10, 30); }
String message; void setup() { size(300, 200); message = new String ("Hello world"); } void draw() { textSize (30); text (message, 10, 30); }
String message; int size; void setup() { size(300, 200); message = new String ("Hello world"); size = 10; } void draw() { textSize (size); text (message, 10, 30); }
String message; int size; void setup() { size(300, 200); frameRate (1); message = new String ("Hello world"); size = 10; } void draw() { textSize (size); text (message, 10, 30); size = size + 1; }
String message; int size; color c; void setup() { size(300, 200); frameRate (1); message = new String ("Hello world"); size = 10; c = color (100, 100, 100); } void draw() { background (c); textSize (size); text (message, 10, 30); size = size + 1; }
String[] message; int size; color c; void setup() { size(300, 200); frameRate (1); message = new String [2]; message[0] = new String ("Hello"); message[1] = new String ("world!"); size = 10; c = color (100, 100, 100); } void draw() { background (c); textSize (size); text (message[(size % 2)], 10, 30); size = size + 1; }
-
Definimos la variable array, que contiene información de tipo string.
-
message = new String [2]: inicializamos el array y decimos que tendrá lugar para 2 elementos de tipo string.
-
message[0] = new String ("Hello"): inicializamos cada una de las posiciones (en este caso el elemento 0) con un dato de tipo string. Aquí lo que puede sorprender es que volvemos a hacer un newString, pero recordad que es porque para crear una cadena de texto normal, también teníamos que hacerlo de esta manera. En el caso de un entero o un decimal, pondríamos directamente el valor. Repasad el ejemplo que está en el apartado de arrays para verlo más claro.
-
Una vez tenemos los dos textos cargados en el array, uno en la posición 0 y otro en la posición 1, hay que buscar la manera de que se vayan alternando. En nuestro caso, aprovecharemos la variable size, que se va incrementando, y la función módulo (%). Al hacer el cálculo (size % 2) nos está devolviendo el valor 0 cuando el valor size es par o 1 cuando es impar, y por lo tanto, lo podemos aprovechar para seleccionar qué elemento del array enseñamos en cada momento.
2.9.Ejemplo: calculando el tiempo
int time_now; int time_old; int time_delta; void setup() { size (400, 150); frameRate (20); time_now = 0; time_old = 0; time_delta = 0; } void draw() { time_now = millis(); time_delta = time_now - time_old; time_old = time_now; background(0, 0, 0); textSize (30); text (time_delta, 50, 35); text ("ms", 130, 35); }
//frameRate (20);
int time_now; int time_old; int time_delta; float sec; void setup() { size (400, 150); //frameRate (20); time_now = 0; time_old = 0; time_delta = 0; sec = 0; } void draw() { time_now = millis(); time_delta = time_now - time_old; time_old = time_now; sec = time_delta / 1000.0; background(0, 0, 0); textSize (30); text (time_delta, 50, 35); text ("ms", 150, 35); text (sec, 50, 70); text ("segons", 150, 70); }
int time_now; int time_old; int time_delta; float sec; float fps; void setup() { size (400, 150); //frameRate (20); time_now = 0; time_old = 0; time_delta = 0; sec = 0; fps = 0; } void draw() { time_now = millis(); time_delta = time_now - time_old; time_old = time_now; sec = time_delta / 1000.0; fps = 1.0 / sec; background(0, 0, 0); textSize (30); text (time_delta, 50, 35); text ("ms", 170, 35); text (sec, 50, 70); text ("segons", 170, 70); text (fps, 50, 105); text ("FPS", 170, 105); }
3.Tipos de datos gráficos
void setup() { size(500, 400); } void draw() { background (255, 255, 255); }
3.1.Formas básicas
3.1.1.Líneas
line (10, 20, 400, 100);
3.1.2.Elipses
ellipse (150, 150, 100, 50); ellipse (150, 250, 100, 100);
3.1.3.Rectángulos
rect (200, 125, 100, 50); rect (200, 200, 100, 100);
rect (310, 125, 100, 50, 10);
rect (310, 200, 100, 100, 10, 20, 30, 40);
3.1.4.Triángulos
triangle (50, 390, 150, 300, 250, 390);
3.2.Gestión del color de las formas
color c_black; color c_white; color c_green; color c_red; color c_blue; void setup() { size(500, 400); c_black = color (0, 0, 0); c_white = color (255, 255, 255); c_green = color (0, 255, 0); c_red = color (255, 0, 0); c_blue = color (0, 0, 255); } void draw() { background (c_black); rect (10, 10, 100, 100); }
3.2.1.Relleno de las formas
void draw() { background (c_black); fill (c_red); rect (10, 10, 100, 100); }
void draw() { background (c_black); fill (c_red); rect (10, 10, 100, 100); rect (120, 120, 200, 200); fill (c_blue); rect (150, 200, 100, 100); }
fill (c_green); rect (200, 150, 200, 200);
noFill (); rect (200, 150, 200, 200);
3.2.2.Contorno de las formas
stroke (c_green);
fill (c_blue); noStroke(); rect (150, 200, 100, 100);
void draw() { background (c_black); stroke (c_green); fill (c_red); rect (10, 10, 100, 100); rect (120, 120, 200, 200); fill (c_blue); noStroke(); rect (150, 200, 100, 100); noFill (); stroke (c_white); rect (200, 150, 200, 200); }
-
Indicamos que el color de fondo es el negro.
-
Definimos que queremos contornear de color verde y pintar de color rojo.
-
Dibujamos dos cuadrados.
-
Definimos que queremos pintar de color azul y que no queremos contornear.
-
Dibujamos el cuadrado pequeño.
-
Definimos que no queremos pintar las figuras y las queremos contornear de color blanco.
-
Dibujamos el cuadrado grande.
4.Animación básica
void setup() { size(800, 400); frameRate (20); } void draw() { background(255, 255, 255); fill (0, 0, 0); }
int ball_x; int ball_y; int ball_radius; void setup() { size(800, 400); frameRate (20); ball_x = 10; ball_y = 200; ball_radius = 10; } void draw() { background(255, 255, 255); fill (0, 0, 0); ellipse (ball_x, ball_y, ball_radius, ball_radius); }
ball_x = ball_x + 1;
4.1.Estructura condicional if...else
void draw() { background(255, 255, 255); fill (0, 0, 0); ellipse (ball_x, ball_y, ball_radius, ball_radius); if (ball_x < 800){ ball_x = ball_x + 1; }else{ text ("STOP", 400, 200); } }
-
if (ball_x < 800): comprobamos si la posición de la bola en le eje x es inferior a 800, que es la anchura de nuestra ventana.
-
Si la condición se cumple, la bola todavía no ha llegado al final de la ventana, incrementamos la variable ball_x para que la bola continúe avanzando.
-
Si la condición no se cumple, la bola ha llegado al final, saltamos al bloque de código que hay en el else, y en este caso escribimos un texto en la pantalla y ya no incrementamos la variable de la posición de la bola.
4.2.Variables height y width
size(400, 400);
void draw() { background(255, 255, 255); fill (0, 0, 0); text ("Height: "+height+", Width: "+width, 10, 15); ellipse (ball_x, ball_y, ball_radius, ball_radius); if (ball_x < width){ ball_x = ball_x + 1; }else{ text ("STOP", 400, 200); } }
if (ball_x < width)
4.3.Simulaciones físicas
ball_x = ball_x + 1;
int ball_x; int ball_y; int ball_radius; void setup() { size(400, 400); frameRate (20); ball_x = 200; ball_y = 10; ball_radius = 10; } void draw() { background(255, 255, 255); fill (0, 0, 0); ellipse (ball_x, ball_y, ball_radius, ball_radius); if (ball_y < height){ ball_y = ball_y + 10; }else{ text ("STOP", width/2, height/2); } }
// Time variables int time_now; int time_old; int time_delta; // Ball variables int ball_x; int ball_radius; float ball_y; float ball_y_old; float ball_y_speed; float ball_y_speed_old; float ball_y_acceleration;
void setup() { size(400, 400); frameRate (20); //Time init time_now = 0; time_old = 0; time_delta = 0; //Ball init ball_x = 200; ball_y = 10.0; ball_y_old = 10.0; ball_radius = 10; ball_y_speed = 0.0; ball_y_speed_old = 0.0; ball_y_acceleration = 9.8; }
time_now = millis(); time_delta = time_now - time_old; time_old = time_now;
if (ball_y < height){ ball_y_speed = ball_y_speed_old + (ball_y_acceleration * (time_delta/1000.0)); ball_y = ball_y_old + (ball_y_speed_old * (time_delta/1000.0)) + ( (ball_y_acceleration * (time_delta/1000.0) * (time_delta/1000.0)) / 2.0 ); ellipse (ball_x, ball_y, ball_radius, ball_radius); ball_y_speed_old = ball_y_speed; ball_y_old = ball_y; }else{ text ("STOP", width/2, height/2); }
-
Calculamos la velocidad que tiene que tener en función de la velocidad anterior y el tiempo que ha pasado. Fijaos que estamos dividiendo la variable time_delta entre 1.000,0, puesto que este valor es en milisegundos y nosotros lo necesitamos expresado en segundos.
-
Calculamos la nueva posición utilizando la ecuación que hemos visto.
-
Dibujamos la bola en la posición nueva que acabamos de calcular.
-
Actualizamos el valor de las variables antiguas con las que hemos calculado ahora, de esta manera ya estaremos preparados para hacer el próximo cálculo.
4.4.Mesa de billar
int ball_x; int ball_y; int ball_radius; void setup() { size(800, 400); frameRate (20); ball_x = 10; ball_y = 200; ball_radius = 10; } void draw() { background(255, 255, 255); fill (0, 0, 0); ellipse (ball_x, ball_y, ball_radius, ball_radius); if (ball_x < 800){ ball_x = ball_x + 1; }else{ text ("STOP", 400, 200); } }
int ball_x; int ball_y; int ball_radius; int inc_x; int inc_y; void setup() { size(800, 400); frameRate (20); ball_x = 10; ball_y = 200; ball_radius = 10; inc_x = 5; inc_y = 2; } void draw() { background(255, 255, 255); fill (0, 0, 0); ball_x = ball_x + inc_x; ball_y = ball_y + inc_y; ellipse (ball_x, ball_y, ball_radius, ball_radius); if ( (ball_x <= 0) || (ball_x >= width)) { inc_x = inc_x * -1; } if ( (ball_y <= 0) || (ball_y >= height)) { inc_y = inc_y * -1; } }
5.Interacción básica: capturar el ratón
void setup() { size(400, 400); frameRate (20); } void draw() { background(0, 0, 0); text ("Mouse position:\n X: "+"\n Y:",10, 20); }
5.1.Conocemos la posición actual
text ("Mouse position:\n X: "+mouseX+"\n Y: "+mouseY,10, 20);
5.2.Perseguimos el ratón
float ball_x; float ball_y; float dir_x; float dir_y;
ball_x = width/2.0; ball_y = height/2.0; dir_x = 1.0; dir_y = 1.0;
-
ball_*: nos sirve para indicar la posición actual de la bola y está inicializada en el centro de la ventana.
-
dir_*: indica hacia dónde se moverá la bola; de momento decimos que se mueva hacia abajo a la derecha.
ball_x = ball_x + dir_x; ball_y = ball_y + dir_y; ellipse (ball_x, ball_y, 10, 10);
void draw() { background(0, 0, 0); text ("Mouse position:\n X: "+mouseX+"\n Y: "+mouseY,10, 20); dir_x = mouseX - ball_x; dir_y = mouseY - ball_y; ball_x = ball_x + dir_x; ball_y = ball_y + dir_y; ellipse (ball_x, ball_y, 10, 10); }
5.3.Capturar los clics del ratón
float ball_x; float ball_y; float dir_x; float dir_y; boolean run; void setup() { size(400, 400); frameRate (20); ball_x = width/2.0; ball_y = height/2.0; dir_x = 1.0; dir_y = 1.0; run = false; } void draw() { background(0, 0, 0); text ("Mouse position:\n X: "+mouseX+"\n Y: "+mouseY,10, 20); if (run == true){ dir_x = mouseX - ball_x; dir_y = mouseY - ball_y; ball_x = ball_x + dir_x; ball_y = ball_y + dir_y; } ellipse (ball_x, ball_y, 10, 10); }
-
Hemos añadido la variable run, que utilizaremos para indicar si la bola se tiene que mover o no. De momento la hemos dejada inicializada con el valor false, de manera que, aunque movamos el ratón, la bola no se moverá.
-
Hemos añadido un bloque if...else que comprueba el valor de la variable run. En el supuesto de que el valor sea true, calculamos el movimiento que tiene que hacer la bola del mismo modo que habíamos visto en el ejemplo anterior.
void mousePressed() { run = true; }
void mousePressed() { if (mouseButton == LEFT){ run = true; }else{ if (mouseButton == RIGHT){ run = false; } } }
5.4.Utilización de la rueda del ratón
void mouseWheel(MouseEvent event) { float incr = event.getAmount(); println(incr); }
-
El valor 1 indicará la velocidad más lenta.
-
El valor 100 indicará la más rápida, que será la velocidad con que se está moviendo ahora la bola.
float vel;
vel = 100.0;
text ("Mouse position:\n X: "+mouseX+"\n Y: "+mouseY+"\n Vel: "+vel,10, 20);
void mouseWheel(MouseEvent event) { float incr = event.getAmount(); vel = vel + incr; if (vel < 1.0){ vel = 1.0; } if (vel > 100.0){ vel = 100.0; } }
if (run == true){ dir_x = mouseX - ball_x; dir_y = mouseY - ball_y; dir_x = (dir_x * vel) / 100.0; dir_y = (dir_y * vel) / 100.0; ball_x = ball_x + dir_x; ball_y = ball_y + dir_y; }
6.Organización del código
6.1.Las funciones
6.1.1.Estructura básica de las funciones
<tipus_retorn> <nom_funció> (<parametres_que_rep>){ <codi_de_la_funció> return <variable_que_retornem> }
void setup(){}
int funcioTornamUnNombre(){}
void nomFuncio (int nombre, String text){}
return variable
int tornaEnter(){}
6.1.2.Definimos la primera función
float ball_x; float ball_y; float dir_x; float dir_y; boolean run; float vel; void setup() { size(400, 400); frameRate (20); ball_x = width/2.0; ball_y = height/2.0; dir_x = 1.0; dir_y = 1.0; run = false; vel = 100.0; } void draw() { background(0, 0, 0); text ("Mouse position:\n X: "+mouseX+"\n Y: "+mouseY+"\n Vel: "+vel,10, 20); if (run == true){ dir_x = mouseX - ball_x; dir_y = mouseY - ball_y; dir_x = (dir_x * vel) / 100.0; dir_y = (dir_y * vel) / 100.0; ball_x = ball_x + dir_x; ball_y = ball_y + dir_y; } ellipse (ball_x, ball_y, 10, 10); } void mousePressed() { if (mouseButton == LEFT){ run = true; }else{ if (mouseButton == RIGHT){ run = false; } } } void mouseWheel(MouseEvent event) { float incr = event.getAmount(); vel = vel + incr; if (vel < 1.0){ vel = 1.0; } if (vel > 100.0){ vel = 100.0; } }
if (run == true){ dir_x = mouseX - ball_x; dir_y = mouseY - ball_y; dir_x = (dir_x * vel) / 100.0; dir_y = (dir_y * vel) / 100.0; ball_x = ball_x + dir_x; ball_y = ball_y + dir_y; }
void calculatePosition() { dir_x = mouseX - ball_x; dir_y = mouseY - ball_y; dir_x = (dir_x * vel) / 100.0; dir_y = (dir_y * vel) / 100.0; ball_x = ball_x + dir_x; ball_y = ball_y + dir_y; }
void draw() { background(0, 0, 0); text ("Mouse position:\n X: "+mouseX+"\n Y: "+mouseY+"\n Vel: "+vel,10, 20); if (run == true){ calculatePosition(); } ellipse (ball_x, ball_y, 10, 10); }
6.1.3.Otros ejemplos
int i; void setup() { size(200, 100); frameRate (1); i = 1; } void draw() { background(0, 0, 0); text ("i value: "+i,10, 20); i = i +1; }
Función plusOne
void draw() { background(0, 0, 0); text ("i value: "+i,10, 20); plusOne(); } void plusOne(){ i = i + 1; }
Función plusX
void draw() { background(0, 0, 0); text ("i value: "+i,10, 20); plusX(10); } void plusX (int x){ i = i + x; }
Función addXY
void draw() { background(0, 0, 0); text ("i value: "+i,10, 20); i = addXY (i, 10); } int addXY (int x, int y){ int sum; sum = x + y; return sum; }
6.2.Los frames y la gestión del flujo del programa
6.2.1.El guion animado y el diagrama de estados
-
Con la rueda del ratón modificamos el tiempo que querremos que se mueva la bola.
-
Al hacer clic en el ratón saltaremos al frame 2.
-
Mientras el tiempo pendiente sea superior a 0, la bola se continúa moviendo.
-
Cuando el tiempo sea 0, saltaremos al estado siguiente.
6.2.2.Del guion animado al código: la estructura switch
if (c == 1){ //Do 1 }else{ if (c == 2){ //Do 2 }else{ if (c == 3){ //Do 3 }else{ //Do 4 } } }
switch(num) { case 0: println("Zero"); break; case 1: println("One"); break; default: println("None"); break; }
int frame; void setup() { size(400, 400); frameRate (20); frame = 1; } void draw() { background(0, 0, 0); switch (frame){ case 1: //Stopped ball, time control, waiting click break; case 2: //Moving ball, countdown break; case 3: //Stopped ball, waiting click break; } }
int frame; int ball_x; int ball_y; int time; String message; float crono; void setup() { size(400, 400); frameRate (20); frame = 1; ball_x = 15; ball_y = height - 15; time = 0; message = new String ("TIME: "); crono = 0.0; } void draw() { background(0, 0, 0); switch (frame){ case 1: //Stopped ball, time control, waiting click break; case 2: //Moving ball, countdown break; case 3: //Stopped ball, waiting click break; } ellipse (ball_x, ball_y, 10, 10); text (message+time, 10, 20); }
Estado 1
void mouseWheel(MouseEvent event) { float incr = event.getAmount(); time = time + int(incr); if (time < 0){ time = 0; } }
void draw() { background(0, 0, 0); switch (frame){ case 1: //Stopped ball, time control, waiting click if (mousePressed){ crono = time; frame = 2; } break; case 2: //Moving ball, countdown break; case 3: //Stopped ball, waiting click break; } ellipse (ball_x, ball_y, 10, 10); text (message+time, 10, 20); text (frame, width-20, 20); }
Estado 2
void draw() { background(0, 0, 0); clock(); switch (frame){ case 1: //Stopped ball, time control, waiting click if (mousePressed){ crono = time; frame = 2; } break; case 2: //Moving ball, countdown countdown(); time = int (crono); break;
void clock() { time_now = millis(); time_delta = time_now - time_old; time_old = time_now; }
void countdown() { crono = crono - (time_delta / 1000.0); }
case 2: //Moving ball, countdown countdown(); time = int (crono); if (time <= 0){ frame = 3; } break;
case 2: //Moving ball, countdown countdown(); time = int (crono); move_ball(); if (time <= 0){ frame = 3; } break;
void move_ball() { ball_x = ball_x + 1; ball_y = ball_y - 1; }
Estado 3
case 3: //Stopped ball, waiting click if (mousePressed){ frame = 1; ball_x = 15; ball_y = height - 15; } break;
7.Trabajar con imágenes
7.1.Elementos básicos
void setup() { size(800, 331); frameRate (20); } void draw() { }
PImage img; void setup() { size(800, 331); frameRate (20); img = loadImage ("background.JPG"); } void draw() { image (img, 0, 0); }
7.2.Tipo de imágenes que podemos utilizar
-
JPG: Es el formato que utilizaremos más, nos permite cargar imágenes y mantener una medida de fichero reducida.
-
GIF: Puede ser útil para imágenes pequeñas con detalles muy finos como los de los iconos, por ejemplo, pero el uso más interesante es que podremos cargar imágenes animadas y ver esta animación al ejecutar el programa.
-
PNG: este formato nos permite trabajar con imágenes con zonas transparentes, cosa que nos puede dar bastante juego. Veremos un ejemplo a continuación.
7.3.Añadimos una bola
PImage img; PImage ball; void setup() { size(800, 331); frameRate (20); img = loadImage ("background.JPG"); ball = loadImage ("ball.jpg"); } void draw() { image (img, 0, 0); image (ball, 20, 20); }
PImage img; PImage ball; PImage ball_alfa; void setup() { size(800, 331); frameRate (20); img = loadImage ("background.JPG"); ball = loadImage ("ball.jpg"); ball_alfa = loadImage ("ball.png"); } void draw() { image (img, 0, 0); image (ball, 20, 20); image (ball_alfa, 300, 20); }
void draw() { image (img, 0, 0); image (ball, 20, 20); image (ball_alfa, 300, 20); image (ball_alfa, 550, 60, 100, 100); }
8.Transformaciones básicas
8.1.Transformaciones
void setup() { size(400, 400); frameRate (20); } void draw() { background(0, 0, 0); ellipse (0, 0, 80, 40); }
8.1.1.Traslación
void draw() { background(0, 0, 0); translate ((width/2), (height/2)); ellipse (0, 0, 80, 40); }
8.1.2.Rotación
void draw() { background(0, 0, 0); translate ((width/2), (height/2)); rotate (HALF_PI); ellipse (0, 0, 80, 40); }
Xradians = radians (Ydegree); Ydegree = degrees (Xradians);
8.1.3.Escala
void draw() { background(0, 0, 0); translate ((width/2), (height/2)); rotate (HALF_PI); scale (3.0); ellipse (0, 0, 80, 40); }
scale (3.0, 3.0);
8.2.El problema de la referencia al origen de coordenadas
void setup() { size(400, 400); frameRate (20); } void draw() { background(0, 0, 0); fill (255, 255, 255); ellipse (300, 50, 80, 40); fill (255, 0, 0); rotate (HALF_PI/2); ellipse (300, 50, 80, 40); }
rect (5, 5, 2, 2);
void draw() { background(0, 0, 0); fill (255, 0, 0); stroke (255, 0, 0); rect (5, 5, 2, 2); noFill (); stroke (0, 0, 255); rect (5, 5, 2, 2); }
void draw() { background(0, 0, 0); fill (255, 0, 0); stroke (255, 0, 0); rect (5, 5, 2, 2); translate (5, 0); noFill (); stroke (0, 0, 255); rect (5, 5, 2, 2); }
-
Desplazamos el origen de coordenadas a la posición (5, 0).
-
Dibujamos el cuadrado teniendo en cuenta las nuevas coordenadas de referencia.
void setup() { size(400, 400); frameRate (20); } void draw() { background(0, 0, 0); fill (255, 0, 0); stroke (255, 0, 0); rect (150, 150, 100, 100); noFill (); stroke (0, 0, 255); rect (150, 150, 100, 100); }
noFill (); stroke (0, 0, 255); rotate (radians (30)); rect (150, 150, 100, 100);
noFill (); stroke (0, 0, 255); translate (150, 150); rotate (radians (30)); rect (150, 150, 100, 100);
noFill (); stroke (0, 0, 255); translate (150, 150); rotate (radians (30)); rect (0, 0, 100, 100);
8.3.Ámbito de las transformaciones
void setup() { size(400, 200); frameRate (20); } void draw() { background(0, 0, 0); rect (20, 20, 20, 20); translate (100,50); rect (20, 20, 20, 20); ellipse (20, 50, 15, 15); }
8.3.1.Ordenación de los elementos en función de las transformaciones
void draw() { background(0, 0, 0); rect (20, 20, 20, 20); ellipse (20, 50, 15, 15); translate (100,50); rect (20, 20, 20, 20); }
8.3.2.Invertir los efectos aplicados
void draw() { background(0, 0, 0); rect (20, 20, 20, 20); translate (100,50); rect (20, 20, 20, 20); translate (-100, -50); ellipse (20, 50, 15, 15); }
8.3.3.La pila de transformaciones
-
pushMatrix: Guardará la situación actual en la pila, con todas las transformaciones que haya aplicadas.
-
PopMatrix: Recuperará el último estado que habíamos guardado, de manera que dejaremos de aplicar las transformaciones que teníamos definidas ahora, y volveremos a utilizar las anteriores.
void draw() { background(0, 0, 0); rect (20, 20, 20, 20); pushMatrix(); translate (100,50); rect (20, 20, 20, 20); popMatrix(); ellipse (20, 50, 15, 15); }
void draw() { background(0, 0, 0); fill (255, 0, 0); rect (20, 20, 20, 20); pushMatrix(); translate (100,50); fill (0, 255, 0); rect (20, 20, 20, 20); pushMatrix (); fill (0, 0, 255); rotate (radians(30)); rect (20, 20, 20, 20); ellipse (20, 50, 15, 15); popMatrix(); fill (0, 255, 0); ellipse (20, 50, 15, 15); popMatrix(); fill (255, 0, 0); ellipse (20, 50, 15, 15); }
-
Color rojo para las figuras sin ninguna transformación aplicada.
-
Color verde para las figuras que solo tienen la traslación.
-
Color azul para las que tienen la traslación y la rotación.
-
Aplicamos una rotación de 30º, que se suma al desplazamiento que ya teníamos aplicado.
-
Dibujamos el cuadrado azul.
-
Dibujamos el círculo azul.
-
Recuperamos el último estado que tenemos en la pila.
9.Bibliotecas
apple (20, red);
-
Minim: Es una biblioteca que por defecto ya está cargada y que nos permite trabajar con ficheros de audio.
-
ControlP5: Esta biblioteca no está cargada por defecto y nos permite crear rápidamente interfaces gráficas con botones, desplegables, etc.
9.1.Gestión de bibliotecas
9.1.1.Instalación de la biblioteca ControlP5
import controlP5.*;
9.2.Biblioteca Minim
void setup() { size(400, 200); } void draw() {
import ddf.minim.spi.*; import ddf.minim.signals.*; import ddf.minim.*; import ddf.minim.analysis.*; import ddf.minim.ugens.*; import ddf.minim.effects.*; void setup() { size(400, 200); } void draw() {
Minim minim; AudioPlayer player;
void setup() { size(400, 200); minim = new Minim(this); player = minim.loadFile("buzzer.mp3"); }
void setup() { size(400, 200); minim = new Minim(this); player = minim.loadFile("buzzer.mp3"); player.play(); }
void draw() { player.play(); }
void mousePressed() { player.play(); }
9.3.Biblioteca ControlP5
void setup() { size(400, 200); } void draw() { background (0, 0, 0); }
import controlP5.*;
import controlP5.*; ControlP5 userinterface; void setup() { size(400, 200); userinterface = new ControlP5 (this); }
void setup() { size(400, 200); userinterface = new ControlP5 (this); userinterface.addButton ("button11", 1, 20, 20, 100, 100); }
void controlEvent(ControlEvent theEvent) { if(theEvent.isController()) { println("control event from : "+theEvent.controller().name()+", value : "+theEvent.controller().value()); if(theEvent.controller().name().equals("button1")) { println ("BUTTON PRESSED"); } } }
import controlP5.*; ControlP5 userinterface; int ball_x; int count; void setup() { size(400, 200); userinterface = new ControlP5 (this); userinterface.addButton ("button1", 1, 20, 20, 100, 100); ball_x = 20; count = 0; } void draw() { background (0, 0, 0); text ("Pressed "+count+" times", 150, 60); ellipse (ball_x, 150, 20, 20); } void controlEvent(ControlEvent theEvent) { if(theEvent.isController()) { println("control event from : "+theEvent.controller().name()+", value : "+theEvent.controller().value()); if(theEvent.controller().name().equals("button1")) { println ("BUTTON PRESSED"); pressedButton1(); } } } void pressedButton1(){ ball_x = ball_x + 10; count = count + 1; }