You are on page 1of 390

Introduccin a

Processing v1.2.1
Ral Lacabanne - 2011
Versin 41
Resumen de los tpicos bsicos del libro:
Processing: A Programming Handbook
for Visual Designers and Artists
de Casey Reas y Ben Fry. MIT Press, 2007.

Design By Numbers
Design By Numbers (DBN) fue
creado como una plataforma de
introduccin al diseo asistido
por ordenador para diseadores
visuales y artistas.
Conceptualizado por John
Maeda en el ACG (Aesthetics +
Computation Group) del MIT,
quien cree que la calidad del
diseo y arte de medios slo
puede mejorar a travs del
establecimiento de
infraestructuras educativas en
escuelas de arte y tecnologa
que fomenten la formacin de
individuos transdiciplinarios
competentes.
John Maeda. DBN. 1999-2001.

Processing
Processing es un lenguaje y
entorno de programacin de
cdigo abierto basado en Java,
de fcil utilizacin, y que sirve
como instrumento didctico
para la enseanza y
produccin de proyectos
multimedia e interactivos de
diseo digital. Fue iniciado por
Ben Fry y Casey Reas.
Processing es desarrollado por
artistas y diseadores como
una herramienta alternativa al
software propietario. Puede ser
utilizado tanto para
aplicaciones locales as como
aplicaciones para la web.
Casey Reas & Ben Fry. 2001.

Parte 1
Elementos de sintaxis

Descarga y descompresin
Dirigirse a la siguiente URL: http://www.processing.org/download/
y descargar la versin apropiada a su sistema operativo. Se
recomienda a los usuarios de Windows descargar la versin
Windows (a secas) y no la versin Windows (Without
Java).
Una vez descargado el archivo, descomprimirlo en alguna
carpeta del disco rgido, ej: el escritorio. Esto quiere decir que el
entorno de desarrollo Processing no necesita instalacin.
A continuacin abrir la carpeta descomprimida y ejecutar el
archivo correspondiente al icono:

Comentarios
En Processing tenemos dos formas de realizar comentarios.
El primero es un comentario simple:
// esto es un comentario...
// ...y esto tambin lo es
el segundo es un bloque de comentario:
/*
esto
tambin
es
un
comentario
*/

Funciones (I)
Las funciones permiten ejecutar algoritmos,
es decir, obtener un resultado a partir de un o
una serie de pasos lgicos y estructurados.
En general, el nombre de una funcin
comienza en minsculas y es seguido por un
par de parntesis.
Los elementos que se encuentran entre los
parntesis se llaman parmetros.

Funciones (II)
Ejemplo de funciones
size(200, 200)
background(102)
noCursor()

Sensibilidad a maysculas y
minsculas
b =/= B
size() =/= Size()

Espaciado
Processing es flexible a los espaciados. Sin
embargo se recomienda ser prudente con los
mismos para que la lectura del cdigo sea
cmoda.

Instrucciones (I)
Si utilizamos una metfora del lenguaje humano,
podemos entender a la instruccin como si fuera
una oracin.
Las instrucciones siempre se deben terminan con el
signo punto y coma (;).
Dentro de una instruccin se pueden realizar las
siguientes acciones:
definir una variable o array,
asignar un valor a una variable (o valores a un array),
ejecutar una funcin,
o construir un objeto

Instrucciones (II)
Ejemplo de un boceto que contiene un
conjunto de instrucciones:
size(200, 200); // Ejecuta la funcin size() con dos parmetros
background(102); // Ejecuta la funcin background() con un parmetro
noCursor();
// Ejecuta la funcin noCursor() con ningn parmetro

Lectura recomendada
Captulo Structure 1: Code Elements (pag. 17).
Reas, C. & Fry, B. "Processing: A Programming Handbook for
Visual Designers and Artists, MIT Press, 2007.

Informacin complementaria

Utilizacin de la consola
// Para imprimir un valor Uso de la funcin print()
print(10); // Imprime 10 en la consola
// Para imprimir un texto, coloque el mismo entre comillas
print(processing"); // Imprime processing a continuacin del dato anterior
// Para imprimir en lneas separadas Uso de la funcin println()
println(10); // Imprime 10 en la consola y salta a una nueva lnea
println(processing"); // Imprime processing y salta a una nueva lnea

Funcin cursor() y noCursor()


cursor()
Sintaxis
cursor()
cursor(MODE)
cursor(image, x, y)

Parmetros

MODE: Puede optar por ARROW, CROSS, HAND, MOVE, TEXT, WAIT
image PImage: cualquier variable del tipo PImage
x int: el punto activo horizontal del cursor
y int: el punto activo vertical del cursor

noCursor()

Parte 2
Coordenadas y
figuras primitivas

Coordenadas
En Processing, el origen se encuentra en el
margen superior izquierdo.
0, 0

+100

+100

Primitivas: punto

point(20,
point(30,
point(40,
point(50,
point(60,

20);
30);
40);
50);
60);

Primitivas: lnea

line(25, 90, 80, 60);


line(50, 12, 42, 90);
line(45, 30, 18, 36);

Primitivas: elipse

ellipse(40, 40, 60, 60); // crculo grande


ellipse(75, 75, 32, 32); // crculo pequeo

Primitivas: rectngulo

rect(15, 15, 40, 40); // cuadrado grande


rect(55, 55, 25, 25); // cuadrado pequeo

Orden de dibujo
En Processing, el orden de dibujo siempre es
secuencial, es decir, la primer instruccin se
representa primero, las siguientes por
encima, y la ltima por sobre todas estas.
rect(15, 15, 60, 60); // cuadrado inferior
rect(20, 20, 40, 40); // cuadrado intermedio
rect(25, 25, 20, 20); // cuadrado superior

Suavizado
smooth()
noSmooth()

Atributos: strokeWeight()
tamao de contorno
smooth();
strokeWeight(1); // por defecto
line(20, 20, 80, 20);
strokeWeight(4); // 4 pixeles
line(20, 40, 80, 40);
strokeWeight(10); // 10 pixeles
line(20, 70, 80, 70);

Atributos: strokeCap()
extremo de contorno
smooth();
strokeWeight(12.0);
strokeCap(ROUND); // redondeado
line(20, 30, 80, 30);
strokeCap(SQUARE); // plano
line(20, 50, 80, 50);
strokeCap(PROJECT); // proyeccin
line(20, 70, 80, 70);

Atributos: strokeJoin()
extremo de contorno
smooth();
strokeWeight(10);
strokeJoin(MITER); // mitra
triangle(50, 20, 80, 80, 20, 80);
smooth();
strokeWeight(10);
strokeJoin(BEVEL); // bisel
triangle(50, 20, 80, 80, 20, 80);
smooth();
strokeWeight(10);
strokeJoin(ROUND); // redondeada
triangle(50, 20, 80, 80, 20, 80);

Lectura recomendada
Captulo Shape 1: Coordinates, Primitives (pag. 23).

Informacin complementaria

Primitivas: tringulo

triangle(60, 10, 25, 60, 75, 65);

Primitivas: cuadriltero

quad(38, 31, 86, 20, 69, 63, 30, 76);

Primitivas: curva bezier

bezier(32, 20, 80, 5, 80, 75, 30, 75);


// Dibujo de puntos de control
line(32, 20, 80, 5);
ellipse(80, 5, 4, 4);
line(80, 75, 30, 75);
ellipse(80, 75, 4, 4);

Ejercicio 1

EJ01: Escribir un boceto con la finalidad de componer un cuadro, con una resolucin
de 300x300 pxeles, que contenga las siguientes figuras:
dos elipses, cuatro lneas y un rectngulo.
Comentar todas las instrucciones.
De aqu en ms adaptar el siguiente comentario (a modo de ttulo) e ingresarlo en el
lugar de la primera instruccin:
//
//
//
//
//
//
//
//
//

***********************************************
* Alumno: Nombre y apellido del alumno
*
* Legajo: xxxxx
*
* Ejercicio Nro: 01
*
* Asignatura: xxxx
*
* Carrera: xxxx
*
* Institucin: UNQ
*
* Ao: XXXX
Cuatrimestre: x *
***********************************************

Ejercicio 2

EJ02: Componer un cuadro con una resolucin de 300x300 que contenga


las siguientes figuras:
dos elipses, cuatro lneas y un rectngulo.

Generar las figuras con cambios de atributos.

Comentar todas las instrucciones.

Parte 3
Modos de color.
Fondo, contorno y relleno

colorMode() - Modo de color


En general trabajamos con RGB pero es ms recomendable
trabajar con HSB ya que se ajusta ms a un modelo de color
plstico. Para esto utilizamos la funcin colorMode().
Veremos que para utilizar la funcin colorMode() podremos
escoger cuatros versiones distintas de dicha funcin:

colorMode(modo)
colorMode(modo, rango)
int
colorMode(modo, rango1, rango2, rango3)
colorMode(modo, rango1, rango2, rango3 , alpha)

HSB o RGB
o float
int o float
int o float

Sintaxis de colorMode()
Sintaxis

colorMode(modo);
colorMode(mode, rango);
colorMode(modo, rango1, rango2, rango3);
colorMode(modo, rango1, rango2, rango3, alpha);

Parmetros
modo
range
rango1
rango2
rango3
alpha

RGB o HSB:
correspondientes a Red/Green/Blue y
Hue/Saturation/Brightness.
int o float: rango para todos los elementos de color
int o float: rango para el Rojo o Tono dependiendo del
modo de color actual.
int o float: rango para el Verde o Saturacin
dependiendo del modo de color actual.
int o float: rango para el Azul o Brillo dependiendo del
modo de color actual.
int o float: rango para Alpha (0 transparencia total,
mximo opacidad total).

Ejemplo de colorMode()
colorMode(HSB, 360, 100, 100);

Fondo, contorno y relleno


Fondo = background()
Valor por defecto = 204 (gris claro)

Contorno = stroke()
Valor por defecto = 0 (negro)
Sin contorno = noStroke()

Relleno = fill()
Valor por defecto = 255 (blanco)
Sin relleno = noFill()

Sintaxis de background()
background(gray)
background(gray, alpha)
background(value1, value2, value3)
background(value1, value2, value3, alpha)
background(color)
background(color, alpha)
background(hex)
background(hex, alpha)

Parmetros de las versiones


de background()
gray
alpha
value1
value2
value3
color
hex

int o float: valores entre blanco y negro.


int o float: valor de opacidad (0 = transparencia
255 = opacidad).
int o float: rojo o valor de matiz (depende del
modo de color).
int o float: verde o valor de saturacin (depende
del modo de color).
int o float: azul o valor de brillo (depende del
modo de color).
color: cualquier valor del tipo de dato color.
int: valor de color en notacin hexadecimal (ej.:
#FFCC00 0xFFFFCC00).

Ejemplos de background()
colorMode(HSB, 360, 100, 100);
background(51);

o bien:
colorMode(HSB, 360, 100, 100);
background(255, 204, 0);

Parmetros de versiones de
background(), stroke() y fill()
gray
alpha
value1
value2
value3
color
hex

int o float: valores entre blanco y negro.


int o float: valor de opacidad (0 = transparencia
255 = opacidad).
int o float: rojo o valor de matiz (depende del
modo de color).
int o float: verde o valor de saturacin (depende
del modo de color).
int o float: azul o valor de brillo (depende del
modo de color).
color: cualquier valor del tipo de dato color.
int: valor de color en notacin hexadecimal (ej.:
#FFCC00 or 0xFFFFCC00).

Sintaxis de stroke()
stroke(gray)
stroke(gray, alpha)
stroke(value1, value2, value3)
stroke(value1, value2, value3, alpha)
stroke(color)
stroke(color, alpha)
stroke(hex)
stroke(hex, alpha)

Ejemplos de stroke()
stroke(153);
rect(30, 20, 55, 55);

o bien:
stroke(204, 102, 0);
rect(30, 20, 55, 55);

Sintaxis de fill()
fill(gray)
fill(gray, alpha)
fill(value1, value2, value3)
fill(value1, value2, value3, alpha)
fill(color)
fill(color, alpha)
fill(hex)
fill(hex, alpha)

Ejemplos de fill()
fill(153);
rect(30, 20, 55, 55);

o bien:
fill(204, 102, 0);
rect(30, 20, 55, 55);

Lectura recomendada
Captulo Color 1: Color by Numbers (pag. 85).

Ejercicio 3

EJ03: Componer un cuadro con una resolucin de 300x300 que contenga


las siguientes figuras:
dos elipses, cuatro lneas y un rectngulo.

Las figuras podrn tener slo dos colores y el fondo de la composicin


(background) otro distinto.

Comentar todas las instrucciones.

Parte 4
Tipos de datos. Variables.

Datos
En general consisten de mediciones de
caractersticas fsicas.
Processing puede administrar distintos tipos de
datos:
nmeros,
letras,
colores,
imgenes,
tipografas
y valores booleanos.

Tipos de datos bsicos


Nombre

Tamao

Rango de valores

boolean

1 bit

true o false

byte

8 bits

-128 a 127

char

16 bits

0 a 65535

int

32 bits

-2,147,483,648 a
2,147,483,647

float

32 bits

-3.40282347E+38 a

Variables (I)
Podemos entender una variable como un contenedor que
nos permite almacenar un tipo de dato.
Las variables permiten la reutilizacin de datos en un
programa tantas veces como se necesite.
Las variables constan de tres partes:
tipo de dato,
=> float
nombre de la variable => altura
y valor
=> 1.72

Variables (II)
En Processing, cuando trabajamos con variables, primero
debemos declararla y luego asignar el valor que
corresponda:
int x;
float y;
boolean b;
x = 50;
y = 12.6;
b = true;

//
//
//
//
//
//

declaracin de
declaracin de
declaracin de
asignacin del
asignacin del
asignacin del

la variable x de tipo int


la variable y de tipo float
la variable b de tipo boolean
valor 50 a la variable x
valor 12.6 a la variable y
valor true a la variable b

Durante la asignacin utilizamos el signo =, el cual es


llamado operador de asignacin. El sentido de asignacin
se da siempre de derecha a izquierda de dicho signo.

Variables (III)
Los pasos de declaracin y asignacin pueden
ser resumidos en una sola lnea de cdigo:
int x = 50;
float y = 12.6;
boolean b = true;

// declaracin y asignacin
// declaracin y asignacin
// declaracin y asignacin

Instrucciones (III)
Otro ejemplo de boceto que contiene un
conjunto de instrucciones:
size(200, 200);
int x;
x = 102;
background(x);

//
//
//
//

Ejecuta la funcin size()


Declara una nueva variable x
Asigna el valor 102 a la variable x
Ejecuta la funcin background()

Lectura recomendada
Captulo Data 1: Variables (pag. 37).

Parte 5
Aritmtica

Operadores aritmticos
bsicos en Processing
+
*
/
%

Suma
Resta
Multiplicacin
Divisin
Mdulo

Orden de ejecucin de
operaciones aritmticas
??? 3 + 4 * 5
1) * / %
2) + 3) =

Expresiones
Podemos pensar en una expresin como si fuera una frase.
Las expresiones contienen frecuentemente o bien un solo valor, o
combinaciones de valores y operadores matemticos y/o
relacionales.
Una expresin siempre tiene un valor determinado por la evaluacin
de su contenido:

Expresin
5
122.3 + 3.1
((3 + 2) * -10) + 1
6>3
54 < 50

Valor
5
125.4
-49
true
false

Muchas veces un conjunto de expresiones conforma una


instruccin.

Uso de una variable como parmetro de


funcin
Ejemplo:
int a = 30;
line(a, 0, a, height);

Uso de una variable como componen-te de


una expresin de asignacin
Ejemplo:
int a = 30;
int b = a + 40;
line(b, 0, b, height);

Uso de variables como componentes de


una expresin perteneciente a un
parmetro de funcin
Ejemplo:
int a = 30;
int b = 40;
line(b - a, 0, b - a, height);

Lectura recomendada
Captulo Math 1: Arithmetic, Functions (pag. 43).

Informacin complementaria

Operador Mdulo %
El operador % calcula el resto de un cociente.
A menudo se lo utiliza para mantener los nmeros
dentro de un rango deseado.
Por ej.: si partimos de un contador ascendente
desde el nmero 0 y queremos obtener cuatro
valores que se reiteren (un ciclo de valores),
usamos la siguiente expresin:
x

10

11

12

x%4

Atajos aritmticos
Operador incremental ++
int x = 1;
println(x); // Imprime "1" en la consola
x++; // Equivale a x = x + 1
println(x); // Imprime "2" en la consola

Operador decremental -int y = 1;


println(y); // Imprime "1" en la consola
y--; // Equivale a y = y - 1
println(y); // Imprime 0" en la consola

x++

++x

x++
En este caso el valor es incrementado LUEGO de que se evala la
expresin.
int x = 1;
println(x++);
println(x);

// Imprime "1" en la consola


// Imprime 2" en la consola

++x
En este segundo caso se actualiza el valor ANTES de evaluar la
expresin.
int x = 1;
println(++x);
println(x);

// Imprime 2" en la consola


// Imprime 2" en la consola

Operadores de asignacin de
suma y substraccin
Se utilizan para realizar saltos de ms de un paso
(una unidad de valor).
Suma +=
int x = 1;
println(x);
x += 5;
println(x);

// Imprime "1" en la consola


// Equivalente a x = x + 5
// Imprime 6" en la consola

Resta -=
int y = 1;
println(y);
y -= 5;
println(y);

// Imprime "1" en la consola


// Equivalente a y = y - 5
// Imprime -4" en la consola

Operadores de asignacin de
multiplicacin y divisin
Se utilizan para realizar saltos de ms de un paso
(una unidad de valor).
Multiplicacin *=
int x = 4;
println(x);
x *= 2;
println(x);

// Imprime "4" en la consola


// Equivalente a x = x * 2
// Imprime "8" en la consola

Divisin /=
int y = 4;
println(y);
y /= 2;
println(y);

// Imprime "4" en la consola


// Equivalente a y = y / 2
// Imprime 2" en la consola

Operadores de negacin
Cambia el signo del valor.
Negacin
int x = 5; // Asigna 5 a x
x = -x; // Equivalente a x = x * -1
println(x); // Imprime "-5"

Ejercicio 4

EJ04: Tomar el EJ03, declarar tres variables y utilizarlas en tres contextos


distintos:
1) como parmetro de funcin.
2) como componente de una expresin de asignacin. Utilizar operadores
aritmticos de suma o resta.
3) como componente de una expresin perteneciente a un parmetro de funcin.
Utilizar operadores aritmticos de suma o resta.

Comentar todas las instrucciones.

Parte 6
Control: Decisiones

Expresiones relacionales
Las expresiones relacionales nos informan la condicin de
verdad de dicha expresin.
Una expresin relacional compara dos valores y evala si
el resultado es verdadero o falso.
Expresin Evaluacin
3>5
false
3<5
true
5<3
false
5>3
true

Operadores relacionales
Operador
>
<
>=
<=
==
!=

Significado
mayor a
menor a
mayor o equivalente a
menor o equivalente a
equivalente a
no equivalente a

Condicional: if

Ejemplo: if

boolean dibujoCirculo = true;


if (dibujoCirculo == true) {
ellipse(50, 50, 50, 50);
}
rect(30, 45, 40, 10);

Condicional: if/else

Ejemplo: if/else
boolean dibujoCirculo = true;
if (dibujoCirculo == true) {
ellipse(50, 50, 50, 50);
} else {
line(25, 25, 75, 75);
line(75, 25, 25, 75);
}
rect(30, 45, 40, 10);

Condicional: if/else if

Ejemplo: if/else if

boolean dibujoCirculo = false;


boolean dibujoElipse = false;
if (dibujoCirculo == true) {
ellipse(50, 50, 50, 50);
} else if (dibujoElipse == true){
ellipse(50, 50, 50, 25);}
rect(30, 45, 40, 10);

Condicional: switch()
Funciona como una estructura if, sin
embargo es ms conveniente utilizar
switch() cuando usted necesita
seleccionar entre tres o ms alternativas.

El control del programa se dirige al caso


(case) que contenga el mismo valor de
la expresin. Todas las dems
instrucciones del switch() sern
ejecutadas a menos que sean redirigidas
mediante un corte (break).

Slo los tipos de datos primitivos que


pueden ser convertidos a un entero
(byte, char e int) pueden ser usados
como parmetro de expresin.
El caso por defecto (default) es
opcional.

Sintaxis
switch(expresin)
{
case etiqueta1:
instrucciones
case etiqueta2:
instrucciones
default:
instrucciones
}

//
//
//
//

Opcional
Opcional
Opcional
Opcional

Parmetros
expresin
byte, char o int
etiqueta
byte, char o int
instrucciones
una o ms

Ejemplo 1/3: switch()


int num = 1;
switch(num) {
case 0:
println("Cero"); // No se ejecuta
break;
case 1:
println("Uno"); // Imprime "Uno"
break;
}
println("Listo!"); // Imprime "Listo!"

Ejemplo 2/3: switch()


char letra = 'N';
switch(letra) {
case 'A':
println("Alfa"); // No se ejecuta
break;
case 'B':
println("Bravo"); // No se ejecuta
break;
default:
// El caso por defecto se ejecuta si
println("Ninguna"); // ninguna etiqueta coincide con el
break;
// parmetro de switch().
}
println("Listo!"); // Imprime "Listo!"

Ejemplo 3/3: switch()


// La remocin de un "break" permite la
// evaluacin de ms de un valor a la vez
char letra = 'b';
switch(letra) {
case 'a':
case 'A':
println("Alfa"); // No se ejecuta
break;
case 'b':
case 'B':
println("Bravo"); // Imprime "Bravo"
break;
}
println("Listo!"); // Imprime "Listo!"

Operadores lgicos (I)


En la lgica proposicional se utilizan conectivas lgicas, tambin
llamadas operadores lgicos.
En programacin se los utilizan para combinar valores de verdad
y obtener nuevos valores que determinen el flujo de control de
un algoritmo o programa.
Los operadores lgicos presentes en Processing se usan para
combinar dos o ms expresiones relacionales y/o para invertir
los valores lgicos. Permiten considerar ms de una condicin
simultneamente.
Operador

&&
||
!

Significado

AND (Y conjuncin)
OR (o disyuncin (disyuncin inclusiva))
NOT (no - negacin)

Operadores lgicos (II)


Tabla de funciones de verdad:
Expresin

Evaluacin

true && true


true && false
false && true
false && false

true
false
false
false

true || true
true || false
false || true
false || false

true
true
true
false

!true
!false

false
true

Operador lgico AND


El operador AND hace que una expresin relacional sea verdadera si AMBAS
partes son verdaderas.
int a = 10;
int b = 20;
//
//
//
if

La expresin "a > 5" debe ser verdadera


y "b < 30 tambien debe serlo.
Debido a que ambas son verdaderas, se ejecutar el cdigo del bloque.
((a > 5) && (b < 30)) {
line(20, 50, 80, 50);

}
//
//
//
if
}

La expresin "a > 15" es falsa, pero "b < 30" es verdadera.
Debido a que el operador AND requiere que ambas sean
verdaderas, no se ejecutar el cdigo del bloque.
((a > 15) && (b < 30)) {
ellipse(50, 50, 36, 36);

Operador lgico OR
El operador OR hace que una expresin relacional sea verdadera si
SLO una parte es verdadera.
int a = 10;
int b = 20;
// Cualquiera de las dos expresiones pueden ser verdaderas.
// Debido a que ambas son verdaderas, se ejecutar el cdigo del bloque.
if ((a > 5) || (b < 30)) {
line(20, 50, 80, 50);
}
// La expresin "a > 15" es falsa, pero "b < 30" es verdadera.
// Debido a que el operador OR requiere slo que una parte sea verdadera
// en toda la expresin, se ejecutar el cdigo del bloque.
if ((a > 15) || (b < 30)) {
ellipse(50, 50, 36, 36);
}

Operador lgico NOT


El operador NOT se nota mediante un signo de exclamacin (!). Invierte
el valor lgico de las variables booleanas asociadas. Es decir cambia
los valores TRUE a FALSE y viceversa. El operador lgico NOT se
aplica slo a variables booleanas.
boolean b = true; // Asigna true a b
println(b);
// Imprime "true"
println(!b); // Imprime "false"
b = !b;
// Asigna false a b
println(b);
// Imprime "false"
println(!b); // Imprime "true"
println(5 > 3);
// Imprime "true"
println(!(5 > 3));
// Imprime "false"
int x = 5;
// Declara y asigna 5 a x
println(!x); // ERROR! Slo es posible trabajar con
// variables booleanas

Lectura recomendada
Captulo Control 1: Decisions (pag. 51).

Ejercicio 5

EJ05: Realizar un boceto donde se declare una variable que, en funcin del
valor dibuje:
TRUE: un crculo con relleno negro.
FALSE: un crculo con relleno blanco.

Comentar todas las instrucciones.

Ejercicio 6

EJ06: Realizar un boceto donde se dibuje una lnea horizontal a mitad de


pantalla, y que adems a partir del valor de la declaracin de una variable
dibuje:
TRUE: un crculo con relleno negro.
FALSE: un crculo con relleno blanco.

Comentar todas las instrucciones.

Ejercicio 7

EJ7: Realizar un boceto donde se declare una variable que en funcin del
valor dibuje:
un crculo sin relleno.
un crculo con relleno blanco.
un crculo con relleno negro.

Comentar todas las instrucciones.

Parte 7
Control: Iteraciones

Las estructuras iterativas para


simplificar instrucciones repetitivas.
Ejemplo cdigo original

Ej. cdigo optimizado

size(200, 200);
size(200, 200);
line(20, 20, 20, 180);
for (int i = 20; i < 150; i += 10) {
line(30, 20, 30, 180);
line(i, 20, i, 180);
line(40, 20, 40, 180);
}
line(50, 20, 50, 180);
line(60, 20, 60, 180);
line(70, 20, 70, 180);
line(80, 20, 80, 180);
line(90, 20, 90, 180);
line(100, 20, 100, 180);
line(110, 20, 110, 180);
line(120, 20, 120, 180);
line(130, 20, 130, 180);
line(140, 20, 140, 180);

Estructura y funcionamiento
general de for
for (init; test; update) {
statements
}

1. Se ejecuta la instruccin init.


2. Se evalua la condicin true o false de test.
3. Si test es true, contina al paso 4. Si el test es false salta al
paso 6.
4. Ejecuta las instrucciones del bloque.
5. Ejecuta la instruccin update y salta al paso 2.
6. Sale de la estructura de iteracin y contina ejecutando el
programa.

Iteracin: for

Ejemplo: for
for (int i = 10; i <= 90; i += 5) {
line(i, 10, i, 90);
}

Iteraciones anidadas
La estructura for produce repeticiones en una dimensin. Si anidamos esta estructura
DENTRO de otra, combinando su efecto, crearemos iteraciones en dos dimensiones.
Ej. 1

for (int y = 10; y < 100; y += 10) {


point(10, y);
}
Ej. 2

for (int x = 10; x < 100; x += 10) {


point(x, 10);
}
Ej. 1 y 2 anidados

for (int y = 10; y < 100; y += 10) {


for (int x = 10; x < 100; x += 10) {
point(x, y);
}
}

Por cada punto


dibujado en la
estructura externa, se
dibujan 9 puntos en la
estructura interna.

Iteracin: while
La estructura while ejecuta una serie de
instrucciones de manera continua
mientras que la expresin sea
verdadera.
La expresin debe ser actualizada
durante la iteracin, de lo contrario
nunca saldremos del while.
Esta funcin puede resultar peligrosa ya
que el cdigo dentro del bucle while() no
se detendr hasta que la expresin
dentro del mismo resulte falsa.
Bloquear cualquier otro cdigo a ser
utilizado (los eventos de ratn no sern
actualizados, etc.). Por lo tanto debemos
ser cautelosos ya que podemos llegar a
inmovilizar el cdigo (y hasta a veces el
entorno Processing mismo) si se usa de
manera incorrecta.

Sintaxis
while (expresin) {
instrucciones
}
Parmetros
expresin
una expresin vlida
instrucciones
una o ms

Ejemplo: while
int i=0;
while(i < 80) {
line(30, i, 80, i);
i = i + 5;
}

Lectura recomendada
Captulo Control 2: Repetition (pag. 61).

Informacin complementaria

Ejemplo 1/16: for


for (int x = -16; x < 100; x += 10) {
line(x, 0, x+15, 50);
}
strokeWeight(4);
for (int x = -8; x < 100; x += 10) {
line(x, 50, x+15, 100);
}

Ejemplo 2/16: for


noFill();
for (int d = 150; d > 0; d -= 10) {
ellipse(50, 50, d, d);
}

Ejemplo 3/16: for


/* Cambio de matiz, mientras la saturacin
y el brillo se mantienen constantes */
colorMode(HSB);
for (int i = 0; i < 100; i++) {
stroke(i*2.5, 255, 255);
line(i, 0, i, 100);
}

Ejemplo 4/16: for


/* Cambio de saturacin, mientras el matiz
y el brillo se mantienen constantes */
colorMode(HSB);
for (int i = 0; i < 100; i++) {
stroke(132, i*2.5, 204);
line(i, 0, i, 100);
}

Ejemplo 5/16: for


/* Cambio de brillo, mientras el matiz y la
saturacin se mantienen constantes */
colorMode(HSB);
for (int i = 0; i < 100; i++) {
stroke(132, 108, i*2.5);
line(i, 0, i, 100);
}

Ejemplo 6/16: for


/* Cambio de saturacin y brillo, mientras
el matiz se mantiene constante */
colorMode(HSB);
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 100; j++) {
stroke(132, j*2.5, i*2.5);
point(i, j);
}
}

Ejemplo 7/16: for


// Cambio del azul al verde en modo RGB
colorMode(RGB);
for (int i = 0; i < 100; i++) {
float r = 61 + (i*0.92);
float g = 156 + (i*0.48);
float b = 204 - (i*1.43);
stroke(r, g, b);
line(i, 0, i, 100);
}

Ejemplo 8/16: for


// Cambio del azul al verde en modo HSB
colorMode(HSB, 360, 100, 100);
for (int i = 0; i < 100; i++) {
float newHue = 200 - (i*1.2);
stroke(newHue, 70, 80);
line(i, 0, i, 100);
}

Ejemplos 9 a 12/16: for

Ejemplos 13 a 16/16: for

Ejemplos 1/8: iteraciones


anidadas
for (int y = 1; y <
for (int x = 1; x
line(x, y, x+6,
line(x+6, y, x,
}
}

100; y += 10) {
< y; x += 10) {
y+6);
y+6);

Ejemplos 2/8: iteraciones


anidadas
noStroke();
for (int y = 0; y < 100; y += 10) {
for (int x = 0; x < 100; x += 10) {
fill((x+y) * 1.4);
rect(x, y, 10, 10);
}
}

Ejemplos 3 a 4/8: iteraciones


anidadas

Ejemplos 5 a 6/8: iteraciones


anidadas

Ejemplos 7 a 8/8: iteraciones


anidadas

Ejercicio 8

EJ08: Utilizar dos estructuras for() para generar:


un fondo con cambio de matiz;
y por sobre este, una serie de ocho cuadrados negros concntricos (el menor
deber tener 10 px de lado y el mayor 80 px), separados por una distancia de 5
px en cada uno de sus lados.

Comentar todas las instrucciones.

Parte 8
Aleatoriedad

Valores inesperados
La funcin random() es utilizada para crear valores
impredecibles dentro de un rango especificado por sus
parmetros.
Los nmeros devueltos por la funcin random() son siempre de
punto flotante.
random(valorAlto)
random(valorBajo, valorAlto)
random(5);
random(5.0);
random(-5.0, 10.2);

// regresa valores entre 0.0 y 5.0


// regresa valores entre 0.0 y 5.0
// regresa valores entre -5.0 y 10.2

Ejemplos (I)
smooth();
strokeWeight(10);
stroke(0, 130);
line(0, random(100),
line(0, random(100),
line(0, random(100),
line(0, random(100),
line(0, random(100),

100,
100,
100,
100,
100,

random(100));
random(100));
random(100));
random(100));
random(100));

Ejemplos (II)
smooth();
strokeWeight(20);
float r = random(5, 45);
stroke(r * 5.6, 230);
line(0, r, 100, random(55, 95));
r = random(5, 45);
stroke(r * 5.6, 230);
line(0, r, 100, random(55, 95));
r = random(5, 45);
stroke(r * 5.6, 230);
line(0, r, 100, random(55, 95));

Ejemplos (III)
background(0);
stroke(255, 60);
for (int i = 0; i < 100; i++) {
float r = random(10);
strokeWeight(r);
float desplazamiento = r * 5.0;
line(i-20, 100, i+desplazamiento, 0);
}

randomSeed() - Semillas
Ya que el ordenador no puede inventar numeros al
azar, estos se obtienen con ms o menos
complejas ecuaciones. Por lo tanto son repetibles.
Para obtener cadenas de valores reiterados,
utilizamos una semilla mediante la funcin
randomSeed().
randomSeed(valor)
El valor debe ser siempre un int.

Ejemplo
int s = 6; // Valor de semilla, probar: s=6 o s=12
background(0);
stroke(255, 60);
randomSeed(s); // Produce los mismos nros cada vez
for (int i = 0; i < 100; i++) {

float r = random(10);
strokeWeight(r);
float desplazamiento = r * 5;
line(i-20, 100, i+ desplazamiento, 0);
}

noise() Ruido (I)


La funcin noise() es utilizada para crear valores
inesperados de una manera ms controlada. Utiliza
la tcnica de ruido Perlin, fue desarrollada por el
matemtico Ken Perlin en 1985.
Funciona interpolando valores aleatorios para crear
transiciones ms suaves que las obtenidas
mediante la funcin random(). Siempre devuelve
valores de punto flotante entre 0.0 y 1.0.

noise() Ruido (II)


noise(x)
noise(x, y)
noise(x, y, z)

La versin con un solo parmetro es utilizada para


crear una secuencia nica de nmeros aleatorios,
Los parmetros adicionales producen ruido en ms
dimensiones (2D: texturas, 3D: formas, texturas 3D
o texturas animadas en 2D).

noise() Ruido (III)


Los nmeros devueltos por noise() pueden resultar ms
cercanos o ms lejanos del anterior mediante cambios en el
parmetro de frecuencia de incremento.
Como regla general, mientras ms pequea sea la diferencia,
ms suave resultar la secuencia de ruido. Entonces resulta que
un incremento pequeo genera nmeros ms cercanos al valor
anterior que un incremento mayor.
Se estila nombrar la variable de incremento como inc.

noiseSeed() semilla de ruido


La funcin noise() suele ser utilizada en
conjunto con la funcin noiseSeed(), siendo
esta similar a randomSeed().
Generalmente se utilizan valores de
incremento que se sitan en el rango 0.005 a
0.03.

Ejemplo con un parmetro


size(600, 100);
float v = 0.0;
float inc = 0.1; // Probar 0.1 o 0.01
noStroke();
fill(0);
noiseSeed(0);
for (int i = 0; i < width; i = i+4) {
float n = noise(v) * 70.0;
rect(i, 10 + n, 3, 20);
v = v + inc;
}

Ejemplo con dos parmetros


float xnoise = 0.0;
float ynoise = 0.0;
float inc = 0.04;
//Probar 0.04, 0.02 o 0.1
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
float gray = noise(xnoise, ynoise) * 255;
stroke(gray);
point(x, y);
xnoise = xnoise + inc;
}
xnoise = 0;
ynoise = ynoise + inc;
}

Lectura recomendada
Captulo Math 4: Random (pag. 127).

Ejercicio 9

EJ09: Utilizar una estructura for() para generar:


diez crculos sin relleno, con posicin, dimetro y color aleatorios.

Usar funcin random().

Comentar todas las instrucciones.

Ejercicio 10

EJ10: Utilizar una estructura for() para generar:


diez rectngulos sin relleno, con posicin, dimetro y color aleatorios pero cuyos
valores resulten cercanos entre s.

Usar funcin noise().

Comentar todas las instrucciones.

Parte 9
Continuidad: de la imagen
esttica a la dinmica

Ejecucin continua
Todos los bocetos programados hasta el
momento son ejecutados por nica vez y
luego se detienen.
Programas animados o sensibles a
informacin en vivo deben ejecutarse
continuamente.

Funcin draw()
Los programas que se ejecutan continuamente
DEBEN incluir una funcin llamada draw().
El cdigo incluido en el bloque de la funcin draw()
se ejecuta en forma de BUCLE hasta que el usuario
presione el botn de detencin o cierre la ventana.
Un programa puede tener un nico draw().
Cada vez que el bloque draw() finaliza, dibuja un
nuevo cuadro (frame) y comienza nuevamente el
cdigo del bloque desde su primera lnea.

Bloque de funcin draw()


Por defecto, el ordenador intenta dibujar 60 cuadros
por segundo.
Si utilizamos la variable de sistema frameRate
podremos saber cuantos cuadros mximos por
segundo puede renderizar nuestro ordenador.
void draw() {
println(frameRate);
}

Funcin frameRate()
La funcin frameRate() determina el nmero mximo de cuadros
por segundo que renderizar el programa siempre y cuando no
exceda los valores posibles a realizar por el sistema.
Si utilizamos la variable de sistema frameCount podremos llevar
un registro de la cantidad de cuadros renderizados hasta el
momento:
void draw() {
frameRate(1);
println(frameCount);
}

Animacin (I)
Creamos animaciones cuando cambiamos
atributos visuales de un cuadro al otro:
float y = 0.0;
void draw() {
frameRate(30);
line(0, y, 100, y);
y = y + 0.5;

Animacin (II)
Debe ser observado que se define la variable
y por fuera del bloque draw(). Qu hubiera
pasado si la incluamos dentro?
void draw() {
frameRate(30);
float y = 0.0;
line(0, y, 100, y);
y = y + 0.5;

Animacin (III)
Para que tengamos una animacin la
variable y debe ser declarada fuera del
bloque, ya que de lo contrario esta se
redefinira y reasignara al MISMO valor cada
vez que se vuelve a iniciar el bucle.

Animacin (IV)
Como podemos observar, el fondo del lienzo va cambiando de color
de acuerdo a cada nueva lnea que aparece.
SI deseamos poder ver el avance de la lnea sobre el fondo,
debemos refrescar el fondo cada vez que reiniciemos el draw()
mediante la funcin background().
float y = 0.0;
void draw() {
frameRate(30);
background(204);
line(0, y, 100, y);
y = y + 0.5;
}

Animacin (V)
Incorporando una pequea expresin en los
parmetros de background(), la animacin va
ganando inters!
float y = 0.0;
void draw() {
frameRate(30);
background(y * 2.5);
line(0, y, 100, y);
y = y + 0.5;
}

Animacin (VI)
Y si incorporamos una pequea estructura de condicional
generamos ciclos visibles!
float y = 0.0;
void draw() {
frameRate(30);
background(204);
line(0, y, 100, y);
y = y + 0.5;
if (y > height) {
y = 0;
}
}

Animacin (VII)
O bien podemos volver a tomar la animacin IV y modificarla para obtener otro resultado visual:
int y = 0;
int direccion = 1;
void draw() {
frameRate(30);
background(204);
if (y > 100) {
direccion = -1;
}
if (y < 0) {
direccion = 1;
}
y = y + (1 * direccion);
line(0, y, 100, y);
}

Animacin (VIII)
Esta es otra manera de resolver la animacin anterior. No existen formas fijas de
resolver un problema, por suerte podemos abordar diferentes enfoques para la
resolucin del mismo:
int y = 0;
int direccion = 1;
void draw() {
frameRate(30);
background(204);
if (y > 100 || y < 0) {
direccion *= -1;
}
y = y + (1 * direccion);
line(0, y, 100, y);
}

Lectura recomendada
Captulo Structure 2: Continuous (pag. 173).

Ejercicio 11

EJ11: Utilizar la estructura draw() y dos variables para animar:


una elipse y tres lneas.

Comentar todas las instrucciones.

Parte 10
Anatoma de un programa
estructurado

Funcin setup()
Para optimizar la programacin, nos damos cuenta que ciertas funciones slo
deben ser ejecutadas una vez. Exponemos como ejemplo la funcin
frameRate() de los bocetos anteriores.
float y = 0.0;
void setup() {
frameRate(30);
}
void draw() {
background(y * 2.5);
y = y + 0.5;
line(0, y, 100, y);
if (y > 100) {
y = 0;
}
}

Bloque de Funcin setup()


Cuando en Processing se ejecuta un programa, el
cdigo que se encuentra fuera de los bloques
setup() y draw() es contemplado en primera
instancia.
Luego, se ejecuta por nica vez el cdigo dentro del
bloque setup().
Por ltimo, se ejecuta continuamente el contenido
del bloque draw().

Diagrama de estructura formal


standard de un programa
Seccin de
variables
globales

Seccin de
inicializacin

Seccin de
dibujo

Ejemplo
float y = 0.0;
void setup() {
size(100, 100);
smooth();
fill(0);

}
void draw() {
background(204);
ellipse(50, y, 70, 70);
y += 0.5;
if (y > 150) {
y = -50.0;

}
}

Observaciones (I)
Las variables que cambian en cada repeticin del
bloque draw() DEBEN ser declaradas fuera de los
bloques de setup() y draw().
Si su programa dibuja un solo cuadro, puede
escribirlo por completo dentro del bloque setup():
void setup() {
size(100, 100);
smooth();
fill(0);
ellipse(50, 50, 66, 66);
}

Observaciones (II)
Otra manera de realizar un solo cuadro, es utilizar la
funcin noLoop() dentro del bloque setup().
void setup() {
size(100, 100);
smooth();
fill(0);
noLoop();
}
void draw() {
ellipse(50, 50, 66, 66);
}

mbito de las variables


int d = 51;

// d variable global

void setup() {
size(100, 100);
int val = d * 2;
fill(val);
}

// val variable local en setup()

void draw() {
int y = 60;
line(0, y, d, y);
y -= 25;
line(0, y, d, y);
}

// y variable local en draw()

Lectura recomendada
Captulo Structure 2: Continuous (pag. 173).

Parte 11
Interactividad: ratn y teclado

Ratn: variables de sistema


El mouse no es ms que un indicador XY de
posicin de pantalla.
Las variables de sistema ms usadas:
mouseX
mouseY
pmouseX
pmouseY
mousePressed
mouseButton

Ejemplo de variables de
sistema mouseX y mouseY 1/6
void draw() {
frameRate(12);
println(mouseX + " : " + mouseY);
}

Ejemplo de variables de
sistema mouseX y mouseY 2/6
void setup() {
size(200, 200);
smooth();
noStroke();
}
void draw() {
background(126);
ellipseMode(CENTER);
ellipse(mouseX, mouseY, 33, 33);
}

Ejemplo de variables de
sistema mouseX y mouseY 3/6
void setup() {
size(200, 200);
smooth();
noStroke();
}
void draw() {
background(126);
ellipse(mouseX, 16, 33, 33);
ellipse(mouseX + 20, 50, 33, 33);
ellipse(mouseX - 20, 84, 33, 33);
}

Ejemplo de variables de
sistema mouseX y mouseY 4/6
void setup() {
size(200, 200);
smooth();
noStroke();
}
void draw() {
background(126);
ellipse(mouseX, 16, 33, 33);
ellipse(mouseX / 2, 50, 33, 33);
ellipse(mouseX * 2, 84, 33, 33);
}

Ejemplo de variables de
sistema mouseX y mouseY 5/6
void setup() {
size(200, 200);
smooth();
noStroke();
}
void draw() {
float x = mouseX;
float y = mouseY;
float ix = width - mouseX; // Inverso de X
float iy = mouseY - height; // Inverso de Y
background(126);
fill(255, 150);
ellipse(x, height/2, y, y);
fill(0, 159);
ellipse(ix, height/2, iy, iy);
}

Ejemplo de variables de
sistema mouseX y mouseY 6/6
void setup() {
size(200, 200);
smooth();
noStroke();
}
void draw() {
background(126);
float normX = mouseX / float(width);
ellipse(mouseX, 16, 33, 33);
ellipse(pow(normX, 4) * width, 50, 33, 33);
ellipse(pow(normX, 8) * width, 84, 33, 33);
}

Ejemplo de variables de sistema


pmouseX y pmouseY 1/2
void draw() {
frameRate(12);
println(pmouseX - mouseX);
}

Ejemplo de variables de sistema


pmouseX y pmouseY 2/2
void setup() {
size(100, 100);
strokeWeight(8);
smooth();
}
void draw() {
background(204);
line(mouseX, mouseY, pmouseX, pmouseY);
}

Ejemplo de if y variable de sistema


mousePressed y otros
void setup() {
size(640, 200);
background(102);
}
void draw() {
stroke(255);
if(mousePressed == true) {
line(mouseX, mouseY, pmouseX, pmouseY);
}
}

Ejemplo de estructura if y variable


de sistema mousePressed
// Pinta el relleno a negro
// cuando se presiona el botn del ratn.
void draw() {
if (mousePressed == true) {
fill(0);
}
else {
fill(255);
}
rect(25, 25, 50, 50);
}

Ejemplo de estructura if y variable


de sistema mouseButton 1/2
// Pinta el relleno a negro si presiono el botn izquierdo,
// a blanco si es el derecho y a gris si es el medio.
// mouseButton acepta las constantes: LEFT, RIGHT y CENTER.
void setup() {
size(100, 100);
}
void draw() {
if (mouseButton == LEFT) {
fill(0); // Negro
}
else if (mouseButton == RIGHT) {
fill(255); // Blanco
}
else {
fill(126); // Gris
}
rect(25, 25, 50, 50);
}

Ejemplo de estructura if y variable


de sistema mouseButton 2/2
// Versin alternativa del ejemplo anterior.
void setup() {
size(100, 100);
}
void draw() {
if (mousePressed == true) {
if (mouseButton == LEFT) {
fill(0); // Negro
}
else if (mouseButton == RIGHT) {
fill(255); // Blanco
}
}
else {
fill(126); // Gris
}
rect(25, 25, 50, 50);
}

Teclado: variables de sistema


Las variables de sistema ms usadas:
keyPressed
key
keyCode

Ejemplo de variable de sistema


keyPressed 1/2
// Dibuja un rectngulo mientras se
// mantiene presionada una tecla.
void setup() {
size(100, 100);
smooth();
strokeWeight(4);
}
void draw() {
background(204);
if (keyPressed == true) {
rect(40, 40, 20, 20);
}
else {
line(20, 20, 80, 80);
}
}

Ejemplo de variable de sistema


keyPressed 2/2
// Mueve una lnea si se
// mantiene presionada una tecla.
int x = 20;
void setup() {
size(100, 100);
smooth();
strokeWeight(4);
}
void draw() {
background(204);
if (keyPressed == true) {
x++;
}
line(x, 20, x-60, 80);
}

Ejemplo de variables de
sistema keyPressed y key
// Dibuja una lnea si se mantiene
// presionada la tecla 'a' o 'A'.
void setup() {
size(100, 100);
smooth();
strokeWeight(4);
}
void draw() {
background(204);
if ((keyPressed == true) && ((key == 'a') || (key == 'A'))) {
line(50, 25, 50, 75);
}
else {
ellipse(50, 50, 50, 50);
}
}

Ejemplo de variables de sistema


keyPressed, key y keyCode
//
//
//
//

Uso de variable de sistema keyCode.


keyCode acepta como constantes:
las teclas de direccin UP, DOWN, LEFT, RIGHT,
y ALT, CONTROL y SHIFT.

int y = 35;
void setup() {
size(100, 100);
}
void draw() {
background(204);
line(10, 50, 90, 50);
if (key == CODED) {
if (keyCode == UP) {
y = 20;
}
else if (keyCode == DOWN) {
y = 50;
}
}
else {
y = 35;
}
rect(25, y, 50, 30);
}

Ratn: Funciones de evento


Las funciones de evento ms usadas:
mousePressed()
El cdigo dentro de esta funcin se ejecuta una vez cuando se
presiona un botn de ratn.

mouseReleased()
El cdigo dentro de esta funcin se ejecuta una vez cuando se
libera un botn de ratn.

mouseMoved()
El cdigo dentro de esta funcin se ejecuta una vez cuando se
mueve un ratn.

mouseDragged()
El cdigo dentro de esta funcin se ejecuta una vez cuando se
mueve un ratn mientras se encuentra presionado un botn de
ratn.

Ejemplo de if...else y funcin


de evento mouseReleased
int valor = 0;
void draw() {
fill(valor);
rect(25, 25, 50, 50);
}
void mouseReleased() {
if(valor == 0) {
valor = 255;
} else {
valor = 0;
}
}

Teclado: Funciones de evento


Las funciones de evento ms usadas:
keyPressed()
El cdigo dentro de esta funcin se ejecuta una vez
cuando se presiona cualquier tecla.

keyReleased()
El cdigo dentro de esta funcin se ejecuta una vez
cuando se libera cualquier tecla.

Ejemplo de funcin de evento


keyPressed() y keyReleased()
boolean drawT = false;
void setup() {
size(100, 100);
noStroke();
}
void draw() {
background(204);
if (drawT == true) {
rect(20, 20, 60, 20);
rect(39, 40, 22, 45);
}
}
void keyPressed() {
if ((key == 'T') || (key == 't')) {
drawT = true;
}
}
void keyReleased() {
drawT = false;
}

Ejemplo de funcin de evento


mousePressed() y keyPressed()
void setup() {
size(200, 200);
background(255);
fill(0, 102);
}
void draw() {
}
void mousePressed() {
rectMode(CENTER);
rect(mouseX, mouseY, 32, 32);
}
void keyPressed() {
background(255);
}

Lectura recomendada
Captulo Input 1: Mouse I (pag. 205).
Captulo Drawing 1: Static Forms (pag. 217).
Captulo Input 2: Keyboard (pag. 223).
Captulo Input 3: Events (pag. 229).

Informacin complementaria

Ejemplo de variables de sistema mouseX y


mouseY y estructura if 1/4
// La posicin del cursor pinta la mitad izquierda
// o derecha de la ventana de visualizacin.
void setup() {
size(100, 100);
noStroke();
fill(0);
}
void draw() {
background(204);
if (mouseX < 50) {
rect(0, 0, 50, 100); // Izquierda
}
else {
rect(50, 0, 50, 100); // Derecha
}
}

Ejemplo de variables de sistema mouseX y


mouseY y estructura if 2/4
// La posicin del cursor pinta el tercio izquierdo
// central o derecho de la ventana de visualizacin.
void setup() {
size(100, 100);
noStroke();
fill(0);
}
void draw() {
background(204);
if (mouseX < 33) {
rect(0, 0, 33, 100); // Izquierda
}
else if ((mouseX >= 33) && (mouseX <= 66)) {
rect(33, 0, 33, 100); // Centro
}
else {
rect(66, 0, 33, 100); // Derecha
}
}

Ejemplo de variables de sistema mouseX y


mouseY y estructura if 3/4
// La posicin del cursor pinta un cuadrante
// de la ventana de visualizacin.
void setup() {
size(100, 100);
noStroke();
fill(0);
}
void draw() {
background(204);
if ((mouseX <= 50) && (mouseY <= 50)) {
rect(0, 0, 50, 50); // Superior-izquierdo
}
else if ((mouseX <= 50) && (mouseY > 50)) {
rect(0, 50, 50, 50); // Inferior-izquierdo
}
else if ((mouseX > 50) && (mouseY < 50)) {
rect(50, 0, 50, 50); // Superior-derecho
}
else {
rect(50, 50, 50, 50); // Inferior-derecho
}
}

Ejemplo de if...else if, variables de


sistema mouseX, mouseY y operadores
lgicos
void setup() {
size(200, 200);
}
void draw() {
background(255);
stroke(0);
line(100, 0, 100, 200);
line(0, 100, 200, 100);
// Relleno de color negro
noStroke();
fill(0);
if (mouseX < 100 && mouseY < 100)
rect(0, 0, 100, 100);
}
else if (mouseX > 100 && mouseY <
rect(100, 0, 100, 100);
}
else if (mouseX < 100 && mouseY >
rect(0, 100, 100, 100);
}
else if (mouseX > 100 && mouseY >
rect(100, 100, 100, 100);
}
}

100) {

100) {

100) {

Ejemplo de variables de sistema mouseX y


mouseY y estructura if 4/4
// La posicin del cursor cambia el color
// de relleno de un rea rectangular.
void setup() {
size(100, 100);
noStroke();
fill(0);
}
void draw() {
background(204);
if ((mouseX > 40) && (mouseX < 80) && (mouseY > 20) && (mouseY < 80)) {
fill(255);
}
else {
fill(0);
}
rect(40, 20, 40, 60);
}

Ejercicio 12

EJ12: Animar tres crculos de acuerdo a los datos ingresados mediante el


ratn.

Comentar todas las instrucciones.

Parte 12
Funciones de usuario

Introduccin 1/2
En Processing cualquier usuario puede programar sus propias funciones. Llamamos
a esto funcin de usuario.
Una funcin es un mdulo de programacin autocontenido.
Las funciones de usuario hacen ms conciso el cdigo redundante al extraer los
elementos comunes e incluirlos en bloques de cdigo para que puedan ejecutarse
tantas veces se quiera dentro del programa.
Esto permite una lectura ms fcil del cdigo y reduce las probabilidades de error al
actualizar el cdigo.
Las funciones generalmente tienen parmetros que definen sus acciones.
Las funciones pueden operar de forma diferente dependiendo del nmero de
parmetros usados.
Una funcin puede ser imaginada como una caja con mecanismos dentro que actan
sobre los datos ingresados y devuelven un resultado.

Introduccin 2/2
Convencionalmente posee una o varias entradas, un bloque de cdigo que procesa dichas
entradas, y finalmente una salida.

Algunos ejemplos de diagramas de funcin de usuario:

Abstraccin 1/2
En terminologa de software se llama abstraccin al proceso que permite esconder
los detalles de realizacin y concentrarnos en el resultado.
En realidad todas las funciones de sistema que hemos visto hasta el momento son,
tcnicamente, abstracciones: los autores han escondido los detalles de
implementacin para que el programador se concentre en los resultados.
Cuando construimos funciones estas podrn devolver un resultado o no. Depende
evidentemente de qu querramos hacer con ella. Pero en el caso de optar por la no
devolucin de un resultado deberemos comenzar por construir el bloque con la
palabra clave void.
Es por esto que todos los ejemplos que veremos a continuacin comienzan a
construirse con dicha palabra clave.

Introduccin a las funciones


1/12
//
//
//
//

Programacin basada en primitivas


usando funciones personalizadas o funciones definidas por el usuario
Autor: Ariel Malka | www.chronotext.org
URL: http://processing.org/discourse/yabb/YaBB.cgi?
board=TheoryandPractice;action=display;num=1078263461
// Traduccin: Ral Lacabanne - 2009
void setup() { // esta funcin ser llamada automticamente por Processing cuando el programa
se ejecute
size(200, 200); // configura el tamao de pantalla
}
void draw() { // esta funcin tambin ser llamada automticamente luego de setup()
rect(100, 30, 90, 160); // crea un rectngulo
}
//
//
//
//
//

El
1)
2)
3)
4)

"flujo de ejecucin" ser el siguiente:


setup()
size(200, 200)
draw()
rect(10, 10, 90, 160);

Introduccin a las funciones


2/12
//
//
//
//
//

Programacin basada en primitivas


usando funciones personalizadas o funciones definidas por el usuario
Autor: Ariel Malka | www.chronotext.org
URL: http://processing.org/discourse/yabb/YaBB.cgi?board=TheoryandPractice;action=display;num=1078263461
Traduccin: Ral Lacabanne - 2009

void setup() {
size(200, 200);
background(255);
}

// establece el color de fondo en blanco

void draw() {
// cuatro llamadas a la funcin definida por el usuario cross()
// el "origen del sistema de coordenadas" por defecto se encuentra en la esquina superior izquierda de la pantalla
cruz();
// esquina superior izquierda de la cruz en 0,0
translate(50, 50); // el "origen del sistema de coordenadas" se mueve 50 px a la derecha y 50 px abajo
cruz();
// esquina superior izquierda de la cruz en 50,50
translate(50, 50); // el "origen del sistema de coordenadas" se mueve otros 50 px a la derecha y 50 px abajo
cruz();
// esquina superior izquierda de la cruz en 100,100
translate(50, 50); // el "origen del sistema de coordenadas" se mueve otros 50 px a la derecha y 50 px abajo
cruz();
// esquina superior izquierda de la cruz en 150,150
}
void cruz() { // nuestra funcin definida por el usuario (podemos nombrarla como querramos)
noStroke();
fill(255, 0, 0); // rojo
rect(0, 10, 30, 10);
rect(10, 0, 10, 30);
}

Introduccin a las funciones


3/12
//
//
//
//
//

Programacin basada en primitivas


usando funciones personalizadas o funciones definidas por el usuario
Autor: Ariel Malka | www.chronotext.org
URL: http://processing.org/discourse/yabb/YaBB.cgi?board=TheoryandPractice;action=display;num=1078263461
Traduccin: Ral Lacabanne - 2009

// cuando dibujamos usando funciones es importante poder tener la posibilidad de dibujar una forma desde el centro...
void setup() {
size(200, 200);
background(255);
}
void draw() {
cruz();

// esquina superior izquierda de la cruz en 0,0

translate(50, 50); // el "origen del sistema de coordenadas" se mueve 50 px a la derecha y 50 px abajo


cruz();
// esquina superior izquierda de la cruz en 50,50
translate(50, 50); // el "origen del sistema de coordenadas" se mueve otros 50 px a la derecha y 50 px abajo
cruz();
// esquina superior izquierda de la cruz en 100,100
translate(50, 50); // el "origen del sistema de coordenadas" se mueve otros 50 px a la derecha y 50 px abajo
cruz();
// esquina superior izquierda de la cruz en 150,150
}
void cruz() {
noStroke();
fill(255, 0, 0);
rectMode(CENTER); // los rectngulos sern dibujados desde el centro
rect(0, 0, 30, 10);
rect(0, 0, 10, 30);
}

Introduccin a las funciones


4/12
//
//
//
//
//

Programacin basada en primitivas


usando funciones personalizadas o funciones definidas por el usuario
Autor: Ariel Malka | www.chronotext.org
URL: http://processing.org/discourse/yabb/YaBB.cgi?board=TheoryandPractice;action=display;num=1078263461
Traduccin: Ral Lacabanne - 2009

// cuando creamos funciones personalizadas es posible agregar un nmero arbitrario de "parmetros"


// que actuarn como variables dentro del bloque de la funcin
void setup() {
size(200, 200);
background(255);
}
void draw() {
// cuando llamamos a nuestra funcin, estamos "pasando" 2 parmetros que
// afectarn la posicin de la cruz
cruz(0, 0);
cruz(50, 50);
cruz(100, 100);
cruz(150, 150);

//
//
//
//

el
el
el
el

centro
centro
centro
centro

de
de
de
de

la
la
la
la

cruz
cruz
cruz
cruz

se
se
se
se

encuentra
encuentra
encuentra
encuentra

en
en
en
en

0,0
50,50
100,100
150,150

}
void cruz(float ejeX, float ejeY) { // estamos usando dos parmetros (los nombramos como querramos)
noStroke();
fill(255, 0, 0);
rectMode(CENTER);
// ejeX y ejeY estn actuando como variables y han sido declaradas por fuera del bloque de la funcin
rect(ejeX, ejeY, 30, 10);
rect(ejeX, ejeY, 10, 30);
}

Introduccin a las funciones


5/12
//
//
//
//
//

Programacin basada en primitivas


usando funciones personalizadas o funciones definidas por el usuario
Autor: Ariel Malka | www.chronotext.org
URL: http://processing.org/discourse/yabb/YaBB.cgi?board=TheoryandPractice;action=display;num=1078263461
Traduccin: Ral Lacabanne - 2009

// introduccin de parmetros adicionales


void setup() {
size(200, 200);
background(255);
}
void draw() {
// definicin de variables que contienen informacin de color
color rojo = color(255, 0, 0);
color azul = color(51, 153, 255);
color gris = color(128, 128, 128);
color verde = color(153, 255, 51);
// estamos pasando un tercer parmetro que afectar el tamao de la cruz
// y un cuarto parmetro que permitir en control de color de la cruz
cruz(0, 0, 1, rojo);
cruz(50, 50, 3, azul);
cruz(100, 100, 0.5, gris);
cruz(150, 150, 5.5, verde);
}
void cruz(float x, float y, float tamanio, color colorCruz) { // 2 nuevos parmetros han sido agregados a la funcin
noStroke();
fill(colorCruz); // esto controla el color de la cruz
rectMode(CENTER);
rect(x, y, 30 * tamanio, 10 * tamanio);
rect(x, y, 10 * tamanio, 30 * tamanio);
}

Introduccin a las funciones


6/12
//
//
//
//
//

Programacin basada en primitivas


usando funciones personalizadas o funciones definidas por el usuario
Autor: Ariel Malka | www.chronotext.org
URL: http://processing.org/discourse/yabb/YaBB.cgi?board=TheoryandPractice;action=display;num=1078263461
Traduccin: Ral Lacabanne - 2009

// cuando se programa es posible alcanzar los mismos resultados utilizando diferentes acercamientos!
void setup() {
size(200, 200);
background(255);
}
void draw() {
fill(255, 0, 0);
cruz(0, 0, 1);
fill(51, 153, 255);
cruz(50, 50, 3);

// rojo
// azul

fill(128, 128, 128); // gris


cruz(100, 100, 0.5);
fill(153, 255, 51); // verde
cruz(150, 150, 5.5);
}
void cruz(float x, float y, float tamanio) {
noStroke();
rectMode(CENTER);
rect(x, y, 30 * tamanio, 10 * tamanio);
rect(x, y, 10 * tamanio, 30 * tamanio);
}

Introduccin a las funciones


7/12
//
//
//
//
//

Programacin basada en primitivas


usando funciones personalizadas o funciones definidas por el usuario
Autor: Ariel Malka | www.chronotext.org
URL: http://processing.org/discourse/yabb/YaBB.cgi?board=TheoryandPractice;action=display;num=1078263461
Traduccin: Ral Lacabanne - 2009

// usar funciones que usan otras funciones...


// primero hagamos dos figuras diferentes y examinmoslas por separado
void setup() {
size(200, 200);
background(255);
fill(0, 0, 0); // todas las figuras con relleno negro
}
void draw() {
bubbles(50, 100);
tube(150, 100);
}
void tube(float x, float y) {
noStroke();
rectMode(CENTER);
ellipseMode(RADIUS);
rect(x, y, 40, 100);
rect(x, y - 50, 60, 10);
ellipse(x, y + 50, 20, 20);
}
void bubbles(float x, float y) {
noStroke();
ellipseMode(RADIUS);
ellipse(x + 4, y - 24, 10, 10);
ellipse(x - 4, y, 9, 9);
ellipse(x + 4, y + 24, 8, 8);
ellipse(x - 4, y + 48, 7, 7);
}

Introduccin a las funciones


8/12
// Programacin basada en primitivas
// usando funciones personalizadas o funciones definidas
por el usuario
// Autor: Ariel Malka | www.chronotext.org
// URL: http://processing.org/discourse/yabb/YaBB.cgi?
board=TheoryandPractice;action=display;num=10782634
61
// Traduccin: Ral Lacabanne - 2009
// usar funciones que usan otras funciones...
// ahora hagamos una funcin que usa juntas y de manera
compuesta nuestras dos funciones anteriores
void setup() {
size(200, 200);
background(255);
}

void tubo(float x, float y) {


noStroke();
rectMode(DIAMETER);
ellipseMode(RADIUS);

void draw() {
peligro(50, 100);
peligro(75, 80);
peligro(100, 100);
peligro(125, 120);
peligro(150, 100);
}

rect(x, y, 40, 100);


rect(x, y - 50, 60, 10);
ellipse(x, y + 50, 20, 20);
}

void peligro(float x, float y) {


fill(0, 0, 0); // negro
tubo(x, y);
fill(255, 255, 255);
burbujas(x, y);
}

void burbujas(float x, float y) {


noStroke();
ellipseMode(RADIUS);
ellipse(x
ellipse(x
ellipse(x
ellipse(x

// blanco
}

+
+
-

4,
4,
4,
4,

y - 24, 10, 10);


y, 9, 9);
y + 24, 8, 8);
y + 48, 7, 7);

Introduccin a las funciones


9/12
// Programacin basada en primitivas
// usando funciones personalizadas o funciones definidas
por el usuario
// Autor: Ariel Malka | www.chronotext.org
// URL: http://processing.org/discourse/yabb/YaBB.cgi?
board=TheoryandPractice;action=display;num=10782634
61
// Traduccin: Ral Lacabanne - 2009
// usar funciones que usan otras funciones...
// generar una funcin que utiliza nuestras 2 piezas
compuestas juntas
// ms la introduccin de escalado (usando un parmetro
adicional)
void setup() {
size(200, 200);
background(255);
}
void draw() {
peligro(50, 100, 13);
peligro(150, 100, 5);
}

void tubo(float x, float y, float tamanio) {


noStroke();
rectMode(DIAMETER);
ellipseMode(RADIUS);
rect(x, y, 4 * tamanio, 10 * tamanio);
rect(x, y - 5 * tamanio, 6 * tamanio, 1 * tamanio);
ellipse(x, y + 5 * tamanio, 2 * tamanio, 2 * tamanio);
}

// ms grande
// ms pequeo

void burbujas(float x, float y, float tamanio) {


noStroke();
ellipseMode(RADIUS);
ellipse(x + 0.4
tamanio, 1 *
ellipse(x - 0.4
tamanio);
ellipse(x + 0.4
tamanio, 0.8
ellipse(x - 0.4
tamanio, 0.7

void peligro(float x, float y, float tamanio) {


fill(0, 0, 0); // negro
tubo(x, y, tamanio);
fill(255, 255, 255); // blanco
burbujas(x, y, tamanio);
}

* tamanio, y - 2.4 * tamanio, 1 *


tamanio);
* tamanio, y, 0.9 * tamanio, 0.9 *
*
*
*
*

tamanio, y + 2.4 * tamanio, 0.8 *


tamanio);
tamanio, y + 4.8 * tamanio, 0.7 *
tamanio);

Introduccin a las funciones


10/12
//
//
//
//

Programacin basada en primitivas


usando funciones personalizadas
Autor: Ariel Malka | www.chronotext.org
URL: http://processing.org/discourse/yabb/YaBB.cgi?
board=TheoryandPractice;action=display;num=10782634
61
// Traduccin: Ral Lacabanne - 2009
// usar funciones que usan otras funciones...
// generar una funcin que utiliza nuestras 2 piezas
compuestas juntas
// ms la introduccin de escalado basado en una matriz
de transformacin
void tubo() {
noStroke();
rectMode(DIAMETER);
ellipseMode(RADIUS);

void setup() {
size(200, 200);
background(255);
}
void draw() {
peligro(50, 100, 1.3);
peligro(150, 100, 0.5);
}
void peligro(float x, float y, float sz) {
fill(0, 0, 0); // negro
pushMatrix();
translate(x, y);
scale(sz);
tubo();
popMatrix();
fill(255, 255, 255);
pushMatrix();
translate(x, y);
scale(sz);
burbujas();
popMatrix();
}

// blanco

rect(0, 0, 40, 100);


rect(0, - 50, 60, 10);
ellipse(0, 50, 20, 20);
}
void burbujas() {
noStroke();
ellipseMode(RADIUS);
ellipse(4, - 24, 10, 10);
ellipse(-4, 0, 9, 9);
ellipse(4, 24, 8, 8);
ellipse(-4, 48, 7, 7);
}

Introduccin a las funciones


11/12
// Programacin basada en primitivas
// usando funciones personalizadas o funciones definidas
por el usuario
// Autor: Ariel Malka | www.chronotext.org
// URL: http://processing.org/discourse/yabb/YaBB.cgi?
board=TheoryandPractice;action=display;num=10782634
61
// Traduccin: Ral Lacabanne - 2009
// usar funciones que usan otras funciones...
// generar una funcin que utiliza nuestras 2 piezas
compuestas juntas
// ms la introduccin de escalado basado en una matriz
de transformacin
void setup() {
size(200, 200);
background(255);
}
void draw() {
peligro(50, 100, 1.3);
peligro(150, 100, 0.5);
}
void peligro(float x, float y, float tamanio) {
fill(255, 0, 0); // rojo
pushMatrix();
translate(x, y);
scale(tamanio);
tubo();
fill(255, 255, 255);
// blanco
burbujas();
popMatrix();
}

void tubo() {
noStroke();
rectMode(DIAMETER);
ellipseMode(RADIUS);
rect(0, 0, 40, 100);
rect(0, - 50, 60, 10);
ellipse(0, 50, 20, 20);
}
void burbujas() {
noStroke();
ellipseMode(RADIUS);
ellipse(4, - 24, 10, 10);
ellipse(-4, 0, 9, 9);
ellipse(4, 24, 8, 8);
ellipse(-4, 48, 7, 7);
}

Introduccin a las funciones


12/12
void setup()
{
size(640, 360);
background(102);
smooth();
}
void draw()
{
elipseVariable(mouseX, mouseY, pmouseX, pmouseY);
}
// elipseVariable() calcula la velocidad del ratn.
// Si el ratn se mueve lentamente: dibuja una elipse pequea,
// si el ratn se mueve rpidamente: dibuja una elipse mayor si
void elipseVariable(int x, int y, int px, int py)
{
float speed = abs(x-px) + abs(y-py);
stroke(speed);
ellipse(x, y, speed, speed);
}

Valor de retorno 1/2


En todos los ejemplos vistos hasta ahora, hemos visto que la salida, por ejemplo,
de una funcion de primitivas ha sido en forma de dibujo en el rea de
representacin.
Sin embargo a veces preferiremos que la salida sea un nmero u otro tipo de
dato. La salida de una funcin se llama valor de retorno.
Se espera que todas las funciones regresen un valor, tal como un entero o un
decimal. Si la funcin no regresa un valor, se utiliza la palabra especial void. El
tipo de dato regresado por una funcin se encuentra a la izquierda del nombre de
funcin.
El comando clave return es usado para salir de una funcin y regresar al lugar
desde el cual fue llamado. Cuando una funcin regresa un valor, return es
usado para especificar qu valor debe ser regresado.
La instruccin que incluye return es tpicamente la ltima de una funcin, ya
que la misma finaliza inmediatamente despus de un retorno.
Ya hemos usado funciones que devuelven valores: por ej.: random() regresa un
decimal, color() regresa un tipo de dato de color, etc.
Si una funcin regresa un valor, dicha funcin casi siempre aparece a la derecha
de un operador de asignacin o como parte de una expresin mayor.
Una funcin que no regresa un valor es frecuentemente usada como una
instruccin completa.

Valor de retorno 2/2


Las funciones no estn limitadas a regresar nmeros: pueden regresar boolean,
String, PImage o cualquier otro tipo de dato.
Para escribir una funcin de usuario que regrese un valor, reemplace void con el
tipo de dato que necesite regresar, e incluya dentro de la funcin la palabra clave
return seguido de la variable que contenga el valor que desee regresar para
habilitar la salida del mismo.
A continuacin veremos un ejemplo:
void setup() {
size(100, 100);
float f = promedio(12.0, 6.0); // Asigna 9.0 a f
println(f);
}
float promedio(float num1, float num2) {
float av = (num1 + num2) / 2.0;
return av;
}

Sobrecarga de funciones
(Function overloading) 1/2
Se llama sobrecarga de funciones al procedimiento de crear diferentes versiones
de una misma funcin.
Las distintas versiones pueden compartir el mismo nombre de funcin siempre y
cuando tengan diferentes nmeros de parmetros o tipos de datos de los
mismos. Es decir, un programa puede tener dos funciones con el mismo nmero
de parmetros, pero slo si el tipo de dato de uno de sus parmetros es
diferente.
Processing identifica qu versin de funcin debe ejecutar al comparar el nmero
y el tipo de dato de sus parmetros.
Veamos el prximo ejemplo:

Sobrecarga de funciones
(Function overloading) 2/2
void setup() {
size(100, 100);
smooth();
}
void draw() {
dibujoX(255); // Ejecuta primer dibujoX()
dibujoX(5.5); // Ejecuta segundo dibujoX()
dibujoX(0, 2, 44, 48, 36); // Ejecuta tercer dibujoX()
}
// dibujoX con el valor de gris determinado por el parmetro
void dibujoX(int gris) {
stroke(gris);
strokeWeight(20);
line(0, 5, 60, 65);
line(60, 5, 0, 65);
}
// dibujoX negro con el valor ancho de contorno determinado por el parmetro
void dibujoX(float ancho) {
stroke(0);
strokeWeight(ancho);
line(0, 5, 60, 65);
line(60, 5, 0, 65);
}
// dibujoX con la posicin , el valor de gris, tamao y el ancho de
// contorno determinados por sus correspondientes parmetros
void dibujoX(int gris, int ancho, int x, int y, int s) {
stroke(gris);
strokeWeight(ancho);
line(x, y, x+s, y+s);
line(x+s, y, x, y+s);
}

Lectura recomendada
Captulo Structure 3: Functions (pag. 181).

Ejercicio 13

EJ13: Crear una forma animada autnoma que comunique la idea de


"orden".

Utilizar funciones de usuario.

Comentar todas las instrucciones.

Ejercicio 14

EJ14: Crear una forma animada autnoma 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
matemticas

Funcin sq() Cuadrado


Para calcular el cuadrado de un nmero usamos la funcin sq(). La
misma nos regresa el resultado, el cual ser siempre un nmero
positivo aunque usemos un valor negativo.
sq(valor)

float x = sq(1);
float y = sq(-5);
float z = sq(9);

// Asigna 1.0 a x: equivalente a 1 * 1


// Asigna 25.0 a y: equivalente a -5 * -5
// Asigna 81.0 a z: equivalente a 9 * 9

Funcin sqrt() Raz cuadrada


La funcin sqrt() es usada para calcular la raz cuadrada de un
nmero. La misma regresa el resultado.
sqrt(valor)

Recordemos que tambin lo podemos expresar de la siguiente


manera: (a) == (a1/2 )
float r = sqrt(6561);
float s = sqrt(625);
float t = sqrt(1);

// Asigna 81.0 a r
// Asigna 25.0 a s
// Asigna 1.0 a t

Funcin pow() Potenciacin


La funcin pow() calcula la potencia en funcin de dos trminos:
base y exponente. La misma regresa el resultado.
pow(base, exponente)

Recordemos que, cuando el exponente es una fraccin irreducible,


tambin lo podemos expresar de la siguiente manera:
(man) == (an/m )
float
float
float
float

d
e
f
g

=
=
=
=

pow(1, 3);
pow(3, 4);
pow(3, -2);
pow(-3, 3);

//
//
//
//

Asigna
1.0
Asigna 81.0
Asigna
0.11
Asigna -27.0

a
a
a
a

d:
e:
f:
g:

equivalente
equivalente
equivalente
equivalente

a
a
a
a

1*1*1
3*3*3*3
1 / (3*3)
-3*-3*-3

Funcin norm() Normalizacin


1/2
Muchas veces se vuelve conveniente convertir un rango de nmeros dados al rango
0.0 a 1.0. A este procedimiento se lo llama normalizacin.
Cuando multiplicamos nmeros 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 normalizacin deben ser realizadas con el
tipo de dato float.
Para normalizar un nmero debemos dividirlo por el valor mximo 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
0.0

Clculo
0.0 / 255.0

Valor normalizado
0.0

102.0

102.0 / 255.0

0.4

255.0

255.0 / 255.0

1.0

Funcin norm() Normalizacin


2/2
Para simplificar esta tarea podemos utilizar la funcin norm():
norm(valor_a_convertir, valor_mnimo, valor_mximo)

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);
float y = norm(102.0, 0.0, 255.0);
float z = norm(255.0, 0.0, 255.0);

// Asigna 0.0 a x
// Asigna 0.4 a y
// Asigna 1.0 a z

Funcin lerp() Interpolacin


lineal 1/2
Luego de la normalizacin, podemos convertir el nmero a otro rango mediante
operaciones aritmticas.
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 nmeros 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 continuacin algunos ejemplos de conversin:
Rango inicial de x Rango de destino de x Conversin
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

Funcin lerp() Interpolacin


lineal 2/2
Nuevamente, para simplificar esta tarea podemos utilizar la funcin
lerp(). La misma presenta tres parmetros
lerp(valor_mnimo_del_rango_a_interpolar,
valor_mximo_del_rango_a_interpolar, valor_a_interpolar)

El tercer parmetro (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);
float s = lerp(-20.0, 60.0, 0.5);
float t = lerp(-20.0, 60.0, 1.0);

// Asigna -20.0 a r
// Asigna 20.0 a s
// Asigna 60.0 a t

Funcin map() Mapeo 1/2


Existe otra funcin que nos permite aplicar las operaciones de normalizacin e
interpolacin lineal en una: hablamos de la funcin map().
Con dicha funcin podemos convertir directamente un valor correspondiente a un
rango de nmeros a otro correspondiente a otro rango de nmeros.
Posee cinco parmetros:
map(valor, mnimo1, mximo1, mnimo2, mximo2)

Donde valor corresponde al nmero de origen a mapear, mnimo1 y mximo1 a los


nmeros del rango origen, y mnimo2 y mximo2 a los nmeros del rango de destino.

Funcin map() Mapeo 2/2


El prximo 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

Funcin constrain() Limitacin


de rangos 1/2
La funcin constrain() permite limitar un nmero a un rango determinado. Trabaja con
enteros o decimales.
Posee tres parmetros:
constrain(valor, mnimo, mximo)

Donde valor corresponde al nmero a limitar, mnimo al valor mnimo posible y


mximo al valor mximo posible. Esta funcin regresa el nmero mnimo si el
parmetro valor es menor o equivalente al antedicho, regresa el nmero mximo 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

Funcin constrain() Limitacin


de rangos 2/2
// Limitar la posicin de una elipse a una regin 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);
}

Funcin dist() Distancia entre


coordenadas 1/3
La funcin dist() calcula la distancia entre dos coordenadas. Trabaja con enteros o
decimales, pero regresa decimales.
Posee cuatro parmetros:
dist(x1, y1, x2, y2)

El primer par de parmetros 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

Funcin dist() Distancia entre


coordenadas 2/3
// La distancia entre el centro de la ventana de representacin
// y el puntero determina el dametro del crculo
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);
}

Funcin dist() Distancia entre


coordenadas 3/3
// Dibujo de una grilla de crculos y clculo de la
// distancia de cada uno de ellos para determinar el tamao
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);
}
}
}

Tcnica Easing Aligeramiento


1/7
La tcnica de animacin llamada Easing, es en realidad una tcnica de interpolacin
entre dos puntos. Al mover en cada cuadro una fraccin de la distancia total de una
figura, el movimiento de esta parece desacelerarse (o acelerarse) al acercarse a la
ubicacin de destino.
El siguiente diagrama muestra qu ocurre cuando un punto siempre se mueve la
mitad del recorrido entre su posicin actual y la posicin de destino:

A medida que la figura se acerca a la posicin de destino, la distancia recorrida


disminuye en cada fotograma, por lo tanto el movimiento de la misma parece
ralentizarse.

Tcnica Easing Aligeramiento


2/7
En el siguiente ejemplo la variable x corresponde a la posicin horizontal actual del
crculo y la varible destinoX corresponde a la posicin de destino.
La variable easing dispone la fraccin de la distancia entre la posicin actual del
crculo y la posicin del ratn que el crculo se mueve en cada cuadro. El valor de
esta variable cambia la rapidez con que el crculo llega al destino.
El valor de easing debe estar siempre entre 0.0 y 1.0, y los nmeros cercanos a 0.0
causan que el movimiento se ralentice ms.
Un valor de easing de 0.5 har que el crculo se mueva la mitad de la distancia en
cada cuadro, mientras que un valor de 0.01 har que el crculo se mueva una
centsima de la distancia en cada cuadro.
El crculo superior es dibujado de acuerdo a la posicin destinoX, mientras que el
crculo inferior es dibujado de acuerdo a la posicin interpolada.
Ahora s veamos el ejemplo:

Tcnica Easing Aligeramiento


3/7
float x = 0.0;
// Distancia actual en x
float easing = 0.05; // Nmeros 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);
}

Tcnica Easing Aligeramiento


4/7
En el siguiente ejemplo utilizamos dos variables para controlar la tcnica easing en
las dos dimensiones. Observe que estructuralmente es igual al anterior. El ejemplo
se encuentra en la siguiente pgina:

Tcnica Easing Aligeramiento


5/7
float x = 0;
// Distancia actual en x
float y = 0;
// Distancia actual en y
float easing = 0.05; // Nmeros 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); //Crculo blanco grande interpolado
fill(153);
ellipse(mouseX, mouseY, 20, 20); //Crculo gris pequeo destino
}

Tcnica Easing Aligeramiento


6/7
Los dos ejemplo previos continan realizando el clculo para la posicin del crculo
incluso luego de haber alcanzado su destino. Desde el punto de vista informtico
resulta ineficiente, y si hubieran cientos de crculos todos aligerando las posiciones,
esto ralentizara el programa en general.
Para detener los clculos cuando estos no son necesarios, evale que la posicin de
destino y la posicin actual sean equivalentes y detenga el clculo si esta condicin
resulta verdadera.
El siguiente ejemplo presenta el uso de la funcin abs() la cual devuelve el valor
absoluto de un nmero.
Esta es necesaria ya que los valores resultantes de la tcnica Easing pueden ser
tanto negativos como positivos dependiendo de si la posicin se encuentra a la
izquierda o a la derecha del destino.

Tcnica Easing Aligeramiento


7/7
float x = 0.0;
// Distancia actual en x
float easing = 0.05; // Nmeros 0.0 a 1.0
void setup() {
size(100, 100);
smooth();
}
void draw() {
background(0);
float destinoX = mouseX;
// Distancia desde l posicin hasta el destino
float dx = destinoX - x;
// Si la distancia entre la posicin actual y el destino
// es mayor a 1.0, actualizo la posicin
if (abs(dx) > 1.0) {
x += dx * easing;
println(dx);
}
ellipse(mouseX, 30, 40, 40);
ellipse(x, 70, 40, 40);
}

Clculo de velocidad 1/3


A continuacin calcularemos la velocidad del ratn mediante la comparacin de la posicin
actual con la posicin anterior.
Esto lo haremos usando la funcin dist() con los valores de parmetros de las variables
mouseX, mouseY, pmouseX y pmouseY.
Entonces, el siguiente ejemplo calcula la velocidad del ratn y convierte este valor en el dimetro
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);
}

Clculo de velocidad 2/3


El ejemplo previo muestra la velocidad instantnea del ratn. Los nmeros
producidos son extremos saltan constantemente entre cero y otros valores ms
grandes de un cuadro al otro.
Se puede utilizar la tcnica Easing para incrementar o mermar la velocidad de forma
suavizada.
El siguiente ejemplo muestra cmo aplicar la tcnica Easing en dicho contexto. La
barra superior representa la velocidad instantnea mientras que la inferior representa
la velocidad aligerada:

Clculo de velocidad 3/3


float velocidad = 0.0;
float easing = 0.05; // Nmeros 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);
}

Orientacin 1/4
La funcin atan2() es usada para calcular el ngulo desde cualquier punto del rea de
representacin a la coordenada de origen (0, 0). Tiene dos parmetros:
atan2(y, x)
Donde los parmetro x e y corresponden a la coordenada de inters. Note que la posicin de
ambos parmetros se presentan en reverso comparado a cmo 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 funcin degrees().
Veamos un ejemplo donde aplicamos estas dos funciones:

Orientacin 2/4
// El ngulo se incrementa a medida de que el ratn
// 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);
}

Orientacin 3/4
Por ltimo, para calcular la orientacin relativa a otro punto de referencia que no sea la
coordenada de origen (0, 0), utilizamos la funcin atan2() cuyos parmetros son substrados por
los valores correspondientes al otro punto de referencia que se desea fijar.
Veamos lo antedicho en el siguiente ejemplo:

Orientacin 4/4
// Rota el tringulo apuntando siempre
// a la posicin 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
Captulo Shape 2: Vertices (pag. 69).
Captulo Math 2: Curves (pag. 79).
Captulo Math 3: Trigonometry (pag. 117).
Captulo Transform 1: Translate, Matrices (pag. 133).
Captulo Transform 2: Rotate, Scale (pag. 137).
Captulo Shape 3: Parameters, Recursion (pag. 197).
Captulo Input 4: Mouse II (pag. 237).

Informacin complementaria

Reduccin de rango
Disponemos de cinco funciones bsicas:
ceil()
floor()
round()
min()
max().

ceil() - techo
Calcula el valor entero ms cercano que el valor
ms grande o igual del de su parmetro.
int w = ceil(2.0);
int x = ceil(2.1);
int y = ceil(2.5);
int z = ceil(2.9);

// Asigna 2 a w
// Asigna 3 a x
// Asigna 3 a y
// Asigna 3 a z

floor() - piso
Calcula el valor entero ms cercano que el valor
ms pequeo o igual del de su parmetro.
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 ms cercano al valor de la
media de su parmetro.
int w = round(2.0);
int x = round(2.1);
int y = round(2.5);
int z = round(2.9);

// Asigna 2 a w
// Asigna 2 a x
// Asigna 3 a y
// Asigna 3 a z

min() - mnimo
int u = min(5, 9);
int v = min(-4, -12, -9);
float w = min(12.3, 230.24);

// Asigna 5 a u
// Asigna -12 a v
// Asigna 12.3 a w

max() - mximo
int x = max(5, 9);
int y = max(-4, -12, -9);
float z = max(12.3, 230.24);

// Asigna 9 a x
// Asigna -4 a y
// Asigna 230.24 a z

Parte 14
Movimientos simples

Movimiento
En esta seccin revisaremos tres clases de movimiento:
Movimiento implcito
Movimiento explcito
Movimiento mediante transformacin

Movimiento implcito en una


direccin 1/2
Para poner en movimiento una figura, necesitamos al menos usar
una variable para cambiar un atributo.
El siguiente ejemplo presenta un movimiento implcito, es decir un
movimiento rectilneo uniforme que no contempla posicin de origen
ni de destino:

Movimiento implcito en una


direccin 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 rectngulo
semitransparente dentro del bloque draw().
La cantidad de desenfoque es controlado por el valor del parmetro
de transparencia usado para pintar el relleno del rectngulo (la
funcin fill()).
Los nmeros cercanos a 255 refrescarn rpidamente la pantalla,
mientras que los cercanos a 0 crearn un fundido lento.
Veamos su aplicacin 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 implcito en dos


direcciones 1/2
Tambin 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 crculo
float velocidadX = 1.0; // Velocidad de mov. en eje X
float velocidadY = 0.4; // Velocidad de mov. en eje Y
int direccionX = 1; // Direccin de mov. en eje X
int direccionY = -1; // Direccin de mov. en eje X
void setup() {
size(100, 100);
smooth();
noStroke();
ellipseMode(RADIUS);
}
// ***contina***

Movimiento implcito 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 explcito en dos


direcciones 1/2
Si deseamos mover una figura desde y hasta una posicin
especfica, debemos incorporar algunas variables de control ms:
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; // Tamao de cada paso (0.0 a 0.4)
float pct = 0.0; // Porcentaje recorrido (0.0 a 1.0)

// ***contina***

Movimiento explcito 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 explcito + 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; // Tamao 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 conjuncin con la funcin pow() para
producir incrementos y decrementos exponenciales de nmeros 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);

// Clculo 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);
y *= 100;
point(x, y);
}

// Clculo de curva
// Rango 0.0 a 100.0

Curvas simples 3/5

Curvas simples 4/5

Curvas simples 5/5

Movimiento explcito curvo 1/5


Entonces podemos utilizar ecuaciones exponenciales para generar recorridos curvos
en vez de rectilneos:
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; // Tamao de cada paso (0.0 a 1.0)
float pct = 0.0; // Porcentaje recorrido (0.0 a 1.0)
// *** contina ***

Movimiento explcito 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 explcito 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; // Tamao de cada paso (0.0 a 1.0)
float pct = 0.0; // Porcentaje recorrido (0.0 a 1.0)
int direccion = 1;

// *** contina ***

Movimiento explcito 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;
}

// *** contina ***

Movimiento explcito 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


ecuacin exponencial 1/3
El siguiente ejemplo muestra el cambio de velocidad del movimiento de una figura
mediante una ecuacin exponencial. El crculo comienza a moverse muy lentamente
y luego se detiene en el mrgen inferior del rea de representacin. La variable
exponente describe la pendiente de la curva, la cual cambia la velocidad del
movimiento. Utilice el botn del ratn 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; // Tamao de cada paso (0.0 a 1.0)
float pct = 0.0; // Porcentaje recorrido (0.0 a 1.0)
// *** contina ***

Cambio de velocidad mediante


ecuacin exponencial 2/3
void setup() {
size(100, 100);
noStroke();
smooth();
distX = destinoX - origenX;
distY = destinoY - origenY;
}

// *** contina ***

Cambio de velocidad mediante


ecuacin 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
transformacin 1/3
Las funciones de transformacin (translate(), rotate(), y scale()) tambin
pueden crear movimiento al cambiar los valores de sus parmetros. 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
transformacin 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
transformacin 3/3
Las funciones de transformacin 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
Captulo Motion 1: Lines, Curves (pag. 279).

Parte 15
Movimientos mecnico y
orgnico

Movimiento mecnico 1/4


Generalmente asociamos al movimiento mecnico con aquel producido por diversos
dispositivos: el pndulo, el metrnomo, el reloj, el pistn, etc.
Todos se caracterizan por el ritmo regular, la repeticin y la eficiencia.
La funcin sin() se utiliza regularmente para producir un movimiento elegante.
La misma puede generar un movimiento de velocidad variable (ms lento en los
extremos y ms rpido en el centro) como podemos ver en la figura siguiente:

Movimiento mecnico 2/4


El siguiente ejemplo utiliza la funcin sin() para poner en movimiento un crculo:
float angulo = 0.0;

// ngulo actual

float velocidad = 0.1;


float rango = 30.0;

// Velocidad del movimiento

// Rango del movimiento

void setup() {
size(100, 100);
noStroke();
smooth();
}
void draw() {
fill(0, 20);
rect(0, 0, width, height);
fill(255);
angulo += velocidad;
float sinval = sin(angulo);
float yoffset = sinval * rango;
ellipse(50, 50 + yoffset, 40, 40);
}

Movimiento mecnico 3/4


A continuacin veremos otro ejemplo que utiliza una combinacin de funciones
sin() y cos() para generar, mediante ecuaciones ms elaboradas, movimientos
visualmente ms complejos:
float angulo = 0.0;

// ngulo actual

float velocidad = 0.05;


float rango = 30.0;
float sx = 1.0;
float sy = 2.0;
void setup() {
size(100, 100);
noStroke();
smooth();
}

// *** contina ***

// Velocidad del movimiento

// Rango del movimiento

Movimiento mecnico 4/4


void draw() {
fill(0, 4);
rect(0, 0, width, height);
angulo += velocidad;

// Actualiza ngulo

float sinVal = sin(angulo);


float cosVal = cos(angulo);
// Configuro la posicin de crculo pequeo basado
// en los valores nuevos de sin() y cos()
float x = 50 + (cosVal * rango);
float y = 50 + (sinVal * rango);
fill(255);
ellipse(x, y, 2, 2);

// Dibujo crculo pequeo

// Configuro la posicin de crculo grande basado


// en la nueva posicin de crculo pequeo
float x2 = x + cos(angulo * sx) * rango/2;
float y2 = y + sin(angulo * sy) * rango/2;
ellipse(x2, y2, 6, 6);
}

// Dibujo crculo grande

Fase 1/3
La fase de una funcin corresponde a una iteracin completa a travs de todos sus
valores posibles.
El desplazamiento de fase ocurre cuando se comienza a recorrer una funcin desde
un lugar diferente al inicial:

El desplazamiento de fase del ngulo usado para generar valores de la funcin


sin() provee la misma secuencia de nmeros, pero compensados en distintos
cuadros de la animacin.

Fase 2/3
float angulo = 0.0;
float velocidad = 0.1;
void setup() {
size(100, 100);
noStroke();
smooth();
}
void draw() {
background(0);
angulo += velocidad;
ellipse(50 + (sin(angulo + PI) * 5), 25, 30, 30);
ellipse(50 + (sin(angulo + HALF_PI) * 5), 55, 30, 30);
ellipse(50 + (sin(angulo + QUARTER_PI) * 5), 85, 30, 30);
}

Fase 3/3
float angulo = 0.0;

// ngulo

float velocidad = 0.05;

// Velocidad de crecimiento

void setup() {
size(100, 100);
noStroke();
smooth();
fill(255, 180);
}
void draw() {
background(0);
circuloFase(0.0);
circuloFase(QUARTER_PI);
circuloFase(HALF_PI);
angulo += velocidad;
}
void circuloFase(float fase) {
float diameter = 65 + (sin(angulo + fase) * 45);
ellipse(50, 50, diameter, diameter);
}

Movimiento orgnico 1/12


Algunas exploraciones a travs de software hechas en los ltimos veinte aos han
servido para modelar diversos tipos de comportamientos de movimientos orgnicos.
Ejemplos de movimiento orgnico incluyen: la cada de una hoja, el camino recorrido
por un insecto, el vuelo de un pjaro, la respiracin de una persona, el fluir de un ro,
el desplazamiento del humo en el aire, etc.
Este tipo de movimiento es considerado idiosincrtico y estocstico.
The Boids, software creado por Craig Reynolds en 1986, simula el comportamiento
de movimiento colectivo de aves y peces posibilitando as nuevas comprensiones de
estos tipos de movimientos emergentes.
Evolved Virtual Creatures, realizado por Karl Sims en 1994, presenta un trabajo
donde criaturas virtuales construidas a partir de bloques rectangulares se disponen
en abierta competencia entre s, a partir de movimientos de tipo orgnico. Es notable
apreciar cmo diversos sujetos de observacin describen sensaciones de cualidades
emotivas al percibir sus acciones.

Movimiento orgnico 2/12


A continuacin veremos un ejemplo de movimiento browniano, llamado as en honor
al reconocido botnico Robert Brown. Es un tipo de movimiento estocstico, muy
variable, que originalmente fue relacionado al tipo de movimiento realizado por las
diminutas partculas suspendidas en el aire.
Este movimiento puede ser simulado mediante software determinando, en cada
cuadro, una nueva posicin para una partcula, sin preferencia determinada de la
direccin del movimiento. Si dejamos el rastro de las posiciones anteriores nos
permitir ver el recorrido realizado en el espacio:

Movimiento orgnico 3/12


float x = 50.0;

// coordenada X

float y = 80.0;

// coordenada Y

void setup() {
size(100, 100);
randomSeed(0);

// Fuerza los mismos valores aleatorios

background(0);
stroke(255);
}
void draw() {
x += random(-2, 2);

// Asigna nueva coordenada X

y += random(-2, 2);

// Asigna nueva coordenada Y

point(x, y);
}

Movimiento orgnico 4/12


Las funciones sin() y cos() pueden ser usadas para crear un movimiento
impredecible cuando se emplean junto a la funcin random(). El siguiente ejemplo
presenta una lnea con una posicin y direccin determinadas que en cada cuadro
cambia levemente su direccin mediante un rango aleatorio pequeo entre -0.3 y 0.3:

Movimiento orgnico 5/12


float x = 0.0; // coordenada X
float y = 50.0; // coordenada Y
float angulo = 0.0; // Direccin de movimiento
float velocidad = 0.5; // Velocidad de movimiento
void setup() {
size(100, 100);
background(0);
stroke(255, 130);
randomSeed(121); // Fuerza los mismos valores aleatorios
}
void draw() {
angulo += random(-0.3, 0.3);
x += cos(angulo) * velocidad; // Asigna nueva coordenada X
y += sin(angulo) * velocidad; // Asigna nueva coordenada Y
translate(x, y);
rotate(angulo);
line(0, -10, 0, 10);
}

Movimiento orgnico 6/12


En este otro ejemplo la variable angulo cambia para producir un movimiento de
balanceo. Dado que los ngulos para cada figura se acumulan con cada unidad, las
figuras ms grandes las que tienen ms unidades se balancean de lado a lado
generando una curvatura mayor:

Movimiento orgnico 7/12


float inc = 0.0;

void setup() {
size(100, 100);
stroke(255, 204);
smooth();
}
void draw() {
background(0);
inc += 0.01;
float angulo = sin(inc)/10.0 + sin(inc*1.2)/20.0;
alga(18, 9, angulo/1.3);
alga(33, 12, angulo);
alga(44, 10, angulo/1.3);
alga(62, 5, angulo);
alga(88, 7, angulo*2);
}
// ***contina***

Movimiento orgnico 8/12


void alga(int x, int unidades, float angulo) {
pushMatrix();
translate(x, 100);
for (int i = unidades; i > 0; i--) {
strokeWeight(i);
line(0, 0, 0, -8);
translate(0, -8);
rotate(angulo);
}
popMatrix();
}

Movimiento orgnico 9/12


La funcin noise() es otro buen recurso para producir un movimiento orgnico. Ya
que los nmeros producidos con noise() son fciles de controlar, se presentan
como una buena forma para agregar sutiles irregularidades al movimiento.
Veamos un ejemplo:

Movimiento orgnico 10/12


float inc1 = 0.1;
float n1 = 0.0;
float inc2 = 0.09;
float n2 = 0.0;
void setup() {
size(100, 100);
stroke(255);
strokeWeight(20);
smooth();
}
void draw() {
background(0);
float y1 = (noise(n1) - 0.5) * 30.0; // Valores -15 a 15
float y2 = (noise(n2) - 0.5) * 30.0; // Valores -15 a 15
line(0, 50, 40, 50 + y1);
line(100, 50, 60, 50 + y2);
n1 += inc1;
n2 += inc2;
}

Movimiento orgnico 11/12


La funcin noise() tambin es til para producir texturas dinmicas. En el siguiente
ejemplo los dos primeros parmetros son usados para producir una textura
bidimensional mientras que el tercero incrementa su valor en cada cuadro para variar
la textura.
Los cambios en la variable densidad modifican la resolucin de la imagen, mientras
que los cambios en la variable inc modifican la resolucin de la textura:

Movimiento orgnico 12/12


float inc = 0.06;
int densidad = 4;
float zRuido = 0.0;
void setup() {
size(100, 100);
noStroke();
}
void draw() {
float xRuido = 0.0;
float yRuido = 0.0;
for (int y = 0; y < height; y += densidad) {
for (int x = 0; x < width; x += densidad) {
float n = noise(xRuido, yRuido, zRuido) * 256;
fill(n);
rect(y, x, densidad, densidad);
xRuido += inc;
}
xRuido = 0;
yRuido += inc;
}
zRuido += inc;
}

Lectura recomendada
Captulo Motion 2: Machine, Organism (pag. 291).

Parte 16
Arrays

Introduccin 1/5
El trmino array hace referencia a una agrupacin sistemtica de objetos.
Es posible encontrar en la bibliografa en espaol diversas traducciones del
antedicho trmino tales como arreglo, vector o matriz, siendo la primera una
traduccin literal, la segunda haciendo referencia al vector algebraico (generalmente
de una dimensin), y la tercera a una matriz algebraica (generalmente de dos).
Pocas veces es traducido como el objeto matemtico tensor (multidimensional).
En informtica llamamos array a un conjunto de elementos de datos, todos ellos
almacenados bajo un mismo nombre.
Los arrays pueden almacenar nmeros, caracteres, cadenas de texto, valores
booleanos, datos de posicin de vrtices correspondientes a una figura compleja,
teclas pulsadas, clics de botones de ratn, datos leidos de un archivo de texto, etc.

Introduccin 2/5
Veamos un ejemplo: queremos almacenar cinco datos (elementos), en este caso
cinco nmeros enteros, correspondientes a un conjunto ordenado de datos que
llamaremos fechas:

Los elementos de un array son numerados a partir del nmero cero. El primer
elemento se encuentra en la posicin [0], el segundo en la posicin [1], etc.
La posicin de cada elemento es determinada por el desplazamiento desde el inicio
del array. El primer elemento se encuentra en la posicin [0] ya que existe
desplazamiento; el segundo elemento se encuentra en la posicin [1] ya que su lugar
se encuentra desplazado un espacio desde el inicio del array.
La ltima posicin se calcula mediante la sustraccin de 1 a la longitud (cantidad
total de elementos) del array. En este ejemplo el ltimo elemento se encuentra en la
posicin [4] ya que tenemos un total de cinco elementos en el array.

Introduccin 3/5
Los arrays pueden facilitar mucho la programacin. Si bien su uso no es obligatorio,
son estructuras valiosas y eficaces para la administracin de datos.
A continuacin veremos, en un ejemplo concreto de aplicacin, algunos de los
beneficios de utilizar arrays en lugar de un gran nmero de variables:
Partimos de un conjunto de datos que determinan las coordenadas de posicin de
los vrtices que dibujan una figura estrella.
La estrella est conformada por 10 puntos vrtice, cada uno con 2 valores (pos. x e
y). Si quisieramos utilizar variables deberamos declarar 20 variables, cantidad
bastante considerable.

Introduccin 4/5
Si utilizsemos arrays, existen dos maneras de resolverlo: implementar 10 arrays
que integren los valores de las coordenadas xy para cada punto, o bien implementar
2 arrays que integren todos los valores de los puntos para cada eje (x e y).

Introduccin 5/5
Si bien el cdigo en el medio mejora notablemente la situacin, es posible optimizarlo
an ms. El cdigo en la derecha muestra cmo los elementos de datos pueden ser
agrupados de manera lgica en 2 arrays, uno para la abscisa y el otro para la
ordenada.
A continuacin veremos cmo es posible implementar el ejemplo y cmo acceder a
cada valor de los arrays mediante el uso de una estructura for:
void setup() {
int[] x = {50, 61, 83, 69, 71, 50, 29, 31, 17, 39};
int[] y = {18, 37, 43, 60, 82, 73, 82, 60, 43, 37};
beginShape();
// Lee un elemento de cada array por vez mediante el for()
for (int i = 0; i < x.length; i++) {
vertex(x[i], y[i]);
}
endShape(CLOSE);
}

Uso de arrays 1/3


En Processing, cuando trabajamos con un array, en primer lugar debemos
declararlo, en segundo crearlo y por ltimo asignarlo:
Los arrays deben ser declarados de forma similar a las variables pero se
distinguen por el uso de los corchetes [ y ]. Adems se debe especificar el tipo
de dato que almacena.
Luego de la declaracin se debe crear el array mediante la palabra clave new.
Este paso adicional designa un espacio en la memoria del ordenador para
almacenar los datos del array.
Una vez creado el array, se puede asignar los valores al mismo.

Uso de arrays 2/3


Existen diversas formas de declarar, crear y asignar arrays:
int[] datos;

// Declaracin

void setup() {
datos = new int[5]; // Creacin
datos[0] = 19;
// Asignacin
datos[1] = 40;
datos[2] = 75;
datos[3] = 76;
datos[4] = 90;
println(datos[1]);
}
int[] datos = {19, 40, 75, 76, 90};

int[] datos = new int[5]; // Declaracin y creacin


void setup() {
datos[0] = 19;
datos[1] = 40;
datos[2] = 75;
datos[3] = 76;
datos[4] = 90;
println(datos[1]);
}

// Asignacin

// Declaracin, creacin y asignacin

void setup() {
println(datos[1]);
}

Estos tres ejemplos asumen que los tres arrays estn siendo usados junto a
estructuras setup() y draw().

Uso de arrays 3/3


Los pasos de declaracin, creacin y asignacin nos habilitan a la lectura de los
valores de los distintos elementos del array.
Se puede obtener el valor de uno de los elementos del array llamando al nombre del
array seguido de los corchetes los cuales encierran el nmero ndice del elemento
que se desea acceder:
int[] datos = {19, 40, 75, 76, 90};
line(datos[0], 0, datos[0], height);
line(datos[1], 0, datos[1], height);
line(datos[2], 0, datos[2], height);
line(datos[3], 0, datos[3], height);
line(datos[4], 0, datos[4], height);

Processing responder con el mensaje ArrayIndexOutOfBoundsException con


cualquier nmero ndice ingresado que exceda el rango actual del array.

Uso del campo length


Para obtener la cantidad total de elementos almacenados en un array usamos el
campo length. Ms adelante veremos qu es un campo en relacin a la
programacin orientada a objetos, pero por el momento diremos que es posible
acceder a un campo mediante el operador punto (.).
El siguiente ejemplo muestra cmo utilizarlo:
int[] datos1 = {19, 40, 75, 76, 90};
int[] datos2 = {19, 40};
int[] datos3 = new int[127];
println(datos1.length); // Imprime "5" en la consola
println(datos2.length); // Imprime "2" en la consola
println(datos3.length); // Imprime "127" en la consola

Uso de la estructura for 1/4


Usualmente se utiliza una estructura for para acceder a los elementos de un array,
especialmente cuando ste contiene numerosos elementos.
El presente ejemplo
int[] datos = {19, 40, 75, 76, 90};
line(datos[0], 0, datos[0], height);
line(datos[1], 0, datos[1], height);
line(datos[2], 0, datos[2], height);
line(datos[3], 0, datos[3], height);
line(datos[4], 0, datos[4], height);

puede ser reemplazado por este otro:


int[] datos = {19, 40, 75, 76, 90};
for (int i = 0; i < datos.length; i++) {
line(datos[i], 0, datos[i], 100);
}

Uso de la estructura for 2/4


La estructura for tambin puede ser usada para ingresar datos en un array.
El siguiente ejemplo se almacena en un array los valores provenientes de una
funcin sin() dentro del bloque setup(), y luego muestra dichos valores a travs
del color de contorno de lneas dentro del bloque draw():
float[] ondaSeno;
void setup() {
size(100, 100);
ondaSeno = new float[width];
for (int i = 0; i < width; i++) {
// Llena el array con los valores de sin()
float r = map(i, 0, width, 0, TWO_PI);
ondaSeno[i] = abs(sin(r));
}
}
void draw() {
for (int i = 0; i < ondaSeno.length; i++) {
// Aplica los valores del array en la funcin stroke()
stroke(ondaSeno[i] * 255);
line(i, 0, i, height);
}
}

Uso de la estructura for 3/4


Otra forma de hacer ms sencilla la lectura y gestin de un programa puede darse
gracias al uso de un array para almacenar las coordenadas de gran cantidad de
elementos.
En el siguiente ejemplo el array x[] almacena la coordenada-x para cada uno de
los 12 elementos, y el array velocidad[] almacena la relacin correspondiente a
cada uno de ellos.
La escritura de este programa sin arrays hubiera requerido la inclusin de 24
variables independientes.
En cambio, de esta manera, resulta sencillo cambiar el valor asignado a numLineas
para modificar el nmero de elementos dibujados en la pantalla.

Uso de la estructura for 4/4


int numLineas = 12;
float[] x = new float[numLineas];
float[] velocidad = new float[numLineas];
float offset = 8; // Espacio entre lneas
void setup() {
size(100, 100);
smooth();
strokeWeight(10);
for (int i = 0; i < numLineas; i++) {
x[i] = i; // Posicin inicial
velocidad[i] = 0.1 + (i / offset); // Velocidad inicial
}
}
void draw() {
background(204);
for (int i = 0; i < x.length; i++) {
x[i] += velocidad[i]; // Actualiza posicin de la lnea
if (x[i] > (width + offset)) { // Si sale por derecha,
x[i] = -offset * 2;

// regresa por la izquierda.

}
float y = i * offset; // Determina la posicin-y de la lnea
line(x[i], y, x[i]+offset, y+offset); // Dibuja la lnea
}
}

Almacenamiento de datos del


ratn 1/4
Los arrays tambin son muy usados para almacenar los datos obtenidos del ratn.
Las variables de sistema pmouseX y pmouseY almacenan las coordenadas del ratn
del cuadro previo, pero no existe una manera ya incorporada en el sistema para
acceder a los valores del cursor de cuadros anteriores.
En cada cuadro, los valores de las variables mouseX, mouseY, pmouseX y pmouseY
son reemplazadas con nuevos valores y los previos son descartados.
La forma ms sencilla de almacenar la historia de dichos valores se da gracias al uso
de un array.
En el siguiente ejemplo, los 100 ltimos valores de mouseY son almacenados en un
array y son mostrados en pantalla mediante una lnea que la recorre de izquierda a
derecha.
En cada cuadro, los valores del array son transladados a la derecha y el valor ms
reciente es agregado al inicio.

Almacenamiento de datos del


ratn 2/4
int[] y;
void setup() {
size(100, 100);
y = new int[width];
}
void draw() {
background(204);
// Desplaza los valores a la derecha
for (int i = y.length-1; i > 0; i--) {
y[i] = y[i-1];
}
// Agrega nuevos valores al inicio
y[0] = constrain(mouseY, 0, height-1);
// Muestra cada par de valores como una lnea
for (int i = 1; i < y.length; i++) {
line(i, y[i], i-1, y[i-1]);
}
}

Almacenamiento de datos del


ratn 3/4
Aplique el mismo cdigo a los valores de mouseX y mouseY para almacenar la
posicin del cursor.
La visualizacin de estos valores en cada cuadro crea una estela detrs del cursor:
int num = 50;
int[] x = new int[num];
int[] y = new int[num];

void draw() {
background(0);
// Desplaza los valores a la derecha
for (int i = num-1; i > 0; i--) {
x[i] = x[i-1];
y[i] = y[i-1];
}

void setup() {
size(100, 100);
noStroke();
smooth();
fill(255, 102);
}

// Agrega los nuevos valores al inicio del array


x[0] = mouseX;
y[0] = mouseY;
// Dibuja los crculos
for (int i = 0; i < num; i++) {
ellipse(x[i], y[i], i/2.0, i/2.0);
}

// *** contina ***

Almacenamiento de datos del


ratn 4/4
El siguiente ejemplo produce el mismo resultado que el anterior pero usa una tcnica ms
eficiente. En lugar de ordenar los elementos del array en cada cuadro, el programa escribe los
nuevos datos en la prxima posicin del array disponible.
Los elementos del array permanecen en la misma posicin una vez escritos, pero son ledos en
un orden diferente en cada cuadro. La lectura comienza en la posicin del elemento ms antiguo
y contina hasta el final del array. Al final del array, se usa el operador % para volver nuevamente
al principio.
Esta tcnica es especialmente til para aplicar a arrays de gran tamao para evitar la copia de
datos innecesarios que puede llevar a una considerable reduccin de velocidad del programa.
int num = 50;
int[] x = new int[num];
int[] y = new int[num];
int indicePosicion = 0;

void draw() {
background(0);
x[indicePosicion] = mouseX;
y[indicePosicion] = mouseY;

void setup() {
size(100, 100);
noStroke();
smooth();
fill(255, 102);
}

// Ciclo entre 0 y el nmero de elementos


indicePosicion = (indicePosicion + 1) % num;
for (int i = 0; i < num; i++) {
// Determina la posicin del array a leer
int pos = (indicePosicion + i) % num;
float radio = (num-i) / 2.0;
ellipse(x[pos], y[pos], radio, radio);
}

// *** contina ***

Funciones de array
Processing provee un grupo de funciones que permiten asistir en la gestin de los
arrays:
append()
shorten()
expand()
arrayCopy()
concat()
subset()
sort()
reverse()
splice()

Funcin de array: append()


Expande un elemento del array, aade los datos en la nueva posicin y regresa el
array incrementado.
El tipo de dato del segundo parmetro (elemento) debe ser el mismo que el tipo de
dato del array.
int[] numeros = {1, 3};
append(numeros, 5); // INCORRECTO! No cambia el array
println(numeros); // Imprime "1" y "3"
println();
numeros = append(numeros, 5); // Agrega "5" al final
println(numeros); // Imprime "1", "3" y "5"
println();
// Agrega "7" al final del array "numeros", y crea un nuevo
// array donde guarda el cambio
int[] masNumeros = append(numeros, 7);
println(masNumeros); // Imprime "1", "3", "5" y "7"

Funcin de array: shorten()


Disminuye un array en un elemento y regresa el array acortado.

int[] numeros = {1, 3, 5, 7};


numeros = shorten(numeros); // Recorta el ltimo elemento
println(numeros); // Imprime "1", "3" y "5"

Funcin de array: expand()


Incrementa el tamao de un array. Puede expandirlo a un tamao determinado
(segn el segundo parmetro) o, si no se especifica el tamao, se lo dobla.

int[] numeros = {1, 3, 5, 7};


println(numeros.length); // Imprime "4
numeros = expand(numeros);
println(numeros.length); // Imprime "8"
numeros = expand(numeros, 512);
println(numeros.length); // Imprime "512"

Funcin de array: arrayCopy()


Copia un array (o parte de l) a otro array.
Existen tres versiones de dicha funcin:

arrayCopy(arrayOrigen, arrayDestino)
arrayCopy(arrayOrigen, arrayDestino, cantElementosACopiar)
arrayCopy(arrayOrigen, arrayOrigenPos, arrayDestino, arrayDestinoPos,
cantElementosACopiar)

int[] numeros1 = {1, 3, 5, 7};


int[] numeros2 = {2, 4, 6, 8};
arrayCopy(numeros1, numeros2);
println(numeros2); // Imprime "1", "3", "5" y "7"
int[] numeros1 = {1, 3, 5, 7};
int[] numeros2 = {2, 4, 6, 8};
arrayCopy(numeros1, 1, numeros2, 0, 2);
println(numeros2); // Imprime "3", "5", "6" y "8"

Funcin de array: concat()


Concatena dos arrays.
int[] numeros1 = {1, 3, 5, 7};
int[] numeros2 = {2, 4, 6, 8};
numeros1 = concat(numeros1, numeros2);
println(numeros1); // Imprime "1", "3", "5", "7", "2", "4", "6" y "8"

Funcin de array: reverse()


Invierte el orden de un array.
int[] numeros = {1, 3, 5, 7};
numeros = reverse(numeros);
println(numeros); // Imprime "7", "5", "3" y "1"

Funcin de array: sort()


Ordena un array de nmeros de menor a mayor, o pone en orden alfabtico un array
de palabras. El array original no resulta modificado, se regresa un array re-ordenado.
float[] decimales = {3.4, 2, 0, 7.1};
decimales = sort(decimales);
println(decimales); // Imprime "0.0", "2.0", "3.4" y "7.1"

Funcin de array: splice()


Inserta un valor o un array de valores dentro de un array existente.
splice(array, valorASerInsertado, posIndiceArray)
splice(array, arrayASerInsertado, posIndiceArray)

int[] numeros = {1, 3, 5, 7};


numeros = splice(numeros, 2, 1);
println(numeros); // Imprime "1", "2", "3", "5" y "7"

int[] numeros1 = {1, 3, 5};


int[] numeros2 = {2, 4, 6};
numeros2 = splice(numeros1, numeros2, 2);
println(numeros2); // Imprime "1", "3", "2", "4", "6" y "5"
int[] numeros1 = {1, 3, 5};
int[] numeros2 = {2, 4, 6};
numeros1 = splice(numeros2, numeros1, 2);
println(numeros1); // Imprime "2", "4", "1", "3", "5" y "6"

Funcin de array: subset()


Extrae una serie de elementos de un array.
El parmetro array define el array desde el cual sern tomados los elementos.
El parmetro offset define la posicin desde la cual se comienza a extraer (primer
valor).
El parmetro numeroDeValoresAExtraer determina la cantidad de elementos que
sern extrados. Si este parmetro no es utilizado, los elementos sern extrados
desde el offset hasta el final del array.
subset(array, offset)
subset(array, offset, numeroDeValoresAExtraer)

int[] numeros1 = {1, 3, 5, 7};


int[] numeros2 = subset(numeros1, 2);
println(numeros2); // Imprime "5" y "7"
int[] numeros1 = {1, 3, 5, 7, 9, 11};
int[] numeros2 = subset(numeros1, 2, 3);
println(numeros2); // Imprime "5", "7" y 9"

Consideraciones particulares sobre


los arrays 1/3
Se pueden escribir nuevas funciones que realizan operaciones sobre los arrays, pero
los arrays se comportan de manera diferente a otros tipos de dato como int o char.
Cuando un array es usado como parmetro de funcin, la direccin (ubicacin en la
memoria) del array es transferida dentro de la funcin en lugar de los datos reales.
No resulta creado ningn array nuevo, y los cambios realizados dentro de la funcin
afectan al array usado como parmetro.

Consideraciones particulares sobre


los arrays 2/3
En el siguiente ejemplo, el array datos[] es usado como parmetro de la funcin
mitad(). La direccin de datos[] es pasada al array d[] mediante la funcin
mitad(). Ya que la direccin de d[] y datos[] es la misma, ellos afectan al mismo
contenido. Cuando se realizan cambios en d[], estos cambios se producen sobre
los valores del array datos[].
float[] datos = {19.0, 40.0, 75.0, 76.0, 90.0};
void setup() {
mitad(datos);
println(datos[0]); // Imprime "9.5"
println(datos[1]); // Imprime "20.0"
println(datos[2]); // Imprime "37.5"
println(datos[3]); // Imprime "38.0"
println(datos[4]); // Imprime "45.0"
}
void mitad(float[] d) {
for (int i = 0; i < d.length; i++) { // Cada elemento del array,
d[i] = d[i] / 2.0;
// se divide por dos.
}
}

Consideraciones particulares sobre


los arrays 3/3
El cambio de los datos de un array dentro de una funcin, sin modificar el array
original, requiere algunas lneas de cdigo adicional.
En el siguiente ejemplo, se pasa el array como parmetro dentro de una funcin, se
crea un nuevo array, los valores del array original son copiados en el nuevo array, los
cambios son realizados en el nuevo array, y finalmente se regresa el array
modificado.
float[] datos = {19.0, 40.0, 75.0, 76.0, 90.0};
float[] mitadDatos;
void setup() {
mitadDatos = mitad(datos); // Ejecuta la funcin mitad()
println(datos[0] + ", " + mitadDatos[0]); // Imprime "19.0, 9.5"
println(datos[1] + ", " + mitadDatos[1]); // Imprime "40.0, 20.0"
println(datos[2] + ", " + mitadDatos[2]); // Imprime "75.0, 37.5"
println(datos[3] + ", " + mitadDatos[3]); // Imprime "76.0, 38.0"
println(datos[4] + ", " + mitadDatos[4]); // Imprime "90.0, 45.0"
}
float[] mitad(float[] d) {
float[] numeros = new float[d.length]; // Crea un nuevo array
arraycopy(d, numeros);
for (int i = 0; i < numeros.length; i++) { // Cada elemento del array,
numeros[i] = numeros[i] / 2;
// se divide por dos.
}
return numeros; // Regresa el nuevo array
}

Arrays bidimensionales 1/2


Los datos tambin pueden ser almacenados y recuperados mediante arrays con ms
de una dimensin.
A partir del ejemplo de la introduccin de esta seccin, mostraremos cmo utilizar un
array 2D para almacenar los puntos vrtice de la estrella:

Un array 2D es esencialmente una lista de arrays 1D. Debe ser primero declarado,
luego creado, y por ltimo asignado tal como un array 1D. A continuacin el cdigo:
int[][] puntos = { {50,18}, {61,37}, {83,43}, {69,60}, {71,82},
{50,73}, {29,82}, {31,60}, {17,43}, {39,37} };
println(puntos[4][0]); // Imprime "71"
println(puntos[4][1]); // Imprime "82"
println(puntos[4][2]); // ERROR! Este elemento se encuentra fuera de
rango
println(puntos[0][0]); // Imprime "50"
println(puntos[9][1]); // Imprime "37"
println(puntos[1]);
// Imprime "61" y "37"

Arrays bidimensionales 2/2


El prximo ejemplo muestra cmo se aplica el array 2D en el ejemplo de la estrella:
int[][] puntos = { {50,18}, {61,37}, {83,43}, {69,60}, {71,82},
{50,73}, {29,82}, {31,60}, {17,43}, {39,37} };
void setup() {
size(100, 100);
fill(0);
smooth();
}
void draw() {
background(204);
translate(mouseX - 50, mouseY - 50);
beginShape();
for (int i = 0; i < puntos.length; i++) {
vertex(puntos[i][0], puntos[i][1]);
}
endShape();
}

Si bien es posible crear arrays multidimensionales (3D, 4D o ms) extrapolando


estas tcnicas, su implementacin suele ser muy compleja y frecuentemente se
prefiere aplicar mltiples arrays 1D o 2D.

Lectura recomendada
Captulo Data 4: Arrays (pag. 301).

Parte 17
Objetos

Introduccin 1/2
El paradigma planteado por la programacin estructurada tradicional define las variables (datos)
y las funciones (procedimientos) como los bloques bsicos de construccin. Distintas funciones
sern frecuentemente usadas en conjunto para trabajar sobre una serie determinada de
variables.
La programacin orientada a objetos (POO) fue desarrollada para hacer ms explcito este
proceso.
La POO utiliza clases y objetos como bloques bsicos de construccin.
Una clase define un grupo de mtodos (funciones) y campos (variables).
Un objeto es una nica instancia de una clase.
Los campos dentro de un objeto se acceden, tpicamente, slo a travs de sus propios mtodos,
permitiendo a un objeto ocultar su complejidad de otras partes del programa.

Introduccin 2/2
La POO difiere de la programacin estructurada tradicional, en la que los datos y los
procedimientos estn separados y sin relacin, ya que lo nico que se busca es el
procesamiento de unos datos de entrada para obtener otros de salida.
La programacin estructurada anima al programador a pensar sobre todo en
trminos de procedimientos o funciones, y en segundo lugar en las estructuras de
datos que esos procedimientos manejan.
En la programacin estructurada slo se escriben funciones que procesan datos. Los
programadores que emplean POO, en cambio, primero definen objetos para luego
enviarles mensajes solicitndoles que realicen sus mtodos por s mismos.

Programacin estructurada

Progr. orientada a objetos

Variable

Campo

Funcin

Mtodo

POO 1/3
Un programa modular est compuesto de mdulos de cdigo los cuales realizan,
cada uno, una tarea especfica.
El uso de variables es un medio fundamental para estudiar la reutilizacin de
elementos dentro de un programa. Permite que un determinado valor aparezca las
veces que se necesite dentro de un programa y que sea fcilmente cambiado.
Las funciones resumen una tarea especfica y permiten que bloques de cdigo sean
usados en todo el programa. Tpicamente, uno se concentra slo en qu es lo que la
funcin hace, no en cmo esta trabaja.
Todo esto permite que la mente se concentre en los objetivos del programa antes
que en las complejidades de la infraestructura.

POO 2/3
La programacin orientada a objetos ampla an ms la modularidad -el uso de
variables y escritura de funciones- al permitir la agrupacin de funciones
relacionadas.
Podemos asociar los objetos de la POO con artefactos concretos:
Clase

Manzana

Mariposa

Campo

color, peso

especie, genero

Mtodo

crecer(), caer(), descomponer()

vatirAlas(), tomarTierra()

Clase

Radio

Auto

Campo

frecuencia, volumen

marca, modelo, color

Mtodo

encender(), sintonizar(), ajustarVol()

acelerar(), frenar(), girar()

Si extendemos el ejemplo de la Manzana podremos apreciar un poco ms las


consideraciones acerca de las relaciones entre los objetos concretos y los objetos de
software: el mtodo crecer() podra tener entradas para temperatura y
humedad; el mtodo caer() podra continuamente controlar peso y hacerla caer
cuando supere un determinado umbral; el mtodo descomponer() podra entonces
hacerse cargo comenzando a disminuir el valor de peso y cambiar color.

POO 3/3
Los objetos son creados a partir de una clase, y una clase describe un conjunto de
campos y mtodos.
Una instancia de una clase debe tener un nombre nico. Si ms de un objeto es
creado a partir de una clase, cada uno debe tener un nombre nico. Por ejemplo de
la clase Manzana podemos crear dos objetos con sus correspondientes valores de
campos:
Objeto

deliciosa

grannySmith

Campos

color: rojo

color: amarillo

peso: 200

peso: 230

Se accede a los campos y mtodos de un objeto mediante el operador punto (.).


Para obtener el valor del campo color del objeto deliciosa, se utiliza la sintaxis
deliciosa.color.
Para activar (o llamar) al mtodo crecer() del objeto grannySmith, tambin se
utiliza la siguiente sintaxis con el operador punto: grannySmith.crecer().

Uso de clases y objetos 1/12


Definir una clase es, en definitiva, crear nuestro propio tipo de dato.
A diferencia de otros tipos primitivos como int, float y boolean, se trata de un
tipo compuesto -como String, PImage y PFont. Esto significa que puede
almacenar muchas variables y mtodos bajo un mismo nombre.
Al momento de crear una clase, se debe pensar cuidadosamente sobre qu quiere
que el cdigo haga.
Es comn realizar primero una lista de variables (estas sern los campos) y resolver
los tipos de dato correspondientes.
Ejemplifiquemos: queremos dibujar un crculo blanco en la pantalla, por lo tanto
pensamos en tres campos: dos para la posicin y uno para el dimetro, prefiriendo el
tipo float para aportar mayor flexibilidad para controlar el movimiento:
float

coordenada-x del crculo

float

coordenada-y del crculo

float

diametro

dimetro del crculo

Uso de clases y objetos 2/12


El nombre de la clase debe ser cuidadosamente considerado. Por convencin se
recomienda utilizar una letra mayscula en la primera letra para diferenciarlo de las
variables.
Una vez determinados el nombre de la clase y los campos, considere cmo hubiera
escrito el programa sin el uso de objetos:
float x = 33;
float y = 50;
float diametro = 30;
void setup() {
size(100, 100);
smooth();
noStroke();
}
void draw() {
background(0);
ellipse(x, y, diametro, diametro);
}

Uso de clases y objetos 3/12

En el prximo ejemplo veremos cmo aplicar la POO en el cdigo: moveremos los campos que pertenecen al
crculo a su propia clase.

La primera lnea declara el objeto circ de tipo Circulo.

La clase Circulo se declara a continuacin del bloque setup() y draw().

El objeto circ es construido dentro de setup(), permitiendo as el acceso a sus campos. En las tres lneas
siguientes se asignan valores a los campos dentro de Circulo.

Se accede a estos valores dentro de draw() para determinar la posicin y el tamao del crculo.

El operador punto (.) se usa para asignar setup()- y acceder draw()- a las variables de la clase.
Circulo circ;
// Declaracin del objeto
void setup() {
size(100, 100);
smooth();
noStroke();
circ = new Circulo(); // Construccin del objeto
circ.x = 33;
// Asigna 33 al campo x
circ.y = 50;
// Asigna 50 al campo y
circ.diametro = 30;
// Asigna 30 al campo diametro
}
void draw() {
background(0);
ellipse(circ.x, circ.y, circ.diametro, circ.diametro); //Accede a los campos
}
class Circulo {
float x, y;
// Coordenadas xy
float diametro;
// Dimetro del crculo
}

Uso de clases y objetos 4/12

La clase Circulo que hemos declarado no es muy til por el momento, sin embargo es un inicio. El prximo
ejemplo se construye sobre el anterior y agrega un mtodo a dicha clase.

El mtodo mostrar() ha sido agregado a la definicin de la clase para dibujar la figura en la pantalla.

La ltima lnea en draw() ejecuta el mtodo mostrar() delegado al objeto circ al escribir los nombres del
objeto y del mtodo conectados por un operador punto (.).

Note tambin que no se usa el nombre del objeto para acceder a los campos. Esto sucede as porque que la
funcin ellipse() se llama desde dentro de la clase Circulo. Ya que esta lnea es parte del mtodo
mostrar(), este puede acceder a sus propias variables sin especificar su propio nombre.
Circulo circ ;
void setup() {
size(100, 100);
smooth();
noStroke();
circ = new Circulo();
circ.x = 33;
circ.y = 50;
circ.diametro = 30;
}
void draw() {
background(0);
circ.mostrar();
}
class Circulo {
float x, y, diametro;
void mostrar() {
ellipse(x, y, diametro, diametro);
}
}

// Declaracin del objeto

// Construccin del objeto

// Campos
// Mtodo

Uso de clases y objetos 5/12


Resulta prudente a esta altura reforzar la diferencia que existe entre la clase
Circulo y el objeto circ.
Aunque el cdigo pueda parecer indicarnos que los campos x, y y diametro, y el
mtodo mostrar() pertenecen a la clase, Circulo es slo la definicin para
cualquier objeto creado a partir de dicha clase.
Cada uno de estos elementos pertenecen a (estn encapsulados por) la variable
circ, la cual es una instancia del tipo de dato Circulo.
El prximo ejemplo presenta un nuevo elemento de programacin llamado
constructor.

Uso de clases y objetos 6/12


Un constructor es un bloque de cdigo activado al momento de la creacin de un
objeto.
El constructor siempre tiene el mismo nombre que la clase y es tpicamente usado
para asignar valores a los campos de un objeto cuando este se construye.
El constructor funciona como cualquier otro mtodo, excepto en que no es precedido
con un tipo de dato o la palabra clave void ya que no contempla ningn tipo de
retorno.
Cuando se crea el objeto circ, los parmetros 33, 50 y 30 son asignados en
correspondencia a las variables xpos, ypos y diam dentro del constructor. Dentro
del bloque constructor, estos valores resultan asignados a los campos x, y y diam del
objeto.
Para que los campos sean accesibles entre cada mtodo del objeto, estos son
declarados fuera del constructor. Recuerde las reglas del mbito de las variables: si
los campos son declarados dentro del constructor, estos no pueden ser accedidos
por fuera del constructor.

Uso de clases y objetos 7/12


Ahora s veamos el ejemplo:
Circulo circ;

// Declaracin del objeto

void setup() {
size(100, 100);
smooth();
noStroke();
circ = new Circulo(33, 50, 30);
}

// Construccin del objeto

void draw() {
background(0);
circ.mostrar();
}
class Circulo {
float x, y, diametro;
Circulo(float xpos, float ypos,
x = xpos;
// Asigna 33
y = ypos;
// Asigna 50
diametro = diam; // Asigna 30
}

// Campos
float diam) { // Constructor
a x
a y
a diametro

void mostrar() {
ellipse(x, y, diametro, diametro);
}
}

// Mtodo

Uso de clases y objetos 8/12


El comportamiento de la clase Circulo puede ser extendido an ms gracias a la
incorporacin en su definicin de una mayor cantidad de campos y mtodos.
El siguiente ejemplo extiende la clase para que el crculo se mueva hacia arriba y
hacia abajo, y que cambie de direccin cuando este alcance el borde superior o
inferior de la ventana de visualizacin.
Ya que el crculo estar movindose, este necesita un campo que defina la velocidad
y otro campo que almacene la direccin. Llamaremos a estos campos velocidad y
direccion.
El campo velocidad ser un float para maximizar el rango de valores obtenibles,
mientras que direccion ser suficiente un int para aplicar operaciones
aritmticas bsicas (1 direccin hacia arriba, -1 direccin hacia abajo).

Uso de clases y objetos 9/12


Para crear el movimiento deseado, necesitamos actualizar la posicin del crculo en
cada cuadro.
La direccin tambin debe actualizarse cuando alcance los bordes de la ventana de
visualizacin. La evaluacin de borde se da cuando la coordenada-y es menor que el
radio del crculo, o cuando esta es mayor que la altura de la ventana menos el radio
del crculo. Luego la direccin cambiar cuando el borde exterior del crculo (en vez
de su centro) llegue al borde de la ventana.
Adems de decidir qu necesitan hacer los mtodos y qu nombre tendrn, debemos
considerar tambin el tipo de retorno. Ya que no se devolver nada, se usar la
palabra clave void.
Los cdigos dentro de los mtodos mover() y mostrar() podran haber sido
combinados en un solo mtodo; fueron separados para hacer ms claro el ejemplo.
El cambio de la posicin del objeto y la visualizacin en la pantalla del mismo son
tareas distintas, y el uso de mtodos separados as lo refleja.

Uso de clases y objetos 10/12


Circulo circ;
// Declaracin del objeto
void setup() {
size(100, 100);
smooth();
noStroke();
circ = new Circulo(33, 50, 30, 1.5); // Construccin del objeto
}
void draw() {
fill(0, 15);
rect(0, 0, width, height);
fill(255);
circ.mover();
circ.mostrar();
}
class Circulo {
// Campos
float x, y, diametro;
float velocidad;
// Distancia recorrida en cada cuadro
int direccion = 1; // Direccin del movimiento (1 hacia abajo, -1 hacia arriba)
// Constructor
Circulo(float xpos, float ypos, float diam, float vel) {
x = xpos;
y = ypos;
diametro = diam;
velocidad = vel;
}
// Mtodos
void mover() {
y += (velocidad * direccion);
if ((y > (height - diametro/2)) || (y < diametro/2)) {
direccion *= -1;
}
}
void mostrar() {
ellipse(x, y, diametro, diametro);
}
}

Uso de clases y objetos 11/12


Al igual que una funcin, una clase bien escrita permite al programador concentrarse
en comportamiento resultante y no en los detalles de ejecucin.
Los objetos deben ser escritos con la finalidad de reutilizacin.
Como ocurre con otros tipos de variables, objetos adicionales son agregados al
declarar ms nombres.
El siguiente ejemplo tiene tres objetos hechos a partir de la clase Circulo. Cada
uno de estos objetos (circ1, circ2 y circ3) tienen su propio conjunto de campos
y mtodos.
Se ejecuta un mtodo declarado en la clase por cada objeto que lo llama.
Cuando se llaman a estos mtodos, ellos acceden a los valores de los campos
pertenecientes a cada objeto. Es decir, cuando circ2 llama por primera vez al
mtodo mover(), el valor del campo y es actualizado por el valor 2.0 del campo
velocidad ya que dicho valor fue pasado al objeto circ2 a travs del contructor.

Uso de clases y objetos 12/12


Ahora s veamos el ejemplo:
Circulo circ1, circ2, circ3; // Declaracin de los objetos
void setup() {
size(100, 100);
smooth();
noStroke();
circ1 = new Circulo(20, 50, 40, 0.5); // Construccin del objeto circ1
circ2 = new Circulo(50, 50, 10, 2.0); // Construccin del objeto circ2
circ3 = new Circulo(80, 50, 30, 1.5); // Construccin del objeto circ3
}
void draw() {
fill(0, 15);
rect(0, 0, width, height);
fill(255);
circ1.mover();
circ2.mover();
circ3.mover();
circ1.mostrar();
circ2.mostrar();
circ3.mostrar();
}
// Insertar aqu la clase Circulo

Otro ejemplo 1/2


Huevo humpty;

// Declaracin del objeto

void setup() {
size(100, 100);
smooth();
// Entradas: coord-x, coord-y, factor de balanceo y altura
humpty = new Huevo(50, 100, 8, 80); // Construccin del objeto
}
void draw() {
background(0);
humpty.balancear();
humpty.mostrar();
}
class Huevo {
// Campos
float
float
float
float
float

x, y;
inclinacion;
balanceo;
angulo;
altura;

//
//
//
//
//

coords-xy
Offset ngulo izquierda y derecha
Factor de balanceo
ngulo de balanceo
Altura del huevo

// Constructor
Huevo(int xpos, int ypos, float balFactor, float h) {
x = xpos;
y = ypos;
balanceo = balFactor;
altura = h / 100.0;
}
// *** contina ***

Otro ejemplo 2/2


// Mtodos
void balancear() {
inclinacion = cos(angulo) / balanceo;
angulo += 0.1;
}
void mostrar() {
noStroke();
fill(255);
pushMatrix();
translate(x, y);
rotate(inclinacion);
scale(altura);
beginShape();
vertex(0, -100);
bezierVertex(25, -100, 40, -65, 40, -40);
bezierVertex(40, -15, 25, 0, 0, 0);
bezierVertex(-25, 0, -40, -15, -40, -40);
bezierVertex(-40, -65, -25, -100, 0, -100);
endShape();
popMatrix();
}
}

Ejercicio 16

EJ16: Crear dos "entes autnomos" en el escenario. Uno debe exhibir


movimientos de cualidades ms bien mecnicas y el otro orgnicas.

Utilizar clases.

Comentar todas las instrucciones.

Lectura recomendada
Captulo Structure 4: Objects I (pag. 395).

Parte 18
Arrays de objetos

Introduccin
El trabajo con arrays de objetos es similar al trabajo con arrays de otros tipos de dato.
Como todo array, un array de objetos se distingue de cualquier objeto gracias a los corchetes.
Ya que cada elemento de array es un objeto, cada elemento del array debe ser creado antes de
que pueda ser accedido.
Los pasos para el trabajo con un array de objetos son los siguientes:
1. Declaracin del array
2. Creacin del array
3. Creacin de cada objeto del array
Veamos cmo se implementa en los prximos dos ejemplos:

Ejemplo 1 1/2
int numCirc = 6;
// Declaracin y creacin del array
Circulo[] circulos = new Circulo[numCirc];
void setup() {
size(100, 100);
smooth();
noStroke();
for (int i = 0; i < circulos.length; i++) {
float x = 10 + i*16;
float rate = 0.5 + i*0.05;
// Creacin de cada objeto del array
circulos[i] = new Circulo(x, 50, 16, rate);
}
}
void draw() {
fill(0, 12);
rect(0, 0, width, height);
fill(255);
for (int i = 0; i < circulos.length; i++) {
circulos[i].mover(); // Move each object
circulos[i].mostrar(); // Display each object
}
}
// *** contina ***

Ejemplo 1 2/2
class Circulo {
// Campos
float x, y, diametro;
float velocidad;
// Distancia movida en cada cuadro
int direccion = 1; // Direccin del movimiento (1 hacia abajo, -1
hacia arriba)
// Constructor
Circulo(float xpos, float ypos, float diam, float vel) {
x = xpos;
y = ypos;
diametro = diam;
velocidad = vel;
}
// Mtodos
void mover() {
y += (velocidad * direccion);
if ((y > (height - diametro/2)) || (y < diametro/2)) {
direccion *= -1;
}
}
void mostrar() {
ellipse(x, y, diametro, diametro);
}
}
// *** contina ***

Ejemplo 2 1/2
Anillo[] anillos;

// Declaracin del array

int numAnillos = 50;


int actualAnillo = 0;
void setup() {
size(100, 100);
smooth();
anillos = new Anillo[numAnillos]; // Creacin del array
for (int i = 0; i < numAnillos; i++) {
anillos[i] = new Anillo();
// Creacin de cada objeto
}
}
void draw() {
background(0);
for (int i = 0; i < numAnillos; i++) {
anillos[i].crecer();
anillos[i].mostrar();
}
}
// Click para crear un nuevo anillo
void mousePressed() {
anillos[actualAnillo].iniciar(mouseX, mouseY);
actualAnillo++;
if (actualAnillo >= numAnillos) {
actualAnillo = 0;
}
}
// *** contina ***

Ejemplo 2 2/2
class Anillo {
float x, y;
// Coordenadas-xy
float diametro;
// Dimetro del anillo
boolean on = false; // Enciende o apaga la visualizacin
void iniciar(float xpos, float ypos) {
x = xpos;
y = ypos;
on = true;
diametro = 1;
}
void crecer() {
if (on == true) {
diametro += 0.5;
if (diametro > 400) {
on = false;
}
}
}
void mostrar() {
if (on == true) {
noFill();
strokeWeight(4);
stroke(155, 153);
ellipse(x, y, diametro, diametro);
}
}
}

Multiples archivos
Cuando un programa crece de sobremanera resulta ms conveniente dividirlo y separarlo en
mltiples archivos.
Esta prctica tambin es aconsejada cuando se desea reusar clases en otros programas.
Para realizar esto se recomienda primero guardar el cuerpo principal del programa en un archivo,
por ejemplo, anillos-main, y luego hacer clic en el botn del extremo derecho, en el sector de
lengetas.

All se despliega un men contextual y se seleccionar la primera opcin New Tab.


Entonces se nos pide el nombre del nuevo archivo e ingresaremos Anillo-clase.
Finalizamos con clic en OK.
En la carpeta correspondiente a anillos-main encontraremos dos archivos: anillos-main.pde
y Anillo-clase.pde.

Lectura recomendada
Captulo Structure 4: Objects I (pag. 395).

Parte 19
Objetos II

Mltiples constructores 1/3


A medida que el programa comienza a crecer y las ideas se hacen ms ambiciosas,
los conceptos y tcnicas avanzados sobre POO se vuelven ineludibles para la
gestin del cdigo.
Una clase puede tener mltiples constructores que asignan los campos de formas
diferentes. A veces resulta beneficioso especificar cada aspecto de los datos de un
objeto al asignar parmetros a los campos, pero otras veces puede resultar
apropiado definir slo uno o algunos de ellos.
En el siguiente ejemplo, un constructor aplica los valores de los campos x, y, y
radio, mientras que el otro aplica valores por defecto.
Cuando el objeto es creado, Processing elige el constructor apropiado de acuerdo a
la identificacin del nmero y tipo de variables especificado:

Mltiples constructores 2/3


Circulo circ1, circ2;
void setup() {
size(100, 100);
smooth();
noLoop();
// Ejecuta el constructor sin parmetros
circ1 = new Circulo();
// Ejecuta el constructor con tres parmetros
circ2 = new Circulo(66, 50, 20);
}
void draw() {
circ1.mostrar();
circ2.mostrar();
}
// *** contina ***

Mltiples constructores 3/3


class Circulo {
float x, y, radio;
// Primera versin del constructor Circulo;
// se asigna a los campos valores por defecto
Circulo() {
x = 33;
y = 50;
radio = 8;
}
// Segunda versin del constructor Circulo;
// se asigna a los campos los valores de los parmetros
Circulo(float xpos, float ypos, float r) {
x = xpos;
y = ypos;
radio = r;
}
void mostrar() {
ellipse(x, y, radio*2, radio*2);
}
}

Objetos compuestos 1/5


Un objeto puede incluir otros objetos. La creacin de semejantes objetos compuestos resultan
una forma apropiada para aplicar el principio de modularidad y construir niveles ms altos de
abstraccin.
En el mundo concreto, los objetos frecuentemente poseen componentes que operan
autnomamente pero en relacin a otros componentes.
Si se permite usar una analoga biolgica, puede crear una clase celula, grupos de ellas que
combinadas conforman un tejido muscular o un tejido nervioso. Estos tejidos pueden ser
combinados en rganos, y los rganos en un organismo.
Con mltiples capas de abstraccin, cada paso es construido a partir de compuestos de una
capa anterior.
El siguiente ejemplo combina la clase Huevo y la clase Anillo para crear una nueva clase
llamada HuevoAnillo. Cuando se usa la clase HuevoAnillo en un programa, cada instancia
dibuja un huevo en la pantalla con un anillo creciendo desde su centro.
El ejemplo cuenta con un objeto de tipo Huevo llamado ovoide, creado en el constructor, y un
objeto de tipo Anillo llamado circulo, creado en la base de la clase.
El mtodo transmitir() llama a los mtodos de ambas clases y reinicializa circulo cuando
el objeto alcanza su mximo tamao.
Ahora s, veamos el ejemplo:

Objetos compuestos 2/5


HuevoAnillo ha1, ha2;
void setup() {
size(100, 100);
smooth();
ha1 = new HuevoAnillo(33, 66, 16, 33);
ha2 = new HuevoAnillo(66, 90, 8, 66);
}
void draw() {
background(0);
ha1.transmitir();
ha2.transmitir();
}

// Se debe incluir las sig. Clases: Huevo, Anillo y HuevoAnillo

Objetos compuestos 3/5


class Huevo {
float x, y;
// coords-xy
float inclinacion;
// Offset ngulo izquierda y derecha
float balanceo;
// Factor de balanceo
float angulo;
// ngulo de balanceo
float altura;
// Altura del huevo
Huevo(int xpos, int ypos, float balFactor, float h) {
x = xpos;
y = ypos;
balanceo = balFactor;
altura = h / 100.0;
}
void balancear() {
inclinacion = cos(angulo) / balanceo;
angulo += 0.1;
}
void mostrar() {
noStroke();
fill(255);
pushMatrix();
translate(x, y);
rotate(inclinacion);
scale(altura);
beginShape();
vertex(0, -100);
bezierVertex(25, -100, 40, -65, 40, -40);
bezierVertex(40, -15, 25, 0, 0, 0);
bezierVertex(-25, 0, -40, -15, -40, -40);
bezierVertex(-40, -65, -25, -100, 0, -100);
endShape();
popMatrix();
}
}

Objetos compuestos 4/5


class Anillo {
float x, y;
// Coordenadas-xy
float diametro;
// Dimetro del anillo
boolean on = false; // Enciende o apaga la visualizacin
void iniciar(float xpos, float ypos) {
x = xpos;
y = ypos;
on = true;
diametro = 1;
}
void crecer() {
if (on == true) {
diametro += 0.5;
if (diametro > 400) {
on = false;
}
}
}
void mostrar() {
if (on == true) {
noFill();
strokeWeight(4);
stroke(155, 153);
ellipse(x, y, diametro, diametro);
}
}
}

Objetos compuestos 5/5


class HuevoAnillo {
Huevo ovoide;
Anillo circulo = new Anillo();
HuevoAnillo(int x, int y, float t, float sp) {
ovoide = new Huevo(x, y, t, sp);
circulo.iniciar(x, y - sp/2);
}
void transmitir() {
ovoide.balancear();
ovoide.mostrar();
circulo.crecer();
circulo.mostrar();
if (circulo.on == false) {
circulo.on = true;
}
}
}

Herencia
Una clase puede ser definida usando otra clase como fundamento. En trminos de POO, una
clase puede heredar campos o mtodos de otra.
Un objeto que hereda de otro (heredero) es llamado subclase, mientras que el objeto del cual se
hereda (antecesor) es llamado superclase.
Una subclase extiende las capacidades de una superclase. Cuando una clase extiende a otra,
todos los campos y mtodos de la superclase resultan automticamente incluidos en la subclase.
Cuando se define la subclase se utiliza la palabra clave extends antecediendo el nombre de la
superclase.
Se puede agregar nuevos campos y mtodos a la subclase para poder trabajar sobre los datos y
los comportamientos de la superclase.
Si un nombre de mtodo es repetido dentro de la subclase, y adems tiene el mismo prototipo
(mismo nmero de parmetros y mismo tipo de datos) que el presente en la superclase, el
mtodo de la subclase anula el de la superclase, por lo tanto lo reemplaza.
Cuando un campo o mtodo de la superclase es llamado desde la subclase, el nombre es
antecedido por la palabra clave super para hacer saber a Processing que dicho campo o
mtodo es parte de la superclase.
El siguiente ejemplo refleja estos nuevos trminos y conceptos:

Herencia
Ejemplo (Giro: superclase)
class Giro {
float x, y, velocidad;
float angulo = 0.0;
Giro(float xpos, float ypos, float vel) {
x = xpos;
y = ypos;
velocidad = vel;
}
void actualizar() {
angulo += velocidad;
}
}

Herencia
Ejemplo (GiroLinea: subclase)
class GiroLinea extends Giro {
GiroLinea(float x, float y, float v) {
super(x, y, v);
}
void mostrar() {
strokeWeight(1);
stroke(0);
pushMatrix();
translate(x, y);
angulo += velocidad;
rotate(angulo);
line(0, 0, 100, 0);
popMatrix();
}
}

Herencia
Ejemplo (GiroCirculos: subclase)
class GiroCirculos extends Giro {
float dimen;
GiroCirculos(float x, float y, float v, float d) {
super(x, y, v);
dimen = d;
}
void mostrar() {
noStroke();
pushMatrix();
translate(x, y);
angulo += velocidad;
rotate(angulo);
ellipse(-dimen/2, 0, dimen, dimen);
ellipse(dimen/2, 0, dimen, dimen);
popMatrix();
}
}

Herencia
Ejemplo (animacion: main)
GiroCirculos circulos;
GiroLinea linea;
void setup() {
size(100, 100);
smooth();
linea = new GiroLinea(width/2, height/2, 0.01);
circulos = new GiroCirculos(width/2, height/2, -0.02, 33.0);
}
void draw() {
background(204);
linea.actualizar();
linea.mostrar();
circulos.actualizar();
circulos.mostrar();
}

Lectura recomendada
Captulo Structure 5: Objects II (pag. 453).

Parte 20
ArrayList

ArrayList
La clase Java ArrayList permite implementar arrays de tamao flexible, donde es
posible agregar o remover elementos del principio, mitad o final del array.
El uso de un ArrayList conceptualmente es similar al de un array estandar, pero lo
que difiere es la sintxis.
El siguiente ejemplo muestra el uso de ArrayList para crear una aplicacin que
genera un emisor de partculas.
Cada vez que presionamos el botn del mouse, la aplicacin genera una partcula en
cada fotograma mientras dure la presin del mouse.

ArrayList
Ejemplo (ArrayList: main)
//
//
//
//

Learning Processing
Daniel Shiffman
http://www.learningprocessing.com
Ejemplo 23-2: Sistema de partculas simple con ArrayList

ArrayList particulas;
void setup() {
size(200,200);
particulas = new ArrayList();
smooth();
}
void draw() {
// Cuando el botn del mouse es presionado, se agrega un nuevo
// objeto Particula al ArrayList en cada ciclo del draw().
if (mousePressed) {
particulas.add(new Particula());
}
background(255);
// Iteracin a travs del ArrayList y obtiene cada partcula.
// ArrayList mantiene un seguimiento del nmero total de partculas.
for (int i = 0; i < particulas.size(); i++ ) {
Particula p = (Particula) particulas.get(i);
p.ejecutar();
p.gravedad();
p.mostrar();
}
// Si ArrayList contiene ms de 100 elementos, eliminamos
// el primer elemento usando el mtodo remove().
if (particulas.size() > 100) {
particulas.remove(0);
}
}

ArrayList
Ejemplo (Particula: clase)
// Learning Processing
// Daniel Shiffman
// http://www.learningprocessing.com
// Ejemplo 23-2: Sistema de partculas simple con ArrayList
// Una clase de Partcula simple
class Particula {
float
float
float
float

x;
y;
xVelocidad;
yVelocidad;

Particula() {
x = mouseX;
y = mouseY;
xVelocidad = random(-1,1);
yVelocidad = random(-2,0);
}
void ejecutar() {
x = x + xVelocidad;
y = y + yVelocidad;
}
void gravedad() {
yVelocidad += 0.1;
}
void mostrar() {
stroke(0);
fill(0,75);
ellipse(x,y,10,10);
}
}

Lectura recomendada
Captulo 23 Java (pag. 423).
Shiffman, D. Learning Processing - A Beginners Guide to
Programming Images, Animation, and Interaction, Morgan Kaufman,
2008.

Ej 17

EJ17: Crear una superficie sensible a datos de entrada (mouse y/o teclado)
cuya programacin haga uso de las tcnicas, procedimientos y estructuras
aprendidas durante el curso.

Comentar todas las instrucciones.

Trabajo Prctico Final

TPFinal: Crear un sistema generativo de imagen (processing) y sonido


(pure data), en el cual se establezcan relaciones de influencia audiovisual
en una o en dos vas a travs de datos enviados entre s mediante el
formato de contenido Open Sound Control.

Comentar todas las instrucciones.

FIN

You might also like