La función vertex() nos permite dibujar líneas rectas, cuando queremos dibujar curvas utilizamos dos funciones curveVertex() y bezierVertex().
Estas funciones pueden correr entre beginShape() y endShape() solo si beginShape() no tiene parámetros.
La función curveVertex() es usada para definir una serie de puntos que se conectan con una curva. Dos parámetros definen las coordenadas X y las coordenadas Y.
curveVertex(x, y)
El primer y último curveVertex() dentro de un beginShape() y endShape() actúan como puntos de control, definen la curvatura para el principio y el final de la línea.
La curvatura para cada segmento es calculada para cada par de puntos que son considerados antes y después. Por lo tanto, debe haber al menos cuatro curveVertex() dentro de un beginShape() y endShape() para dibujar un segmento.
Cada bezierVertex() define la posición de dos puntos de control y un punto de ancla de una curva Bezier:
bezierVertex(cx1, cy1, cx2, cx2, x, y)
El primer tiempo bezierVertex() es usado dentro de beginShape(), debe ser precedido de vertex() para establecer el primer punto de anclaje. La línea es dibujada entre el punto definido por vertex() y el punto definido por las coordenadas x e y de bezierVertex()
Las curvas continuas se pueden hacer con bezierVertex(). Después del primer vertex() y bezierVertex(), cada sub-secuencia llama a la función continua de la forma conectando cada nuevo punto al punto anterior.
La función curveVertex() define coordenadas que son conectadas con formas curvas. El primero y el último son puntos de control que definen la forma de la curva en el final y en el principio.
Para crear un giro brusco, utiliza la misma posición para especificar el vértice y el siguiente punto de control. Para cerrar la forma, utiliza la misma posición para especificar el primer y último vértice.
Una buena técnica para trabajar la creación de formas complejas con beginShape() y endShape() es trabajar primero con Inkscape o Ilustrator.
Las coordenadas pueden ser leídas como números en este entorno y luego utilizadas en Processing.
También puedes importar imágenes en formato SVG. Otras bibliotecas admiten más formatos y mayor complejidad, puedes encontrar más información en la web de Processing.
Los ejemplos de este capítulo usan una doble barra inclinada (//) al final de algunas líneas para añadir comentarios a nuestros códigos.
Los comentarios son partes de un programa que son ignorados cuando el programa está corriendo.
Se suelen utilizar para escribir notas para ti mismo explicando qué está pasando. Si otros están leyendo tu código, los comentarios son especialmente importantes para ayudarles a entender todo el proceso.
Los comentarios son especialmente útiles cuando estamos programando, ya que nos permite elegir diferentes opciones.
Al poner al comienzo de la línea las dos barras invertidas, desactivas la función. O puedes borrar rápidamente las dos barras y volver a activar la función.
Si quieres puede “comentar” bloques enteros de código:
/* Esto también es un comentario */
/* Podemos
comentar
varias
líneas
*/
Con esta entrada terminamos el capítulo 3. Este capítulo solo sirve para que nos familiaricemos con las herramientas básicas de dibujo y comencemos a perder el miedo a ir introduciendo líneas de código en nuestro editor de texto.
Si trabajar con Ilustrator o Photoshop, debes pensar que tener que escribir tanto código para crear líneas, ellipses o rectángulos es poco intuitivo, pero el potencial de Processing aparece cuando mezclamos las herramientas primitivas de dibujo con los conceptos básicos de programación.
Podrás dibujar 1000 ellipses en tres líneas de código, y eso supone mucho ahorro de tiempo, esfuerzo y otra forma de enfocar tus procesos.
Realmente, es a partir del capítulo 4, es cuando vamos a introducir conceptos que tienen más que ver con la programación. Veremos qué son las variables, aprenderemos sobre los bucles for, operaciones aritméticas, etc. Comenzarás a entender el potencial que tiene Processing para incorporarlo en tu proceso creativo.
Esta función es nueva en Processing 3.0. Se abre una ventana de reproducción con el tamaño completo de la pantalla del ordenador. Esta función debe ser la primera línea de código en setup().
fullScreen()
El primer parámetro define el renderizador que deseas usar y el segundo parámetro define ya sea una pantalla individual o para abrir una pantalla completa a través de todas las pantallas conectadas si hay más de una.
size() y fullScreen() no pueden ser utilizados juntos en el mismo programa, simplemente selecciona uno.
Antes de Processing 3.0 un programa a pantalla completa era definido con size(displayWidth, displayHeight).
void draw(){ rect(x, height*0.2, 1, height*0.6); x = x + 2; }
Ejemplo 02
/* Si tienes más de una pantalla instalada en tu ordenador, puedes definir en cual de ellas correrá tu programa a pantalla completa definiendo el parámetro en fullScreen()*/
Podemos utilizar varias analogías para describir y explicar qué es una variable. Podemos decir que una variable es como una caja, donde puedes depositar algo y recuperarlo cuando lo vuelvas a necesitar y así podemos seguir intentando poner ejemplos, pero no lo vamos a hacer, ya que no sé si realmente necesitamos utilizar una analogía ya que el concepto es en sí bastante simple.
Aquí está mi propuesta. El equipo tiene memoria. ¿Por qué lo llamamos memoria? Debido a que es lo que usa la computadora para recordar las cosas que necesita.
Técnicamente hablando, una variable es un puntero llamando a una ubicación en la memoria del ordenador (“Dirección de memoria”), donde se almacenan los datos. Dado que los ordenadores sólo procesan la información de una en una, una variable permite a un programador guardar información de un punto en el programa y referirnos de nuevo a él en un momento posterior.
Para un programador de Processing, esto es increíblemente útil; las variables pueden realizar un seguimiento de la información relacionada con las formas, el color, el tamaño, la ubicación. Las variables son exactamente lo que necesitas para cambiar un triángulo azul a púrpura, que un círculo aparezca volando a través de la pantalla y reducir el tamaño de un rectángulo hasta hacerlo desaparecer.
De todas las analogías disponibles, tiendo a preferir el enfoque de pedazo de papel cuadriculado.
Imagínate que la memoria de la computadora es una hoja de papel cuadriculado y cada cuadrado tiene una dirección.
Ya hemos aprendido a hacerlo con píxeles, con números de fila y columna- ¿No sería bueno si pudiéramos nombrar a cada cuadradito? Con las variables podemos hacerlo.
Vamos a nombrar un “score” y a darle un valor de 100. De manera que cada vez que queramos usar “score” no tenemos que recordar el valor de 100. Se encuentra allí en la memoria y la podemos llamar por su nombre.
El poder de una variable no se limita a descansar con la capacidad de recordar un valor. El punto central de una variable es que esos valores varían, y se presentan situaciones más interesantes cuando alteramos periódicamente ese valor.
Consideremos un juego de cartas entre Juan y Ana. Para hacer un seguimiento de la puntuación, Juan lleva la cuenta con lápiz y papel, escribe dos columnas con: Puntuación de Ana y Puntuación de Juan. Cuando comienza el juego una cuenta con las puntuaciones de cada jugador comienza a correr debajo de cada columna.
Si imaginamos este concepto como un juego virtual programado en un ordenador, de repente vamos a entender como emerge el concepto de una variable que varía según aparece. El pedazo de papel es la memoria del ordenador y en ese papel, la información está escrita: “Puntuación de Juan y Puntuación de Ana” son las variables en la memoria donde se almacenan los puntos totales de cada jugador y que cambian con el tiempo.
En nuestro ejemplo de juego de cartas, la variable tiene dos elementos, un nombre (por ejemplo “Puntuación de Juan”) y un valor (por ejemplo, 101). En Processing, las variables pueden contener diferentes tipos de valores y se nos requiere que especifiquemos y definamos el tipo de valor antes de que podamos usar una variable dada.
Una variable almacena un valor en memoria para que pueda ser utilizado más tarde en un programa. La variable puede ser utilizada varias veces en un solo programa, y el valor cambia fácilmente mientras el programa se está ejecutando.
La razón principal por la que usamos variables es evitar repetirnos en el código. Si estás escribiendo el número más de una vez, considera realizarlo a través de una variable para que el código sea más general y más fácil de actualizar.
___________________________________________________ Código 4.1: Reutilizar los mismos valores.
Por ejemplo, puedes utilizar el mismo valor para la coordenada Y, y para el diámetro de las ellipses.
Código 4.1
/
size(480, 120);
int y = 60;
int d = 80;
ellipse(75, y, d, d);
ellipse(175, y, d, d);
ellipse(275, y, d, d);
Sin las variables, tendríamos que cambiar la coordenada y tres veces y el diámetro en seis ocasiones. Si observamos ambos códigos, vemos que las últimas líneas son exactas y que solo se han modificado los valores de las variables "y" y "d". Las variables te permiten separar las líneas de código que cambian de la líneas que no lo hacen, lo que hace los programas más fáciles de modificar. Por ejemplo, si coloca las variables que controlan colores y tamaños de formas en un solo lugar, entonces puedes explorar rápidamente diferentes opciones visuales, centrándose en solo unas líneas de código.
Las variables pueden contener valores primitivos o referencias a objetos y arras. Por ahora, sólo vamos a preocuparnos por valores primitivos.
Los valores primitivos son los componentes básicos de datos en el ordenador y por lo general implican una pieza singular de información, como un número o un carácter.
Las variables primero se declaran indicando el tipo, seguido por el nombre. Los nombres de las variables deben ser una solo palabra (sin espacios) y debe comenzar con una letra (puede incluir números, pero no pueden comenzar por un número). Tampoco puede incluir ninguna puntuación o caracteres especiales con la excepción del guión bajo “_”.
Un tipo es el tipo de datos almacenados en esa variable. Este podría ser un número entero, un número decimal, un caracter, etc.
Estos son los tipos de datos más habituales:
Números enteros: tales como 0, 1, 2, 3, -1, -2, y así sucesivamente. Se almacenan como enteros y la palabra clave para los números enteros es “int” (Integer).
Números decimales: como 3.14159, 2.5 y -9.95. Normalmente se almacenan como “valores de coma flotante” y la palabra clave para el tipo decimal es “float”. Los números decimales a menudo son usados para aproximarnos a lo analógico o valores continuos ya que tienen una resolución decimal.
booleanos: solo pueden contener dos valores: true (verdadero) o false (falso). El nombre boolean se refiere al matemático George Boole (1815). Inventor del álgebra Booleana. Los fundamentos de cómo trabajan los ordenadores.
Caracteres: como ‘a’, ‘b’, ‘c’, ‘d’, y así sucesivamente. Se almacenan en variables de tipo “char” y se declaran como una letra entre comillas simples, es decir ‘a’. Son útiles para determinar qué tecla se está pulsando y para el uso de cadenas de texto.
Todos los tipos primitivos
boolean: true o false.
char: ‘a’, ‘b’, ‘c’, etc.
byte: un número pequeño, -128 a 127
short: un numero grande, -32768 a 32767
int: un numero muy grande -2147483648 a 2147483647
long: un número realmente enorme.
float: un decimal, como 3.141559
double: un número decimal con una cantidad enorme de decimales (solo necesario para programadores avanzados que requieren alta precisión matemáticas.
Tipos de datos
boolean | 1 bit | verdadero o falso byte | 8 bit | -128 a 127 char | 16 bit | 0 a 65535 int | 32 bit | -2.147.483.648 a 2.147.483.647 float | 32 bit | 3.40282347E + 38 a -3.40282347E + 38 color | 32 bit | 16.777.216 colores
NO OLVIDES
Las variables deben tener un tipo ¿Por qué? Es la manera de decir al ordenador cuanta memoria debe asignarse.
Las variables deben tener un nombre.
Una vez se declara una variable, podemos asignarle un valor definiéndola como igual a algo. En la mayoría de los casos, si nos olvidamos de inicializar una variable, processing le dará un valor predeterminado, tal como 0 para los números enteros, 0.0 a float, y así sucesivamente. Sin embargo, es bueno tener el habito de inicializar las variables para evitar confusiones.
int count;
count = 50;
Para ser más concisos, podemos combinar las declaraciones en una sola línea.
int count = 50;
Más de una variable puede ser declarada en una sola linea y los valores asignados separadamente:
float x, y, z;
x = -3.9;
y = 10.1;
z = 124.23;
int x; // Declara una variable “x” de tipo entero
float y; // Declara una variable “y” de tipo decimal
boolean b; // Declara una variable “b” de tipo booleano
x = 50; // Asigna el valor 50 a “x”
y = 12.6; // Asigna el valor 12.6 a “y”
b = true; // Asigna el valor true a “b”
Esto mismo lo podríamos haber escrito en tres líneas en lugar de seis.
int x = 50;
float y = 12.6;
boolean b = true;
Cuando se declara una variable, es necesario indicar el tipo de datos antes de su nombre; pero una vez declarada, el tipo de datos no se puede cambiar o actualizar. Si se vuelve a intentar crear una variable con el mismo nombre, especificando el mismo tipo de datos. Processing mostrará un mensaje de error.
int x = 69; // Asignar 69 a “x”
x = 70; // Asignar 70 a “x”
int x = 71; // ¡ERROR! El tipo de dato para “x” está duplicado
El símbolo “=” se llama operador de asignación. Se asigna el valor de la parte derecha del símbolo “=” a la parte izquierda. los valores pueden ser asignados solo a las variables. Intentar asignar una constante a otra constante produce un error.
// ¡ERROR! El lado izquierdo de una asignación tiene que ser una variable
5 = 12;
Cuando se trabaja con variables de diferentes tipos en el mismo programa, ten cuidado de no mezclar los “tipos de datos” de manera que pueda provocar un error. Por ejemplo no puedes asignar un número decimal a una variable “int”.
// ¡ERROR! No es posible definir un decimal dentro de un int
int x = 24.8;
float f = 12.5;
// ¡ERROR! No es posible definir un decimal dentro de un int
int y = f;
Las variables deben tener nombres que describan su contenido. Esto hace que los programas sean más fáciles de leer y puede reducir la necesidad de comentar el código. Es responsabilidad del programador las decisiones de cómo va a nombrar a las variables.
Por ejemplo, una variable que almacena la temperatura de una habitación podría llamarse lógicamente de la siguiente manera:
t
temp
temperature
roomTemp
roomTemperature
Las variables como “t” no son muy recomendables, aunque es minimalista, es demasiado ciática. Sin embargo, “roomTemperature” puede hacer el código demasiado tedioso de leer y escribir. Si estuviésemos escribiendo un programa, nuestra referencia sería la utilización del nombre “roomTemp”, porque es a las vez conciso y descriptivo. El nombre “temp” también podría funcionar, pero como es usado en ocasiones como una abreviación para “temporary”, podría no ser la mejor elección.
Convenciones
Hay una serie de convenciones que hacen más fácil cuando otras personas lean tus programas. Los nombres de las variables comienzan en minúsculas, y si hay varias palabras en el nombre, la primera letra de cada palabra adicional deben ser en mayúsculas.
roomTemp
Reglas absolutas
Los nombres de las variables no pueden comenzar por un número. (Aunque pueden contener números).
Los nombres de las variables deben ser una sola palabra. Esto quiere decir que no pueden contener espacios.
Los nombres de las variables no pueden incluir ninguna puntuación o caracteres especiales con la excepción del guión bajo “_”.
Las variables no deben tener los mismos nombres que los elementos del lenguaje Processing. (Referencia Processing)
Aunque pueda parecer inicialmente más complicado tener que usar palabras en lugar de los números, las variables nos hacen la vida más fácil y más interesante.
Vamos a ver un ejemplo sencillo de un programa que dibuja tres eclipses en pantalla:
size(720, 400);
ellipse(160, 200, 100, 100);
ellipse(360, 200, 100, 100);
ellipse(560, 200, 100, 100);
Uno de los usos que tienen las variables es evitar repetirnos en el código. Podemos crear variables en cualquier parte de nuestro código, pero para evitar problemas, de momento, todas nuestras variables las crearemos en la parte superior de nuestro código. Creamos una variable de números enteros llamada “diametro” y le damos un valor de 150. Acto seguido usamos la variable como parámetro de ancho y alto de nuestras elipses.
int diametro = 150;
size(720, 400);
ellipse(160, 200, diametro, diametro);
ellipse(360, 200, diametro, diametro);
ellipse(560, 200, diametro, diametro);
De esta manera, modificando el valor de la variable diámetro, podemos modificar el diámetro de las tres elipses a la vez sin tener que modificar el parámetro en seis ocasiones.
int diametro = 150;
int circleY = 200;
size(720, 400);
ellipse(160, circleY, diametro, diametro);
ellipse(360, circleY, diametro, diametro);
ellipse(560, circleY, diametro, diametro);
La ejecución de este código, se logra el mismo resultado que en el primer ejemplo. Aparecen tres círculos en el centro de nuestra ventana de reproducción, pero a estas alturas de nuestro código, podemos realizar cambios en la representación de nuestras elipses, modificando la altura y el tamaño de las mismas con solo modificar dos parteros en lugar de nueve.
Vamos a incluir dos variables más. Si te fijas en el código, la elipse central tiene una posición en “x” de 360 px. La de la izquierda tiene una posición en “x” de 150 px, exactamente 200 px menos que la central. Y por último la elipse de la derecha, tiene una posición “x” de 560, que son 200 pieles más que la elipse central.
De esta manera, nuestras tres elipses se dibujarán teniendo como parámetros variables o cálculos con dichas variables. Para modificar su posición o dimensión, nos centraremos en modificar solo los valores de dichas variables sin volver a tocar os parámetros dentro de las funciones ellipse().
Veamos otro ejemplo:
void setup(){
size(800, 800);
}
void draw(){
background(255);
stroke(0);
fill(175);
ellipse(400, 400, 200, 200);
}
Aunque aun no hemos estudiado esta estructura, vemos que existen dos partes bien diferenciadas por un lado setup() y por otro draw(). Esto le indica a Processing que queremos que nuestro sketch sea interactivo. Ponemos aquí este programa para probar cómo nuestras variables pueden hacer que nuestras formas se muevan por la pantalla.
No hay una regla de oro de cuándo usar una variable. Sin embargo, si te encuentras en tu código un montón de números, revisa el código y cambia estos valores por variables.
Algunos programadores dicen que si parece un número tres o más veces, debe ser una variable. En lo personal, yo diría que si un número aparece una vez, utiliza un variable. Utiliza siempre variables.
int circleX = 100;
int circleY = 100;
void setup(){
size(800, 800);
}
void draw(){
background(255);
stroke(0);
fill(175);
ellipse(circleX, circleY, 400, 200, 200);
}
La ejecución de este código, logra el mismo resultado que el primer ejemplo: aparece un círculo en el centro de la pantalla. Sin embargo debemos recordar que una variable no es simplemente un marcador de posición para un valor constante. Lo llamamos variable, ya que varía. Para cambiar su valor, escribiremos una operación de asignación, que asigna un nuevo valor. Hasta ahora, cada línea de código que hemos escrito llamaba a una función. Las variables introducen operaciones de asignación a la mezcla. Esto es lo que parece (que se realiza de la misma forma que inicializar una variable, solamente que no se necesita declarar la variable.
Nombre de variable = expresión
x = 5;
x = a + b;
x = y – 10 * 20;
x = x * 5;
Un ejemplo común es la incrementación. En el código anterior, circleX comienza con un valor de 100. Si queremos incrementar circleX por uno, decimos que circleX es igual a sí mismo más uno.
En código esto equivale a “circleX = circleX + 1;”
Vamos a intentar añadir esto a nuestro programa. Comenzaremos dando el valor de 0 a circleX.
Example 4-3: Variando variables
int circleX = 0;
int circleY = 100;
void setup(){
size(800, 800);
}
void draw(){
background(255);
stroke(0);
fill(175);
ellipse(circleX, circleY, 400, 200, 200);
circleX = circleX + 1;
}
Si ejecutamos este código, podemos observar que el círculo se mueve de izquierda a derecha, esto es porque draw() se repite una y otra vez, a la vez que conserva el valor de circleX en la memoria. Aprenderemos más sobre setup() y draw() en el siguiente capítulo, así como las bases del movimiento en Processing en el capítulo dedicado a ello.
El lenguaje Processing ha incorporado variables para almacenar datos de uso cotidiano. La altura y la anchura de la ventana de visualización se almacenan en variables denominadas “width” y “height”. Si un programa no incluye size(), las variables de anchura y altura serán establecidas en 100. Prueba ejecutando los siguientes programas.
println(width +“, ”+height);
// Imprime 100, 100 en la consola.
size(300, 400);
println(width +“, ”+height);
// Imprime 300, 400 en la consola.
size(1280, 1024);
println(width +“, ”+height);
// Imprime 1280, 1024 en la consola.
Usar las variables “width” y “height” es muy útil cuando estamos escribiendo un programa para escalar a diferentes tamaños. Esta técnica permite que con un simple cambio de parámetro en size() se pueda modificar las dimensiones y proporciones de un programa, en lugar de tener que cambiar los valores a través de código.
Al trabajar con las variables “width” y “height” puedes crear programas basándote en las proporciones para definir posiciones y tamaños, y modificando un solo valor, modificar todos los elementos.
Las variables de Processing son necesarias como piezas de datos asociados con todos nuestros bocetos, (tales como el ancho de la ventana, la tecla que está siendo pulsada en el teclado, etc.). Al asignar nombres a nuestras propias variables, lo mejor es evitar los nombres de las variables del sistema, sin embargo, si se utiliza de manera inadvertida, la variable se convertirá en primaria y anulará la del sistema.
Aquí está una lista de variables de sistema de uso común (hay más que se pueden encontrar en la referencia de Processing).
width – ancho en pixeles de la ventana de reproducción.
height – alto en pixeles de la ventana de reproducción.
mouseX – posición en el eje X del ratón en nuestra ventana de reproducción.
mouseY – posición en el eje Y del ratón en nuestra ventana de reproducción.
pmouseX – posición en el eje X del ratón en el frame anterior.
pmouseY – posición en el eje Y del ratón en el frame anterior.
mousePressed – ¿Verdadero o falso? ¿Está presionando el ratón?
mouseButton – ¿Qué botón está presionando?
key – La tecla más reciente presionada en tu teclado.
keyCode – Código numérico por tecla presionada.
keyPressed – ¿Verdadero o falso? ¿Está presionando una tecla?
frameCount – Número de frames procesados.
frameRate – Frames procesados por segundo.
El siguiente ejemplo hace uso de algunas de estas variables; no vamos a utilizar todas, sin embargo, necesitaremos usarlas para realizar algunos conceptos más avanzados para hacer uso de muchas características.
Las matemáticas pueden ser un aspecto importante de la programación, pero no es necesario ser bueno en matemáticas para entender o disfrutar de la programación. Hay tantos estilos de programación, como personas que programan, y es vuestra decisión utilizar o ignorar las matemáticas. Las personas que disfrutan con las matemáticas suelen escribir programas para visualizar ecuaciones o deleitarse en la exploración de fenómenos como los fractales. Las personas que lucharon con las matemáticas en el colegio a veces encuentran que les gustan y lo entienden mejor cuando se aplica para formas y movimiento.
Este libro trata de aritmética, álgebra, trigonometría al servicio y la producción de formas y movimiento. Una sorprendente variedad de formas y movimiento sutiles se pueden crear con las matemáticas básicas, y una comprensión más matizada de estas técnicas puede dar más control sobre el software. Matemáticas más avanzadas, como el álgebra lineal y el cálculo se utilizan con frecuencia para imágenes y movimiento, pero queda fuera del alcance de este libro.
ARITMÉTICA
En programación, las propiedades visuales de una imagen en la pantalla se definen por los números, lo que significa que la imagen se puede controlar matemáticamente.
Por ejemplo, un rectángulo podría tener una posición horizontal de 50, una posición vertical de 30, una anchura y una altura de 80, y un valor de gris de 153. Si el valor de gris se almacena en una variable grayVal y 102 se añade a esta variable, el valor de gris se convertirá en 255 y aparecerá la forma blanca en pantalla. Esto se demuestra mejor usando un ejemplo:
int grayVal = 153;
fill(grayVal);
rect(10, 10, 55, 55);
grayVal = grayVal + 102;
fill(grayVal);
rect(35, 30, 55, 55);
Se evalúa la expresión a la derecha del símbolo “=” antes de que el valor se asigne a la variable de la izquierda. Por lo tanto, la sentencia a = 5 + 4 añade primero 5 y 4 para producir 9 y luego asigna el valor 9 a la variable a.
Dentro del dominio visual, suma, resta, multiplicación y división se pueden utilizar para controlar la posición de los elementos en pantalla o cambiar atributos como el tamaño o el valor de gris. El símbolo + se utiliza para sumar, el símbolo – para resta, el símbolo * para la multiplicación y el símbolo / para la división.
int a = 30;
line(a, 0, a, height);
a = a + 40;
strokeWeight(4);
line(a, 0, a, height);
________________________________
int a = 30;
int b = 40;
line(a, 0, a, height);
line(b, 0, b, height);
strokeWeight(4);
line(b-a, 0 b-a, height);
________________________________
int a = 8;
int b = 10;
line(a, 0, a, height);
line(b, 0, b, height);
strokeWeight(4);
line(a*b, 0, a*b, height);
________________________________
int a = 8;
int b = 10;
line(a, 0, a, height);
line(b, 0, b, height);
strokeWeight(4);
line(a/b, 0, a/b, height);
________________________________
int y = 20;
line (0, y, width, y);
y = y + 6; // Asignar 26 a y
line(0, y, width, y);
y = y + 6; // Asignar 32 a y
line(0, y, width, y);
y = y + 6; // Asignar 38 a y
line(0, y, width, y);
________________________________
float y = 20;
line(0, y, width, y);
y = y * 1.6 // Asignar 32.0 a y
line(0, y, width, y);
y = y * 1.6 // Asignar 51.2 a y
line(0, y, width, y);
y = y * 1.6 // Asignar 81.920006 a y
line(0, y, width, y);
________________________________
OPERADOR MÓDULO %
Los símbolos +, – *, / o = probablemente te sean familiares, pero % (módulo) es algo más exótico. El operador % calcula el resto cuando un número se divide por otro. El %, la notación en código para el modulo, devuelve el resto entero después de dividir el número a la izquierda del símbolo por el número de la derecha.
9%3 obtiene un resultado de 0, porque 9 dividido entre 3 es igual a 3, resto 0.
9%2 obtiene un resultado de 1, porque 9 dividido entre 2 es igual a 4, resto 1.
35%4 obtiene un resultado de 3, porque 35 dividido entre 4 es igual a 8, resto 3.
El operador maduro se utiliza a menudo para mantener los números dentro de un rango deseado. Por ejemplo, si una variable está aumentando continuamente (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, etc.), aplicando el operador módulo puede transformar esta secuencia. Un número creciente puede hacer un ciclo continuo entre 0 y 3 aplicando %4
Veremos muchos ejemplos con % durante el curso y los estudiaremos con más detenimiento.
Ya hemos comentado , que cuando se trabaja con operadores matemáticos y variables, es importante ser conscientes de los tipos de datos que se están usando en las variables.
La combinación de dos números enteros siempre resultará un entero (int). La combinación de dos números decimales, siempre resultará un número decimal, pero cuando un entero (int) y un decimal (float) operan, el resultado es un decimal.
println(4/3); // Prints “1”
println(4.0/3); // Prints “1.3333334”
println(4/3.0); // Prints “1.3333334”
println(4.0/3.0); // Prints “1.333334”
Los valores enteros pueden ser asignados a las variables decimales (float) o también conocidas como de punto flotante, pero no a la inversa. La asignación de un número decimal o una variable de números enteros hace que el número sea menos preciso, por lo que la elaboración requiere que se haga de forma explícita.
int a = 4/3; // Asigna 1 a a
int b = 3/4; // Asigna 0 a b
int c = 4.0/3; // ¡ERROR!
int d = 4.0/3.0; // ¡ERROR!
float e = 4.0/3; // Asigna 1.33333334 a e
float f = 4.0/3.0 // Asigna 1.3333334 a f
Los dos últimos resultados requieren explicación adicional. El resultado de dividir dos números enteros siempre será un número entero: dividir el número entero 4 entre 3 es igual a 1. El resultado se convierte en una variable de números decimales una vez que el cálculo ha terminado, por lo que 1 se convierte en 1.0 sólo una vez que se ha alcanzado el lado izquierdo del signo =. Si bien esto puede parecer confuso, puede ser útil para programas más avanzados.
float a = 4/3 // Asigna 1.0 a “a”
float b = 3/4; // Asigna 0.0 a “b”
Las reglas de cálculo de los valores int y float pueden volverse más oscuras cuando se utilizan variables en lugar de números reales. Es importante ser consciente de los tipos de datos de nuestras variables para evitar este problema.
int i = 4;
float f = 3.0;
int a = i/f; // ¡ERROR! Asigna un decimal a un entero.
float b = i/f; // Asigna 1.333334 a “b”
LIMITADORES DE NÚMEROS
Las funciones ceil(), floor(), round(), min(), max() se utilizan para realizar cálculos con números que los operadores aritméticos estándar no puede.
Estas funciones son diferentes a las que usamos para dibujar formas, tales como line() y ellipse(), debido a que devuelven valores. Esto significa que la función genera un número que se puede asignar a una variable.
la función ceil() calcula el número entero (int) más cercano que es mayor que o igual que el valor de su parámetro.
int w = ceil(2.0); // Asigna 2 a w
int x = ceil(2.1); // Asigna 3 a x
int y = ceil(2.5); // Asigna 3 a y
int z = ceil(2.9); // Asigna 3 a z
La función floor() calcula el número entero (int) más cercano que es menor que o igual que el valor de su parámetro:
int w = floor(2.0); // Asigna 2 a w
int x = floor(2.1); // Asigna 2 a x
int y = floor(2.5); // Asigna 2 a y
int z = floor(2.9); // Asigna 2 a z
La función round() calcula el valor entero (int) más cercano al valor de su parámetro. Valores que terminan con 0.5 ronda hasta el siguiente valor entero:
int w = round(2.0); // Asigna 2 a w
int x = round(2.1); // Asigna 2 a x
int y = round(2.5); // Asigna 3 a y
int z = round(2.9); // Asigna 3 a z
A pesar que ceil(), floor() y round() actúan sobre los números de cómo flotante (float), el resultado siempre es un número entero, porque esta es la forma en la que estas funciones son útiles. Para convertir un float, simplemente asigna el resultado a un variable float.
La función min() determina el valor más pequeño en una secuencia de números. La función max() determina el valor más grande de una secuencia de números. Ambas funciones pueden tener dos o tres parámetros:
int u = min(5,9); // Asigna “5” a “u”
int v = min(-4, -12, -9); // Asigna “-12” a “v”
float w = min(12.3, 230.24); // Asigna “12.3” a “w”
int x = max(5, 9); // Asigna “9” a “x”
int y = max(-4, -12, -9); // Asigna “-4” a “y”
float z = max(12.3, 230.24); // Asigna 230.24 a z
También es importante prestar atención al valor de las variables para evitar cometer errores aritméticos. Por ejemplo, dividir un número por cero produce el “infinito” en matemáticas, al go que en software provoca un error.
int a = 0;
int b = 12/a; // ¡ERROR! ArithmeticException: / by zero
Del mismo modo, dividir por un número extremadamente pequeño puede producir un enorme resultado. Esto puede ser confuso cuando usamos el dibujo de formas, ya que no serán visibles en la ventana de visualización.
float a = 0.0001;
float b = 12/a; // Asigna 1200000.0 a “b”
ORDEN DE LAS OPERACIONES, AGRUPACIÓN
El orden de la operaciones determinan qué operadores realizan sus cálculos antes que otros. Por ejemplo, la multiplicación siempre se evalúa antes que la suma con independencia de la secuencia de los elementos.
La expresión 3 + 4 * 5 es igual a 23. Porque 4 se multiplica primero por 5 para dar 20 y después se añade 3 para dar 23.
El orden de las operaciones especifica que la multiplicación siempre precede a la suma sin tener en cuenta el orden en el que aparezca en la expresión.
El orden de las operaciones para evaluar expresiones se puede cambiar añadiendo un paréntesis. Por ejemplo, si una operación de suma aparece entre paréntesis, se realiza antes que la multiplicación. De la expresión (3 + 4) * 5 se obtiene un resultado de 35, porque 3 se añade a 4 para dar 7, que luego se multiplica por 5 para obtener 35. Esto se expresa de forma más concisa en código.
x = 3 + 4 * 5; // Asigna 23 a “x”
y = (3 + 4) * 5; // Asigna 35 a “y”
En muchos casos, los paréntesis son necesarios para obligar a los elementos de una expresión a que sean evaluados antes que otros, pero a veces solo se utilizan para aclarar el orden de las operaciones. Las siguientes líneas de código evalúan el mismo resultado porque la multiplicación siempre ocurre antes de la adición, pero es posible encontrar la segunda línea más clara.
x = 10 * 20 + 5; // Asigna 205 a “x”
y = (10 * 20) + 5; // Asigna 205 a “y”
La siguiente tabla muestra la prioridad de los operadores introducidos hasta el momento. Los signos en la parte superior preceden a los de la parte inferior.
Multiplicativo * / %
Aditivo + –
Asignación =
SHORTCUTS
Hay muchas expresiones repetitivas en programación, por lo que los accesos directos o atajos se utilizan para hacer nuestros programas más concisos. El operador incremento ++ suma el valor 1 a una variable y el operador decremento — resta 1 al valor.
int x = 1;
println(x); // Imprime “1” en la consola
x++; // Equivale a x = x + 1;
pinrtln(x); // Imprime “2” en la consola
_______________________________
int y= 1;
println(y); // Imprime “1” en la consola
y–; // Equivale a y = y – 1;
printnl(y); // Imprime “0” en la consola
El valor se incrementa o decrementa después se evalúa la expresión. A menudo, esto crea confusión y se muestra en el siguiente ejemplo:
int x = 1;
println(x++); // Imprime “1” en la consola
println(x); /7 Imprime “2” en la consola
Para actualizar el valor antes de que se evalúe la expresión, coloca el operador delante de la variable.
int x = 1;
println(++x);
println(x);
El operador suma asignación += combina la suma y la asignación. El operador de asignación de resta – = combina con la asignación de resta:
int x = 1;
println(x);
x += 5;
println(x);
_____________________________
int y = 1;
println(y);
y -= 5;
println(y);
El operador de multiplicación de asignación *= combina con la multiplicación de asignación. El operador de asignación de división /= combina con la asignación:
int x = 4;
println(x); // Imprime “4” en la consola
x * 2; // Equivale a x = x * 2
println(x); // Imprime “8” en la consola
______________________________
int y = 4;
println(y); // Imprime “4” en la consola
y /= 2; // Equivale a y = y / 2
println(y);
El operador de negación – cambia el signo del valor a su derecha. Se puede utilizar en lugar de la multiplicación de un valor por -1.
¿Qué es verdad? Es fácil responder a esta difícil pregunta filosófica en el contexto de la programación debido a que las nociones lógicas de verdadero y falso están bien definidas.
Los elementos de código llamados expresiones relacionales se evalúan como verdadero o falso. una expresión relacional se compone de dos valores que se comparan con un operador relacional. En Processing, dos valores se pueden comparar con los operadores relacionales de la siguiente manera:
la iteración es el proceso generativo de repetir un conjunto de reglas o pasos una y otra vez. Es un concepto fundamental de la programación de computadoras y que pronto descubrirás que hace la vida de los programadores bastante más agradables. Vamos a empezar.
Por el momento, vamos a ver un ejemplo:
size(500, 500);
line(50, 50, 100, 450);
line(75, 50, 125, 450);
line(100, 50, 150, 450);
line(125, 50, 175, 450);
line(150, 50, 200, 450);
line(175, 50, 225, 450);
line(200, 50, 250, 450);
line(225, 50, 275, 450);
line(250, 50, 300, 450);
line(275, 50, 325, 450);
line(300, 50, 350, 450);
line(325, 50, 375, 450);
line(350, 50, 400, 450);
line(375, 50, 425, 450);
line(400, 50, 450, 450);
En el ejemplo anterior, las líneas se han dibujado de x = 50 pixeles hasta x = 150 pixeles, con una línea cada 10 pixeles.
El código logra esto, sin embargo, aplicando las variables que ya hemos aprendido, podemos hacer algunas mejoras sustanciales y eliminar los valores codificados.
En primer lugar, hemos creado las variables para cada parámetro de nuestro sistema: x, y, spacing, len. ten en cuenta que para cada tramo dibujado, solo cambia el valor de x. Todas las demás variables permanecen igual (pero podrían cambiar si queremos).
Ejemplo 4.6-01
size(200, 200);
background(0);
stroke(255);
int y = 80;
int x = 50;
int spacing = 10;
int len = 20;
line(x, y, x, y + len);
x = x + spacing;
line(x, y, x, y + len);
x = x + spacing;
line(x, y, x, y + len);
x = x + spacing;
line(x, y, x, y + len);
x = x + spacing;
line(x, y, x, y + len);
x = x + spacing;
line(x, y, x, y + len);
x = x + spacing;
line(x, y, x, y + len);
x = x + spacing;
line(x, y, x, y + len);
x = x + spacing;
line(x, y, x, y + len);
x = x + spacing;
line(x, y, x, y + len);
x = x + spacing;
No está mal, supongo. Curiosamente, aunque esto es técnicamente más eficiente (que podría ajusta la variable de separación, por ejemplo, cambiando una sola línea de código). Hemos dado un paso hacia atrás, después de haber producido el doble de código. ¿Y si quisiéramos dibujar 100 líneas? Por cada línea, necesitamos dos líneas de código. En 200 líneas de código para 100 líneas. Para evitar este problema, nos gustaría ser capaces de decir:
Dibuja una línea cien veces
¡Aha! ¡Una sola línea de código!
Obviamente, no somos los primeros programadores para llegar a este dilema y que es fácil de resolver con el uso común de control de estructura de bucle. Una estructura de bucle es similar en sintaxis para un condicional. (Lo veremos en el siguiente capítulo)
Sin embargo, en vez de pedir un sí o un no para determinar si un bloque de código debe ser ejecutado una vez, nuestro código le pedirá un sí o un no para determinar cuántas veces se debe repetir el bloque de código, esto se conoce como iteración.
BUCLE WHILE
Existen tres tipos de bucles:
while
do-while
for
Al igual que con las estructuras condicionales (if/else), un bucle while emplea una condición de prueba boleada. Si la prueba da como resultado true (verdadero), las instrucciones que se incluyen entre las llaves se ejecuta; si es falsa, seguimos a la siguiente línea de código.
La diferencia aquí es que las instrucciones dentro del bloque while seguirán siendo ejecutadas una y otra vez hasta que la condición de prueba se convierte en falsa.
while (BOOLEAN TEST)
A. DO THIS
B. DO THIS
REPEAT
size(200, 200);
int x = 50;
int y = 80;
int spacing = 10;
int len = 20;
int endLegs = 150;
stroke(0);
while(x <= endLegs){
line(x, y, x, y + len);
x = x + spacing;
}
En lugar de escribir “line(x, y, x, y + len);” tantas veces como lo hicimos al principio, ahora lo escribimos solo una vez dentro del bucle while, diciendo “siempre que x es menos que 150, dibuja una línea en x, a la vez aumenta el valor de x. De esta manera 21 líneas de código se reducen a 4”. Además podemos cambiar la variable de espaciado para generar más líneas.
int spacing = 4;
while(x <= endLegs){
line(x, y, x, y + len);
x = x + spacing;
}
Veamos un ejemplo más utilizando rectángulos en lugar de líneas. Hay que hacer tres preguntas claves.
1. ¿Cuál es la condición inicial para el bucle? Aquí, desde el primer rectángulo es en “y”localización 10, queremos comenzar con nuestro bucle con y = 10.
int y = 10;
2. ¿Cuándo debe parar tu bucle? Dado que queremos visualizar rectángulos hasta la parte inferior de la ventana, el bucle debe parar cuando y es mayor que height. En otras palabras, queremos que el bucle se mantenga el mayor tiempo posible, siempre que y sea menor que la altura.
while(y < 200){
//loop!
}
3. ¿Cuál es su funcionamiento de bucle? En este caso, cada paso por el bucle, queremos dibujar un rectángulo nuevo debajo de la anterior. Podemos lograr esto llamando a la función rect() es incrementando y en un 20px.
rect(100, y, 100, 10);
y = y + 20;
Poniendo todo junto:
int y = 10;
while(y < height){
rect(100, y, 100, 10);
y = y + 20;
}
EXIT Conditions
Hay que tener cuidado con los bucles infinitos.
WHILE (ALWAYS TRUE)
DO THIS FOREVER AND EVER…
Si examinamos el ejemplo 6-3 podemos ver que tan pronto como x es mayor que 150, el bucle se detiene. Y esto es debido a los incrementos de x por spacing, que siempre es un número positivo. No es un accidente, cada vez que nos embarcamos en la programación con una estructura de bucle, hay que asegurarse de que el tiempo se cumple la condición de salida de bucle!.
Processing no señalará un error, repetirá el bucle de manera infinita.