Programar es un tipo de escritura. Como todos los tipos de escritura, programar tiene reglas específicas. Para comparar, mencionaremos rápidamente algunas de las reglas del español a las que probablemente no les has puesto atención porque te son naturales.
5 | 6 |Algunas de las reglas más invisibles son escribir de izquierda a derecha y poner un espacio entre cada palabra. Otras reglas más evidentes son las convenciones de ortografía, la mayúscula en los nombres de personas y lugares y el uso de puntuación al final de las frases. Si rompes una o más de estas reglas al escribir un correo a un amigo, el mensaje igualmente se puede entender. Por ejemplo, "hola ben. como estas oy?" se entiende casi tan bien como "Hola, Ben. ¿Cómo estás hoy?" Sin embargo, la flexibilidad de las reglas de escritura no se transfiere a la programación. Como estás escribiendo para comunicarte con un computador, en lugar de otra persona, necesitas ser más preciso y cuidadoso. Un carácter fuera de lugar es a menudo la diferencia entre un programa que funciona y otro que no.
7 | 8 |Tu navegador trata de indicarte dónde has cometido errores y de adivinar cuál es el error. Cuando ejecutas tu programa, si hay problemas gramaticales (sintaxis) en tu código (los llamamos bugs), la consola muestra un mensaje de error con un número de línea que indica dónde puede estar el error. El texto en la consola trata de ser de ayuda y sugiere el problema, pero a veces el mensaje es demasiado difícil de entender. Para un principiante, estos mensajes de error pueden ser frustrantes. Ten en cuenta que tu navegador está tratando de ayudar, pero tiene un conocimiento limitado sobre lo que tú estás tratando de lograr.
9 | 10 |Adicionalmente, tu navegador solamente puede encontrar un error a la vez. Si tu programa tiene muchos errores, necesitarás continuar ejecutando el programa y arreglando un error a la vez.
11 | 12 |Por favor lee y vuelve a leer las siguientes sugerencias detenidamente para ayudarte a escribir código limpio. Para un tutorial más profundo sobre correción de errores, revisa https://p5js.org/es/learn/debugging.html.
13 | 14 |Los programas están compuestos de muchas partes pequeñas, las que se agrupan para formar estructuras más grandes. En español tenemos un sistema similar: las palabras son agrupadas en frases, las que son combinadas para formar oraciones, las que luego son combinadas para crear párrafos. La misma idea existe en código, pero las pequeñas partes tienen nombres distintos y se comportan de forma diferente. Las funciones y los parámetros son dos partes importantes. Las funciones son los bloques básicos para construir un programa en p5.js. Los parámetros son los valores que definen cómo se comporta una función.
18 | 19 |Considera una función como background()
. Como el nombre lo sugiere ("background" significa "fondo"), se usa para definir el color del fondo del lienzo. La función tiene tres parámetros que definen el color. Estos números son los componentes rojo, verde y azul para definir el color. Por ejemplo, el código a continuación pinta azul el fondo:
22 | background(51, 102, 153);23 | 24 |
Revisa cuidadosamente esta linea de código. Los detalles clave son los paréntesis despues del nombre de la función que rodean a los números, y las comas entre cada número. Todas estas partes necesitan estar presentes para que el código se ejecute. Compara la línea de ejemplo anterior a estas dos versiones de la misma línea, pero con errores:
25 | 26 |27 | background 51, 102, 153; // ¡Error! Faltan los paréntesis 28 | background(51 102, 153); // ¡Error! Falta una coma29 | 30 |
También hay un punto y coma al final de cada línea. El punto y coma se usa como un punto. Señala que se acabó una instrucción, para que el computador pueda buscar el inicio de la siguiente. Si omites el punto y coma, tu navegador lo averiguará de todos modos, pero se recomienda por consistencia que uses punto y coma. Sin embargo, la siguiente línea no tendría problemas:
31 | 32 |33 | background(51, 102, 153)34 | 35 |
El computador no perdona ni la menor omisión o desviación de lo esperado. Si recuerdas estos consejos, cometerás menos errores. Pero si te equivocas al escribir, como nos ocurre a todos, no es un problema. Tu navegador te alertará sobre el problema, y cuando esté corregido, el programa se ejecutará correctamente.
36 |p5.js distingue entre letras mayúsculas y minúsculas y por lo tanto lee "Hola" como una palabra distinta de "hola". Si estás tratando de dibujar un rectángulo con la función rect()
y escribes Rect()
, el código no funcionará.
p5.js es flexible en cuanto a la cantidad de espacio usado para darle formato a tu código. A p5.js no le importa si escribes:
67 | 68 |69 | rect(50, 20, 30, 40);70 | 71 |
o:
72 | 73 |74 | rect (50,20,30,40);75 | 76 |
o:
77 | 78 |79 | rect ( 50,20, 80 | 30, 40) ;81 | 82 |
Sin embargo, es conveniente que tu código sea de fácil lectura. Esto se hace especialmente importante a medida que tu código aumenta en longitud. Un formato limpio hace que la estructura del código sea legible de inmediato, y un mal formato a menudo esconde los problemas. Toma el hábito de escribir código limpio. Existen muchas formas de formatear bien tu código, y la forma en que usas espacios es una preferencia personal.
83 |La consola es un panel en tu navegador que puede ser usado para ayudar a corregir errores en tu programa. Puedes escribir mensajes en la consola con la función print()
. Por ejemplo, el siguiente código imprime un mensaje y a continuación imprime la hora actual:
91 | print("Hola p5.js."); 92 | print("La hora es " + hour() + ":" + minute());93 | 94 |
La consola es esencial para ver lo que está pasando dentro de tus programas mientras se ejecutan. Se usa para imprimir el valor de las variables y así comprobarlas, para confirmar si están ocurriendo eventos, y para determinar si un programa está teniendo un problema.
95 |Te recomendamos escribir unas pocas líneas de código a la vez y ejecutar el código frecuentemente para asegurarte que no se acumulen errores sin que te des cuenta. Todo programa ambicioso es escrito línea a línea. Divide tu proyecto en subproyectos más simples y hazlos uno a la vez para que puedas lograr muchas pequeñas victorias, en vez de un grupo de errores. Si cometes un error, trata de aislar el área del código donde crees que está el problema. Trata de imaginar que la corrección de errores es como resolver un misterio o un rompecabezas. Si te quedas atascado o te frustras, toma una pausa para refrescar tu cabeza o pídele ayuda a otra persona. A veces, la respuesta está delante tuyo, pero necesitas una segunda opinión para lograr encontrarla.
101 |Cuando se realizan cálculos matemáticos en un programa, cada operación ocurre de acuerdo a un orden predeterminado. Este orden de operaciones asegura que el código se comporte de la misma manera cada vez que se ejecute. Esto no es muy distinto que en aritmética o álgebra, no obstante en la programación existen operadores que son menos conocidos.
5 | 6 |En la siguiente tabla, los operadores de la sección superior son ejecutados antes que los de la sección inferior - por lo tanto, una operación dentro de paréntesis será ejecutada al principio y una asignación será ejecutada al final:
7 | 8 |Nombre | 12 |Símbolo | 13 |Ejemplos | 14 |
---|---|---|
19 | Paréntesis 20 | |
21 |
22 |
|
24 |
25 |
|
27 |
30 | Sufijo, Unario 31 | |
32 |
33 |
|
35 |
36 |
|
38 |
41 | Multiplicativo 42 | |
43 |
44 |
|
46 |
47 |
|
49 |
52 | Aditivo 53 | |
54 |
55 |
|
57 |
58 |
|
60 |
63 | Relacional 64 | |
65 |
66 |
|
68 |
69 |
|
71 |
74 | Igualdad 75 | |
76 |
77 |
|
79 |
80 |
|
82 |
85 | AND lógico 86 | |
87 |
88 |
|
90 |
91 |
|
93 |
96 | OR lógico 97 | |
98 |
99 |
|
101 |
102 |
|
104 |
107 | Asignación 108 | |
109 |
110 |
|
112 |
113 |
|
115 |
La regla del ámbito de variable se define simplemente como: una variable creada dentro de un bloque (código dentro de llaves: {
y }
) solamente existe dentro de ese bloque.
Esto significa que una variable creada dentro de setup()
solamente puede ser usada dentro del bloque setup()
, y de la misma forma, una variable declarada dentro de draw()
solamente puede ser usada dentro del bloque draw()
. La excepción a esta regla es una variable declarada fuera de setup()
y draw()
. Estas variables pueden ser usadas dentro de tanto setup()
como draw()
(o dentro de cualquier otra función que hayas creado). Piensa en el área fuera de setup()
y draw()
como un bloque de código implícito. Estas variables reciben el nombre de variables globales, porque pueden ser usadas en cualquier parte dentro del programa. A una variable que solamente podemos usar dentro de un único bloque la llamamos variable local. A continuación hay un par de ejemplos de código que explican con más detalles el concepto. Primer ejemplo:
9 | var i = 12; // Declara variable global i y asigna el valor 12 10 | 11 | function setup() { 12 | createCanvas(480, 320); 13 | var i = 24; // Declara variable local i y asigna el valor 24 14 | print(i); // Imprime 24 en la consola 15 | } 16 | 17 | function draw() { 18 | print(i); // Imprime 12 en la consola 19 | }20 | 21 |
Segundo ejemplo:
22 | 23 |24 | function setup() { 25 | createCanvas(480, 320); 26 | var i = 24; // Declara variable local i y asigna el valor 24 27 | } 28 | 29 | function draw() { 30 | print(i); // ERROR! La variable i es local a setup() 31 | }32 |
p5.js está inspirado y guiado por otro proyecto, que empezó hace alrededor de 15 años. En el año 2001, Casey Reas y Ben Fry empezaron a trabajar en una nueva plataforma para hacer más fácil la programación de gráficas interactivas; la nombraron Processing. Ellos estaban frustrados con lo difícil que era escribir este tipo de software con los lenguajes que normalmente usaban (C++ y Java) y fueron inspirados por lo simple que era escribir programas interesantes con los lenguajes de su niñez (Logo y BASIC). Su mayor influencia fue Design by Numbers (DBN), un lenguaje que ellos en ese tiempo estaban manteniendo y enseñando (y que fue creado por su tutor de investigación, John Maeda).
5 | 6 |Con Processing, Ben y Casey estaban buscando una mejor manera para probar sus ideas fácilmente y en código, en vez de solamente conversar sobre ellas o pasar demasiado tiempo programándolas en C++. Su otro objetivo fue construir un lenguaje para enseñar programación a estudiantes de diseño y de arte y ofrecerle a estudiantes más avanzados una manera más fácil de trabajar con gráficas. Esta combinación es una desviación positiva de la manera en que usualmente se enseña programación. Los nuevos usuarios comienzan concentrándose en gráficos e interacción en vez de estructuras de datos y resultados en forma de texto en la consola.
7 | 8 |A través de los años, Processing se ha transformado en una gran comunidad. Es usado en salas de clases a lo largo del mundo, en planes de estudios de artes, humanidades y ciencias de la computación y de forma profesional.
9 | 10 |Hace dos años, Ben y Casey me hicieron una pregunta: ¿cómo sería Processing si funcionara en la web? p5.js nace con el objetivo original de Processing, hacer que programar sea accesible para artistas, diseñadores, educadores y principiantes, y luego lo reinterpreta para la web actual usando JavaScript y HTML.
11 | 12 |El desarrollo de p5.js ha sido como reunir mundos distintos. Para facilitar la transición a la web de los usuarios de la comunidad existente de Processing, seguimos la sintaxis y las convenciones de Processing tanto como fue posible. Sin embargo, p5.js está construido en JavaScript, mientras que Processing está construido en un lenguaje llamado Java. Estos dos lenguajes tienen distintos patrones y funciones, así que en ocasiones nos tuvimos que alejar de la sintaxis ya familiar de Processing. También fue importante que p5.js pudiera ser integrado sin problemas a las existentes características, herramientas y estructuras de la web, para así atraer a usuarios familiarizados con la web, pero sin experiencia en programación creativa. Sintetizar todos estos factores fue un desafío, pero el objetivo de unir estas estructuras proporcionó un camino claro a seguir en el desarrollo de p5.js.
13 | 14 |Una primera versión beta fue lanzada en agosto del 2014. Desde ese entonces, ha sido usado e integrado a programas de estudios en todo el mundo. Existe un editor oficial de p5.js que está actualmente en desarrollo, y se está progresando en muchas nuevas características y bibliotecas.
15 | 16 |p5.js es un esfuerzo comunitario - cientos de personas han contribuido funciones esenciales, soluciones a errores, ejemplos, documentación, diseño, reflexiones y discusión. Pretendemos continuar la visión y el espíritu de la comunidad de Processing mientras la expandimos aún más en la web.
17 | 18 |Los capítulos de este libro están organizados de la siguiente manera:
22 | 23 |1/Hola: aprende sobre p5.js.
26 |2/Empezando a programar: crea tu primer programa en p5.js.
29 |3/Dibujar: define y dibuja figuras simples.
32 |4/Variables: almacena, modifica y reusa datos.
35 |5/Respuesta: controla e influye en programas con el ratón, el teclado y el tacto.
38 |6/Trasladar, rotar, escalar: transforma las coordenadas.
41 |7/Medios: carga y muestra medios, incluyendo imágenes y tipos de letras.
44 |8/Movimiento: mueve y coreografía figuras.
47 |9/Funciones: construye nuevos módulos de código.
50 |10/Objetos: crea módulos de código que combinan variables y funciones.
53 |11/Arreglos: simplifica el trabajo con listas de variables.
56 |12/Datos: carga y visualiza datos.
59 |13/Extensión: aprende sobre sonido y DOM.
62 |Este libro fue escrito para personas que quieren crear imágenes y programas interactivos simples con una introducción casual y concisa a la programación de computadores. Es para personas que quieren una ayuda para entender los miles de ejemplos de código en p5.js y los manuales de referencia disponibles en la web de forma gratuita y libre. Introducción a p5.js no es un libro de referencia sobre programación; como el título lo sugiere, te ayudará a empezar. Es útil para adolescentes, adultos, entusiastas y cualquier persona interesada.
70 | 71 |Este libro también es apropiado para personas con experiencia en programación que quieran aprender los conceptos básicos de gráficos computacionales interactivas. Introducción a p5.js contiene técnicas que pueden ser aplicadas en la creación de juegos, animaciones e interfaces.
72 |En este libro se usan las siguientes convenciones tipográficas:
78 | 79 |Indican nuevos términos, URLS, direcciones de email, nombres de archivos y extensiones de archivos.
83 |Ancho constante
Usado para listados de programas y dentro de párrafos para referirse a elementos de programas como nombres de variables o funciones, bases de datos, tipos de datos, variables de ambiente, declaraciones y palabras clave.
87 |Ancho constante y cursiva
Muestra texto que debería ser reemplazado por valores provistos por el usuario o por valores determinados por el contexto.
91 |Este tipo de párrafo indica una nota general.
96 |Este libro está aquí para ayudarte a que logres hacer tu trabajo. En general, puedes usar el código de este libro en tus programas y documentación. No necesitas contactarnos para pedir permiso a menos que estés reproduciendo una porción significativa del código. Por ejemplo, escribir un programa que usa múltiples trozos de código de este libro no requiere permiso. Sí requiere permiso la venta o distribución de ejemplos de libros Make:. Responder una pregunta citando este libro y citar códigos de ejemplo no requiere permiso. Sí requiere permiso incorporar una cantidad significativa de código de ejemplo de este libro en la documentación de tu producto.
103 | 104 |Apreciamos, pero no requerimos, atribución. Una atribución usualmente incluye el tÍtulo, autor, editorial e ISBN. Por ejemplo: “ Make: Getting Started with p5.js por Lauren McCarthy, Casey Reas y Ben Fry, Copyright 2015 Maker Media, Inc., 978-1-457-18677-6."
105 | 106 |Si sientes que tu uso de los ejemplos de código se aleja del uso justo o de los permisos dados aquí, siéntete libre de contactarnos en permissions@oreilly.com.
107 |Safari Books Online es una biblioteca digital on-demand que ofrece contenido experto en los formatos libro y video de los autores líderes del mundo en tecnología y negocios.
114 |Profesionales de la tecnología, desarrolladores de software, diseñadores web y profesionales de negocios y creativos usan Safari Books Online como su fuente principal de investigación, resolución de problemas, aprendizaje y entrenamiento certificado.
117 | 118 |Safari Books Online ofrece un rango de planes y precios para el sector empresarial, gubernamental, educacional, y para individuos.
119 | 120 |Los miembros tienen acceso a miles de libros, videos de entrenamiento y manuscritos prepublicados en una base de datos completamente buscable de editores como Maker Media, O’Reilly Media, Prentice Hall Professional, Addison-Wesley Professional, Microsoft Press, Sams, Que, Peachpit Press, Focal Press, Cisco Press, John Wiley & Sons, Syngress, Morgan Kaufmann, IBM Redbooks, Packt, Adobe Press, FT Press, Apress, Manning, New Riders, McGraw-Hill, Jones & Bartlett, Course Technology, y cientos más. Para más información sobre Safari Books Online, por favor visítanos en línea.
121 |Por favor dirige tus comentarios y preguntas sobre este libro a a la editorial:
127 | 128 |Make: une, inspira, informa y entretiene a una creciente comunidad de gente inventiva que se embarca en proyectos asombrosos en sus patios, sótanos y cocheras. Make: celebra tu derecho de modificar, hackear y torcer cualquier tecnología como quieras. La audiencia de Make: sigue siendo una cultura en expansión y una comunidad que cree en mejorarnos a nosotros mismos, a nuestro medio ambiente, a nuestro sistema educacional - al mundo entero. Esto es mucho más que una audiencia, es un movimiento mundial que Make: está liderando - lo llamamos el movimiento Maker.
137 | 138 |Para más información sobre Make:, visítanos en línea:
139 | 140 |Le agradecemos a Brian Jepson y a Anna Kaziunas France por su gran energía, apoyo y visión.
152 | 153 |No podemos imaginar este libro sin Getting Started with Arduino (Maker Media) de Massimo Banzi. El excelente libro de Massimo fue el prototipo.
154 | 155 |Un pequeño grupo de individuos ha, durante años, contribuido tiempo y energía esenciales a Processing. Dan Shiffman es nuestro compañero en la Fundación Processing, la organización 501(c)(3) que apoya al software Processing. La mayor parte del código principal de Processing 2.0 y Processing 3.0 proviene de las mentes brillantes de Andres Colubri y Manindra Moharana. Scott Murray, Jamie Kosoy y Jon Gacnik han construido una maravillosa infraestructura web para el proyecto. James Grady está haciendo un genial trabajo en la interfaz de usuario 3.0. Le agradecemos a Florian Jenett por sus años de trabajo en diversas áreas, incluyendo foros, sitio web y diseño. Elie Zananiri y Andreas Schlegel han creado la infraestructura para construir y documentar las bibliotecas contribuidas y han pasado innumerables horas curando las listas. Muchos otros han contribuido significativamente al proyecto, los datos precisos están disponibles en https://github.com/processing.
156 | 157 |Este libro surgió de la enseñanza con Processing en UCLA. Chandler McWilliams ha sido instrumental en definir estas clases. Casey le agradece a los estudiantes de pregrado en el Departamento de Design Media Arts en UCLA por su energía y entusiasmo. Sus ayudantes del curso han sido grandes colaboradores para definir cómo Processing es enseñado. Agradecimientos a Tatsuya Saito, John Houck, Tyler Adams, Aaron Siegel, Casey Alt, Andres Colubri, Michael Kontopoulos, David Elliot, Christo Allegra, Pete Hawkes y Lauren McCarthy.
158 | 159 |p5.js es desarrollado por una gran comunidad de contribuyentes a lo largo del mundo. Dan Shiffman, Jason Sigal, Sam Lavigne, K. Adam White, Chandler McWilliams, Evelyn Eastmond, los miembros del grupo de trabajo de p5 en ITP, los asistentes a la primera p5.js Contributor's Conference en el Frank-Ratchye STUDIO for Creative Inquiry de Carnegie Mellon University, y los estudiantes y mentores del Processing Google Summer of Code han sido instrumentales para hacer que p5.js sea lo que es hoy. Apoyo significativo para el proyecto ha sido provisto por la Processing Foundation, NYU ITP, RISD y Bocoup. Puedes ver la lista de lista completa de contribuyentes en https://github.com/processing/p5.js#contributors. Lauren también le agradece a Kyle McDonald por su perpetuo apoyo e inspiración.
160 | 161 |Este libro ha sido transformado por las artísticas ilustraciones de Taeyoon Choi. Fueron desarrolladas en parte a través de una residencia en el Frank-Ratchye STUDIO for Creative Inquiry en Carnegie Mellon University, con apoyo del programa Art Works del National Endowment for the Arts. Charlotte Stiles ayudó tremendamente con la edición de los ejemplos e imágenes de este libro.
162 | 163 |A través de la fundación del Aesthetics and Computation Group (1996–2002) en el MIT Media Lab, John Maeda hizo todo esto posible.
166 | 167 |p5.js sirve para escribir software que produce imágenes, animaciones e interacciones. La motivación es escribir una línea de código y que un círculo aparezca en la pantalla. Añade unas pocas líneas de código, y ahora el círculo sigue al ratón. Otra línea de código, y el círculo cambia de color cuando presionas el ratón. A esto lo llamamos bosquejar con código. Escribes una línea, luego añades otra, luego otra, y así. El resultado es un programa creado parte por parte.
5 | 6 |Los cursos de programación típicamente se enfocan primero en estructura y teoría. Cualquier aspecto visual - una interfaz, una animación - es considerado un postre que solo puede ser disfrutado después de que terminas de comer tus vegetales, el equivalente a varias semanas de estudiar algoritmos y métodos. A través de los años, hemos visto a muchos amigos tratar de tomar estos cursos, para luego abandonarlos después de la primera sesión o después de una muy larga y frustrante noche previa a la entrega de la primera tarea. Toda curiosidad inicial que tenían sobre cómo hacer que el computador trabaje para ellos es perdida porque no pueden vislumbrar un camino claro entre lo que tienen que aprender al principio y lo que quieren crear.
7 | 8 |p5.js ofrece una manera de programar a través de la creación de gráficas interactivas. Existen muchas maneras posibles de enseñar código, pero los estudiantes usualmente encuentran apoyo y motivación al tener una retroalimentación visual inmediata. p5.js provee esta retroalimentación, y su énfasis en imágenes, prototipado y comunidad es discutido en las siguientes páginas.
9 | 10 |Bosquejar es una forma de pensar; es juguetón y rápido. El objetivo básico es explorar muchas ideas en un corto periodo de tiempo. En nuestro propio trabajo, usualmente empezamos bosquejando en papel y luego trasladamos nuestros resultados a código. Las ideas para animación e interacción son usualmente bosquejadas como un guión gráfico con anotaciones. Después de hacer algunos bosquejos en software, las mejores ideas son seleccionadas y combinadas en prototipos (Figura 1-1). Es un proceso cíclico de hacer, probar y mejorar que va y viene entre papel y pantalla.
14 | 15 |Tal como un cinturón de herramientas para software, p5.js está compuesto de muchas herramientas que funcionan en conjunto y en diversas combinaciones. Como resultado, puede ser usado para exploraciones rápidas o para investigación en profundidad. Como un programa hecho con p5.js puede ser tan corto como unas pocas líneas de código o tan largo como miles de líneas, existe espacio para crecimiento y variación. Las bibliotecas de p5.js lo extienden a otros dominios incluyendo el trabajo con sonido y la inclusión de botones, barras deslizadoras, ingreso de datos y captura de cámara con HTML.
24 |Las personas han estado haciendo imágenes con computadores desde los años 1960s, y hay mucho que podemos aprender de esta historia. Por ejemplo, antes de que los computadores pudieran proyectar a pantallas CRT o LCD, se usaban grandes máquinas trazadoras (Figura 1-2) para dibujar las imágenes. En la vida, todos nos paramos sobre hombros de gigantes, y los titanes de p5.js incluyen pensadores del diseño, gráfica computacional, arte, arquitectura, estadística y otras disciplinas afines. Dale un vistazo a Sketchpad (1963) de Ivan Sutherland, Dynabook (1968) de Alan Kay y a otros artistas destacados en el libro de Ruth Leavitt Artist and Computer http://www.atariarchives.org/artist/ (Harmony Books, 1976). Los archivos de ACM SIGGRAPH y de Ars Electronica brindan atisbos fascinantes en la historia de la gráfica y el software.
30 | 31 |Tal como los lenguajes humanos, los lenguajes de programación pertenecen a familias de lenguajes relacionados. p5.js es un dialecto de un lenguaje de programación llamado JavaScript. La sintaxis del lenguaje es casi idéntica, pero p5.js añade características personalizadas relacionadas a gráficas e interacción (Figura 1-3) y provee un acceso simple a características nativas de HTML5 que ya están soportadas por los navegadores web. Por estas características compartidas, aprender p5.js es un primer paso útil para aprender a programar en otros lenguajes y usar otras herramientas computacionales.
40 | 41 |Miles de personas usan p5.js cada día. Al igual que ellos, tú puedes descargar p5.js gratuitamente. Incluso tienes la opción de modificar el código de p5.js para que se adapte a tus necesidades. p5.js es un proyecto FLOSS (free/libre/open source software, lo que significa software gratis libre y de código abierto), y siguiendo el espíritu de esta comunidad, te alentamos a participar y compartir tus proyectos y tu conocimiento en http://p5js.org/es (Figura 1-4).
50 | 51 |Para aprovechar al máximo este libro, no basta con solamente leerlo. Necesitas experimentar y practicar. No puedes aprender a programar solamente leyendo - se aprende haciendo. Para empezar, descarga p5.js y escribe tu primer bosquejo.
5 | 6 |Primero, necesitarás un editor de código. Un editor de código es similar a un editor de texto (como Bloc de notas), excepto que posee una funcionalidad especial para editar código en vez de texto plano. Puedes usar cualquier editor que quieras; te recomendamos Atom y Brackets, ambos descargables de forma gratuita.
10 | 11 | 12 | 13 |Comienza visitando https://p5js.org/es/download/ y selecciona "p5.js completo". Haz doble click en el archivo .zip descargado, y arrastra el directorio a una ubicación en tu disco duro. Puede ser Archivos de programa o Documentos o simplemente el escritorio, lo importante es que el directorio p5 sea extraido del archivo .zip.
19 | 20 |El directorio p5 contiene un proyecto de ejemplo con el que puedes empezar a trabajar. Abre tu editor de código. Luego abre el directorio llamado empty-example (ejemplo vacio) en tu editor de código. En la mayoría de los editores de código, puedes hacer esto yendo al menú Archivo, usando la opción Abrir y luego seleccionado el directorio empty-example. ¡Ahora estás listo para empezar tu primer programa!
21 |Cuando abras el directorio empty-example, lo más probable es que veas una barra lateral con el nombre del directorio en la parte superior y una lista con los archivos contenidos en este directorio. Si haces click en alguno de estos archivos, verás los contenidos del archivo aparecer en el área principal.
27 | 28 |Un bosquejo en p5.js está compuesto de varios lenguajes distintos usados en conjunto. HTML (HyperText Markup Language) brinda la columna vertebral, enlazando todos los otros elementos en la página. JavaScript (y la biblioteca p5.js) te permiten crear gráficas interactivas que puedes mostrar en tu página HTML. A veces se usa CSS (Cascading Style Sheets) para definir elementos de estilo en la página HTML, pero no cubriremos este lenguaje en este libro.
29 | 30 |Si revisas el archivo index.html, te darás cuenta que contiene un poco de código HTML. Este archivo brinda la estructura a tu proyecto, enlazando la biblioteca p5.js y otro archivo llamado sketch.js, donde tú escribirás tu propio programa. El código que crea estos enlaces tiene la siguiente apariencia:
31 | 32 |33 | <script language="javascript" type="text/javascript" src="../35 | 36 |
p5.js"></script> 34 | <script language="javascript" type="text/javascript"
src="sketch.js"></script>
No necesitas hacer nada en el código HTML por el momento — ya está configurado para ti. A continuacion,haz click en sketch.js y revisa el código:
37 | 38 |39 | function setup() { 40 | // put setup code here 41 | } 42 | 43 | function draw() { 44 | // put drawing code here 45 | }46 | 47 |
El código plantilla contiene dos bloques, o funciones, setup()
y draw()
. Puedes escribir tu código en cualquiera de los dos lugares, y cada lugar tiene un propósito específico.
Cualquier código que esté involucrado en la definición del estado inicial de tu programa corresponde al bloque setup()
. Por ahora, lo dejaremos vacío, pero más adelante en el libro, añadirás código aquí para especificar el tamaño del lienzo para tus gráficas, el grosor de tu trazado o la velocidad de tu programa.
Cualquier código involucrado en realmente dibujar contenido en la pantalla (definir el color de fondo, dibujar figuras, texto o imágenes) será puesto dentro del bloque draw()
. Es aquí donde empezarás a escribir tus primeras líneas de código.
Entre las llaves del bloque draw()
, borra el texto // put drawing code here
y reemplázalo con lo siguiente:
59 | background(204); 60 | ellipse(50, 50, 80, 80);61 | 62 |
Tu programa completo deberá verse así:
63 | 64 |65 | function setup() { 66 | // put setup code here 67 | } 68 | 69 | function draw() { 70 | background(204); 71 | ellipse(50, 50, 80, 80); 72 | }73 | 74 |
Esta nueva línea de código significa "dibuja una elipse, con su centro 50 pixeles a la derecha desde el extremo izquierdo y 50 pixeles hacia abajo desde el extremo superior, con una altura y un ancho de 80 pixeles". Graba el código presionando Command-S, o escogiendo la opción Archivo→Grabar del menú.
75 | 76 |Para ver el código en ejecución, puedes abrir el archivo index.html en cualquier navegador web (como Chrome, Firefox o Safari). Navega al directorio empty-example en tu explorador de archivos y haz doble click en index.html para abrirlo. Otra alternativa es hacerlo desde el navegador web, escoger Archivo→Abrir y seleccionar el archivo index.html.
77 | 78 |Si has escrito todo correctamente, deberías ver un círculo en tu navegador. Si no lo ves, asegúrate de haber copiado correctamente el código de ejemplo. Los números tienen que estar entre paréntesis y tener comas entre ellos. La línea debe terminar con un punto y coma. 79 |
80 | 81 |Una de las cosas más difíciles al empezar a programar es que tienes que ser muy específico con la sintaxis. El software p5.js no es siempre suficientemente inteligente como para entender lo que quieres decir, y puede ser muy exigente con la puntuación. Te acostumbrarás a esto con un poco de práctica.
84 | 85 |A continuación, avanzaremos para hacer más emocionante nuestro bosquejo.
86 |Borra el texto del ejemplo anterior, y prueba este. Graba tu código, y refresca (Command-R) index.html en tu navegador para verlo actualizado.
92 | 93 |98 | function setup() { 99 | createCanvas(480, 120); 100 | } 101 | 102 | function draw() { 103 | if (mouseIsPressed) { 104 | fill(0); 105 | } else { 106 | fill(255); 107 | } 108 | ellipse(mouseX, mouseY, 80, 80); 109 | }110 | 111 |
Este programa crea un lienzo para gráficas que tiene un ancho de 480 pixeles y una altura de 120 pixeles, y luego empieza a dibujar círculos blancos en la posición del ratón. Cuando presionas un botón del ratón, el color del círculo cambia a negro. Explicaremos después y en detalle más de los elementos de este programa. Por ahora, ejecuta el código, mueve el ratón y haz click para experimentarlo.
112 |El navegador tiene incluido una consola que puede ser muy útil para corregir errores en los programas. Cada navegador tiene una manera distinta de abrir la consola. Aquí están las instrucciones sobre cómo hacerlo en los navegadores más típicos:
119 | 120 |Ahora deberías ver un recuadro en la parte inferior o lateral de tu pantalla (Figura 2-1). Si hay un error de tipeo u otro error en tu programa, aparecerá texto rojo explicando qué error es. Este texto puede a veces ser críptico, pero si revisas al lado derecho de la línea, estará el nombre del archivo y el número de la línea de código donde fue detectado el error. Ese es un lugar adecuado donde empezar a buscar errores en tu programa.
128 | 129 | 138 | 139 |Has creado un bosquejo a partir de un ejemplo vacío, ¿pero cómo creas un nuevo proyecto? La manera más fácil de hacerlo es ubicando el directorio empty-example en tu explorador de archivos, luego copiar y pegarlo para crear un segundo empty-example. Puedes renombrar el directorio como quieras — por ejemplo, Proyecto-2.
150 | 151 |Ahora puedes abrir este directorio en tu editor de código y empezar a hacer un nuevo bosquejo. Cuando quieras verlo en el navegador, abre el archivo index.html ubicado en tu nuevo directorio Proyecto-2.
152 | 153 |Siempre es una buena idea grabar frecuentemente tus bosquejos. Mientras vas probando cosas nuevas, graba tu bosquejo con diferentes nombres, (Archivo→Guardar como), para que así siempre puedas volver a versiones anteriores. Esto es especialmente útil si algo falla.
154 | 155 |Un error común es estar editando un proyecto pero estar viendo otro en el navegador, haciendo que no puedas ver los cambios que has realizado. Si te das cuenta que tu programa se ve igual a pesar de haber hecho cambios en tu código, revisa que estás viendo el archivo index.html correcto.
157 |Aprender a programar con p5.js involucra explorar mucho código: ejecutarlo, alterarlo, romperlo y mejorarlo hasta que lo hayas reconfigurado y hecho algo novedoso. Con esto en mente, el sitio web de p5.js tiene docenas de ejemplos que demuestran diferentes características de la biblioteca. Visita la página de Ejemplos para verlos. Puedes jugar con ellos editanto el código en la página y luego haciendo click en "Ejecutar." Los ejemplos están agrupados en distintas categorías según su función, como forma, color, e imagen. Encuentra un tema que te interese en la lista y prueba un ejemplo.
164 | 165 |Si ves una parte del programa con la que no estás familiarizado o sobre la que quieres aprender su funcionalidad, visita la Referencia de p5.js.
166 | 167 |La Referencia de p5.js explica cada elemento de código con una descripción y ejemplos. Los programas de la Referencia son mucho más cortos (usualmente cuatro o cinco líneas) y más fáciles de seguir que los ejemplos de la página Aprender. Ten en cuenta que estos ejemplos por simplicidad usualmente omiten setup()
y draw()
, pero estas líneas de código que ves deberán ubicarse dentro de uno de estos bloques para poder ser ejecutadas. Recomendamos mantener la página de Referencia abierta mientras estés leyendo este libro y mientras estés programando. Puede ser navegada por tema o usando la barra de búsqueda en la parte superior de la página.
La Referencia fue escrita pensando en el principiante; esperamos que sea clara y fácil de entender. Estamos muy agradecidos de las personas que han encontrado errores y los han señalado. Si crees que puedes mejorar una entrada en la referencia o que has encontrado algún error, por favor haznos saber esto haciendo click en el enlace en la parte inferior de cada página de referencia.
170 |Una técnica alternativa para posicionar y mover objetos en la pantalla es cambiar el sistema de coordenadas de la pantalla. Por ejemplo, puedes mover una figura 50 pixeles a la derecha, o puedes mover la ubicación de la coordenada (0,0) 50 pixeles a la derecha - el resultado visual en la pantalla es el mismo.
5 | 6 |Al modificar el sistema de coordenadas por defecto, podemos crear diferentes transformaciones incluyendo traslación, rotación, y escalamiento.
7 | 8 |Trabajar con transformaciones puede ser difícil, pero la función translate()
es la más sencilla, así que empezaremos con esta. Tal como la Figura 6-1 muestra, esta función puede trasladar el sistema de coordenadas hacia la izquierda, derecha, arriba y abajo.
En este ejemplo, observa que el rectángulo está dibujado en la coordenada (0,0), pero está en otra posición en el lienzo, porque es afectado por la función translate()
:
27 | function setup() { 28 | createCanvas(120, 120); 29 | background(204); 30 | } 31 | 32 | function draw() { 33 | translate(mouseX, mouseY); 34 | rect(0, 0, 30, 30); 35 | }36 | 37 |
La función translate()
define la coordenada (0,0) de la pantalla en la ubicación del ratón (mouseX
y mouseY
). Cada vez que el bloque draw()
se repite, el rect()
es dibujado en el nuevo origen, derivado de la posición actual del ratón.
Después de que la transformación es realizada, es aplicada a todas las funciones de dibujo a continuación. Observa lo que pasa cuando una segunda función translate
es añadida para controlar un segundo rectángulo:
50 | function setup() { 51 | createCanvas(120, 120); 52 | background(204); 53 | } 54 | 55 | function draw() { 56 | translate(mouseX, mouseY); 57 | rect(0, 0, 30, 30); 58 | translate(35, 10); 59 | rect(0, 0, 15, 15); 60 | }61 | 62 |
Los valores para la función translate()
se suman. El rectángulo pequeño es trasladado según mouseX
+ 35 y mouseY
+ 10. Las coordenadas x e y de ambos rectángulos son (0,0), pero las funciones translate()
los mueven a otras posiciones en el lienzo.
Sin embargo, incluso cuando las transformaciones se acumulan dentro del bloque draw()
, se anulan cada vez que la función time draw()
se ejecuta nuevamente desde el principio.
La función rotate()
rota el sistema de coordenadas. Tiene un parámetro, que es el ángulo (en radianes) a rotar. Siempre rota relativo a (0,0), lo que se conoce como rotar en torno al origen. Figura 3-2 muestra los valores de ángulo en radianes. Figura 6-2 muestra la diferencia entre rotar con números positivos y negativos.
Para rotar una figura, primero define el ángulo de rotación con rotate()
, luego dibuja la figura. En este bosquejo, el parámetro para rotar (mouseX / 100.0
) tendrá un valor entre 0 y 1.2 para definir el ángulo de rotación porque mouseX
tendrá un valor entre 0 y 120, el ancho del lienzo según lo definido en createCanvas()
:
87 | function setup() { 88 | createCanvas(120, 120); 89 | background(204); 90 | } 91 | 92 | function draw() { 93 | rotate(mouseX / 100.0); 94 | rect(40, 30, 160, 20); 95 | }96 |
Para rotar una figura en torno a su propio centro, debe ser dibujada con la coordenada (0,0) en su centro. En este ejemplo, como la figura tiene un ancho de 160 y una altura de 20 según lo definido en la función rect()
, es dibujada en la coordenada (-80, -10) para poner la coordenada (0,0) al centro de la figura:
108 | function setup() { 109 | createCanvas(120, 120); 110 | background(204); 111 | } 112 | 113 | function draw() { 114 | rotate(mouseX / 100.0); 115 | rect(-80, -10, 160, 20); 116 | }117 | 118 |
El anterior par de ejemplos muestra cómo rotar alrededor de la coordenada (0,0), ¿pero qué otras posibilidades hay? Puedes usar las funciones translate()
y rotate()
para mayor control. Cuando son combinadas, el orden en que aparecen afecta el resultado. Si el sistema de coordenadas es trasladado y después rotado, es distinto que primero rotar y después mover el sistema de coordenadas.
Para girar una figura en torno a su centro a un lugar en la pantalla lejos del origen, primero usa la función translate()
para mover la figura a la ubicación donde quieres la figura, luego usa rotate()
, y luego dibuja la figura con su centro en la coordenada (0,0):
131 | var angulo = 0.0; 132 | 133 | function setup() { 134 | createCanvas(120, 120); 135 | background(204); 136 | } 137 | 138 | function draw() { 139 | translate(mouseX, mouseY); 140 | rotate(angulo); 141 | rect(-15, -15, 30, 30); 142 | angulo += 0.1; 143 | }144 |
El siguiente ejemplo es idéntico a Ejemplo 6-5, excepto que translate()
y rotate()
ocurren en el orden inverso. La figura ahora rota alrededor de la esquina superior izquierda, con la distancia desde la esquina definida por translate()
:
156 | var angulo = 0.0; 157 | 158 | function setup() { 159 | createCanvas(120, 120); 160 | background(204); 161 | } 162 | 163 | function draw() { 164 | rotate(angulo); 165 | translate(mouseX, mouseY); 166 | rect(-15, -15, 30, 30); 167 | angulo += 0.1; 168 | }169 | 170 |
También puedes usar las funciones rectMode()
, ellipseMode()
y imageMode()
para hacer más simple el dibujo de figuras desde su centro. Puedes leer sobre estas funciones en la Referencia de p5.js.
En este ejemplo, hemos unido una serie de funciones translate()
y rotate()
para crear un brazo articulado. Cada función translate()
mueve la posición de las líneas, y cada función rotate()
añade a la rotación previa para poder girar más:
185 | var angulo = 0.0; 186 | var anguloDireccion = 1; 187 | var velocidad = 0.005; 188 | 189 | function setup() { 190 | createCanvas(120, 120); 191 | } 192 | 193 | function draw() { 194 | background(204); 195 | translate(20, 25); // Mover a la posición inicial 196 | rotate(angulo); 197 | strokeWeight(12); 198 | line(0, 0, 40, 0); 199 | translate(40, 0); //Mover a la siguiente articulación 200 | rotate(angulo * 2.0); 201 | strokeWeight(6); 202 | line(0, 0, 30, 0); 203 | translate(30, 0); // Mover a la siguiente articulación 204 | rotate(angulo * 2.5); 205 | strokeWeight(3); 206 | line(0, 0, 20, 0); 207 | 208 | angulo += velocidad * anguloDireccion; 209 | if ((angulo > QUARTER_PI) || (angulo < 0)) { 210 | anguloDireccion *= -1; 211 | } 212 | }213 | 214 |
La variable angulo
aumenta desde 0 hasta QUARTER_PI
(un cuarto del valor de pi), luego disminuye hasta que es menor que cero, luego el ciclo se repite. El valor de la variable anguloDireccion
está siempre entre 1 y -1 para hacer que el valor de angulo
correspondiente aumente o disminuya.
La función scale()
estira las coordenadas del lienzo. Como las coordenadas se expanden o se contraen cuando cambia la escala, todo lo que está dibujado en el lienzo aumenta o disminuye sus dimensiones. La cantidad de escalamiento se escribe en porcentajes decimales. Entonces, el parámetro 1.5 en la función scale()
corresponde a 150% y 3 a 300% (Figura 6-3).
Tal como rotate()
, la función scale()
transforma desde el origen. Entonces, tal como rotate()
, para escalar una figura desde su centro, debemos trasladar su ubicación, escalar y luego dibujar con el centro en la coordenada (0,0):
237 | function setup() { 238 | createCanvas(120, 120); 239 | background(204); 240 | } 241 | 242 | function draw() { 243 | translate(mouseX, mouseY); 244 | scale(mouseX / 60.0); 245 | rect(-15, -15, 30, 30); 246 | }247 |
De las líneas gruesas de Ejemplo 6-8, puedes ver cómo la función scale()
afecta el grosor del trazado. Para mantener un grosor consistente de trazado a medida que la figura se escala, divide el trazado deseado por el valor escalar:
255 | function setup() { 256 | createCanvas(120, 120); 257 | background(204); 258 | } 259 | 260 | function draw() { 261 | translate(mouseX, mouseY); 262 | var scalar = mouseX / 60.0; 263 | scale(scalar); 264 | strokeWeight(1.0 / scalar); 265 | rect(-15, -15, 30, 30); 266 | }267 |
Para aislar los efectos de las transformaciones para que no afecten otras funciones, usa las funciones push()
y pop()
. Cuando ejecutas push()
, se almacena una copia del sistema de coordenadas actual y luego puedes restaurar ese sistema ejecutando pop()
. Esto es útil cuando necesitas transformar una figura, pero no quieres afectar otras.
En este ejemplo, el rectángulo pequeño siempre se dibuja en la misma posición porque translate(mouseX, mouseY)
es cancelado por pop()
:
285 | function setup() { 286 | createCanvas(120, 120); 287 | background(204); 288 | } 289 | 290 | function draw() { 291 | push(); 292 | translate(mouseX, mouseY); 293 | rect(0, 0, 30, 30); 294 | pop(); 295 | translate(35, 10); 296 | rect(0, 0, 15, 15); 297 | }298 | 299 |
Las funciones push()
y pop()
siempre se usan de a pares. Por cada push()
, tiene que haber un correspondiente pop()
.
Las funciones translate()
, rotate()
, y scale()
son utilizadas para modificar el bosquejo del robot. En relación a Robot 3: respuesta, translate()
es usado para hacer el código más fácil de leer. Aquí, observa como ya no es necesario sumar el valor de x
a cada función de dibujo porque la función translate()
mueve todo. Similarmente, la función scale()
es usada para definir las dimensiones del robot completo. Cuando el ratón no está presionado, el tamaño es de un 60% y cuando sí está presionado, es de un 100% en relación a las coordenadas originales. La función rotate()
es usada dentro del bucle para dibujar una línea, rotarla un poco, luego dibujar una segunda línea, luego rotarla un poco más, y así hasta que el bucle ha dibujado 30 líneas en forma de círculo para darle estilo al pelo de la cabeza del robot:
315 | var x = 60; // Coordenada x 316 | var y = 440; // Coordenada y 317 | var radius = 45; // Radio de la cabeza 318 | var bodyHeight = 180; // Altura del cuerpo 319 | var neckHeight = 40; // Altura del cuello 320 | 321 | var easing = 0.04; //suavizado 322 | 323 | function setup() { 324 | createCanvas(360, 480); 325 | strokeWeight(2); 326 | ellipseMode(RADIUS); 327 | } 328 | 329 | function draw() { 330 | 331 | var neckY = -1 * (bodyHeight + neckHeight + radius); 332 | 333 | background(204); 334 | 335 | translate(mouseX, y); // Mueve todo a (mouseX, y) 336 | 337 | if (mouseIsPressed) { 338 | scale(1.0); 339 | } else { 340 | scale(0.6); // 60% de tamaño si el ratón no está presionado 341 | } 342 | 343 | // Cuerpo 344 | noStroke(); 345 | fill(102); 346 | ellipse(0, -33, 33, 33); 347 | fill(0); 348 | rect(-45, -bodyHeight, 90, bodyHeight-33); 349 | 350 | // Cuello 351 | stroke(102); 352 | line(12, -bodyHeight, 12, neckY); 353 | 354 | // Pelo 355 | push(); 356 | translate(12, neckY); 357 | var angle = -PI/30.0; //angulo 358 | for (var i = 0; i <= 30; i++) { 359 | line(80, 0, 0, 0); 360 | rotate(angle); 361 | } 362 | pop(); 363 | 364 | // Cabeza 365 | noStroke(); 366 | fill(0); 367 | ellipse(12, neckY, radius, radius); 368 | fill(255); 369 | ellipse(24, neckY-6, 14, 14); 370 | fill(0); 371 | ellipse(24, neckY-6, 3, 3); 372 | 373 | }374 |
Las funciones son los bloques fundamentales de los programas hechos en p5.js. Han aparecido en cada ejemplo que hemos presentado. Por ejemplo, hemos usado a menudo la función createCanvas()
, la función line()
, y la función fill()
. Este capítulo muestra cómo escribir nuevas funciones para extender las capacidades de p5.js más allá de sus características ya incorporadas.
El poder de las funciones es su modularidad. Las funciones son unidades de software independientes que son usadas para construir programas complejos - como bloques de LEGO, donde cada tipo de ladrillo sirve para un propósito específico y hacer un modelo complejo requiere usar las diferentes partes en conjunto. Al igual que las funciones, el verdadero poder de estos ladrillos es la capacidad de construir muchas formas distintas usando el mismo conjunto de elementos. El mismo grupo de LEGOs que forma una nave espacial puede ser reusado para construir un camión, un rascacielos y muchos otros objetos.
7 | 8 |Las funciones son útiles si quieres dibujar una forma más compleja como un árbol, una y otra vez. La función para dibujar un árbol puede estar compuesta de funciones de p5.js, como line()
, Después de que el código para dibujar el árbol es escrito, no necesitas pensar en los detalles para dibujar un árbol nuevamente - puedes simplemente escribir arbol()
(o algún otro nombre que le hayas puesto a la función) para dibujar la figura. Las funciones permiten que una secuencia compleja de declaraciones pueda ser abstraída, para que te puedas enfocar en una meta de alto nivel (como dibujar un árbol), y no en los detalles de la implementación (las funciones line()
que definen la forma del árbol). Una vez que una función es definida, el código dentro de la función no necesita ser repetido.
Un computador ejecuta los programas una línea de código a la vez. Cuando una función es ejecutada, el computador salta a donde la función está definida y corre el código ahí, luego vuelve a donde estaba anteriormente.
14 | 15 |Este comportamiento es ilustrado con la función lanzarDado()
escrita para este ejemplo. Cuando el programa empieza, ejecuta el código en setup()
y luego se detiene. El programa toma un desvío y ejecuta el código dentro de lanzarDado()
cada vez que aparece:
21 | function setup() { 22 | print(¡Listo para lanzar los dados!"); 23 | lanzarDado(20); 24 | lanzarDado(20); 25 | lanzarDado(6); 26 | print("Listo."); 27 | } 28 | 29 | function lanzarDado(numeroLados) { 30 | var d = 1 + int(random(numeroLados)); 31 | print("Lanzando... " + d); 32 | }33 | 34 |
Las dos líneas de código en lanzarDado()
seleccionan un número aleatorio entre 1 y el número de caras del dado e imprime ese número a la consola. Como los números son aleatorios, verás diferentes números cada vez que el prorgama es ejecutado:
37 | ¡Listo para lanzar los dados! 38 | Lanzando... 20 39 | Lanzando... 11 40 | Lanzando... 1 41 | Listo.42 | 43 |
Cada vez que la función lanzarDado()
es ejecutada dentro de setup()
, el código dentro de la función se ejecuta de arriba a abajo, luego el programa continúa con la siguiente línea dentro de setup()
.
La función random()
(descrita en Aleatoreidad) retorna un número entre 0 y hasta (pero sin incluir) el número especificado. Entonces random(6)
entrega un número entre 0 y 5.99999. . . Como random()
retorna un número con punto decimal, también usamos la función int()
para convertir el número a uno entero. Entonces int(random(6))
retornará 0, 1, 2, 3, 4, o 5. Le sumamos 1 para que el número retornado esté entre 1 y 6 (como en un dado).Como en muchas otros casos en este libro, contar desde 0 hace más fácil usar los resultados de random()
en conjunto con otros cálculos.
Si se hubiera hecho un programa equivalente, pero sin la función lanzarDado()
, hubiera sido así:
54 | function setup() { 55 | print("¡Listo para lanzar los dados!"); 56 | var d1 = 1 + int(random(20)); 57 | print("Lanzando... " + d1); 58 | var d2 = 1 + int(random(20)); 59 | print("Lanzando... " + d2); 60 | var d3 = 1 + int(random(6)); 61 | print("Lanzando... " + d3); 62 | print("Listo."); 63 | }64 | 65 |
La función lanzarDado()
en el Ejemplo 9-1 hace que el código sea más fácil de leer y mantener. El programa es más claro, porque el nombre de la función claramente determina su propósito. En este ejemplo, podemos ver la función random()
en setup()
, pero su uso no es tan obvio. El número de lados en un dado es más claro con una función: cuando el código dice lanzarDado(6)
, es obvio que está simulando el lanzamiento de un dado de seis caras. Además, el Ejemplo 9-1 es fácil de mantener, porque la información no está repetida. La frase Lanzando...
se repite tres veces en este caso. Si quieres cambiar el texto a algo distinto, tienes que actualizar el código en tres lugares, en vez de hacer una sola edición dentro de la función lanzarDado()
. Además, como verás en el Ejemplo 9-5, una función puede hacer un programa mucho más corto (y por lo tanto más fácil de mantener y leer), lo que ayuda a reducir el potencial número de errores.
En esta sección, dibujaremos una lechuza para explicar los pasos necesarios para hacer una función.
73 | 74 |Primero, dibujaremos la lechuza sin usar una función:
78 | 79 |84 | function setup() { 85 | createCanvas(480, 120); 86 | } 87 | 88 | function draw() { 89 | background(204); 90 | translate(110, 110); 91 | stroke(0); 92 | strokeWeight(70); 93 | line(0, -35, 0, -65); // Cuerpo 94 | noStroke(); 95 | fill(204); 96 | ellipse(-17.5, -65, 35, 35); // Pupila izquierda 97 | ellipse(17.5, -65, 35, 35); // Pupila derecha 98 | arc(0, -65, 70, 70, 0, PI); // Barbilla 99 | fill(0); 100 | ellipse(-14, -65, 8, 8); // Ojo izquierdo 101 | ellipse(14, -65, 8, 8); // Ojo derecho 102 | quad(0, -58, 4, -51, 0, -44, -4, -51); // Pico 103 | }104 | 105 |
Observa que la función translate()
es usada para mover el origen (0, 0) 110 pixeles a la derecha y 110 pixeles hacia abajo. Luego la lechuza es dibujada relativa al (0,0), con sus coordenadas algunas veces positivas y otras negativas, centradas alrededor del nuevo punto (0,0). (Ver Figura 9-1.)
El código del Ejemplo 9-3 agregamos una segunda lechuza, el largo del código es casi el doble:
116 | 117 |122 | function setup() { 123 | createCanvas(480, 120); 124 | } 125 | 126 | function draw() { 127 | background(204); 128 | 129 | // Lechuza izquierda 130 | translate(110, 110); 131 | stroke(0); 132 | strokeWeight(70); 133 | line(0, -35, 0, -65); // Cuerpo 134 | noStroke(); 135 | fill(204); 136 | ellipse(-17.5, -65, 35, 35); // Pupila izquierda 137 | ellipse(17.5, -65, 35, 35); // Pupila derecha 138 | arc(0, -65, 70, 70, 0, PI); // Barbilla 139 | fill(0); 140 | ellipse(-14, -65, 8, 8); // Ojo izquierdo 141 | ellipse(14, -65, 8, 8); // Ojo derecho 142 | quad(0, -58, 4, -51, 0, -44, -4, -51); // Pico 143 | 144 | // Lechuza derecha 145 | translate(70, 0); 146 | stroke(0); 147 | strokeWeight(70); 148 | line(0, -35, 0, -65); // Cuerpo 149 | noStroke(); 150 | fill(255); 151 | ellipse(-17.5, -65, 35, 35); // Pupila izquierda 152 | ellipse(17.5, -65, 35, 35); // Pupila derecha 153 | arc(0, -65, 70, 70, 0, PI); // Barbilla 154 | fill(0); 155 | ellipse(-14, -65, 8, 8); // Ojo izquierdo 156 | ellipse(14, -65, 8, 8); // Ojo derecho 157 | quad(0, -58, 4, -51, 0, -44, -4, -51); // Pico 158 | }159 | 160 |
El programa aumenta de 21 líneas de código a 34, el código para dibujar la primera lechuza fue copiado y pegado en el programa y una función translate()
fue insertada para moverla 70 pixeles a la derecha. Esto es una manera tediosa e ineficiente de dibujar la segunda lechuza, sin mencionar el dolor de cabeza que será añadir una tercera lechuza con este método. Duplicar el código es innecesario, porque este es el tipo de situación donde una función puede llegar al rescate.
En este ejemplo, se introduce una función para dibujar dos lechuzas con el mismo código. Si hacemos que el código que dibuja una lechuza en la pantalla sea una nueva función, entonces el código solamente necesita aparecer una vez en el programa:
167 | 168 |173 | function setup() { 174 | createCanvas(480, 120); 175 | } 176 | 177 | function draw() { 178 | background(204); 179 | lechuza(110, 110); 180 | lechuza(180, 110); 181 | } 182 | 183 | function lechuza(x, y) { 184 | push(); 185 | translate(x, y); 186 | stroke(0); 187 | strokeWeight(70); 188 | line(0, -35, 0, -65); // Cuerpo 189 | noStroke(); 190 | fill(255); 191 | ellipse(-17.5, -65, 35, 35); // Pupila izquierda 192 | ellipse(17.5, -65, 35, 35); // Pupila derecha 193 | arc(0, -65, 70, 70, 0, PI); // Barbilla 194 | fill(0); 195 | ellipse(-14, -65, 8, 8); // Ojo izquierdo 196 | ellipse(14, -65, 8, 8); // Ojo derecho 197 | quad(0, -58, 4, -51, 0, -44, -4, -51); // Pico 198 | pop(); 199 | }200 | 201 |
Puedes ver por las ilustraciones de este ejemplo y del Ejemplo 9-4 que tienen el mismo resultado, pero que este ejemplo es más corto, porque el código para dibujar la lechuza aparece solamente una vez, dentro de la función llamada lechuza()
. Este código es ejecutado dos veces, porque es llamado dos veces dentro de draw()
. La lechuza es dibujada en dos ubicaciones distintas porque los parámetros ingresados en la función determinan las coordenadas x e y.
Los parámetros son una parte importante de las funciones, porque proveen flexibilidad. Vimos otro ejemplo de esto en la función lanzarDado()
; el parámetro único numeroLados
hizo posible simular un dado de 6 caras, uno de 20 y cualquier otro número de caras. Esto es parecido al caso de otras funciones de p5.js. Por ejemplo, los parámetros de la función line()
permiten dibujar una línea de un pixel a otro en el lienzo. Sin los parámetros, la función solo sería capaz de dibujar una línea desde un punto fijo a otro fijo.
Cada parámetro es una variable que es creada cada vez que la función se ejecuta. Cuando este ejemplo se ejecuta, la primera vez que se llama a la función y
, el valor del parámetro x
es 110, y el parámetro y
también es 110. En el segundo uso de la función, el valor de x
es 180 e y
nuevamente es 110. Cada valor es pasado a la función y luego cada vez que el nombre de la variable aparece dentro de la función, es reemplazado con el valor.
Ahora que tenemos una función básica para dibujar la lechuza en cualquier ubicación, podemos ahora dibujar eficientemente muchas lechuzas poniendo la función dentro de un bucle for
y cambiando el primer parámetro cada vez que corre el bucle:
218 | function setup() { 219 | createCanvas(480, 120); 220 | } 221 | 222 | function draw() { 223 | background(204); 224 | for (var x = 35; x < width + 70; x += 70) { 225 | lechuza(x, 110); 226 | } 227 | } 228 | 229 | // Insertar la función lechuza() del Ejemplo 9-5230 | 231 |
Es posible seguir añadiendo más y más parámetros a la función para cambiar diferentes aspectos de cómo la lechuza es dibujada. Se pasan valores a la función para cambiar el color de la lechuza, la rotación, la escala o el diámetro de los ojos.
232 |En este ejemplo, hemos añadido dos parámetros para cambiar el valor de gris y el tamaño de cada lechuza:
238 | 239 |244 | function setup() { 245 | createCanvas(480, 120); 246 | } 247 | 248 | function draw() { 249 | background(204); 250 | randomSeed(0); 251 | for (var i = 35; i < width + 40; i += 40) { 252 | var gris = int(random(0, 102)); 253 | var escalar = random(0.25, 1.0); 254 | lechuza(i, 110, gris, escalar); 255 | } 256 | } 257 | 258 | function lechuza(x, y, g, s) { 259 | push(); 260 | translate(x, y); 261 | scale(s); // Define la escala 262 | stroke(g); // Define el valor de gris 263 | strokeWeight(70); 264 | line(0, -35, 0, -65); // Cuerpo 265 | noStroke(); 266 | fill(255-g); 267 | ellipse(-17.5, -65, 35, 35); // Pupila izquierda 268 | ellipse(17.5, -65, 35, 35); // Pupila derecha 269 | arc(0, -65, 70, 70, 0, PI); // Barbilla 270 | fill(g); 271 | ellipse(-14, -65, 8, 8); // Ojo izquierdo 272 | ellipse(14, -65, 8, 8); // Ojo derecho 273 | quad(0, -58, 4, -51, 0, -44, -4, -51); // Pico 274 | pop(); 275 | }276 |
Las funciones pueden hacer un cálculo y luego retornar un valor al programa principal. Ya hemos usado funciones de este tipo, incluyendo random()
y sin()
. Observa que cuando esta función aparece, el valor de retorno es usualmente asignado a una variable:
285 | var r = random(1, 10);286 | 287 |
En este caso, la función random()
retorna un valor entre 1 y 10, el que luego es asignado a la variable r
.
Las funciones que retornan un valor son frecuentemente usadas como un parámetro de otra función, como por ejemplo:
290 | 291 |292 | point(random(width), random(height));293 | 294 |
En este caso, los valores de random()
no son asignados a una variable - son pasados como parámetros a la función point()
y son usados para posicionar el punto dentro del lienzo.
Para hacer que una función retorne un valor, especifica el dato a ser retornado con la palabra clave return
. En este ejemplo se incluye una función llamada pesoMarte()
que calcula el peso de una persona u objeto en nuestro planeta vecino Marte:
302 | function setup() { 303 | var tuPeso = 60; 304 | var pesoMarte = calcularMarte(tuPeso); 305 | print(pesoMarte); 306 | } 307 | 308 | function calcularMarte(p) { 309 | var pesoNuevo = p * 0.38; 310 | return pesoNuevo; 311 | }312 | 313 |
Revisa la última línea del código del bloque, que retorna la variable pesoNuevo
. En la segunda línea de setup()
, el valor es asignado a la variable pesoMarte
. (Para ver tu propio peso en Marte, cambia el valor asignado a la variable tuPeso
por tu peso.)
En contraste con el Robot 2 (revisar Robot 2: variables), este ejemplo usa una función para dibujar cuatro variaciones del robot dentro del mismo programa. Como la función dibujarRobot()
aparece cuatro veces dentro de la función draw()
, el código dentro del bloque dibujarRobot()
es ejecutado cuatro veces, cada vez con un diferente conjunto de parámetros para cambiar la posición y la altura del cuerpo del robot.
Observa cómo las variables globales en Robot 2 ahora han sido aisladas dentro de la función dibujarRobot()
. Como estas variables aplican solamente al dibujo del robot, tienen que estar dentro de las llaves que definen el bloque de la función dibujarRobot()
. Como el valor de la variable radius
no cambia, no necesita ser un parámetro. En cambio, es definida al principio de dibujarRobot()
:
329 | function setup() { 330 | createCanvas(720, 480); 331 | strokeWeight(2); 332 | ellipseMode(RADIUS); 333 | } 334 | 335 | function draw() { 336 | background(204); 337 | dibujarRobot(120, 420, 110, 140); 338 | dibujarRobot(270, 460, 260, 95); 339 | dibujarRobot(420, 310, 80, 10); 340 | dibujarRobot(570, 390, 180, 40); 341 | } 342 | 343 | function dibujarRobot(x, y, alturaCuerpo, alturaCuello) { 344 | 345 | var radius = 45; //radio 346 | var ny = y - alturaCuerpo - alturaCuello - radius; 347 | 348 | // Cuello 349 | stroke(102); 350 | line(x+2, y - alturaCuerpo, x+2, ny); 351 | line(x+12, y - alturaCuerpo, x+12, ny); 352 | line(x+22, y - alturaCuerpo, x+22, ny); 353 | 354 | // Antenas 355 | line(x+12, ny, x-18, ny-43); 356 | line(x+12, ny, x+42, ny-99); 357 | line(x+12, ny, x+78, ny+15); 358 | 359 | // Cuerpo 360 | noStroke(); 361 | fill(102); 362 | ellipse(x, y-33, 33, 33); 363 | fill(0); 364 | rect(x-45, y - alturaCuerpo, 90, alturaCuerpo - 33); 365 | fill(102); 366 | rect(x-45, y - alturaCuerpo + 17, 90, 6); 367 | 368 | // Cabeza 369 | fill(0); 370 | ellipse(x+12, ny, radius, radius); 371 | fill(255); 372 | ellipse(x+24, ny-6, 14, 14); 373 | fill(0); 374 | ellipse(x+24, ny-6, 3, 3); 375 | fill(153); 376 | ellipse(x, ny-8, 5, 5); 377 | ellipse(x+30, ny-26, 4, 4); 378 | ellipse(x+41, ny+6, 3, 3); 379 | }380 |
La programación orientada a objetos (OOP) es una manera diferente de pensar tus programas. Los objetos son también una manera de agrupar variables con funciones relacionadas. Como ya sabes cómo trabajar con variables y funciones, los objetos simplemente combinan lo que ya has aprendido en un paquete más fácil de entender.
5 | 6 |Los objetos son importantes, porque permiten dividir las ideas en bloques más pequeños. Esto se parece al mundo real donde, por ejemplo, los órganos están hechos de tejido, el tejido está hecho de células y así. Similarmente, a medida que tu código se va volviendo más complejo, tienes que pensar en términos de estructuras más pequeñas que forman estructuras más complicadas. Es más fácil escribir y mantener secciones de código más pequeñas y fáciles de entender, que trabajan en conjunto con otras, que escribir una gran sección de código que hace todo al mismo tiempo.
7 | 8 |Un objeto es un conjunto de variables y funciones relacionadas. En el contexto de los objetos, una variable se llama propiedad (o variable de instancia) y una función se llama método. Las propiedades y los métodos funcionan tal como las variables y las funciones vistas en los capítulos anteriores, pero usaremos estos nuevos términos para enfatizar que son parte de un objeto. Para decirlo de otra manera, un objeto combina datos relacionados (propiedades) con acciones y comportamientos relacionados (métodos). La idea es agrupar datos y métodos relacionados que pueden operar sobre datos.
12 | 13 |Por ejemplo, para hacer un modelo de una radio, piensa en los parámetros que pueden ser ajustados y las acciones que pueden afectar estos parámetros:
14 | 15 |volumem
, frecuencia
, banda
(FM, AM), poder
(encendido, apagado)definirVolumen
, definirFrecuencia
, definirBanda
Modelar un dispostivo mecánico simple es fácil comparado a modelar un organismo como una hormiga o una persona. No es posible reducir un organismo complejo a unas pocas propiedades y métodos, pero es posible modelarlo suficientemente bien como para crear una simulación interesante. El video juego The Sims es un ejemplo claro. Este juego consiste en administrar las actividades diarias de personas simuladas. Los personajes tienen la suficiente personalidad como para hacer adictivo el juego, pero no más que eso. De hecho, ellos solo tienen cinco atributos de personalidad: ordenado, extrovertido, activo, juguetón y simpático. Con el conocimiento de que es posible hacer un modelo altamente simplificado de organismos complejos, podríamos empezar a programar una hormiga con unas pocas propiedades y métodos:
23 | 24 |tipo
(trabajador, soldado), peso
, altura
caminar
, pellizcar
, liberarFeromonas
, comer
Si hicieras una lista de las propiedades y métodos de una hormiga, podrías escoger enfocarte en modelar diferentes aspectos de la hormiga. No existe una manera correcta de hacer un modelo, mientras sea apropiado para lograr las metas de tu programa.
32 |Para crear un objeto, empieza por definir una función constructor. Una función constructor es la especificación de un objeto. Usando una analogía arquitectónica, una función constructor es como el plano de una casa, y un objeto es como la casa en sí misma. Cada casa construida con el mismo plano puede tener variaciones, y el plano es la única especificación, no una estructura fija. Por ejemplo, una casa puede ser azul y otra roja, una casa puede tener una chimenea y la otra no. Tal como los objetos, el constructor define los tipos de datos y comportamientos, pero cada objeto (casa) hecho a partir de la misma función constructor (plano) tiene variables (color, chimenea) que tienen distintos valores. Para usar un término más técnico, cada objeto es una instancia y cada instancia tiene su propio conjunto de propiedades y métodos.
38 | 39 |Antes de que escribas una función constructor, recomendamos un poco de planificación. Piensa en cuáles propiedades y métodos deberían tener tus objetos. Haz una lluvia de ideas para imaginar todas las opciones posibles y luego prioriza y haz tu mejor conjetura sobre qué funcionará. Harás cambios durante el proceso de programación, pero es importante empezar bien.
40 | 41 |Elige nombres claros para tus propiedades. Las propiedades de un objeto pueden almacenar cualquier tipo de datos. Un objeto puede almacenar al mismo tiempo muchos booleans, números, imagenes, strings, etc. Ten en cuenta que una razón para construir un objeto es agrupar elementos relacionados. Para tus métodos, selecciona nombres claros y decide los valores de retorno (si tienen). Los métodos son usados para modificar los valores de las propiedades y para realizar acciones basadas en los valores de las propiedades.
42 | 43 |Para nuestra primera función constructor, convertiremos el Ejemplo 8-9 del libro. Empezamos por hacer una lista de las propiedades del ejemplo:
44 | 45 |46 | var x 47 | var y 48 | var diametro 49 | var velocidad50 | 51 |
El siguiente paso es resolver cuáles métodos pueden ser útiles para el objeto. Revisando la función draw()
del ejemplo que estamos adaptando, vemos dos componentes principales. La posición de la figura es actualizada y dibujada en la pantalla. Creamos dos métodos para nuestro objeto, uno para cada tarea:
54 | function mover() 55 | function mostrar()56 | 57 |
Ninguno de nuestros métodos retorna un valor. Una vez que hemos determinado las propiedades y métodos que el objeto debería tener, escribiremos nuestra función constructor para asignarlos a cada instancia del objeto que crearemos (Figura 10-1).
58 | 59 |El código dentro la función constructor es ejecutado una vez cuando el objeto es creado. Para crear la función constructor, seguiremos tres pasos:
64 | 65 | 66 |Crear un bloque de función.
69 |Añadir las propiedades y asignarles valores.
72 |Añadir los métodos.
75 |Primero, creamos un bloque de función para nuestro constructor:
79 | 80 |81 | function JitterBug() { 82 | 83 | }84 | 85 |
Observa que el nombre JitterBug
empieza con mayúscula. No es necesario nombrar la función constructor con letra mayúscula, pero es una convención (que recomendamos encarecidamente) usada para denotar que es un constructor. (La palabra clave function
, sin embargo, debe ser minúscula porque es una regla del lenguaje de programación.)
En segundo lugar, añadimos las propiedades. JavaScript posee una palabra reservada especial, this
, que puedes usar dentro la función constructor para referirte al objeto actual. Cuando declaras una propiedad de un objeto, dejamos fuera el símbolo var
, y en vez de eso anteponemos el nombre de la variable con this.
para indicar que estamos asignando una propiedad, una variable del objeto. Podemos declarar y asignar la propiedad velocidad
de la siguiente manera:
90 | function JitterBug() { 91 | this.velocidad = 0.5; 92 | }93 | 94 |
Mientras estamos haciendo esto, tenemos que decidir qué propiedades tendrán sus valores pasados a través del constructor. Como regla general, los valores de las propiedades que quieres que sean diferentes para cada instancia son pasados a través del constructor, y los otros valores de propiedades pueden ser definidos dentro del constructor, como velocidad
en este caso. Para el objeto JitterBug
, hemos decidido que los valores de x
, y
, y diametro
serán ingresados. Cada uno de los valores pasados es asignado a una variable temporal que existe solo mientras el código es ejecutado. Para aclarar esto, hemos añadido el nombre temp
a cada una de estas variables, pero pueden ser nombradas con cualquier nombre que prefieras. Serán usadas solo para asignar los valores de las propiedades que son parte del objeto. Así que añadimos tempX
, tempY
, y tempDiametro
como parámetros de la función, y las propiedades son declaradas y asignadas así:
97 | function JitterBug(tempX, tempY, tempDiametro) { 98 | this.x = tempX; 99 | this.y = tempY; 100 | this.diametro = tempDiametro; 101 | this.velocidad = 0.5; // El mismo valor para cada instancia 102 | }103 | 104 |
El último paso es añadir los métodos. Esto es igual que escribir funciones, pero aquí están contenidas dentro de la función constructor, y la primera línea es escrita un poco distinta. Normalmente, una función para actualizar variables se escribe así:
105 | 106 |107 | function mover() { 108 | x += random(-velocidad, velocidad); 109 | y += random(-velocidad, velocidad); 110 | }111 | 112 |
Como queremos hacer que esta función sea un método del objeto, nuevamente necesitamos usar la palabra reservada this
. La función anterior puede ser convertida en un método así:
115 | this.mover = function() { 116 | this.x += random(-this.velocidad, this.velocidad); 117 | this.y += random(-this.velocidad, this.velocidad); 118 | };119 | 120 |
La primera línea se ve un poco extraña, pero la manera de interpretarla es "crea una variable de instancia (propiedad) llamada move
, y luego asígnale como valor esta función." Luego, cada vez que nos referimos a las propiedades del objeto, podemos nuevamente usar this.
, tal como lo hacemos cuando están inicialmente declaradas. Juntando todo en el constructor el resultado es este:
123 | function JitterBug(tempX, tempY, tempDiametro) { 124 | 125 | this.x = tempX; 126 | this.y = tempY; 127 | this.diametro = tempDiametro; 128 | this.velocidad = 2.5; 129 | 130 | this.mover = function() { 131 | this.x += random(-this.velocidad, this.velocidad); 132 | this.y += random(-this.velocidad, this.velocidad); 133 | }; 134 | 135 | this.mostrar = function() { 136 | ellipse(this.x, this.y, this.diametro, this.diametro); 137 | }; 138 | 139 | }140 | 141 |
También observa el espaciado en el código. Cada línea dentro del constructor está indentada unos pocos espacios para indicar lo que está dentro del bloque. Dentro de estos métodos, el código está espaciado nuevamente para mostrar claramente la jerarquía.
142 |Ahora que has definido una función constructor, para usarla en un programa debes crear un instancia de objeto con ese constructor. Existen dos pasos para crear un objeto:
148 | 149 |Declara la variable de objeto.
152 |Crea (inicializa) el objeto con la palabra clave new
.
Para crear tu primer objeto, empezaremos mostrando cómo esto funciona en un bosquejo de p5.js y luego explicaremos cada parte en profundidad:
162 | 163 |168 | var bug; 169 | 170 | function setup() { 171 | createCanvas(480, 120); 172 | background(204); 173 | // Crea un objeto y pasa los parámetros 174 | bug = new JitterBug(width/2, height/2, 20); 175 | } 176 | 177 | function draw() { 178 | bug.mover(); 179 | bug.mostrar(); 180 | } 181 | 182 | // Copia aquí el código del constructor de Jitterbug183 | 184 |
Declaramos variables de objeto de la misma manera que todas las otras variables - el objeto es declarado escribiendo la palabra reservada var
seguida del nombre de la variable:
187 | var bug;188 | 189 |
El segundo paso es inicializar el objeto con la palabra reservada new
. Reserva espacio en la memoria para el objeto con todas sus propiedades y métodos. El nombre del constructor es escrito a la derecha de la palabra reservada new
, seguido de los parámetros dentro del constructor, si es que tiene alguno:
192 | bug = new JitterBug(width/2, height/2, 20);193 | 194 |
195 | Los tres números dentro de los paréntesis son los parámetros pasados a la función constructor JitterBug
. El número y orden de estos parámetros deben corresponder con los del constructor.
En el Ejemplo 10-1, vimos algo nuevo: el punto que es usado para acceder a los métodos del objeto dentro de draw()
. El operador punto es usado para unir el nombre del objeto con sus propiedades y métodos. Es análogo a la manera en que usamos this.
dentro de la función constructor, pero cuando nos referimos a esto fuera del constructor, this
es reemplazado por el nombre de la variable.
Esto se vuelve más claro en este ejemplo, donde se hacen dos objetos a partir del mismo constructor. La función jit.mover()
se refiere al método mover()
que pertenece al objeto jit
, y bug.mover()
se refiere al método mover()
que pertenece al objeto llamado bug
:
210 | var jit; 211 | var bug; 212 | 213 | function setup() { 214 | createCanvas(480, 120); 215 | background(204); 216 | jit = new JitterBug(width * 0.33, height/2, 50); 217 | bug = new JitterBug(width * 0.66, height/2, 10); 218 | } 219 | 220 | function draw() { 221 | jit.mover(); 222 | jit.mostrar(); 223 | bug.mover(); 224 | bug.mostrar(); 225 | } 226 | 227 | // Copia aquí el código del constructor de JitterBug228 | 229 |
Ahora que la función constructor existe como su propio módulo de código, cualquier cambio modificará los objetos hechos con élla. Por ejemplo, podrías añadir una propiedad al constructor JitterBug
que controla el color, u otra que determina su tamaño. Estos valores pueden ser pasados usando el constructor o usando métodos adicionales, como setColor()
o setSize()
. Y como es una unidad auto-contenida, también puedes usar el constructor JitterBug
en otro bosquejo.
Ahora es un buen momento para aprender a usar múltiples archivos en JavaScript. Repartir tu código en más de un archivo hace que un código largo sea más fácil de editar y más manejable en general. Usualmente se crea un nuevo archivo por cada constructor, lo que refuerza la modularidad de trabajar con objetos y hace que el código sea más fácil de encontrar.
232 | 233 |Crea un nuevo archivo en el mismo directorio que tu actual archivo sketch.js. Puedes nombrarlo como quieras, pero es una buena idea nombrarlo JitterBug.js por conceptos de organización. Mueve la función constructor JitterBug a este nuevo archivo. Enlaza el archivo JitterBug.js en tu archivo HTML añadiendo una línea dentro de HEAD
debajo de la línea donde enlazas el archivo sketch.js:
236 | <script type="text/javascript" src="sketch.js"></script> 237 | <script type="text/javascript" src="JitterBug.js"></script>238 |
Un objeto en software puede combinar métodos (funciones) y propiedades (variables) en una unidad. La función constructor Robot
en este ejemplo define todos los objetos robot que serán creados a partir de ella. Cada objeto Robot
posee su propio conjunto de propiedades para almacenar una posición y la ilustración que dibujará en la pantalla. Cada uno posee métodos para actualizar la posición y mostrar la ilustración.
Los parámetros de bot1
y bot2
en setup()
definen las coordenadas x e y y el archivo .svg que será usado para dibujar el robot. Los parámetros tempX
y tempY
son pasados al constructor y asignados a las propiedades xpos
y ypos
. El parámetro imgPath
es usado para cargar la ilustración asociada. Los objetos (bot1
y bot2
) dibujan en su propia ubicación con una ilustración distinta porque cada uno tienen valores distintos pasados a los objetos a través de sus constructores:
253 | var img1; 254 | var img2; 255 | 256 | var bot1; 257 | var bot2; 258 | 259 | function preload() { 260 | img1 = loadImage("robot1.svg"); 261 | img2 = loadImage("robot2.svg"); 262 | } 263 | 264 | function setup() { 265 | createCanvas(720, 480); 266 | bot1 = new Robot(img1, 90, 80); 267 | bot2 = new Robot(img2, 440, 30); 268 | } 269 | 270 | function draw() { 271 | background(204); 272 | 273 | // Actualiza y muestra el primer robot 274 | bot1.actualizar(); 275 | bot1.mostrar(); 276 | 277 | // Actualiza y muestra el segundo robot 278 | bot2.actualizar(); 279 | bot2.mostrar(); 280 | } 281 | 282 | function Robot(img, tempX, tempY) { 283 | // Define los valores iniciales de las propiedades 284 | this.xpos = tempX; 285 | this.ypos = tempY; 286 | this.angulo = random(0, TWO_PI); 287 | this.botImage = img; 288 | this.ydesplazamiento = 0.0; 289 | 290 | // Actualiza las propiedades 291 | this.actualizar = function() { 292 | this.angulo += 0.05; 293 | this.ydesplazamiento = sin(this.angulo) * 20; 294 | } 295 | 296 | // Dibuja el robot en la pantalla 297 | this.mostrar = function() { 298 | image(this.botImage, this.xpos, 299 | this.ypos + this.ydesplazamiento); 300 | } 301 | }302 |
Este libro se enfoca en usar p5.js para realizar gráficas interactivas, porque eso es lo principal que p5.js hace. Sin embargo, este software puede realizar mucho más y está siendo extendido aún más todo el tiempo.
5 | 6 |Una biblioteca de p5.js es un conjunto de código que extiende el software más allá de sus funciones principales. Las bibliotecas han sido importantes para el crecimiento de este proyecto, porque le permite a los desarrolladores añadir nuevas funciones rápidamente. Como proyectos autocontenidos y más pequeños, las bibliotecas son más fáciles de manejar que si sus características estuvieran integradas al software principal.
7 | 8 |El archivo .zip completo de p5.js incluye las bibliotecas p5.dom y p5.sound. También puedes descargar otras bibliotecas desde http://p5js.org/es/libraries/. Para usar una de estas bibliotecas, primero asegúrate de que está dentro del directorio que contiene tus archivos HTML y JavaScript. En segundo lugar, añade una línea de código a tu archivo HTML para indicar que la biblioteca será usada en el bosquejo actual. Esta línea debería verse así:
9 | 10 |11 | <script language="javascript" type="text/javascript"12 | 13 |
src="ruta/relativa/a/p5.nombreBiblioteca.js"></script>
ruta/relativa/a debería ser reemplazado por la ubicación requerida para ubicar el archivo de biblioteca relativo al archivo HTML. Si necesitas subir un directorio, inserta "..". Por ejemplo, si estás trabajando con el ejemplo vacío y con p5.sound.js de la descarga de p5.js completo, la línea sería así.
14 | 15 |16 | <script language="javascript" type="text/javascript" src="../17 | 18 |
p5.sound.js"></script>
La biblioteca de audio p5.sound tiene la habilidad de reproducir, analizar y generar (sintetizar) sonido. A continuación se presentan unas pocas funciones clave; consulta la Referencia de p5.js para conocer más objetos que pueden ser creados y funciones que pueden ser llamadas: http://p5js.org/es/reference/#/libraries/p5.sound.
22 | 23 |Al igual que las imágenes, los archivos JSON, y los archivos de texto introducidos en el capítulo 7/Medios, un archivo de sonido es otro tipo de medio capaz de extender un bosquejo de p5.js. Sigue las instrucciones en ese capítulo para aprender cómo cargar un archivo de sonido en el directorio de un bosquejo. La biblioteca p5.sound puede cargar un gran rango de formatos de archivos de audio incluyendo WAV, AIFF y MP3. Una vez que un archivo es cargado, puede ser reproducido, detenido y repetido, además de ser distorsionado con funciones de efecto.
24 | 25 |El uso más común de la biblioteca p5.sound es reproducir un sonido cuando un evento ocurre en la pantalla o como música de fondo. Este ejemplo se basa en el Ejemplo 8-5 para reproducir un sonido cuando la figura llega a los bordes de la pantalla. El archivo blip.wav es incluido en la carpeta media que puede ser descargada siguiendo las instrucciones del capítulo 7/Medios. Así como con otros archivos, en la parte superior del bosquejo se define una variable para almacenar un objeto p5.SoundFile
(lo que la función loadSound()
retorna), es cargada dentro de preload()
, y después de eso, puede ser usada en cualquier parte del programa:
31 | var blip; 32 | 33 | var radio = 120; 34 | var x = 0; 35 | var velocidad = 1.0; 36 | var direccion = 1; 37 | 38 | function preload() { 39 | blip = loadSound("blip.wav"); 40 | } 41 | 42 | function setup() { 43 | createCanvas(440, 440); 44 | ellipseMode(RADIUS); 45 | x = width/2; // Parte en el centro 46 | } 47 | 48 | function draw() { 49 | background(0); 50 | x += velocidad * direccion; 51 | if ((x > width - radio) || (x < radio)) { 52 | direccion = -direccion; // Invertir direccion 53 | blip.play(); 54 | } 55 | if (direccion == 1) { 56 | arc(x, 220, radio, radio, 0.52, 5.76); // Hacia la derecha 57 | } else { 58 | arc(x, 220, radio, radio, 3.67, 8.9); // Hacia la izquierda 59 | } 60 | }61 | 62 |
El sonido es reproducido cada vez que se ejecuta el método play()
. Este ejemplo funciona bien porque el sonido solamente se reproduce cuando el valor de la variable x
está dentro de los bordes de la pantalla. Si el sonido fuera reproducido en cada ejecución de draw()
, el sonido se reiniciaría 60 veces por segundo y no tendría tiempo de terminar de reproducirse. El resultado sería un sonido distorsionando rápidamente. Para reproducir un archivo más largo mientras se ejecuta un programa, llama a los métodos play()
o loop()
del sonido dentro de setup()
para que así el sonido se ejecute una sola vez.
El objeto p5.SoundFile
posee muchos métodos para controlar cómo un sonido es reproducido. Los más esenciales son play()
para reproducir la muestra una sola vez, loop()
para reproducirlo de principio a fin una y otra vez, stop()
para detener la reproducción, y jump()
para saltar a un momento específico dentro del archivo.
Además de reproducir sonidos, p5.js puede escuchar. Si tu computador posee un micrófono incorporado o conectado, la biblioteca p5.sound puede escuchar audio en vivo a través de él. Una vez que los datos del micrófono están conectados al software, los puedes analizar, modificar o reproducir:
73 | 74 |79 | var mic; 80 | var amp; 81 | 82 | var escala = 1.0; 83 | 84 | function setup() { 85 | createCanvas(440, 440); 86 | background(0); 87 | // Crea una entrada de audio y empieza a escuchar 88 | mic = new p5.AudioIn(); 89 | mic.start(); 90 | // Crea un nuevo analizador de amplitud y conéctalo a la entrada 91 | amp = new p5.Amplitude(); 92 | amp.setInput(mic); 93 | } 94 | 95 | 96 | function draw() { 97 | // Dibuja un fondo que se vaya a negro 98 | noStroke(); 99 | fill(0, 10); 100 | rect(0, 0, width, height); 101 | // El método getLevel() retorna valores entre 0 y 1, 102 | // así que map() es usado para convertir los valores 103 | // a números mayores 104 | escala = map(amp.getLevel(), 0, 1.0, 10, width); 105 | // Dibuja el círculo basado en el volumen 106 | fill(255); 107 | ellipse(width/2, height/2, escala, escala); 108 | } 109 |110 | 111 |
Hay dos secciones que están obteniendo la amplitud (volumen) del micrófono conectado. El objeto p5.AudioIn
es usado para obtener la señal del micrófono y el objeto p5.Amplitude
es usado para medir la señal.
Las variables para almacenar ambos objetos está definidas en la parte superior del código y creadas dentro de setup()
. Después del objeto p5.Amplitude
(en este programa se llama amp
), el objeto p5.AudioIn
, llamado mic
, es conectado al objeto amp
on el método setInput()
. Después de eso, el método getLevel()
del objeto amp
puede ser ejecutado en cualquier momento para leer la amplitud de los datos de micrófono dentro del programa. En este ejemplo, esto es realizado en cada ejecución de draw()
y el valor es usado para definir el tamaño del círculo.
Además de reproducir un sonido y analizar un sonido como fue demostrado en los últimos dos ejemplos, p5.js puede directamente sintetizar sonido. Los bloques fundamentales de la síntesis de sonido son ondas, entre las que se incluyen ondas sinusoidales, ondas triangulares y ondas cuadradas. Una onda sinusoidal tiene un sonido agradable, una onda cuadrada es más dura y una onda triangular está entre medio. Cada onda tiene un número de propiedades. La frecuencia, medida en Hertz, determina la altura, cuán grave o agudo es el tono. La amplitud de la onda determina el volumen, el nivel de intensidad.
116 |En el siguiente ejemplo, el valor de mouseX
determina la frecuencia de una onda sinusoidal. A medida que el ratón se mueve hacia izquierda y derecha, la frecuencia audible y la correspondiente visualización de la onda aumenta y decae:
128 | var sinusoide; 129 | 130 | function setup() { 131 | createCanvas(440, 440); 132 | // Crea e inicializa el oscilador sinusoidal 133 | sinusoide = new p5.SinOsc(); 134 | sinusoide.start(); 135 | } 136 | 137 | function draw() { 138 | background(0); 139 | // Mapea el valor de mouseX entre 20 Hz y 440 Hz 140 | // para la frecuencia 141 | var hertz = map(mouseX, 0, width, 20.0, 440.0); 142 | sinusoide.freq(hertz); 143 | // Dibuja una onda para visualizar la frecuencia del sonido 144 | stroke(204); 145 | for (var x = 0; x < width; x++) { 146 | var angulo = map(x, 0, width, 0, TWO_PI * hertz); 147 | var valorSinusoide = sin(angulo) * 120; 148 | line(x, 0, x, height/2 + valorSinusoide); 149 | } 150 | } 151 |152 | 153 |
El objeto sinusoide
, creado a partir del constructor p5.SinOsc
, es definido al principio del código y luego creado dentro de setup()
. El método start()
causa que la onda empiece a generar sonido. Dentro de draw()
, el método freq()
define continuamente la frecuencia de la onda, basándose en la posición izquierda y derecha del ratón.
La biblioteca p5.dom posee la habilidad de crear e interactuar con elementos HTML fuera del lienzo gráfico. DOM proviene de Document Object Model, que se refiere a un conjunto de métodos para interactuar programáticamente con la página HTML. Los siguientes ejemplos introducen unas pocas funciones clave. Revisa la Referencia de p5.js para conocer más elementos que pueden ser creados y funciones que pueden ser llamadas: http://p5js.org/es/reference/#/libraries/p5.dom.
161 | 162 |Tal como createCanvas()
crea un lienzo gráfico en la página, p5.dom incluye un número de otros métodos create
para añadir otros elementos HTML a la página. Entre los ejemplos se incluyen video, enlaces URL, cuadros para ingresar texto y barras deslizadoras.
createCapture()
accede a la cámara de tu computador y crea un elemento HTML que muestra su audio y video. Una vez que el elemento de captura es creado, puede ser dibujado en el lienzo y manipulado:
174 | var captura; 175 | 176 | function setup() { 177 | createCanvas(480, 120); 178 | captura = createCapture(); 179 | captura.hide(); 180 | } 181 | 182 | function draw() { 183 | var relacionDeAspecto = captura.height/capture.width; 184 | var h = width * relacionDeAspecto; 185 | image(captura, 0, 0, width, h); 186 | filter(INVERT); 187 | } 188 |189 | 190 |
El objeto captura está definido en la parte superior del código y luego es creado dentro de setup()
. createCapture()
de hecho adjunta un nuevo elemento a la página, pero como queremos dibujarlo en el lienzo, se usa el método hide()
para esconder el objeto de captura. Revisa lo que pasa cuando descomentas esta línea de código.
Deberías ver dos copias del video, una invertida y una normal.
193 | 194 |Los datos del objeto captura son dibujados en el lienzo en la función draw()
e invertidos usando el método filter()
.
createSlider()
crea una barra deslizadora que puede ser usada para manipular aspectos del bosquejo. Acepta tres argumentos - el valor mínimo, el valor máximo y el valor inicial:
207 | var barra; 208 | 209 | function setup() { 210 | createCanvas(480, 120); 211 | barra = createSlider(0, 255, 100); 212 | barra.position(20, 20); 213 | } 214 | 215 | function draw() { 216 | var gris = barra.value(); 217 | background(gris); 218 | } 219 |220 | 221 |
El objeto barra es definido en la parte superior del código y luego creado dentro de setup()
. Por defecto, el elemento será adjuntado a la página, justo después del elemento más recientemente creado en la página. El método position()
permite darle una posición relativa a la esquina superior izquierda. El método value()
retorna el valor actual de la barra deslizadora, el cual está siendo usado para definir el color del fondo del lienzo en draw()
.
createInput()
añade un recuadro que puede ser usado para ingresar texto a tu programa. createButton()
añade un botón que puede gatillar cualquier función que escojas. En este caso, el botón es usado para ingresar el texto dentro del recuadro de entrada al programa:
234 | var entrada; 235 | var boton; 236 | 237 | function setup() { 238 | createCanvas(480, 120); 239 | entrada = createInput(); 240 | entrada.position(20, 30); 241 | boton = createButton("submit"); 242 | boton.position(160, 30); 243 | boton.mousePressed(dibujarNombre); 244 | 245 | background(100); 246 | noStroke(); 247 | text("Ingresa tu nombre.", 20, 20); 248 | } 249 | 250 | function dibujarNombre() { 251 | background(100); 252 | textSize(30); 253 | var nombre = entrada.value(); 254 | for (var i=0; i < 30; i++) { 255 | fill(random(255)); 256 | text(nombre, random(width), random(height)); 257 | } 258 | } 259 |260 | 261 |
Los objetos entrada y boton son definidos en la parte superior del código y creados dentro de setup()
. createButton()
acepta un argumento, la etiqueta a ser mostrada en el botón. El método mousePressed()
es usado para asignar una función a ejecutar cuando el botón es presionado. Dentro de drawName()
, los contenidos del recuadro de entrada son leídos usando el método value()
y usados para rellenar el fondo con el texto.
El tipo de letra del cuerpo es TheSerif diseñado por Luc(as) de Groot. El tipo de letra del código es TheSansMono por Luc(as) de Groot.
5 |Copyright © 2016 Maker Media. Todos los derechos reservados. Traducción al español © 2018 Processing Foundation
7 | 8 |Impreso en Estados Unidos.
9 | 10 |Publicado por Processing Foundation, Inc. https://processingfoundation.org
11 | 12 | 13 | 14 |Aunque la editorial y los autores se han esforzado de buena fe en asegurar que la información y las instrucciones contenidas en esta obra sean correctos, la editorial y los autores niegan toda responsabilidad por los posibles errores y omisiones, incluyendo sin limitaciones la responsabilidad por los daños resultantes del uso o de la confianza puesta en esta obra. El uso de la información y las instrucciones contenidas en este trabajo se realiza bajo tu propio riesgo. Si cualquier porción de código u otra tecnología contenidos o descritos por esta obra está sujeto a licencias de código abierto o a los derechos propiedad intelectual de terceros, es tu propia responsabilidad asegurarte que tu uso cumpla con estas licencias y/o derechos.
43 |978-0-9998813-0-9
49 | 50 | 51 |Prefacio.......................................................................................................................... 5
6 | 7 |1/Hola............................................................................................................................ 13
8 | 9 |2/Empezando a programar..................................................................................... 20
10 | 11 |3/Dibujar..................................................................................................................... 28
12 | 13 |4/Variables.................................................................................................................. 53
14 | 15 |5/Respuesta................................................................................................................ 70
16 | 17 |6/Trasladar, rotar, escalar.................................................................................... 100
18 | 19 |7/Medios.................................................................................................................... 114
20 | 21 |8/Movimiento.......................................................................................................... 131
22 | 23 |9/Funciones............................................................................................................. 149
24 | 25 |10/Objetos................................................................................................................. 163
26 | 27 |11/Arreglos................................................................................................................ 176
28 | 29 |12/Datos..................................................................................................................... 192
30 | 31 |13/Extensión.............................................................................................................. 211
32 | 33 |A/Consejos de programación............................................................................... 221
34 | 35 |B/Orden de operaciones........................................................................................ 225
36 | 37 |C/Ámbito de variable............................................................................................. 226
38 | 39 | 40 | 41 | 42 |
Comentarios
40 | 41 |Los comentarios son notas que te escribes a ti mismo (o a otra gente) dentro del código. Debes usarlos para aclarar en palabras simples lo que el código está haciendo y para proveer información adicional como el título y el autor del programa. Un comentario empieza con dos barras oblicuas (
42 | 43 | 45 | 46 |//
) y continúa hasta el final de la línea:Puedes hacer un comentario de varias líneas con
47 | 48 | 53 | 54 |/*
y terminarlo con*/
. Por ejemplo:Cuando escribes un comentario de forma correcta, el texto será de color gris. El área comentada completa se vuelve gris para que puedas ver claramente dónde empieza y termina.
55 |