GAmuza. Hybrid live coding/modular application. Un programa para

Anuncio
GAmuza. Hybrid live coding/modular application
Un programa para arte interactivo y electrónico
1
Contents
1. Introducción
1.1. Premisas
14
1.2. Qué es GAmuza
15
1.3. Instalación
17
1.4. ScriptEditor
20
1.5. Comandos de teclado 21
2. Interface. Módulos de aplicación
GAmuza. Hybrid live coding/modular application. rel 04
© 2012 Emanuele Mazza
Texto: Emanuele Mazza && María José Martínez de Pisón
Dibujos: Carlos Maiques
Valencia, España.
Este texto forma parte de un libro en preparación sobre el entorno de desarrollo GAmuza
Algunos derechos reservados. Reconocimiento - Compartir Igual (by-sa): Se permite el uso
comercial de la obra y de las posibles obras derivadas, la distribución de las cuales se debe
hacer con una licencia igual a la que regula la obra original.
2
9
23
2.1. Setting Manager
23
2.2. Interface Live Coding
30
2.2.1. Timeline
34
2.3. Tracking Video
35
2.3.1. Computer vision
38
2.3.2. Kinect
44
2.4. Análisis del audio en arte sonoro
49
2.4. Audio Stream (Input/Output)
52
2.5. Interfaces físicas
57
2.6. Arduino
60
2.7. Comunicación OSC 61
3
3. Lenguaje de programación
63
3.1. Elementos básicos de programación: datos, variables y funciones 65
3.1.1. Variables I
67
3.1.2. Funciones
69
3.1.3. Variables II
75
3.2. Funciones internas: formas geométricas básicas 3.2.1. Formas irregulares
4. Interactividad
134
141
4.1. Definiciones de interactividad
141
4.2. Código para interactividad. Eventos de ratón 146
4.3. Eventos de teclado
150
85
3.3. Estructuras de programación básicas
89
3.3.1. Expresiones aritméticas
89
3.3.2. Expresiones relacionales
90
3.3.3. Expresiones condicionales y operadores lógicos
90
3.3.4. Expresiones de iteración. Repetición
94
3.4. Color
4
77
3.9.3. Clases en GAmuza
98
3.5. Azar y probabilidad
103
3.5.1. Noise
108
3.6. Textos y tipografía
111
3.7. Trigonometría 116
3.8. Transformar: traslación, rotación
121
3.9. Programación orientada a objetos. POO
124
3.9.1. Tablas [arrays]
125
3.9.2. Clases y objetos
132
5
6
7
1. Introducción
Este texto se ha desarrollado en el contexto de una facultad de Bellas Artes tras dos décadas de
enseñanza de arte electrónico y digital, lo que nos ha hecho conscientes de la dificultad, y también de
la necesidad, de hibridar la capacidad de abstracción y atención que requiere la formación técnica,
con el sentido crítico y especulativo que impulsa la formación humanista. Ambos pseudo-perfiles
amalgamados se enfocan hacia el arte contemporáneo, lo que suma no pocas incertidumbres al
estudiante que crece en esta emulsión.
Para reducir tensión a la mixtura, la experiencia acumulada en docencia e investigación se ha vertido
en el desarrollo de GAmuza, una herramienta pensada para impulsar el salto, solventar problemas y
facilitar el aprendizaje.
En el aula, como en la vida cotidiana, hay una presencia masiva de dispositivos técnicos de
comunicación que, además de ser el reflejo comercial de una industria creciente, indican también un
cambio de paradigma mayor que debería despertar la necesidad de comprender las nuevas relaciones
que se están dando entre hombre y mundo. En este cambio de paradigma el lenguaje sigue teniendo
un papel importante que involucra el desarollo de otros lenguajes.
Durante las últimas décadas del siglo XX el arte se hizo eco del debate entre la prevalencia del lenguaje
sobre la imagen o viceversa [picture turn <--> linguistic turn]. Hoy sentimos una polaridad similar entre
aquellos debates artístico-filosóficos y el impulso del lenguaje científico, cuya lógica, consciente en parte
de sus fallidos principios de verificación, ha ido filtrando las incertidumbres e indeterminaciones de una
nueva ciencia que, poco a poco, (o mucho a mucho) va encarnando nuevos esquemas conceptuales,
diagramas que dibujan en el horizonte una nueva imagen-mundo, enunciada y representada con el
lenguaje numérico, informático.
Las conexiones que el hombre establece hoy con las imágenes-mundo, pasan por las “sinuosidades
de nuevos campos de relación”1 que llevan hasta el espacio cotidiano la posibilidad de acceso a las
1 Vilem Flusser (2005) “La sociedad alfanumérica” en Revista Austral de Ciencias Sociales nº 9, pág. 105.
8
9
Introducción
GAmuza Hybrid live coding / modular application
investigaciones sobre partículas del universo, el principio de Incertidumbre de Heisemberg, la teoría de
La base del pensamiento visual y la percepción espacial se fundamenta en estructuras geométricas
las Catástrofes de René Thom, la teoría del Caos de Ilya Prygogine, y muchas otras que han incidido
cuyo origen también está vinculado a las ciencias ópticas y el estudio de la luz. Paul Virilio nos dice que
en ese cambio de visión y comprensión del mundo.
actualmente hay otra óptica, otra luz y otra transparencia, “trans-apariencia electrónica [que] prepara
A partir del Teorema de Nysquist, la base numérica de la imagen digital permite imaginizar sistemas
o situaciones complejos de forma dinámica, de las muchas repercusiones que este hecho ha tenido,
destacamos cómo el proceso ha ganado importancia sobre el resultado, dejando visibles los pasos que
el pensamiento traduce en términos de programación. No hay límite en el lenguaje ni en el pensamiento,
hay un discontinuo work in progress, que debería estar vinculado o impulsado por el marco social y
cultural, como reflejo de una época que no puede ya ordenar linealmente los acontecimientos, no
puede reflejar fijamente lo cambiante, y abre redes, ramificaciones e interconexiones.
No hay simples códigos trabajando cuando las personas interactúan con las imágenes, entre
ellos está su cultura, o su contexto. Esta es la razón por la que he insistido en la noción de
visualización (con especial referencia a lo que hacen los seres humanos), tanto en la creación
como en la respuesta, tanto en la generación como en el reconocimiento hay intersecciones entre
conocimiento, información y pensamiento2.
Podemos quedarnos a contemplar la apariencia de esa imagen-mundo como usuarios, enganchados a
los dispositivos técnicos de comunicación, o saltar la valla, no sin esfuerzo, para observar o experienciar
lo que conlleva esa espacialidad y temporalidad diferentes, moverse por niveles de complejidad, caos,
azar e iterabilidad.
geometría nació con una sombra arrojada en la cambiante superficie de la arena del desierto, ¿cómo
fijar un punto allí donde toda huella es borrada por el viento? Y de la luz que arrojó aquella sombra
comenta:
Cualquier óptico te dirá que la división claro-oscuro no es distinta más que en circunstancias
excepcionales. Y, con precisión, cuando no hay atmósfera, cuando no hay fluidos turbulentos (...)
En la atmósfera, nunca homogénea, nunca isótropa, los medios locales están distribuidos de forma
múltiple, de suerte que los rayos, así puede decirse, buscan fortuna en el mundo. Se quiebran por
doquier y ejecutan un recorrido caprichoso. Contornean pues los obstáculos y producen un clarooscuro, un confuso-distinto. Y es así como se ve lo más comúnmente del mundo. No se necesita,
donde sea y siempre, la presencia del sol. La luz se difunde. Si el ver es un modelo del saber, el
conocimiento es casi siempre difuso. En absoluto confuso y oscuro, sino multiplicado por franjas
y difracciones.4
También el sonido y la música tienen una base matemática y generan formas geométricas sinuosas,
ondas sujetas a franjas y difracciones similares a las de la luz, pero que oscilan en longitudes distintas
y con velocidad diferente.
Si para el ser humano el mundo es lenguaje (o no podemos tener otra imagen del mundo que la
***
Tal vez esta simplificación de situaciones pueda servir para clarificar inicialmente posiciones, pero
no podemos plantearnos el desarrollo del pensamiento siguiendo polaridades: pensamiento científico
por un lado y filosófico por otro. No. Como veremos, fue Leibniz quien acuñó los términos «función»,
«variable», «constante» y «parámetro» en un momento en el que, como hoy, el análisis de la lógica
pertenecía tanto al campo de la filosofía como al matemático.
Los sistemas de análisis filosófico, desde Moore o Russell, inspeccionaban todo aquello en lo que se
detiene el ojo de la mente, fragmentándolo, observando las relaciones de esos pequeños trozos de
mundo; desarticulando lo complejo en partes significativas más simples, desde los objetos materiales
a los datos de los sentidos, para articularlo después por medio de un análisis conectivo. Este mismo
sistema de análisis es la base para introducirnos y aprender a desarrollar estructuras complejas con
los lenguajes numéricos (alfanuméricos) de programación. Nuestro propósito es clarificar cómo el
pensamiento traduce las situaciones en algoritmos, utilizando estructuras de código significativas
comentadas con imágenes de resultados, explicación del proceso y su relación con referentes artísticos.
2 Burnett, Ron (2004). How images think, Massachusetts: The MIT Press, Pág. 203 [texto on-line] [06.08.2012] <http://www.
learndev.org/dl/HowImagesThink.pdf>
10
un nuevo régimen de relaciones”3 Michel Serres se sitúa mucho más atrás, para decirnos que la
que el lenguaje nos brinda), la hibridación y feedback del análisis de los lenguajes visuales, sonoros,
lingüísticos e informáticos, permite generar otras formas sintácticas de expresión, que como el mundo
actual, son más proteicas, cambiantes.
El arte contemporáneo, como generador de la parte expresiva y simbólica de este mundo, ha estado
atravesado desde los años 60 por estas nociones de feedback transdisciplinar, buscando nuevas
relaciones entre esos lenguajes para modelizar imágenes, sonidos o acontecimientos.
No vamos a desarrollar en este texto las teorías vinculadas a estos fenómenos, aunque en algunos
momentos aludamos a ellas, lo que queremos subrayar es cómo convergen los modos de comprensión
estéticos, filosóficos y científicos, a la espera de que la fascinación que nos procura esta imagen
impulse a los estudiantes a superar las dificultades o rechazos que el campo de la programación les
genera a priori.
Y en ello va también un reconocimiento, porque nuestro propio impulso debe mucho a la herencia
de Processing y openFrameworks, y también a las metodologías aportadas por Casey Reas, Ben
3 Paul Virilio, “Todas las imágenes son consanguíneas” [Texto on-line] <http://www.upv.es/laboluz/2222/textos/virilio.htm>
[07.08.2012]
4 Michel Serres, (1991). El paso del Noroeste. Madrid: Debate, pág. 48.
11
Introducción
GAmuza Hybrid live coding / modular application
Fry, Daniel Shiffman, Zachary Lieberman, Theo Watson y Arturo Castro y las comunidades de ambos
Por último señalar de nuevo que, en este contexto, el proceso toma mayor importancia que el objeto
software, por eso los contenidos de este texto van a seguir en parte los pasos aportados por estos y
acabado, y, aunque ahora tengas ante los ojos este libro materializado, o digitalizado, con una forma
otros autores.
concreta, es muy posible que nuestros ordenadores estén tramando ya otra versión de texto y software
Así, en los primeros apartados del capítulo Lenguage de Programación se van a mostrar algunos
elementos de forma comparativa con el uso del lenguaje en Processing. Pero más allá de las referencias
concretas, su influencia está latente en el deseo de entender y trasmitir el código como algo diferente
a un tutorial, a un manual de instrucciones, articulando datos informáticos con reflexiones estéticas
que esperamos amplíe, limpie y mejore esta.
Iterabilidad, inevitable cualidad de lo digital que como Sísifo remonta una y otra vez su peñasco.
.
y proyectos profesionales. Con este conjunto de nociones técnicas, teóricas e históricas esperamos
avanzar hacia una situación que supere la disyuntiva planteada por Lev Manovich.
Lo que no debemos esperar de Turing-land es un arte aceptable en Duchamp-land. Duchampland quiere arte, no la investigación de nuevas posibilidades estéticas de los nuevos medios. La
convergencia no va a suceder.5
En la parte más técnica subyace el conocimiento de la naturaleza de los elementos que propician la
interactividad, la generación de formas por el sonido, el movimiento de dispositivos por código, por
lo que conoce bien cómo se construye la casa del arte digital, sus habitáculos y aperturas al exterior,
su extenso jardín y el laberinto que contiene. Para mostrar la relación de esos elementos básicos con
los referentes artísticos recurriremos a minuciosos dibujos que, a modo de ilustraciones botánicas,
resaltarán en cada caso la cuestión a analizar, al tiempo que abren una puerta de fuga (backdoor) para
salir por caminos diferentes a los del enmarañado mundo de los derechos de publicación.
Respecto al habitual ¿cómo leer este libro?, el nivel de atención y orden de lectura es algo que depende
del background de cada uno. Como dice Derrida, “el lenguaje escrito se dirige inevitablemente a más
de una singularidad”,6 y si tú, lector particular, estás acostumbrado a utilizar software de programación,
es posible que algunas descripciones de código te parezcan obvias; esperamos que eso no consuma
tu deseo, piensa que otros posibles lectores se están iniciando, y que tanto GAmuza como este texto
buscan facilitar el aprendizaje.
Para abrir la linealidad del texto se han planteado algunas conexiones cruzadas entre determinadas
prácticas que vuelven una y otra vez con construcciones de programación diferentes, conforme se van
incorporando más estructuras en el texto. En estos casos cabe el juego de seguir las indicaciones de
páginas para, más que comparar sus distintas construcciones, observar diferentes maneras de pensar
un algoritmo.
5 Lev Manovich, “The Death of Computer Art” [texto on-line] [12.05.2012] http://www.manovich.net/TEXT/death.html.
6 Safaa Fathy, (1999) D’Ailleurs, Derrida. Gloria Films [Documental DVD]
Y Derrida continúa diciendo: “yo sé que cuando eso esté escrito, y formulado en un idioma, y por lo tanto legible, cuando la huella
sea descifrable, perderá la unicidad del destinatario, de la destinataria”.
12
13
Introducción
GAmuza Hybrid live coding / modular application
1.1. Premisas
Dilema GUI versus Code
En el campo de la enseñanza del arte digital es común ver posiciones que defienden el uso de software
libre, pero entre ellos se plantea otro dilema: el uso de software de programación gráfica, como Pure
data, o enseñar código, línea de comandos, como Processing.
1.2. Qué es GAmuza
Conscientes de estas premisas, GAmuza es un software híbrido que conjuga un entorno ScriptEditor
con distintas aplicaciones modulares para el desarrollo de diseño interactivo, la realización de
performances audiovisuales en directo y principalmente la enseñanza de arte interactivo o electrónico.
Es open-source, se distribuye bajo licencia MIT10 y está desarrollado para Linux Ubuntu x86 y para Mac
OSX 10.6 o superior. Puede descargarse en: http://www.gamuza.cc
Hay un complicado entramado de relaciones y significancias entre ambas posturas que a veces
parecen responder a campañas de índole casi publicitaria: graficos-amigables versus entornos de
programación-hostil. El adjetivo tras el guión indica el tono y posicionamiento del discurso. De nuevo el
debate entre imagen y texto (textual turn7 vs. pictorial turn8), y como hemos señalado antes, GAmuza
opta por la hibridación.
Las interfaces gráficas de usuario (GUI) de los módulos están programadas y diseñadas para facilitar
procesos de comunicación con dispositivos de audio, vídeo o Arduino, pero no para ocultar conceptos
o estructuras de programación, por eso incorpora un ScriptEditor, estableciendo una situación híbrida
Live-Coding
El núcleo central de GAmuza es el entorno Live-coding para hacer prototipos gráficos, performances
o enseñar programación visualizando las modificaciones del código de forma casi inmediata. Está
basado en el lenguaje de scripting integrable Lua11, (utilizando la librería Luabind12 y una versión
modificada de ofxLua13) y comprende toda la API OpenFrameworks14 v.007, estableciendo conexiones
de inputs/outputs entre las funciones y los módulos de aplicación.
que aúna GUI y Code.
Facilitar, para que los estudiantes, artistas o gente interesada no experta pierda el miedo a algo que
comúnmente se califica como demasiado complicado. Pero lo complicado o difícil es solo lo que no
se comprende. Por eso….
Tecnología para la gente
…GAmuza no oculta los conceptos o estructuras. Comprender las herramientas que usamos todos
los días, es el primer paso para no ser esclavo de la tecnología.
Más allá del tipo de relación que los estudiantes de arte mantienen con las tecnologías de información,
la gente en general está multiplicando el tiempo y tipo de usos con estos medios.
Se ha hecho popular publicar ideas personales, intereses, conversaciones, gustos, opiniones, fotos,
videos… Todo el mundo está en línea, desde su portátil o Smartphone, y en 5 minutos te hacen
sentir que eres el webmaster de todas tus ficciones o vidas virtuales diferentes, constantemente
conectado con todos tus amigos virtuales, y lo puedes hacer sin conocer la tecnología que estás
utilizando, y esto significa un montón de cosas, una es “gente para la tecnología”, o en otras
palabras, los medios están preparando “gente a la que vender tecnología”. Gamuza es sólo un
software, pero creado con un concepto en mente: “Tecnología para la gente”, no lo contrario.9
7 Rosalind Krauss (1966), “Welkome to the Cultural Revolution” en October, Vol. 77 [artículo on-line] <http://www9.georgetown.
edu/faculty/irvinem/theory/Krauss-October-77-1996-WelcomeToTheCulturalRevolution.pdf > [30.08.2012]
8 Liderado en gran medida por W. J. T. Mitchell <http://humanities.uchicago.edu/faculty/mitchell/home.htm> [30.08.2012]
9 Mazza, Emanuele, “Why Gamuza” [texto on-line] <http://gamuza.d3cod3.org/about/concept/> [11.05.2012]
14
Sistema modular
GAmuza comprende distintas aplicaciones modulares fácilmente configurables a través de GUI. Cada
uno de estos módulos puede activarse, o no, en función del tipo de trabajo a realizar y para reducir el
consumo del equipo. Los módulos activos enlazan directamente con las funciones y variables de salida
del ScrpitEditor. Actualmente los módulos son:
• Computer vision
• Sensor Kinect
• Audio input, output
• Arduino
En resumen, GAmuza es un software que recoge y coordina de forma particular lenguajes (Lua y C++) y
plataformas (openFrameworks, openCV) ya existentes, e incorpora otras librerías propias, para facilitar
los primeros pasos de estudiantes y artistas en el campo de la programación creativa. Por otra parte,
combina las dos vías habituales de programación: consola de código textual (ScriptEditor) vinculada
10 MIT License <http://mit-license.org/> [11.05.2012]
11 The programming language Lua <http://www.lua.org/> [11.05.2012]
12 Luabind es una librería que ayuda a crear enlaces entre C++ y Lua. Ver http://www.rasterbar.com/products/luabind.html
[12.05.2012]
13 ofxLua es un addon de Open Frameworks para que funcionen scripts Lua incrustados dentro de una aplicación OpenFrameworks.
Ver https://github.com/danomatika/ofxLua [12.05.2012]
14 openFrameworks <http://www.openframeworks.cc/> [12.05.2012]
15
Introducción
GAmuza Hybrid live coding / modular application
a las aplicaciones modulares que se ajustan mediante GUI, para que ese proceso de aprendizaje
creativo sea más fácil, pero sin ocultar las estructuras de programación. Para hacer funcionar esta
hibridación se han programado librerías específicas de GAmuza, que como veremos más adelante, se
diferencian sintácticamente de las retomadas de otras plataformas. Retomando un término de Armando
Montesinos, GAmuza más que un collage de lenguajes y plataformas, reconstruye un entorno de
programación por medio de “zurcidos”, utiliza parches y genera tejido nuevo entrecruzando funciones,
sin ocultar los fragmentos.
La facilidad de uso de GAmuza reside en la simplificación del lenguaje Lua (en sí bastante ligero) y la
comunicación de dispositivos externos por los módulos GUI, manteniendo la estabilidad y potencia del
lenguaje C++.
1.3. Instalación
GAmuza está programado para funcionar en mac OSX 10.6 (Snow Leopard) y 10.7 (Lion) y en Ubuntu
Linux x86.
Mac OSX
Desde <http://gamuza.d3cod3.org> descargar la aplicación, abrir (montar) el archivo .dmg y arrastrar
el icono de GAmuza al acceso directo de la carpeta Aplicaciones, tal como indica la flecha en la
imagen. El proceso de instalación ha terminado.
El lenguaje de programación en el ScriptEditor aglutina el uso de código en lenguaje Lua15 con funciones
propias de openFrameworks16 y otras funciones específicas de GAmuza que comunican directamente
con los datos de entrada y salida de las interfaces gráficas de los módulos. Es importante entender esta
movilidad o flexibilidad de niveles y lenguajes.
Si abrimos la carpeta de GAmuza veremos que contiene dos aplicaciones: ScripEditor y GAmuza.
Ubuntu Linux x86
Descargar el archivo .tar.gz desde <http://gamuza.d3cod3.org>, abrir la ventana del Terminal y escribir:
tar xvfz GAmuza-xxxx-Linux.tar.gz
-- sustituid -xxxx- por el nº de la versión descargada de GAmuza
Esto creará una carpeta llamada GAmuza, después cambiamos al directorio
cd GAmuza
Abrir la carpeta install y ejecutar el archivo
cd install && sudo sh 00_install_dependencies.sh
15 The language programing Lua <http://www.lua.org/> [11.06.2012]
16 openFrameworks <http://www.openframeworks.cc/documentation/> [10.06.2012]
16
Después
17
Introducción
GAmuza Hybrid live coding / modular application
sudo sh 01_get_GAmuza_source.sh
En algunas versiones de Linux a veces aparece un error relacionado con el archivo /usr/include/
c++/4.5/complex;
En tal caso, editar el archivo
sudo gedit /usr/include/c++/4.5/complex
Ir a la línea 953, donde está la función template, inline complex, pow
#ifndef __GXX_EXPERIMENTAL_CXX0X__
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 844. complex pow return type is ambiguous. template
inline complex
ScriptEditor:
• En Mac hay una aplicación independiente para escribir el código.
• En Linux está integrado en el módulo Live Coding. Puede escribirse el código directamente
ahí, o usar cualquier editor de texto, guardar el script como archivo .txt, .lua, o .ga y abrirlo
desde el botón “Load script” situado en la parte inferior de Live Coding, igualmente pueden
guardarse los scripts desde “Save script”.
Setting Manager.
• En Linux es una aplicación independiente que se ajusta antes de iniciar GAmuza, si previamente
no se había configurado el proyecto.
• En mac está incluida como una pestaña más de los módulos. Tras configurar el proyecto
debe reiniciarse GAmuza
Teclas de comando.
• Hay atajos de taclado para Mac y Linux, y otros específicamente para Linux [ver página xxx]
pow(const complex& __z, int __n)
{ return std::__pow_helper(__z, __n); }
#endif
y comentar la función completa
#ifndef __GXX_EXPERIMENTAL_CXX0X__
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 844. complex pow return type is ambiguous. /* template
inline complex
pow(const complex& __z, int __n)
{ return std::__pow_helper(__z, __n); }*/
#endif
Después, ejecutar 02_install_GAmuza.sh
–
sudo sh 02_install_GAmuza.sh
GAmuza tiene una configuración de aplicaciones diferente en Mac OSX y Linux x86.
Las principales diferencias son:
18
19
Introducción
GAmuza Hybrid live coding / modular application
1.4. ScriptEditor
ScriptEditor solo está disponible en Mac. Al abrir la aplicación se activan tanto el editor de texto como
GAmuza. Las dos son independientes pero vinculadas por OSC. Puede cerrarse una de ellas y la otra
seguirá activa.
1.5. Comandos de teclado
Para compatibilizar y optimizar las posibilidades de GAmuza se han programado comandos de
teclado, es recomendable conocerlos antes de utilizar las interfaces de los módulos de aplicación.
La combinación se realiza prioritariamente con la tecla Alt para evitar duplicidades con los sistemas
operativos, pero manteniendo dentro de lo posible la letra habitual para facilitar su aprendizaje:
Mac OSX y Linux
Alt+f. Poner/quitar la aplicación a pantalla completa. Para que se active la segunda pantalla es
necesario que esté en pantalla completa.
Alt+j. Amplia/reduce el tamaño de ventana del previo en la interface Live coding.
Alt+w. Mostrar/ocultar el script sobre la ventana de salida o el previo ampliado.
Alt+t. Mostrar/ocultar el Timeline
Alt+g. Reproducir/Parar el Timeline
Alt+p. Imprimir el frame actual, hace falta una impresora conectada al ordenador.
La interface del ScriptEditor sigue directamente el modelo marcado por el PDE Processing, como epígono
de una de sus influencias directas. Principalmente aporta un editor de texto para el código que en su parte
superior dispone un menú y barra de herramientas, y en su parte inferior una consola de salida.
En el menú desplegable superior se encuentra: File (abrir, guardar, cerrar, imprimir...), Edit (deshacer, rehacer,
cortar,copiar, pegar, borrar, seleccionar todo, encontrar, reemplazar...), Script (enviar a GAmuza, borrar
consola), Tools (selector de color). Y en la barra de herramientas unos botones para facilitar las labores
Alt+r. Procesa el script. Hay también un botón en la interface para hacerlo.
Alt+d. Abrir un script guardado (aparece un cuadro de diálogo para seleccionarlo)
Alt+s. Guardar el script, lo hace directamente en la carpeta GAmuza/data/scripts con el nombre
“gamuzaScript_xxxxxxxxxx.lua” donde las x corresponden a: año mes día hora minutos
segundos
usuales: enviar a GAmuza, limpiar script, nuevo script, abrir script y guardar como y limpiar consola.
Ctrl+x. Cortar (información solo utilizable en la propia consola live coding)
El editor de texto tiene una columna numerada a la izquierda para facilitar la localización de errores.
Ctrl+c. Copiar (información solo utilizable en la propia consola live coding)
También asigna una serie de colores a términos que reconoce vinculados a:
Ctrl+v. Pegar (información que proviene de la propia consola live coding)
• Funciones y términos de GAmuza: naranja of.setColor(255)
• Constantes, azul OUTPUT_W
• openGL: funciones, azul turquesa y constantes: marrón pardo glBegin(GL_QUADS)
• Strings (cadena caracteres entrecomillados): rojo “texto entrecomillado”
• Comentarios: gris // comentario
• Negro para todo lo demás. x = 125
20
Sólo en Linux
Alt+a. Seleccionar todo el texto
Alt+e. Limpiar editor (borrar todo el código)
Alt+b. Ampliar el tamaño del cursor momentáneamente para verlo con facilidad.
21
2. Interface. Módulos de aplicación
En realidad, la tarea de descifrar las historias una por una me ha hecho descuidar hasta ahora la
peculiaridad más saliente de nuestro modo de narrar, a saber, que todo relato corre al encuentro
de otro relato y mientras un comensal avanza en su fila, desde la otra punta avanza otro en sentido
opuesto, porque las historias contadas de izquierda a derecha o de abajo hacia arriba pueden
también leerse de derecha a izquierda o de arriba hacia abajo, y viceversa17
Italo Calvino
Cuando se abre GAmuza, desde ScriptEditor o directamente, la primera interface que aparece es el
módulo Live coding. En su parte superior hay una serie de rectángulos de color, estos rectángulos son
las pestañas que indican los módulos que están activos y dan acceso a ellos. Tal como advierte Italo
Calvino, toda estructura modular puede describirse siguiendo direcciones distintas.
2.1. Setting Manager
Vamos a empezar a describir la última pestaña blanca de la versión para Mac OSX que corresponde al
Setting Manager (en linux la aplicación SettingManager.app es independiente y está en la carpeta de
GAmuza). Con esta interface se activan o desactivan los módulos y se ajusta su configuración.
No es necesario, ni recomendable, tener módulos activos si no se van a utilizar, porque supone un
consumo innecesario de los recursos del sistema. Al abrir GAmuza, un buen hábito de inicio es ir
al Setting Manager, ajustar la configuración de GAmuza a las características del ordenador y las
necesidades del proyecto.
Pasamos a describir la interface del Setting Manager, a partir de su imagen general y analizando
después paso a paso los elementos configurables de cada módulo.
17 Italo Calvino (1993), El Castillo de los destinos cruzados. Madrid: Siruela, pág. 37.
22
23
GAmuza Hybrid live coding / modular application
24
Interface. Módulos de aplicación
25
Interface. Módulos de aplicación
GAmuza Hybrid live coding / modular application
El primer grupo de opciones se refiere a los módulos GUI, simplemente hay que seleccionar o
deseleccionar los módulos que se quieren activar o desactivar, clicando en el cuadrado que hay a la
OUTPUT MAPPING
izquierda de los nombres. Las opciones son.
GAmuza genera una rejilla sobre la imagen de salida para
MODULES
el número de nodos de esa rejilla, desde un mínimo de 1
proyecciones de mapping. Con un slider se puede elegir
SENSOR KINECT -- Tracking con el sensor Kinect
(significa que el rectángulo de la proyección tiene un punto de
COMPUTER VISION
-- con otras cámaras que reconozca el ordenador
la proyección según las necesidades), a un máximo de 20 (la
AUDIO STREAM (INPUT/OUTPUT)
-- análisis de entrada y/o salida de audio
ARDUINO
-- trabajar con el microcontrolador
ajuste activo en cada vértice, con los que se puede deformar
imagen tiene 400 rectángulos ajustables).
Imagen con 8 nodos de mapping, 64 rectángulos ajustables.
Arduino
IMPORTANTE, si se activa el módulo Sensor Kinect, por ejemplo, y no está la Kinect conectada
al ordenador, muy probablemente GAmuza se cerrará al no encontrar el dispositivo. Lo
mismo se recomienda para los otros módulos, no deben activarse si no están los dispositivos
apropiados conectados.
SCREENS
MAIN SCREEN: abre un menú desplegable para seleccionar la
resolución de la pantalla principal. La resolución mínima para visualizar
AUTOMATION (INSTALATION MODE)
Opción pensada para la presentación de instalaciones. Permite
seleccionar un script, “Choose script”, abriendo una ventana de
diálogo para elegirlo dentro del ordenador. Si se activa “Autoload
script on start” GAmuza se inicia con ese script. Y por último, si se
activa “Auto fullscreen” al abrirse el programa, está directamente a
pantalla completa y procesando el script seleccionado.
GAmuza es 1280x 800 píxeles.
COMPUTER VISION
SECONDARY SCREEN: menú desplegable para seleccionar la resolución de la segunda pantalla, (se
corresponde al tamaño de la ventana de salida). En ambos casos,
elegir según la resolución de los monitores o proyectores que se
utilicen. Las últimas opciones hacen referencia al uso de tarjetas que
duplican o triplican el tamaño de la ventana de salida. Si hay una de
estas tarjetas conectada y el ordenador la reconoce, GAmuza genera
una ventana de salida para sus dimensiones.
Si se cambian las dimensiones de la segunda pantalla hay que
resetear los ajustes del mapping en el módulo de Live Coding. O
cargar un archivo de mapping si previamente se había guardado uno
para las nuevas dimensiones de pantalla.
26
Estas opciones se ajustan si el módulo Computer Vision está
seleccionado. USE TESTING VIDEO ofrece la posibilidad de utilizar
un archivo de video como test, es decir, desactiva la webcam o
cámaras de video, y utiliza los algoritmos y ajustes de tracking video
sobre el archivo de video seleccionado con CHOOSE VIDEO.
La opción CHOOSE HAAR FINDER File permite elegir el algoritmo de
reconocimiento de partes del cuerpo. Por defecto, GAmuza carga
el reconocimiento de rostro frontal, para cambiarlo, al clicar esta
opción se abre una ventana de diálogo y hay seleccionarla en la
carpeta: GAMUZA/DATA/SETTINGS/HAARXML, o donde uno tenga
ficheros .xml de haar cascade.
27
Interface. Módulos de aplicación
GAmuza Hybrid live coding / modular application
SENSOR KINECT
ARDUINO
Esta sección solo se utiliza si se ha activado el módulo Sensor Kinect.
Como en los casos anteriores, esta sección del Setting Manager solo
Las opciones son simples, se puede activar el uso de visión infrarroja,
se ajusta si el módulo de Arduino está seleccionado.
si no kinect utilizará visión normal. En el menú desplegable de abajo
se puede desactivar el led frontal del sensor kinect (OFF), y si quiere
utilizarse, se puede elegir el color del Led y si parpadea o no:
BAUDRATE (57600 por defecto) y SERIAL PORT (el puerto serie).
Puede utilizarse el software de Arduino para comprobar mediante el
Serial Monitor cuál es el puerto asignado y seleccionar en GAmuza
el mismo.
AUDIO STREAM (INPUT/OUTPUT)
Esta sección se ajusta solo si el módulo del mismo nombre está
activado.
Lo primero es seleccionar AUDIO DEVICE, el dispositivo de audio
con el que trabajará GAmuza. El menú desplegable muestra los que
están accesibles en el ordenador.
OSC ENGINE
Ajustes para el protocolo de transferencia de datos OSC, se
introducen directamente en el campo de texto. Los dos primeros
SENDING TO IP y SENDING TO PORT envían datos a un ordenador
con el número de IP y puerto que se pongan. El último, RECEIVING
AT PORT indica el puerto de este ordenador que recogerá los datos
enviados desde otro.
En la opción SAMPLING RATE (Frecuencia de muestreo) hay que
seleccionar una acorde con el dispositivo: en la consola de texto del
Setting Manager aparecen todos los dispositivos de audio que reconoce
el sistema con el Sample Rate que soportan.
En BUFFER SIZE, seleccionar el tamaño de Buffer con que se va
a trabajar (cantidad de muestras almacenadas), 512 es un tamaño
válido para la mayoría de los proyectos, porque no produce clics o
chasquidos en el audio, si se trabaja con Bins o FFT (ver pág. xxx)
En linux estas opciones se pueden modificar en el archivo de
configuración setingManager.xml
MIDI
Aunque no existe un módulo de MIDI, se pueden recoger datos
de estos dispositivos y hay funciones específicas de GAmuza para
comunicar con ellos.
MIDI INPUT
MIDI DEVICE
Vestax PC-CONTROLLER
puede requir un tamaño mayor, hay que tener en cuenta que a mayor
buffer más recursos de procesador consume.
Tras seleccionar las opciones necesarias hay que guardar la configuración clicando Save en la parte
superior de la interface. Diferencias entre Mac y Linux:
Algunos ordenadores tienen la entrada y salida de audio por separado,
si se selecciona el dispositivo de entrada, no se pueden generar
sonidos de salida. La mayoría de las tarjetas de audio presentan la
opción de entrada y salida juntas, por lo que permiten hacer ambas.
Mac: se abrirá un cuadro de diálogo para seleccionar la capeta donde se quieran guardar los ajustes,
GAmuza genera un archivo XML con la configuración. Antes de empezar a trabajar con GAmuza,
clicar Restart (botón superior izquierdo) para que se reinicie el programa con los ajustes realizados.
También puede cargarse un archivo de configuración que ha sido previamente guardado.
Linux: se guardan los cambios directamente en el archivo gamuzaSettings.xml. Cerrar la aplicación
SettingManager.app y volver a abrir GAmuza.
28
29
GAmuza Hybrid live coding / modular application
30
Interface. Módulos de aplicación
31
Interface. Módulos de aplicación
GAmuza Hybrid live coding / modular application
2.2. Live Coding
MAPPING SETTING
Hace referencia a la rejilla de mapping con las siguiente opciones:
• Activa/desactiva que se muestre la rejilla
Los algoritmos son pensamientos, las motosierras son herramientas18.
• Resetea los cambios (vuelve al estado regular)
• Abrir una configuración previamente guardada.
• Guardar la configuración del mapping
Live coding significa programar en directo, un término vinculado tanto a los entornos de programación
con un tiempo de compilación infraleve —‘just in time programming’ o ‘real time’—, como a la
realización de directos de audio y/o imagen que utilizan esos entornos, y donde la presencia del código
como imagen o sobre la imagen que generan, es uno de los rasgos que lo caracterizan.
Los software de Live Coding, Fluxus19 y Zajal20, fueron los que más influyeron en el desarrollo de
COLOR CORRECTION SETTINGS Ajustar ecolor y aplicar efectos:
• GAMMA CORRECTION: ajusta la “sensación” de contraste de
la imagen si se percibe blanquecina o “lavada”.
• BRIGHTNESS: ajusta el brillo de la imagen.
GAmuza. Fluxus es un entorno de progración en tiempo real basado en C++ / Scheme y desarrollado
• SATURATION: satura o desatura el color de la imagen.
por Artem Baguinski. Zajal es un lenguaje de programación creativo, basado en Ruby y que funciona
• CONTRAST: ajusta el contraste.
bajo openframeworks, desarrollado por Ramsey Nasser.
Siguiendo sus pasos, en las primeras
versiones de GAmuza, hasta rel.0398,
el código se escribía directamente en el
módulo de Live Coding, y aun es así en
GAmuza para Linux. En la versión 041 para
Mac OSX el sistema Live coding se hibrida
un paso más, el código puede mostrarse
• FILM BLEACH: emulación de una técnica de revelado
analógico que produce contraste alto y saturación baja.
También llamado Bleach Bypass.
• FILM TECHNICOLOR: emulación del rango de color de los
TV de tubo catódico de los 80’s.
• FILM FORCE B&W: Los tres últimos filtros están relacionados
y el ajuste de uno repercute en los otros. Este aporta otra
forma para desaturar.
en la ventana de salida, pero cuenta con
• FILM WHITE EXPOSURE: ajusta la sensación de luz.
un editor independiente, combinando
• FILM WHITE DIFFUSION: emulación del uso de filtros de
gelatina White Diffusion para suavizar sombras.
las necesidades de las performances en
directo con su uso para la enseñanza de
programación.
En el módulo de Live Coding existen también opciones de ajuste y, como en la interface anterior,
pasamos a describirlas individualmente.
VIDEO OUTPUT SETTINGS
• Activa/desactiva la segunda pantalla. Para que se visualice
GAmuza debe estar a Pantalla completa: Alt+f
• USE VERTICAL SYNC: sincroniza el número de frames con
la tasa de refresco de la tarjeta gráfica, para reducir defectos
visuales, como bandas o parpadeos y tener frames constantes
Bajo la ventana del previo de vídeo, hay un monitor de los fotogramas
18 Stephen Ramsay, Algorithms are Thoughts, Chainsaws are Tools. [video on-line] <https://vimeo.com/9790850> [04.09.2012]
19 (Fluxus) <http://www.pawfal.org/fluxus/> [03.09.2012]
20 Zajal, < http://zajal.cc/> [03.09.2012]
32
por segundo a los que está procesando GAmuza, si se selecciona
Vertical Sync se puede observar el cambio.
33
GAmuza Hybrid live coding / modular application
34
Interface. Módulos de aplicación
35
Interface. Módulos de aplicación
GAmuza Hybrid live coding / modular application
2.2.1. Timeline
El Timeline21 no es exactamente un módulo de aplicación GUI, sino una ampliación del Live coding
Los sistemas de tracking video están vinculados al
para facilitar la programación, con la que se puede visualizar el tiempo, poner keyframes (fotogramas-
campo de computer vision, su aplicación en el ámbito
clave) y triggers (etiquetas). Las pistas de keyframe se definen con código en el ScriptEditor, utilizando
del arte proporciona una información importante para
la función de GAmuza ga.addTimelineKeyframes(), que lleva 4 parámetros: “nombreVariable”,
explorar nuevos modos de conexión e interactividad
mínimo de la variable, Valor máximo.
del mundo digital. A través del ojo de la cámara, el
“nombreVariable.xml” (genera un fichero que almacena los datos de esa línea del timeline), Valor
Se pueden hacer tantas líneas de keyframe como funciones se pongan, en la imagen se han definido
2, cuyos nombres de variable son; posX y posY. La duración en frames se determina con la función
ga.setTimelineFrames() (ver página xxxx). Una vez generada la línea, los keyframes se sitúan
temporalmente clicando con el ratón sobre el frame deseado, se pueden desplazar con el ratón, o
borrarlos. La transición entre un keyframe y otro se establece mediante unas reglas de interpolación
que que se visualizan clicando con el botón derecho sobre el keyframe, mostrando las siguientes
opciones:
• lineal
• curva sinusoide
• circular
• parábola de una función cuadrática
• cúbica
• quíntica (ecuación polinómica de quinto grado)
• exponencial
• técnicas de backoff
• con rebotes
• elástica
En todas ellas se puede añadir la característica:
entre el cuerpo físico del espectador y la representación
sistema puede reconocer posiciones, movimientos,
colores, gestos, rostros, dentro de su campo visual,
siempre que las condiciones de iluminación sean
favorables.
Conociendo esos datos, se pueden programar
aplicaciones ante las que el espectador puede
interactuar de forma más intuitiva, denominándose por
ello interfaces gestuales, es decir, se interactúa con la
pieza sin tocar botones u otros interfaces físicos. En
el arte interactivo y electrónico son numerosos los
ejemplos de este tipo de aplicaciones, que también ha
incrementado su presencia en las artes escénicas.
Estos dos ejemplos mantienen una relación inversa
entre obra y el espectador. En Bubbles , una de las
piezas pioneras de arte interactivo con tracking video,
el espectador juega con las formas proyectadas,
modificando su movimiento al colisionar con su
sombra. En Body Navigation23, el cuerpo de los
bailarines genera las formas. Aunque en ambos casos,
es el sistema el que las modifica o produce al conocer
• entrada y salida suavizada
o de los bailarines.
activan un evento, actúan como etiquetas reconocibles, reduciendo mucho las líneas que deberían
escribirse en el script si estos elementos, keyframes y triggers, no estuvieran.
La línea inferior del Timeline actúa como un escalímetro para ampliar/reducir su tamaño.También puede
regularse la altura de las líneas de keyFrame con el ratón
21 La base del TimeLine procede de James George, ofxTimeline <http://jamesgeorge.org/opensource.html> [12.08.2012]
Basado en Bubbles, (2002) W. Muench y K. Furukawa
22
• entrada suavizada
• salida suavizada
La pista inferior se denomina Trigger. Los trigger son elementos que
36
2.3. Tracking Video
con precisión la posición del cuerpo del espectador
Basado en Body Navigation (2008) O. Kristensen y J. Jongejan
El tracking de movimiento, colores o formas puede utilizarse también para generar o modificar sonidos,
activar o desactivar dispositivos, simplemente hay que comprender su procedimiento.
Por ello, a continuación se describe la interface del módulo Computer Visión que cubriría las primeras
fases de este proceso: analizar determinadas características de algo exterior, recoger datos de su
comportamiento, seleccionar y/o ajustar esos datos, para después generar con ellos otra situación que
responda en tiempo real a sus cambios. 22 Bubbles, (2002) W. Muench y K. Furukawa <http://at.zkm.de/node/193 > [10.07.2012]
23 Body Navigation (2008) O. Kristensen y J. Jongejan <https://vimeo.com/1362832 > [10.07.2012]
37
GAmuza Hybrid live coding / modular application
38
Interface. Módulos de aplicación
39
Interface. Módulos de aplicación
GAmuza Hybrid live coding / modular application
2.3.1. Computer vision
GENERAL SETTINGS
FLIP SOURCE IMAGE voltea la imagen-video que proviene de la
El módulo Computer vision24 se corresponde con la pestaña roja y
facilita la aplicación de algoritmos para tracking video, permitiendo
regular con sliders, menús y botones las condiciones básicas de
entrada de datos al sistema. Como en el apartado Live coding,
pasamos a describir su interface.
El monitor de entrada de la señal video, COLOR INPUT, permite
reducir el área a trackear, este crop se ajusta arrastrando con el
ratón los puntos resaltados de los vértices. Los demás monitores
muestran solo la zona seleccionada. El crop se resetea con RESET
cámara, su ajuste depende de las condiciones de exhibición:
• OFF: la imagen se percibe sin ningún cambio
• HORIZONTAL: se selecciona cuando los movimientos ante
la imagen responden al efecto de estar frente a un espejo.
• VERTICAL: imagen video cabeza abajo.
• HORIZONTAL + VERTICAL: voltea en los dos sentidos.
SOURCE BLUR: desenfoque de la imagen de entrada de video.
CONTRAST: contraste. BRIGHTNESS: brillo.
QUAD WARPING.
USE DEVICE. Activa/desactiva el módulo, cuando no se utiliza pero sí
se usará después, sin tener que reiniciar el programa.
UNDISTORT (LENS CORRECCTION), sirve para desactivar ajustes
previos hechos con la aplicación Lens Correction25.
El monitor BALANCED TRACKING muestra el resultado de todos los
algoritmos de tracking seleccionados y ajustados con los sliders,
menús y botones del bloque derecho.
CAPTURE BACKGROUND, al clicar el botón se captura un frame de la
imagen video que debe corresponder con el fondo. Esta imagen se
BACKGROUND SUBTRACTION SETTINGS
SUBSTRACTION TECHNIQUE, seleccionar entre:
• COLOR ABS: color absoluto
• B&W ABS: blanco y negro absoluto
• LIGHTER THAN. Cuando la figura a trackear es más clara
que el fondo.
• DARKEN THAN. Cuando La figura a trackear es más oscura
que el fondo.
SUBSTRACTION THRESHOLD, ajusta el umbral de detección.
toma como referencia para comparar los cambios que se producen
BLUR, desenfoca la imagen procesada
entre el valor de sus píxeles y el de los frames de la imagen a trackear,
ERODE, reduce las superficies detectadas
aplicando el algoritmo Background Subtraction. Es el primer nivel
para el cálculo de Tracking, y siempre activo. Según las condicones
DILATE, expande las superficies detectadas
de íluminación, puede mejorarse la imagen activando USE CONTRAST
STRETCH: incrementa el rango de los valores más intensos de la imagen
40
en escala de grises.
OSC DATA SETTINGS
El resultado de BACKGROUND SUBSTRACTION se ve en el monitor
USE KALMAN FILTER. En la transferencia de datos a otras
inferior.
aplicaciones, el filtro de Kalman suaviza los cambios grandes entre
24 Las aplicaciones de tracking video se han articulado en dos interfaces diferentes por las particularidades técnicas del sensor
kinect, por ello en este módulo nos referiremos al uso de cualquier webCam o cámara de vídeo conectada y que el ordenador
reconozca
25 Lens Correction es una aplicación, disponble en la web de GAmuza, diseñada para corregir las aberraciones de las ópticas.
establecidos.
los valores obtenidos, desechando aquellos que superan unos límites
SMOOTHING FACTOR ajustar el rango de suavizado.
41
Interface. Módulos de aplicación
GAmuza Hybrid live coding / modular application
USE COLOR TRACKING
Las opciones de ajuste son:
Color Tracking es un algoritmo de reconocimiento del color. Requiere
condiciones de iluminación estables y la elección de un color de
HUE, selecciona el tono a trackear según la escala de valores de GAmuza
entre 0 y 1. La franja de color sirve de orientación.
seguimiento muy diferenciado del contexto.
HUE RANGE, amplía el rango del tono seleccionado.
USE COLOR TRACKING, activa/desactiva su uso y los resultados se
SATURATION, asigna el nivel de saturación del tono (hue)
seleccionado. El valor 0 es igual a blanco, 1 es el tono puro,
dependiendo del nivel de luminosidad (value).
ven en el monitor inferior.
SATURATION RANGE, amplia el rango de saturación seleccionado.
COLOR TRACKING SETTINGS
La configuración de este bloque solo se ajustan si está activado USE COLOR TRACKING. El Tracking Color
transforma el espacio de color RGB al sistema HSV, porque asigna los vaores del tono del color de una
VALUE, regula el nivel de luminosidad (value) del tono. El valor 0
es igual a negro, 1 es igual al tono puro, dependiendo del valor de
saturación.
VALUE RANGE, amplía el rango de luminosidad seleccionado.
HSV BLUR, filtro de desenfoque de la imagen en HSV.
forma más estable. HSV identifica cada tono con un número que va de 0ª a 360ª según su posición en el
ERODE, reduce las superficies detectadas.
círculo cromático; en GAmuza el rango va de 0 a 1 quedando su equivalencia tal como muestra la imagen.
DILATE, expande las superficies detectadas.
BLOB TRACKING SETTINGS
Los blob son las zonas independientes que el tracking
detecta según los algoritmos seleccionados, sus opciones de
configuración son:
MIN BLOB, tamaño mínimo de los blobs en píxeles.
MAX BLOB, tamaño máximo.
CONTOUR DETAILL, el detalle del contorno se puede ajusta en:
• RAW, todo el perímetro tal cual es
• SMOOTH, suavizado
• SIMPLE, adaptado a formas geométricas simples
CONTOUR SMOOTH FACTOR, si se ha seleccionado smooth, ajusta
el nivel de suavizado
CONTOUR SIMPLE TOLERANCE, si se ha seleccionado simple,
ajusta el rango de vértices que articulan el contorno.
42
43
Interface. Módulos de aplicación
GAmuza Hybrid live coding / modular application
MOTION DETECTION SETTINGS
COMPUTING ALGORITHM SELECTOR
El algoritmo para detección de movimiento está siempre activo. El
En este bloque se seleccionan otros algoritmos específicos que se pueden aplicar, además de los
monitor MOTION DETECTION muestra el cálculo de la cantidad de
movimiento que se registra en la imagen y señala la posición media
de ese movimiento. Los ajustes para su configuración son:
mencionados hasta ahora.
COMPUTE CONTOUR FINDER, para procesar el contorno de las zonas
detectadas. Sus valores se ajustan con BLOB TRACKING SETTINGS.
COMPUTE OPTICAL FLOW, calcula el flujo óptico del movimiento y lo
• MOTION THRESHOLD, regula la sensibiliad del sistema para
activar la detección, si es poco sensible se debe ampliar el
umbral (Threshold)
• MOTION NOISE COMPENSATION, compensa el ruido de la
señal de imagen video
• MOTION TRIGGER LOW LIMIT, nivel más bajo para activar la
detección de movimiento
• MOTION TRIGGER RANGE LIMIT, limita los niveles de
movimiento, como si bajara la sensibilidad de detección.
describe con vectores que indican la dirección e intensidad.
COMPUTE HAAR FINDER, activa el algoritmo para detectar partes
del cuerpo humano. Hay distintos algoritmos posibles y debe
seleccionarse previamente en el Setting Manager (ver página XXX).
Por defecto, está seleccionado FRONTALFACE_ALT.
COMPUTE TRIGGER AREAS. Activa la posibilidad
de utilizar 8 zonas circulares, que están
numeradas para su identificación. Su posición y
tamaño pueden ajustarse con el ratón; con ellas
se pueden determinar las áreas en las que debe
responder el tracking utilizando las funciones
específicas de GAmuza para ello (ver página XXX)
BALANCED TRACKING SETTINGS
Si hay varias cámaras conectadas al ordenador, habrá un interface Computer Visión para cada una de
Vuelve a ajustar, en conjunto, los valores dados en cada sección.
una interface diferente que puede ajustarse independientemente.
ellas, es decir, si hay dos cámaras conectadas al ordenador, habrán dos pestañas rojas, cada una abre
• BALANCED TRACKING BLUR, ajusta el nivel de desenfoque
global,
• ERODE, reduce las superficies detectadas
• DILATE, expande las superficies detectadas
44
45
GAmuza Hybrid live coding / modular application
Interface. Módulos de aplicación
2.3.2. Sensor Kinect
46
47
Interface. Módulos de aplicación
GAmuza Hybrid live coding / modular application
La configuraación del módulo kinect mantiene muchas semejanzas
con el de computer visión, excepto en las particularidades del sensor.
RECORD DEPTH: Los dos sliders bajo el monitor permiten ajustar y
GENERAL SETINGS
SENSOR KINECT BLUR: grado de desenfoque de la señal de entrada
visualizar el rango de profundidad a detectar:
ERODE: reducir el área de las superficies detectadas
• NEAR TRESHOLD: determina el plano de los elementos más
próximos, como mínimo desde 70 cm del sensor.
DILATE: ampliar el área de las superficies detectadas
• FAR TRESHOLD: hasta qué plano de profundidad se quiere detectar,
como máximo 6 m.
BLOB TRACKING SETTINGS
MIN BLOB: tamaño mínimo de los blobs
MAX BLOB: tamaño máximo de los blobs
CONTOUR DETAIL: menú con tres opciones, raw, smooth o simple
DEPTH RANGE MASK: monitor que muestra el resultado de los
algoritmos aplicados.
USE KINECT HANDS TRACKING: activa el sistema de detección de
manos, se representa en el monitor de la imagen anterior con puntos
amarillos.
CONTOUR SMOOTH FACTOR, si se ha seleccionado smooth, ajusta el
nivel de suavizado
CONTOUR SIMPLE TOLERANCE, si se ha seleccionado simple, ajusta
el rango de vértices que articulan el contorno.
COMPUTING ALGORITHM SELECTOR
COMPUTE CONTOUR FINDER, para procesar el contorno de las zonas
detectadas. Los valores se ajustan con BLOB TRACKING SETTINGS.
COMPUTE OPTICAL FLOW, calcula el flujo óptico del movimiento y lo
MOTION DETECTION SETTINGS: puede regular la detección de
describe con vectores que indican la dirección e intensidad.
movimiento según niveles de profundidad.
COMPUTE CONTOUR GEOMETRY, determina formas geométricas a
• MOTION TRESHOLD: porcentaje de datos de la detección de
movimiento tortal
anterior si no lo estaba.
• MOTION TRIGGER LOW LIMIT: porcentaje de datos de movimiento
en los planos próximos
• MOTION TRIGGER RANGE LIMIT: porcentaje de datos de
movimiento en los zonas alejadas.
partir de los contornos. Al activarlo se activa automáticamente el
COMPUTE TRIGGER AREAS. Activa la posibilidad de utilizar 8 zonas
circulares, como en el módulo computer vision.
SENSOR KINECT HARDWARE
recoge datos de los sensores internos
SENSOR TILLT: datos de inclinación
ACCELEROMETER X, Y, Z: datos independientes del acelerómetro en
los ejes x, y y z
48
49
Interface. Módulos de aplicación
GAmuza Hybrid live coding / modular application
2.4. Análisis del audio en arte sonoro
Lo natural es que todos los sentidos reciban información. Lo antinatural es el aislamiento de los sentidos.26
El sonido es un medio pasajero que se mueve en el tiempo, difícil de asir, pero la incorporación del
audio en los medios digitales como un elemento casi propio, ha modificado nuestra relación con él,
cambiando los hábitos de escucha y percepción del sonido. Sin perder su cualidad temporal se ha
incrementado mucho su capacidad espacial. En el campo del arte estos cambios se ven reflejados en
las instalaciones de arte sonoro o en las actuaciones de música con visuales, eventos que en muchos
casos han ido borrando la distancia que los separaba, al incorporar sonido espacializado o propuestas
sinestésicas entre audio, vídeo, luz y/o gráficos, estableciendo conexiones directas o indirectas ente la
la materialidad de lo sonoro con la sonoridad de lo visual. El propio sistema Live coding en que se basa
GAmuza es consecuencia o reflejo de estos cambios.
Muchas de estas propuestas artísticas requieren el análisis de los parámetros del sonido. Para el
sistema estos datos suponen solo valores numéricos que pueden aplicarse para producir otras
situaciones sonoras, visuales o físicas, y es la casi simultaneidad de los cambios que se producen en
el sonido analizado y en la respuesta generada la establece un efecto empático ente ambas.
Métodos de medición se convierten en observaciones físicas. Los oídos se vuelven instrumentos
ópticos; el movimiento de los ojos, una manera de entender el funcionamiento del sonido.27
Basado en la obra test pattern [nº3] (2010)
de Rioji Ikeda28
Pasamos a describir la interface Audio Stream de GAmuza que analiza la entrada de sonido, obteniendo
datos del pitch, volumen o FFT, y realizar otros ajustes para el tratamiento de la señal de audio.
26 José Manuel Costa (2011), “Arte sonoro” en Exit Express nº 54, pág. 26
27 Magnus Haglund (2005) “The air between the planets, on the audio and visual works of Carsten Nicolai”, en Carsten Nicolai Anti
Réflex, Frankfurt: Max Hollein, pág 27.
28 Rioji Ikeda < http://www.ryojiikeda.com/project/testpattern/> [08.09.2012]
50
51
GAmuza Hybrid live coding / modular application
52
Interface. Módulos de aplicación
53
Interface. Módulos de aplicación
GAmuza Hybrid live coding / modular application
2.4. Audio Stream (Input/Output)
Antes de describir las opciones de la interface, señalar que este módulo GUI es solo para ajustar el
análisis de entrada de sonido (Input Channel), no la salida. Si en el Setting Manager se ha activado el
módulo Audio Stream (input/output) para generar sonido, y se ha seleccionado un dispositivo solo de
Como en los otros módulos GUI, la transferencia de datos de audio
por OSC puede ajustarse activando USE KALMAN FILTER. El filtro de
Kalman suaviza la relación de los datos cuando presentan grandes
cambios, cortando aquellos que superan unos límites establecidos.
SMOOTHING FACTOR ajusta el rango de ese suavizado.
salida, esta interface no estará visible, pero GAmuza mantendrá comunicación con los dispositivos de
reproducción de audio. Los portátiles mac suelen tener dispsitivos separados para entrada y salida,
por lo que es común esta situación, la mayoría de las tarjetas de audio, por el contrario, permiten
El siguiente bloque de ajustes, PARAMETRIC EQUALIZATION, prepara
ambas cosas a la vez.
la señal para la transmisión de datos, ajustando el control individual
Si el dispositivo seleccionado tiene varios canales de entrada,
ancho de banda.
veremos varios interfaces de Audio Input iguales que periten ajustes
independientes, a cada uno de ellos se accede clicando en una
de las pestañas amarillas. Debajo de las pestañas se indica el
canal que estamos visualizando [CHANNEL 0], [1], [2]..., que será
necesario poner como parámetro en muchas de las funciones de
programación de audio.
Si sólo se va a analizar la entrada de un canal, se pueden desactivar
los otros con el botón USE INPUT CHANNEL.
Debajo hay un slider para regular el nivel de volumen y un botón para silenciarlo.
NOISE REDUCTION SETTINGS es un sistema para grabar el sonido
ambiente que se desee reducir. Clicando REC NOISE, se inicia la
grabación y clicando de nuevo se detiene.
El slider, REDUX FACTOR, gradúa el nivel de reducción a aplicar.
de tres parámetros, en tres bandas: frecuencia central, ganancia y
• CENTER [BIN], selecciona la frecuencia central en Herzios.
• AMPLITUDE [DB], controla la ganancia, determinando
cuánto se amplifican o recortan esas frecuencias, por eso
puede tener valores negativos, como muestra la imagen y
el gráfico en la segunda banda.
• WIDTH [Q], el factor Q determina la nitidez o calidad de la
anchura de banda.
Los ajustes se van visualizando en el gráfico PARAMETRIC EQ. El
gráfico siguiente se corresponde a los valores ajustados en los sliders
de la imagen derecha. Primero se busca la posición de la frecuencia
central y se le ajustan la ganancia y el factor Q.
NORMALIZED RADIAL BASIS FUNCTION NETWORKS (RBFN) es un
algoritmo que genera un sistema de interpolación de datos para
representar el filtro que se está aplicando a la señal de audio, en el
dominio de la frecuencia.
Este proceso se puede visualizar en el gráfico NOISE FILTER, tanto la
grabación como el ajuste de reducción posterior.
54
55
Interface. Módulos de aplicación
GAmuza Hybrid live coding / modular application
La transformáda rápida de Fourier, FFT (Fast Fourier Transform), es un algoritmo muy utilizado para el
VOLUME CHART muestra el gráfico y valores del volumen. Su rango
de valores va de 0.0 a 1.0. La visualización de estos datos permite
calcular mejor si deben escalarse, y por cuánto, para su uso en
tratamiento de la señal de audio. En GAmuza opera sobre las muestras de sonido almacenadas en el
BufferSize, por lo que su rango de valores depende del tamaño de buffer que se haya asignado en el
SettingManager.
programación. La función de GAmuza que recoge el volumen es
Si hay un tamaño de buffer 512, el gráfico Filtered FFT BINS tendrá un tamaño [257], si el buffer es
ga.getVolume().
1024, ese valor cambia a [513], por lo que el algoritmo establece que el tamaño del FFT es el del
PITCH CHART muestra igualmente el gráfico y valores del tono (pitch),
su rango oscila entre 20Hz to 20000Hz, pero cuando los recoge la
función de GAmuza, ga.getPitch(), los normaliza entre 0.0 y 1.0
BufferSize /2 +1, que serán los puntos de análisis de la frecuencia.
En programación, estos datos se utilizan con la función ga.getFFT() que tiene dos parámetros: ID del
canal de entrada de audio:[CHANNEL num], y la posición que ocupa la muestra (sample) en el Buffer,
recorriéndolo desde 0 al valor de la variable global interna BUFFER_SIZE menos 1.
Hay otros dos datos que GAmuza obtiene de este módulo: BIN y FFT.
Los Bins provienen de la escala de Bark29, una escala psicoacústica propuesta por Eberhard Zwicker
en 1961, que corresponde a la subdivisión de las primeras 24 bandas críticas del oído. Los márgenes
de las bandas en Herzios son 0, 100, 200, 300, 400, 510, 630, 770, 920, 1080, 1270, 1480, 1720,
2000, 2320, 2700, 3150, 3700, 4400, 5300, 6400, 7700, 9500, 12000, 15500.
GAmuza obtiene el valor de cada Bin desde el análisis del FFT. Para trabajar con estos datos se utiliza
la función ga.getBin() y la variable interna FFT_BANDS.
29 Definición Bark scale [enciclopedia on-line] http://en.wikipedia.org/wiki/Bark_scale [25.08.2012]
56
57
Interface. Módulos de aplicación
GAmuza Hybrid live coding / modular application
2.5. Interfaces físicas
Cuando muchos de los estudios sobre arte digital auguraban un imparable crecimiento de lo virtual
frente a lo físico, empezó a surgir toda una línea de trabajos en el campo del arte electrónico y el diseño
que hibridaban lo físico y lo virtual, desarrollando interfaces físicas con un carácter muy diferente al
teclado o el ratón para comunicarse con el ordenador o para comunicar los datos que genera o recoge
el ordenador con otros dispositivos electro-mecánicos o electrónicos.
El ordenador no solo puede recoger datos a través de la cámara de vídeo o el análisis del sonido,
también mediante sensores -que detectan magnitudes físicas o químicas y las transforman en variables
eléctricas-, un microcontrolador que haga de intérprete y un software, pueden recoger tantos tipos de
datos como los que registran los sensores30. El microcontrolador más utilizado en el campo del arte
electrónico para este tipo de trabajos es Arduino.
Arduino es una plataforma de open hardware, basada en una placa con un microcontrolador y
un entorno de desarrollo open source, diseñada para facilitar el uso de electrónica en proyectos
multidisciplinares.
hardware abierto significa tener la posibilidad de mirar lo que hay dentro de las cosas, que eso sea
éticamente correcto, y que permita mejorar la educación. Educar en cómo funcionan las cosas…31
30 Tipos de sensores ênciclopedia on-line] <http://es.wikipedia.org/wiki/Sensor#Tipos_de_sensores> [30-08.2012]
31 David Cuartielles (2010) Arduino The Documentary, [video on-line] <https://vimeo.com/18390711> [30-08.2012]
58
59
GAmuza Hybrid live coding / modular application
60
Interface. Módulos de aplicación
61
Interface. Módulos de aplicación
GAmuza Hybrid live coding / modular application
2.6. Arduino
2.7. Comunicación OSC
El módulo Arduino responde a la pestaña azul. Esta interface establece la comunicación entre GAmuza
y el microcintrolador Arduino32, las opciones de configuración son:
Lectura de valores analógicos, del PIN 0 al 5. Cada monitor muestra
el gráfico de la señal y su valor entre 0 y 1023.
La función de GAmuza, ga.analogRead() normaliza ese rango de
valores de 0.0 a 1.0.
En la sección ANALOG PIN CONTROL, hay que seleccionar REPORT ON
en los pin que se deseen leer y REPORT OFF en los no conectados.
Arduino tiene 14 pin digitales, de los cuales 6 PWM (Pulse-width
modulation) de 8 bits pudiendo transmitir un rango de valores de 0
a 254. Si se selecciona la opción Input u output funcionan como los
demás, solo envían o reciben dos datos: HIGH o LOW.
DIGITAL VALUES WRTING: los ajustes de los valores de escritura de
los pin digitlaes y PWM, están vinculados a los datos programados
con la función de GAmuza ga.digitalWrite(pwmPin,valor), el pin
al que haga referencia la función debe estar activado en la interface.
La interface de Comunicación OSC está siempre presente (no se selecciona desde Setting Manager)
y responde a la pestaña de color gris.
Su contenido varía en función de los módulos GUI que estén activados, estableciendo en su interface
grupos de datos de cada uno de ellos, que presentan la opción de activar/desactivar el envío a otros
programas de los datos individualizados que genera cada módulo.
El sistema de recepción de datos por OSC se hace mediante código, no en la interface, y se recibe por
el puerto indicado en el Setting Manager.
32 Arduino < http://www.arduino.cc/> [25.08.2012]
62
63
3. Lenguaje de programación
La mayoría de las escuelas de arte dan clases de “arte digital”, que para ellos significa “cómo utilizar
Adobe Photoshop”. A pesar de que en estos cursos suelen decir que exploran las posibilidades
de un nuevo medio, por lo general exploran poco más que las posibilidades que alguien (es decir,
Adobe) ha encontrado conveniente empaquetar en una pieza de software comercial. El hecho es
que los ordenadores son capaces de hacer un número inimaginablemente mayor de cosas que
cualquier pieza de software específico puede hacernos creer. […] es mi intención alentar a los
artistas visuales a entender y trabajar más allá de las limitaciones impuestas por sus herramientas
de software. […] me gustaría ofrecer una visión de lo que puede lograrse cuando un artista pasa de
Photoshop por completo, y hace sus propias herramientas de software con código.33
GAmuza es un software desarrollado en una facultad de Bellas Artes en la que se ha vivido no solo el
debate que refleja Golan Levin, sino también la dificultad de los estudiantes que, aun deseando utilizar
código de programación para sus prácticas, les resulta difícultoso porque programar no implica solo
adquirir un conjunto de conocimientos (recordar los detalles de la sintaxis), sino que precisa además
desarrollar una habilidad de análisis y comprensión de conceptos abstractos complejos.
Para enseñar a programar debemos distinguir distintos procesos: trasladar el problema planteado a la
forma de un algoritmo y luego traducirlo al lenguaje del código. Entre ambas situaciones puede haber
un proceso intermedio en el que se relacionan las partes significativas del problema con un repertorio
de soluciones fragmentarias obtenidas en experiencias anteriores, este proceso intermedio requiere
cierta experiencia previa. Por eso vamos a enfocar hacia ese nivel intermedio en el que los estudiantes
empiecen a diseccionar y comprender los programas, para que posteriormente puedan relacionar
esas unidades en estructuras cada vez más complejas, hasta llegar a escribir sus propios programas.
Para ello se clarificarán métodos de análisis que traduzcan el problema en estructuras secuenciales
significativas que ayuden a diseñar algoritmos.
[…] los expertos no sólo tienen más información, sino que la tienen mejor organizada. En lugar
de percibir y recordar piezas individuales de información, procesan la información como grupos
significativos, por lo que su percepción es más eficiente y su capacidad de recuerdo tiene un
rendimiento mucho más alto.34
33 Golan Levin, (2001) ‘Essay for 4x4: Beyond Photoshop with Code’ [artículo on-line] <http://www.flong.com/texts/essays/
essay_4x4/> [12.05.2012].
34 Katherine B. McKeithen et al., (1981) “Knowledge Organization and Skill Differences in Computer Programmers” Cognitive
Psychology 13(3) Pág. 307. [Texto on-line] < http://141.213.232.243/bitstream/2027.42/24336/1/0000603.pdf > [12.05.2012].
64
65
3.1. Elementos básicos de programación: datos, variables y funciones
Pero todos estos procesos pueden carecer de sentido si el estudiante no visualiza la finalidad, es decir,
referencias de dónde y cómo se aplican o se han aplicado procedimientos semejantes en resultados
concretos. Lo que en el campo del arte entendemos como referentes artísticos, o en cualquier campo
Un dato por sí mismo no constituye información, es el procesamiento de los datos lo que nos
proporciona información35.
como contextualización referencial.
Aun conscientes de esta necesidad referencial, para poder iniciarse en la realización de aplicaciones hay
algunas estructuras, funciones y expresiones básicas que deben conocerse en su conjunto antes de
trabajar con ellas, por eso en las primeras páginas de este capítulo el número de ejemplos y referencias
que nos clarifiquen la aplicación de código será un poco limitado. En cuanto esos elementos queden
claros empezaremos ya a conectarlos con ejemplos aclaratorios, análisis de aplicaciones y propuestas
que inciten su experimentación.
Como anticipo nos detendremos en la Fórmula giratoria
del Computer art que propone Jim Campbell36, con
elementos de entrada (input), procesamiento y salida
(output). Es común que las piezas de arte digital recojan
datos del entorno, ya sean del contexto físico exterior
o de la propia cabeza del autor, estos datos entran al
ordenador (input) mediante un interprete (sensores,
teclado, ratón…), son procesados de forma invisible
(algoritmo, código) y producen una respuesta sensitiva
(output).
DATOS (INPUT) à PROCESAMIENTO à (OUTPUT) INFORMACIÓN
Siguiendo esta fórmula, los datos de entrada al sistema pueden estar relacionados con el viento, llluvia,
temperatura, tiempo, terremotos, stocks de mercado, niveles de luz…, pero más allá del origen de
los datos, es necesario saber cuál es su naturaleza. Así, los datos del viento pueden ser numéricos
(velocidad km/h), letras (direcciones N, S, E, O), palabras (nombres locales de los vientos), imágenes
(fotografías o gráficos) o vectores (dirección e intensidad)
La base del software es el procesamiento de datos, y necesita conocer su naturaleza porque la cantidad
de memoria que debe reservar es muy diferente para un número o para una cadena de caracteres
y mucha más para una imagen o para una gran cantidad de números organizados en matrices. La
Memoria retiene la información de los datos para que puedan ser utilizados repetidas veces. Este
espacio reservado de la memoria está vinculado con las variables.
En la página siguiente se muestra un gráfico que despliega sobre el papel la fórmula del Computer art
de Jim Campbel, fijando su movimiento.
35 Definición de Dato, [enciclopedia on-line] http://es.wikipedia.org/wiki/Dato [28.06.2012]
36 Jim Campbell, “Formula for Computer art”, http://www.jimcampbell.tv/portfolio/miscellaneous_references/ [28.06.2012]
66
67
3.1.1. Variables I
Una variable es un como un contenedor para almacenar datos que después pueden ser reutilizados
muchas veces en el programa y cuyo valor puede cambiar. El sistema necesita reservar determinada
cantidad de bites de la memoria para que esa variable esté siempre disponible. Para comprender
cómo se estructuran las variables en programación básica, y cómo se utilizan y diferencian los datos,
vamos a comparar su uso en GAmuza y en Processing, por ser uno de los software más utilizados
y documentados en este tipo de aplicación creativa. En Processing, cada variable tiene tres partes:
• identificación del tipo de datos que guarda (int, float, boolean,…)
• nombre (el que decida el programador)
• valor (se asigna un valor inicial)
Processing necesita hacer constar esa identificación, distinguiendo entre:
int // Número entero
float // Número decimal
boolean // Un dato que sólo puede ser verdadero o falso.
PImage
char String
PFont
// Imagen
// Carácter. El valor se define con apostrofes: ‘a’
//Cadena de caracteres. Se define con comillas “antes”
// Fuentes tipográficas
En GAmuza no hay que identificar el tipo de datos, si bien el programador debe ser consciente del
tipo de datos que utiliza. En ambos software hay que declarar la variable y asignarle un valor antes de
utilizarla, en el proceso del programa ese valor puede cambiar.
Processing
GAmuza
int x = 50; x = 50
float y = 12.6;
y = 12.6
boolean b = true;
b = true
Cada programador decide cómo nombrar las variables, pero algunos hábitos han generado una cuasinorma:
• Se recomienda poner a las variables un nombre relacionado con su contenido, para que sea
más fácil leer la programación y se reduzca la necesidad de comentarios.
• Los nombres de las variables deben comenzar con una letra minúscula, y si hay varias
palabras en el nombre, la primera letra de cada palabra adicional debe ser mayúscula (como
tiempoActual)
68
69
3.1.2. Funciones
Hay también algunas normas para nombrar variables:
• El nombre de una variable no puede empezar con números
• No puede coincidir con los términos propios del lenguaje de programación.
Durante los siglos XIX y XX la partir de la Teoría de Conjuntos se amplió el rango de aplicación de
Palabras reservadas en GAmuza (Lua)37
and
break
do
else
elseif
in
local
nil
not
or
end
repeat
false
return
for
then
Fue Leibniz quien en el siglo XVII acuñó los términos «función», «variable», «constante» y «parámetro».
function
true
las funciones matemáticas, estableciéndose la actual definición de función como: la correspondencia
entre los elementos de dos conjuntos dados, no necesariamente numéricos.
if
until
while
En programación, una función es un grupo de instrucciones que se ordenan y articulan con un objetivo
particular y que se efectúa al ser llamada desde otra función o procedimiento. Las funciones deben
tener un nombre único en su entorno de programación, una lista de parámetros de entrada asignada,
Para evitar confusiones, las variables tampoco deberían coincidir con los nombres de las funciones
internas del software utilizado, tales como of.line(), of.ellipse(), of.rect(),….
Otra cuestion importante en relación a las variables es el alcance o ámbito de la variable, es decir,
donde puede ser utilizada en relación a donde se crea o declara, pero esto lo veremos después de
entender qué es una función, ver página 77.
su código y pueden devolver un tipo de datos como resultado.
Las funciones pueden recibir datos desde afuera al ser llamadas a través de los parámetros (INPUT) y
pueden devolver un resultado (OUTPUT). Algunas funciones pueden llamarse múltiples veces e incluso
llamarse a sí misma (función recurrente).
GAmuza, como todo software, requiere una terminología específica , para facilitar el aprendizaje, se ha
mantenido su nombre lo más próximo posible al utilizado en otros lenguajes de programación creativa
como Processing y openFrameworks.
Debemos diferenciar entre funciones de bloque, funciones internas del software y funciones escritas
por cada programador, pero para no complicar las definiciones vamos a ir señalando sus diferencias
con ejemplos que muestren la estructura de programación. Empecemos viendo cuál es la estructura
básica de un programa en el ScriptEditor.
37 Lua 5.1 Reference Manual, [texto on-line] < http://www.lua.org/manual/5.1/manual.html/ > [30.07.2012]
70
71
El sistema lee el código desde arriba hacia abajo y lo primero que aparece son los comentarios. En
GAmuza, los comentarios pueden marcarse de dos maneras:
• Con el código de Lua: --
• O con el habitual de Processing y C++: //
/*
GAmuza 0.4.1 examples
--------------------basics/functionsTemplate.ga
This example just show the environment functions; the basics setup(),
update() & draw(), plus the listener functions to mouse&keyboard.
Cuando el comentario ocupa varias líneas (bloque de comentario), se señalan al principio con /* y al final
del comentario con */, o también puede hacerse al principio --[[ y al final --]] (código Lua).
Las líneas de comentario con // o --, en ambos casos son barras consecutivas, pueden ponerse más
de dos, pero si las dos primeras están más separadas el sistema no lo reconoce como comentario y
da error, se puede detectar el fallo si el texto no adopta el color gris que el ScriptEditor les asigna por
defecto.
Los comentarios son textos que el sistema ignora, no los procesa, pero son importantes para el
programador. El código de programación puede ser muy breve y fácil de leer o tremendamente
extenso, por lo que es fundamental acostumbrarse a comentarlo bien y también a ordenar y tabular las
líneas de código según niveles para facilitar su lectura y revisión.
Tras los comentarios, están las variables globales, pero se describiran en la página 77, y después
los bloques de funciones que estructuran y contienen el código, este código pueden ser funciones
internas, procedimientos o expresiones, según las acciones que deban realizar. Por defecto, el nombre
created by n3m3da | www.d3cod3.org
*/
function setup()
// solo se ejecuta una vez
end
------------------------function update()
// donde se actualizan las variables, se lee en loop
end
------------------------function draw()
// donde va el código a dibujar, se lee en loop.
end
------------------------function mouseDragged()
end
------------------------function mouseMoved()
de las funciones aparece de color naranja.
end
En GAmuza el final de cada bloque de función se señala con el término end, no signos de corchetes
function mousePressed()
{} que marquen principio y final..
El primer bloque es function setup(), cuyo rasgo distintivo es que, cuando se efectúa el programa,
el código que se escribe ahí solo es leído una vez por el sistema.
Contrariamente, el código que se escribe dentro de los bloques function update() y function
draw(), el sistema los lee en loop, de manera que cuando llega a la última línea, genera un frame en la
ventana de salida y empieza de nuevo por la primera línea de código, y así continuamente hasta que
se apaga el programa.
Además de los bloques setup(), draw() y update(), existen otros bloques de funciones usuales en
programas interactivos, como los que aparecen en la siguiente plantilla de GAmuza:
// cuando la acción se da al arrastrar el ratón
// el código actúa cuando se mueve el ratón
------------------------// el código actúa cuando se aprieta un botón
end
------------------------function mouseReleased() // actúa cuando se suelta el botón
end
------------------------function keyPressed()
//el código actúa cuando se presiona una tecla
end
------------------------function keyReleased()
//el código actúa cuando se suelta una tecla
end
-------------------------
Esta plantilla está disponible en menú File/Examples/functionsTemplate.ga
72
73
EXPERIMENTAL OPENFRAMEWORKS ADDONS
Después de los bloques, el siguiente elemento importante son las funciones internas. En GAmuza, los
nombres de estas funciones internas tienen diferentes prefijos según su origen:
-------------------------------------------- of. Son funciones que provienen de openFrameworks, como of.setColor(). La norma establecida
ofxArcText = ofx.arcText()
ofxArcText
para su escritura en el wrapping de GAmuza es of.functionName, es decir, si originalmente
-- la función en openFrameworks es: ofSetColor(), en GAmuza se coloca un punto después
ofxChromaKey --> extending ofImage
de of y se inicia con minúsculas. Cuando el nombre de la función contiene dos conceptos, el
ofxChromaKey = ofx.chromaKey()
segundo empieza en mayúsculas dentro de la misma palabra, quedando of.setColor(). Todas
-- las funciones terminan con (). El 98% de las funciones de openFrameworks está disponible en
ofxDither
GAmuza38.
ofxDither = ofx.dither()
ofx.Son algunas funciones que provienen de las api ofxAddons39. Su sintaxis en GAmuza es ofx.
ofxDmx
functionName, nuevamente es poner un punto después de ofx., empezar con minúscula
ofxDmx = ofx.dmx()
e iniciar en mayúscula el segundo concepto de la función. Dado que el wrapper de ofx no es
ofxFTGLFont
completo, se listan a continuación las clases ofx. disponibles en GAmuza40:
ofxFTGLFont = ofx.FTGLFont() --
--------------------------------------------
ofxFX
OFFICIAL OPENFRAMEWORKS ADDONS
ofxBloom = ofx.bloom()
-------------------------------------------- ofxBlur = ofx.blur()
ofx3DModelLoader
ofxBlurFast = ofx.blurFast()
ofx3DBaseLoader = ofx.BaseLoader3D()
ofxConway = ofx.conway()
ofx3DModelLoader = ofx.ModelLoader3D() ofxFlocking = ofx.flocking()
--
ofxFluid = ofx.fluid()
ofxNetwork
ofxGlow = ofx.glow()
ofxTCPClient = ofx.TCPClient()
ofxGrayScott = ofx.grayScott()
ofxUDPManager = ofx.UDPManager()
ofxMask = ofx.mask()
ofxTCPManager = ofx.TCPManager()
ofxOldTv = ofx.oldTv()
ofxTCPServer = ofx.TCPServer()
ofxWater = ofx.water()
-- -- ofxVectorGraphics
ofxGaussian
ofxVectorGraphics = ofx.vectorGraphics() ofxGaussian = ofx.gaussian() --
--
ofxOpenCv
ofxSubtitles
ofxCvColorImage = ofx.cvColorImage()
ofxSubtitles = ofx.subtitles()
ofxCvGrayscaleImage = ofx.cvGrayscaleImage() -- -------------------------------------------38 Para un listado completo de las funciones de openFrameworks ver <http://www.openframeworks.cc/documentation>
[03.06.2012]
39 ofxAddons. Un directorio de extensiones y librerías para OpenFrameworks. http://ofxaddons.com/ [03.06.2012]
40 ofx all classes [texto on-line] http://gamuza.d3cod3.org/examples/ofx-all-classes/ [03.07.2012]
74
ofxWordPalette
WordWithSize = ofx.WordWithSize()
ofxWordPalette = ofx.wordPalette()
75
ga. son las funciones internas programadas para GAmuza y que principalmente vinculan los
datos de las interfaces gráficas de los módulos con el resto de funciones, también definen
algunas particularidades del entorno de programación, como la función ga.background() que
facilita un mejor sistema de transparencia en el fondo, y otras funciones de aplicación como
ga.mouseX(), ga.mouseY() —devuelve el valor de la posición x e y del ratón sobre la ventana
de salida—, ga.key() — devuelve el valor de la última tecla usada.
Todas las funciones terminan con dos paréntesis que pueden albergar, o no, parámetros . Los
parámetros se sitúan entre los paréntesis, separados por comas, y afectan el modo en que actúa la
función; algunas funciones no tienen parámetros y otras pueden albergar más o menos parámetros
según la situación, como:
-- puede tener un rango de 0 (negro) a 1 (blanco)
ga.background(0.0, 0.5) -- igual + transparencia (gris, alpha)
ga.background(0.0, 0.0, 255,1)
Una vez entendida la estructura, volvemos a las variables para comprender mejor dónde situarlas.
Es necesario pensar dónde se declaran y asignan las variables, porque ello determina su ámbito de
aplicación —dónde se puede acceder a ellas dentro del programa. Las variables declaradas dentro de
un bloque sólo son válidas dentro de ese mismo bloque y dentro de otros bloques encerrados en ese
41
ga.background(0)
3.1.3. Variables II
-- fondo azul opaco (R, G, B, alpha)
Además de las funciones internas propias del software (que se analizarán después con más detalle),
cada programador puede hacer sus propias funciones, como se verá más adelante, cuando entraremos
en los detalles de la programación.
bloque. Las variables declaradas en el nivel de base del programa —antes del setup() y draw()—
pueden acceder a todas partes dentro del programa. Las variables declaradas dentro del setup()
sólo se puede acceder a ellas en el bloque setup(). Las variables declaradas dentro de draw() sólo
se puede acceder en el bloque draw(). El alcance de una variable declarada dentro de un bloque, se
denomina variable local, y se extiende sólo hasta el final de ese bloque. El siguiente ejemplo muestra el
alcance de las variables, en el código se utiliza una expresión condicional if que se verá en la página
92.
d = 50
-- d y val son variables globales,
val = 0
-- pueden usarse en cualquier lugar
function setup()
end
function update()
val = d * 2
end
-- su valor es actualizado desde update()
function draw()
ga.background(0.0,1.0)
of.setColor(val)
y = 150
of.line(0, y, d, y)
y = y - 25
-- y es variable local puede usarse solo en draw()
-- d e y son llamadas desde draw()
of.line(0, y, d, y)
if d > 50 then
x = 10
end
-- x es variable local, solo se puede usar en bloque if
of.line(x, 40, x+d, 40)
of.line(0, 50, d, 50)
of.line(x, 60, d, 60)-- ERROR x no se puede usar fuera del bloque if
41 Algunos textos los denominan argumentos. En nuestro caso mantenemos la nomenclatura utilizada en: Casey Reas y Ben Fry,
(2007) Processing, a Programming Handbook for Visual Designers and Artist and. Cambridge(MA): The MIT Press.
76
end
77
Hay otro tipo de variables que se denominan variables del sistema, tienen un nombre asignado por el
propio software, que le otorga ya su valor. En GAmuza se reconocen:
De sistema
Ancho de la ventana de salida
OUTPUT_W
Alto de la ventana de salida
OUTPUT_H
Traking video
3.2. Formas geométricas básicas
A las esferas les inquieta constantemente su inevitable inestabilidad: comparten con la suerte y el
cristal los riesgos de todo lo que se hace pedazos fácilmente. No serían formas de la geometría
vital si no pudieran implosionar, si no fueran susceptibles de ser destruidas por la presión exterior;
y menos lo serían si no estuvieran en condiciones de agrandarse bajo la presión interior del
crecimiento de los grupos hasta convertirse en estructuras más ricas43.
La programación creativa, por su vinculación a las artes visuales y el diseño, responde principalmente
Altura de la captura de video CAPTURE_H
Ancho de la captura de video CAPTURE_W
Nº de pixels de la captura de video
CAPTURE_PIX
Máximo nº de blobs detectados
MAX_BLOBS
Nº columnas de optical flow
OPTICAL_FLOW_GRID_X
Nº filas optical flow
OPTICAL_FLOW_GRID_Y
a cuestiones visuales y espaciales. En este contexto, el primer elemento a comprender es el propio
espacio de representación que queda definido por la ventana de salida. Sea cual sea su soporte, tipo
de monitor o proyector de vídeo, debemos entenderlo como una matriz de puntos luminosos (píxeles)
que, según los casos, albergará una representación 2D ó 3D de las formas visuales, y cuyo origen o
punto cero se expresa mediante las coordenadas (0,0) ó, (0,0,0) y está situado en el vértice superior
izquierdo de la ventana.
Análisis captura de audio
Nº de bandas FFT en la captura de audio FFT_BANDS
Tamaño del buffer de audio
BUFFER_SIZE
Generación sonido
Tipos de onda
Notas musicales
GA_SIN, GA_COS, GA_SAW, GA_TRI, GA_RECT, GA_NOISE,
GA_PINK, GA_BROWN, GA_PHASOR, GA_PULSE
DO_0,... // las 7 notas con números del 0 al 8
Trigonometría
Radianes
PI, TWO_PI, HALF_PI
De openGL
Las asociadas a las funciones y clases de openGL incluidas en GAmuza42,
Centrándonos de momento en las formas 2D, para dibujarlas dentro de esa matriz es necesario pensar
cuál será su ubicación, expresada en coordenadas (x, y), y las cualidades que permiten definirla. Hay
funciones internas que facilitan el dibujo de figuras geométricas e incluyen en sus parámetros: las
coordenadas y cualidades de la forma.
En la siguiente tabla se muestran las funciones internas más comunes en GAmuza para dibujar figuras
geométricas planas, lo que en programación se denomina Primitivas.
42 Información en openGL Documentation <http://www.opengl.org/sdk/docs/man/xhtml/> [26.08.2012]
78
43 Peter Sloterdijk (2003), Esferas I. Burbujas, Microsferología. Madrid: Siruela, pág. 50.
79
Antes de dibujar hay que tener en cuenta las características de la superficie y particularidades de las
Formas geométricas 2D - Primitivas
formas: color de fondo, así como el color y ancho del borde y si ese color las rellena o no.
of.circle(x, y, 1)
Punto
-- círculo de 1 pixel de diámetro
Funciones básicas, atributos de las formas
-- (coordenadas del centro, diámetro)
Color del fondo
of.line(x1, y1, x2, y2)
Línea
ga.background(gris,alpha)
ga.background(R,G,B,alpha)
-- (coordenadas punto inicio, punto final)
Esta función permite ajustar el color y transparencia del fondo, en escala de grises con dos
parámetros (gris, alfa) o en color con cuatro parámetros (R, G, B, A).
Todos los valores van de 0.0 a 1.0
Salvo excepciones, tiene que estar en el draw()
of.triangle(x1, y1, x2, y2, x3, y3)
Triángulo
-- (coordenadas punto 1, punto 2, punto 3)
Color de relleno
Siempre hay que usarlo para definir el color cuando se va a generar algún gráfico. Si no se
pone, no dibuja nada.
-- puede hacerse también con of.circle(3)
of.rect(x, y, ancho, alto)
Rectángulo
-- (coordenadas vertice, lado, lado)
Si sólo tiene un parámetro funciona en escala de grises. 2 parámetros: escala de grises +
alfa. 3 parámetros: color RGB y 4 parámetros: RGB + alfa. Los parámetros van de 0 a 255.
Rellenar formas
of.fill()
No lleva parámetros
-- ver RECT_MODE, página 82.
Se utiliza si previamente hay un of.noFill() porque
formas por defecto.
of.circle(x, y, radio)
Círculo
of.setColor(0,0,255)
No rellenar
of.setCircleResolution(valor)
GAmuza siempre rellena las
of.noFill()
No lleva parámetros
-- el valor debe ser alto, si no dibula polígonos
of.ellipse(x, y, ancho, alto)
Dibujar borde
No dibujar borde
Elipse
Ancho de la línea
of.noFill()
Por defecto no los dibuja
of.setLineWidth(valor)
Valor = grosor línea en pixeles
of.circle(x, y, radio)
Polígono
of.setCircleResolution(valor)
Suavizar bordes
-- (5)
-- el valor define el nº de lados del polígono
of.enableSmoothing()
No lleva parámetros
No suavizar
of.disableSmoothing()
No lleva parámetros
80
81
Los rectángulos y cuadrados tienen diferentes opciones para determinar el punto de referencia de las
coordenadas que controlan su posición, para ello se utiliza la función: of.setRectMode(). Algunos
ejemplos permitirán revisar mejor lo hasta ahora visto.
El programa tiene los tres bloques básicos de GAmuza. En el bloque setup() la función
of.enableSmoothing() suaviza los bordes de las formas. Si las figuras giraran, apliacaría un ligero
efecto anti-aliasing; al tratarse de una imagen fija no hace falta esa función. Por otra parte, cómo no se
actualiza el valor de las variables, el bloque update() podría también no estar. Después se aplicarán
/*
en la página 91 cambios a las variables y todo cobrará sentido.
GAmuza 0.4.1 examples
---------------------
El bloque draw() es el único que contiene datos para los gráficos. La primera función determina
Basics/OF_RECT_MODE.ga
el fondo y su color; los parámetros (0.0, 1.0) significan negro y opaco, si fueran (1.0, 0.5)
cambia el punto de referencia
significaría blanco con 50% de transparencia. Los parámetros de la función ga.background() siempre
en rectangulos y cuadrados
van de 0.0 a 1.0.
*/
posXY = 300
La primera función of.setColor() tiene solo un parámetro, lo que indica que actúa en escala de
lado = 400
grises, la segunda tiene dos parámetros, escala de grises (blanco) con transparencia. Los valores están
function setup()
compensados por lo que aparentemente dibujan el mismo color.
of.enableSmoothing()
of.setRectMode() es una función interna de openFramewoks que permite modificar las coordenadas
end
de referencia para la posición de rectángulos y cuadrados. Por defecto las coordenadas de la función
of.rect() sitúan el vértice superior izquierdo, que corresonde al parámetro OF_RECTMODE_CORNER,
function update()
la variable OF_RECTMODE_CENTER cambia esa referencia al centro del cuadrado, por eso aunque los
end
parámetros de las dos funciones of.rect() son iguales, los cuadrados se posicionan en lugares
diferentes.
function draw()
ga.background(0.0, 1.0)
-- fondo negro sin transparencia
of.setRectMode(OF_RECTMODE_CENTER) -- referencia: vertice superior izq.
of.setColor(126)
of.rect(posXY, posXY, lado, lado)
of.setRectMode(OF_RECTMODE_CORNER) of.setColor(255, 100)
of.rect(posXY, posXY, lado, lado) -- cuadrado gris
-- referencia: centro
-- cuadrado blanco transparente
end
Retomamos el ejemplo que sirvió de base para explicar la estructura. El primer bloque de comentario
da datos de lo que plantea el ejemplo y la versión del software que se ha utilizado. Cuando pasa el
tiempo este dato cobra importancia porque el software suele actualizarse y con ello puede cambiar el
código, por lo que nos da una referencia.
Hay dos variables globales, la primera actúa por dos para situar la coordenada de las formas, y es así
porque en ambos cuadrados el valor de la coordenada x e y va a ser el mismo (300, 300), siguiendo
Cuando se utiliza una función que define atributos de las formas, se aplica a todas formas (funciones
de las formas) que están situadas debajo y en las que puede incidir, si el color va a ser el mismo en
todas, solo se pone una vez al principio. Aunque una función de dibujo sólo se utilice una vez, debe
ponerse en el bloque draw(), en otros software como Processing podrían ponerse en el setup() pero
en GAmuza las funciones of.noFill(), of.fill() o of.enableLineWidth() tienen que ponerse
en el draw()
El sistema lee el código de arriba a abajo, esto afecta al orden de superposición de las formas: lo
último escrito es lo que se sitúa al frente y las formas de las primeras líneas de código quedan más al
fondo. En el ejemplo, el código del cuadrado blanco está escrito después que el del gris, y por tanto se
le superpone, aunque la transparencia disuelve el gradiente de profundidad por superposición y crea
visualmente otro cuadrado.
En el siguiente ejemplo se usa transparencia, las variables de sistema de GAmuza OUTPUT_W y OUTPUT_H
y se utilizan expresiones aritméticas (ver página 91) para modificar su valor.
una diagonal de 45º. La segunda variable indica el lado del cuadrado. Si queremos modificar el tamaño,
manteniendo las proporciones de la imagen, simplemente se cambia el valor de esas variables.
82
83
/*
GAmuza 0.4.1 examples
--------------------Basics/circulos_alpha.ga
cambia el valor de las variables
con expresiones matemáticas
*/
function setup()
poligonos concéntricos
*/
function setup()
end
of.enableSmoothing()
function draw()
ga.background(0.0,1.0)
of.noFill()
of.setLineWidth(10)
function draw()
ga.background(0.0, 1.0)
of.setColor(255, 20)
of.circle(OUTPUT_W/2, OUTPUT_H/2, 300)
of.circle(OUTPUT_W/2 +30, OUTPUT_H/2 +30, 250)
of.circle(OUTPUT_W/2 -30, OUTPUT_H/2 +30, 250)
of.circle(OUTPUT_W/2 +60, OUTPUT_H/2 +60, 200)
of.setColor(0, 255,0)
of.setCircleResolution(3)
of.circle (OUTPUT_W/2, OUTPUT_H/2, 100)
of.circle(OUTPUT_W/2 -60, OUTPUT_H/2 +60, 200)
of.circle(OUTPUT_W/2 +90, OUTPUT_H/2 +90, 150)
of.circle(OUTPUT_W/2 -90, OUTPUT_H/2 +90, 150)
of.circle(OUTPUT_W/2 -120, OUTPUT_H/2 +120, 100)
of.circle(OUTPUT_W/2 +150, OUTPUT_H/2 +150, 50)
of.circle(OUTPUT_W/2 -150, OUTPUT_H/2 +150, 50)
end
of.setCircleResolution(6)
of.circle (OUTPUT_W/2, OUTPUT_H/2, 220)
of.setColor(0,170,255)
of.circle (OUTPUT_W/2, OUTPUT_H/2, 230)
Las coordenadas del centro del primer círculo son (OUTPUT_W/2, OUTPUT_H/2), estos parámetros
corresponden a las coordenadas del centro de la ventana de salida. Los centros de los otros círculos
mantienen relaciones con ese centro, desplazándose 45º hacia abajo a ambos lados, porque sus dos
coordenadas varían de forma regular y uniforme: sumando de uno a otro 30px en direccion X y 30px en
of.setCircleResolution(7)
of.circle (OUTPUT_W/2, OUTPUT_H/2, 260)
of.setColor(0,85,255)
of.circle (OUTPUT_W/2, OUTPUT_H/2, 270)
dirección Y, los que se desplazan hacia la derecha, y -30px en la X y 30px en la Y los que lo hacen hacia
la izquierda. En la página 94, ésta misma construcción se plantea con una estructura condicional if.
Las once capas de círculos se entremezclan visualmente por la transparencia disolviendo el gradiente
of.setCircleResolution(8)
of.circle (OUTPUT_W/2, OUTPUT_H/2, 300)
of.setColor(170,0,255)
de profundidad por las superposiciones.
Todos tienen el mismo color of.setColor(255, 20) definido desde el principio, color blanco con una
opacidad de aproximadamente el 8% porque todos los parámetros de esta función van de 0 a 255.
of.setColor(255,255,0)
of.setCircleResolution(4)
of.circle (OUTPUT_W/2, OUTPUT_H/2, 140)
of.setColor(85,255,0)
of.circle (OUTPUT_W/2, OUTPUT_H/2, 150)
of.setCircleResolution(5)
of.circle (OUTPUT_W/2, OUTPUT_H/2, 180)
of.setColor(0,255,255)
of.circle (OUTPUT_W/2, OUTPUT_H/2, 190)
of.circle(OUTPUT_W/2 +120, OUTPUT_H/2 +120, 100)
84
of.enableSmoothing()
of.setCircleResolution(50)
end
/*
GAmuza 0.4.1 examples
--------------------Basics/poligonos_circle.ga
of.circle (OUTPUT_W/2, OUTPUT_H/2, 310)
end
85
3.2.1. Formas irregulares
El bloque function setup() solo se lee una vez, no puede contener of.setCircleResolution()
como en el ejemplo anterior porque en el bloque draw() se va a utilizar múltiples veces con valores
distintos.
La función of.setColor() tiene 3 parámetros, lo que indica que está declarada en RGB y sus
valores van de 0 a 255. Para establecer las relaciones de color que siguen el círculo cromático, se han
combinado dividiendo el valor máximo de cada componente del color en tres, 255/3 = 87, y haciendo
También se pueden generar formas irregulares lineales o curvas. Las formas lineales requieren las
funciones:
combinaciones de dos componentes que incrementan o reducen su porcentaje en ese valor.
Como en el ejemplo anterior, se observa que entre los parámetros hay muchos valores repetidos y
otros que mantienen relaciones de crecimiento gradual, esto indica que se puede plantear de otra
forma más sencilla, tal como está formulado en la página 99.
of.beginShape()
-- no lleva parámetros
of.vertex(x, y)
-- coordenadas x, y del vértice
of.endShape(true o false)
-- booleano para cerrar, o no, la forma
of.beginShape()se utiliza como aviso de que se va a iniciar una nueva forma, esta forma estará
definida por una serie de vértives con of.vertex(x, y) y tras ellos debe terminar con la función
of.endShape(). Su variable booleana indica si la forma se cierra, es decir si el último vertex se une al
primero, cuando es true, o si queda abierta cuando es false.
/*
GAmuza 0.4.1 examples
--------------------Basics/begin_end_shape.ga
dibujo de formas lineales irregulares
*/
function setup()
of.enableSmoothing()
end
function draw()
ga.background(0.0,1.0)
of.noFill()
of.setLineWidth(3)
of.setColor(255)
of.beginShape()
of.vertex(146, 75)
of.vertex(210, 117)
of.vertex(210, 589)
of.vertex(226, 589)
of.vertex(190, 217)
of.vertex(254, 132)
of.vertex(310, 117)
of.endShape(false)
-- aviso empieza forma
-- coordenadas de los vértices
-- fin forma: abierta
end
86
87
Para las formas no lineales hay distintas opciones, curvas o bezier, y en ambos tipos la posibiliad de
contrucción con vértices:
Las funciones of.curve() y of.bezier()no requieren señalar que se inicia y finaliza una forma. En
ambas, sus 8 párametros indican dos coordenadas de principio y fin de las curvas (x1, y1, x2, y2)
of.curve(cx1, cy1, x1, y1, x2, y2, cx2, cy2)
of.curveVertex(x, y)
of.bezier(x1, y1, cx1, cy1, cx2, cy2, x2, y2)
of.bezierVertex(cx1, cy1, cx2, cy2, x2, y2)
y dos coordenadas de puntos de control (cx1, cy1, cx2, cy2), desde los que se genera la curva o
el trazado de la bezier. El orden de estos parámetros no es el mismo en las dos funciones. Veamos un
ejemplo con las mismas coordenadas en ambas funciones para obserbar sus diferencias:
La función of.curveVertex(x,y) también necesita señalar el principio y fin de la forma, y lo hace
/*
GAmuza 0.4.1 examples
--------------------Basics/curve_bezier.ga
curveVertex(x,y) porque en la primera y la última, los parámetros (x,y) corresponden a los puntos
*/
con las mismas funciones: ofBeginShape() y ofEndShape(). Deben utilizarse al menos cuatro of.
de control, siendo los parámetros de las otras funciones los que definen los vértices de la curva,
El siguiente ejemplo compara la función of.curveVertex() con el anterior de las formas lineales
con of.vertex(), desplazando el valor de las coordenadas x, además se repiten la primera y ultima
función por ser las de control.
comparación of.curve y of.bezier
function setup()
end
function draw()
ga.background(0.0,1.0)
of.setColor(255)
/*
GAmuza 0.4.1 examples
--------------------Basics/curveVrtex.ga
comparación
of.noFill()
-- representan los puntos de control
of.vertex y of.curveVertex
*/
// pegad aquí ejemplo anterior
of.circle(27, 254, 4) -- para ver donde está punto control 1 (cx1, cy1)
of.circle(115, 350, 4)
-- y dónde punto de control 2 (cx2, cy2)
of.line(27, 254, 190, 210)
-- representa linea de control 1 a inicio curva
of.line(115, 350, 300, 370)
-- representa linea de control 2 a fin curva
of.setLineWidth(3)
-- grosor línea
-- of.curve(cx1, cy1, x1, y1, x2, y2, cx2, cy2)
// sin el end final
para ver orden coordenadas
of.curve(25, 254, 190, 210, 300, 370, 115, 350) -- curva color blanco
of.setColor(0, 0, 200)
of.curveVertex(446, 75)
of.curveVertex(510, 117)
of.curveVertex(510, 589)
of.curveVertex(490, 217)
of.curveVertex(554, 132)
of.curveVertex(610, 117)
of.curveVertex(610, 117)
of.endShape(false)
end
88
of.curveVertex(446, 75)
-- of.bezier(x1, y1, cx1, cy1, cx2, cy2, x2, y2)
of.beginShape()
-- define punto de control 1: no se dibuja
-- inicia la curva
para ver orden coordenadas
of.bezier(190, 210, 25, 254, 115, 350, 300, 370) -- bezier color azul
end
Por último, la función of.bezierVertex(cx1, cy1, cx2, cy2, x2, y2) como tiene sólo 6
parámetros, debe que estar precedida siempre por of.vertex(x,y) cuyas coordenadas indican en
-- termina la curva
-- define
punto de control 2: no se dibuja
-- fin forma: no cierra
inicio de la curva. Los parámetros (cx1, cy1, cx2, cy2,) de of.bezierVertex() posicionan los
dos puntos de control, y (x2, y2) el final de la curva. Si se encadenan varias funciones seguidas, esta
última coordenada indica dónde empezará la siguiente. También deben situarse entre ofBeginShape()
y ofEndShape().
89
/*
GAmuza 0.4.1 examples
--------------------Basics/vertex_bezier.ga
3.3. Estructuras de programación básicas
3.3.1. Expresiones aritméticas
varias curvas bezier encadenadas
usando vertexBezier
*/
Hemos visto que las cualidades visuales de una forma en la pantalla se expresan numéricamente, por
function setup()
pueden llegar a ser complejas para aquellos que disfruten con el campo de las matemáticas o simples
lo que sus relaciones de proporción pueden derivar de operaciones aritméticas. Estas operaciones
para programadores más visuales. En cualquier caso son un instrumento útil para la composición
of.setCurveResolution(60)
de formas, colores o sonidos, combinando variables con operadores aritméticos. Los operadores
end
aritméticos básicos en GAmuza provienen del lenguaje Lua, y son:
function draw()
ga.background(0.0,1.0)
of.noFill()
of.setLineWidth(3)
of.setColor(255)
of.beginShape()
of.vertex(60, 120) --inicia curva 1
of.bezierVertex(80, -20, 280, 20, 160, 140)
of.bezierVertex(10, 280, 180, 420, 280, 280)
of.bezierVertex(350, 175, 440, 230, 390, 330)
of.endShape(false)
end
calcula si un número es proporcional a otro, modular, es decir si cuando el número a la izquierda de
números múltiplos de 2, 3, 4,… Ver su utilización en el ejemplo for + if de la página 97.
Es común utilizar expresiones matemáticas para modificar el valor de las variables o para expresar
control 1, control 2, fin curva 1 que es inicio de la 2
La función de los operadores +, -, *, / y ^ son conocidos por todos, el operador % es menos usual,
% se divide por el que está a su derecha el resto es igual a cero. Es útil cuando se quiere trabajar con
--
+ (suma), - (resta), * (multiplicación), / (división), ^ (exponencial), %(modular)
-- curva 2
-- curva 3
-- fin forma: abierta
los parámetros de una función. Cuando la expresión aritmética se sitúa en el bloque update(),
en cada vuelta del loop aplica de nuevo la actualización del valor, incrementándolo o reduciéndolo
sucesivamente, por lo que puede utilizarse para animar formas, hasta que desaparecan de la ventana.
Las expresiones condicionales regulan estos límites, tal como se muestra en la página 95.
/*
GAmuza 0.4.1 examples
--------------------Basics/aritmetica_anima.ga
*/
y = 20
function setup()
end
function update()
y = y+20 -- suma 20 cada frame
end
function draw()
ga.background (0.0, 0.3) -- fondo transparente, se ve el movimiento de las líneas
of.setColor(255)
of.setLineWidth(4)
of.line(0, y, OUTPUT_W, y)
end
90
91
3.3.2. Expresiones relacionales
la condición if, pasa a evaluar la condición
Sintaxis
> (mayor que) < (menor que)
== (igualdad)
!= (desigualdad)
>= (mayor o igual a) true La expresión elseif, amplía aun más las
opciones de la condicional. Si no se cumple
<= (menor o igual a)
false
Una expresión relacional está compuesta por dos valores que se comparan con un operador relacional.
La expresión relacional evalúa los datos como verdadero o falso (true y false).
Expresión Resultado
12 > 8 true
60 < 40 false
La expresión de igualdad se hace con ==, porque el signo = aislado, significa la asignación de un valor,
como en x = 14.
elseif, y si tampoco se cumple puede aun
establecer un else para efectuar una tercera
instrucción si las dos anteriores no se cumplen.
Las expresiones condicionales utilizan operadores lógicos para combinar dos o más expresiones
relacionales y para invertir los valores lógicos.
Sintaxis
Operadores lógicos
Los operadores lógicos permiten formular más de una condición de forma simultánea. El operador not,
invierte el valor lógico de las variables booleanas, cambiando verdadero a falso, y falso a verdadero. La
estructura condicional if en GAmuza, a diferencia de otros software, no utiliza () ni {}.
if not b then
end
-- end, cierra el bloque if
if b == true then
-- si b es verdadero, entonces
if a > 5 or b < 30 then -- si a es mayor que 5 ó b es menor que 30
end
if a < 5 and b > 30 then --si a es mayor que 5 y b es menor que 30
end
3.3.3. Expresiones condicionales y operadores lógicos
Condicionales Sintaxis
if, elseif, else, (si, sino si, sino)
La expresión condicional if, permite a un programa seguir comportamientos
diferentes, dependiendo de que los valores de sus variables cumplan unas
condiciones u otras, esta apreciación se obtiene a través de una expresión
relacional (test), de modo que las acciones pueden tener lugar, o no, sólo
si una condición específica se cumple: si la condición se cumple (si el test
tiene como resultado true), realiza la instrucción, sino no. Para plantear
el test se utilizan las expresiones relacionales y también se pueden utilizar
if, de manera que cuando la expresión asociada es falsa, el
código del bloque else se ejecuta en su lugar.
if b
-- si b es falso, entonces
-- haz tal cosa
then
instrucción
-- puede ponderse también así, si b
instrucción
--solo hace falta que cumpla una de las condiciones
-- hace falta que se cumplan las dos condiciones
La estructura if con operadores lógicos más las opciones elseif y else amplían mucho la capacidad
del código en situaciones en que las variables son cambiantes .
if a == b then
instrucción 1
elseif a ~= c
then
instrucción 2
else
end
92
instrucción los operadores lógicos.
La expresión else amplía las posibilidades de la estructura
or, and, not (o, y, no)
instrucción 3
-- si a es igual a b, entonces
-- haz instruccion 1
-- sino, pero si a es distinto de c
-- haz instruccion 2
-- si no se cumple ninguna condición anterior
-- haz instruccion 3
93
Retomemos el ejemplo de los círculos transparentes de la pág 84, aplicando la estructura if más else
código. Para dibujar las capas de círculos solo hemos tenido que poner en el draw() una función para
/*
GAmuza 0.4.1 examples
---------------------
valores de las variables incrementan si se cumple la doble condición de if planteada con el operador
los que van hacia la derecha y otra para los que lo hacen hacia la izquierda. En el bloque update(), los
lógico and sólo si el radio es mayor o igual a 50 y menor o igual a 300 el valor de las variables se
Basics/circulos_if.ga
modificarán con las expresiones aritméticas que contiene. Si no se cumplen esas dos condiciones se
*/
aplicará el código que contiene else.
Como se ha mencionado antes, las expresiones condicionales se utilizan con frecuencia para controlar
radio = 300
animaciones, de modo que reasignan nuevos valores de las variables cuando las formas alcanzan los
x1 = OUTPUT_W/2
límites de la ventana de salida, generando un loop en la animación. Retomamos el ejemplo de la pág
x2 = OUTPUT_W/2
91, aplicando control a esos límites, cuando la línea llega al final de la pantalla, su coordenada y vuelve
y = OUTPUT_H/2
a valer 0. En la pág 130, una expresión if en vez de reiniciar el valor a 0, invierte su dirección.
inc = 30
radioDec = 50
/*
GAmuza 0.4.1 examples
function setup()
---------------------
of.setCircleResolution(60)
Basics/aritmetica_anima_if.ga
end
Cómo controlar del movimiento con
expresiones ondicionales
function update()
if radio >=50 and radio <=300 then -- tienen que cumplirse las 2 condiciones
x1 = x1 + inc
x2 = x2 - inc
y = y + inc
radio = radio - radioDec
inc = 20
function setup()
else
x1 = x1-inc
x2 = x2+inc
y = y - inc
radio = radio + radioDec
end
function update()
of.setColor(255, 50)
of.circle(x1, y, radio) end
of.circle(x2, y, radio)
if y < OUTPUT_H
else
end
function draw()
-- ga.background(0.0, 0.1)
end
*/
y = 0
end
94
Con la estructura if se perciben mejor las relaciones entre las formas y se reduce la repetición de
en el bloque update()
se comenta el fondo
-- dibuja los círculos con los datos de update
end
y = y + inc
then
y= 0
function draw()
ga.background(0.0,0.2)
of.setColor(255)
of.setLineWidth(4)
of.line(0, y, OUTPUT_W, y)
end
95
3.3.4. Expresiones de iteración. Repetición
es decir, recorre el eje de las X situando un punto cada 50px.
for, while, repeat
Las estructuras iterativas se utilizan para compactar líneas de código repetitivo, especialmente cuando
que tienen un cambio modular que será aplicado a través de una variable.
La estructura for se articula con tres declaraciones: valor inicial de la
variable, el test con una expresión relacional y la actualización del valor de
la variable (update). Las declaraciones dentro del bloque for se ejecutan
de forma continua, generando un loop dentro de ese bloque mientras
el test sea verdadero, true. El valor inicial de una variable se verifica en
el test, la actualización modifica su valor después de cada iteración del
bloque y la aplica a la instrucción. Cuando el test tiene como resultado
false, el loop termina y el sistema continúa con las líneas de código
que estén después del bloque for. Cuando la actualización del valor es
sumar 1, suelen ponerse solo dos declaraciones: valor inicial variable y
test, asumiendo la estructura que la actualización es sumar 1.
Algunos ejemplos cometados.
estructura for
*/
function setup()
of.enableSmoothing()
end
function draw()
ga.background(0.0, 1.0)
of.setColor(255)
of.setLineWidth(3)
for i = 0, OUTPUT_W, 50 do of.line(i, 0, OUTPUT_W-i, OUTPUT_W-i)
end
end
En el segundo par de coordenadas de las líneas, x e y tienen el mismo valor, comúnmente y suele
estar vinculada a la constante OUTPUT_H, pero en este caso vamos a considerar la ventana de salida
como si fuera un cuadrado. Los puntos con sus dos coordenadas iguales se sitúan siempre en una
diagonal de 45º, y cómo este valor se va reduciendo simultáneamente a como crece la x primera, lo
que recorre el segundo par de coordenadas es la primera línea dibujada por el for, reproduciendo así
la representación plana de un paraboloide hiperbólico.
Subrayar que GAmuza no utiliza () ni {} en la estructura for, y la cierra con end.
La estructura for puede combinarse con if para reajustar la condición ya establecida en el test de
for. En este caso se va a utilizar el if para comprender cómo funciona el operador aritmético % que
vimos en la página 91.
/*
GAmuza 0.4.1 examples
--------------------Basics/for_if.ga
estructura for más if
*/
function setup()
end
/*
GAmuza 0.4.1 examples
--------------------Basics/simple_for.ga
96
ventana de salida, y en cada vuelta tendrá 50 píxeles más. Con esa lista de valores se van dibujando
líneas en cuyo primer par de coordenadas, x responde a ese incremento de 50px e y siempre vale 0,
Sintaxis
Repetición
La estructura for se repetirá en loop hasta que la variable i tenga el valor OUTPUT_W, ancho de la
-- no lleva () ni {}
-- cierra el for con end
function draw()
ga.background(0.0,1.0)
of.setLineWidth(3)
for a = 0, OUTPUT_W, 13 do
if (a % 2) == 0 then
of.setColor(255)
elseif (a % 5) == 0 then
of.setColor(255, 0, 0)
else
of.setColor(0,255,0)
end
of.line(a, 0, a, OUTPUT_H)
end
end
97
Dado que los valores que a va obteniendo en el loop del for tienen que cumplir otras condiciones, se
ha elegido el número 13, raro, para obtener un rango más diverso, pero siempre mantendrá relaciones,
es decir, generará un pattern:
0, 13, 26, 39, 52, 65, 78, 91, 104, 117, 130, 143, 156, 169, 182, 195...,
par, impar, par, impar..., el primer múltiplo de 5 el 6º y luego cada 10, es decir, el primer múltiplo de 5
ha caído en la mitad de su rango por esos límites particulares que suele provocar el número 0. De este
modo el for dibuja las formas y la condicional if determina los colores.
La estructura iterativa for genera repeticiones en una dimensión, si se anida un for dentro de otro for
se generan repeticiones en dos dimensiones.
/*
GAmuza 0.4.1 examples
--------------------Basics/doble_for.ga
estructura for+for retículas 2D
*/
inc = 20
function setup()
of.setCircleResolution(25)
end
function draw()
ga.background(0.0,1.0)
of.setColor(255,255,255)
for i=0, OUTPUT_W, inc do
for j=0 , OUTPUT_H, inc do
if i % j == 0 or j % i == 0 then
of.setColor(0)
else
of.setColor(255)
end
of.circle(i, j, inc/2-1)
end
end
end
En este doble for, cuando la variable i adopta el primer valor, 0, el sistema pasa a asignar el primer
valor a j=0, luego j=20, j=40,.. hasta que j llega al valor de la altura de la ventana, con ello ha
generado las coordenadas (0,0) (0,20) (0,40)… …(0,OUTPUT_H). Después i adquiere el valor
20 y de nuevo pasa a asignar valores a j desde 0 hasta el valor de la altura de ventana, generando las
98
coordenadas de la segunda columna de círculos (20,0) (20,20) (20,40)… Así hasta que completa
toda la tabla cuando i alcanza el valor del ancho de ventana y j el del alto:(OUTPUT_W, OUTPUT_H).
El siguiente ejemplo retoma el planteamiento de los polígonos concéntricos y lo formula con una
estructura for y el uso de color HSB
/*
GAmuza 0.4.1 examples
------------------Basics/for_poligonos.ga
*/
radio = 100
radioMax = 250
radioInc= 30
posX = OUTPUT_W/2
posY = OUTPUT_H/2
doble = 10
lados = 3
c = of.color()
colorInicio = 0
colorInc = 40
function setup()
of.enableSmoothing()
end
function draw()
ga.background(0.0,1.0)
of.noFill()
of.setLineWidth(10)
lados = 3
j = 0
for i=0, 6 do
of.setCircleResolution(lados)
c:setHsb((j/8)*255,255,255)
of.setColor(c.r,c.g,c.b)
of.circle(posX, posY, radio+(i*40))
j = j+1
c:setHsb((j/8)*255,255,255)
of.setColor(c.r,c.g,c.b)
of.circle(posX, posY, radio+(i*40) + 9)
lados = lados + 1
end
end
99
3.4. Color
Solo se ponen de acuerdo en la relación entre complementarios u opuestos
¿Porqué no se puede imaginar un vidrio blanco transparente —inclusive si en la realidad no lo
Complementarios
44
Cian El color es una sensación perceptiva cuyo estudio recae en muy distintas disciplinas: psicología de la
Magenta
Amarillo hay?¿En dónde se pierde la analogía con el vidrio transparente coloreado?
percepción, física-óptica, fisiología, neurología, filosofía….
Según el enfoque de la disciplina, se le considera como un fenómeno visual vinculado a la luz y
Rojo
Verde
Azul
localizado físicamente en una porción del espectro electromagnético (espectro lumínico), o como
sinestesia ente el sujeto que percibe y el objeto percibido dentro de la psicología, o como un proceso
neuro-fisiológico complejo.
Los ordenadores utilizan color-luz porque los materiales de las pantalla o video proyección fosforecen
Como fenómeno que depende de la luz, el color recoge de ella sus paradojas, llegando a ser un claro
de sistematizar las relaciones que se producen entre los componentes o parámetros del color bajo un
ejemplo para mostrar la contradicción entre el mundo tangible y el intangible. Así, todas las relaciones
que se establecen entre los componentes del color pigmento (materia tangible) y en el color-luz
con la mezcla aditiva. Pero existen distintos modelos o espacios de color; un modelo es el resultado
determinado criterio.
Los tres parámetros del color: tono, saturación y luminosidad, están relacionados de manera
(materia intangible) son contrarias.
distinta en cada modelo, incluso utilizan nombres distintos para esos parámetros. El tono a veces lo
Color-pigmento
Mezcla sustractiva
La mezcla de sus primarios es negro
Colores primarios
Magenta, Amarillo, Cian
Colores secundarios
Rojo, Verde, Azul
encontraremos bajo la denominación de color o matiz; y la luminosidad como valor, brillo o intensidad.
Color-luz
Mezcla aditiva
La mezcla de sus primarios es blanco
El término saturación suele permanecer bastante estable en los distintos modelos. Los modelos más
habituales en programación son: RGB, HSB (o HSV) y hexagesimal (principalmente vinculado a la web).
Colores primarios
Rojo, Verde, Azul
Colores secundarios
Cian, Magenta, Amarillo
Magenta + Amarillo = Rojo
Rojo + Azul = Magenta
Amarillo + Cian = Verde
Rojo + Verde = Amarillo
Cian + Magenta = Azul
Verde + Azul = Cian
MODELO RGB
El modelo RGB se basa en los colores-luz primarios (Red, Green, Blue - rojo, verde, azul) más otro
canal denominado alpha que se ocupa de la transparencia. Cada dato de color RGB+alpha tiene 32
bits, 8 bits por canal y cada uno de estos canales tiene un rango de valores que va de 0 a 255, siendo
el valor (0,0,0) el negro, y el valor (255, 255, 255) el blanco.
MODELO HSB
El modelo HSB hace referencia a los parámetros (Hue, Saturation, Brightness – Matiz, Saturación,
Brillo), es muy semejante al modelo HSV 45, donde V significa Value (valor) pero en ambos casos, brillo
y valor es lo mismo que hemos denominado luminosidad. El tono o matiz recorre el círculo cromático
graduándose de 0 a 360º, mientras que los valores de saturación y luminosidad se scalan entre 0 y
100%.
44 Ludwig Wittgenstein (1994) Observación sobre los colores. Barcelona:Paidós, pág. 175.
100
45 El esquema del modelo de color HSV ya se mencionó en la interface de tracking video (ver página 41)
101
En openFrameworks y en GAmuza se puede trabajar con el modelo HSB pero con el rango de sus
valores igual al que utiliza el modelo RGB (todos los parámetros van de 0 a 255) con la ventaja de
mantener la lógica de este modelo que se adecúa mejor en trabajos con graduaciones de escalas
tímbricas de color.
En el caso del tono (Hue) hay que escalar los 360º a 256 valores. En la siguiente imagen se clarifica
este cambio, desplegado el círculo linealmente y con la conversión de valores que se utilizan en
GAmuza para los colores-luz primarios, secundarios e intermedios. La impresión cromática que se ve
es orientativa pues la conversión del modo de color a CMYK, para la edición del texto, altera los tonos.
Colores-luz secundarios.
En RGBs se obtienen incrementando valores iguales en solo dos
componentes y dejando el tercero a 0. En HSB, buscar el tono con
el slider H (hue)
R=255, G=0, B= 255 Magenta máxima luminosidad y saturación
Pérdida de luminosidad color secundario:
Si los valores son R=100, G=0, B=100 veremos un magenta
oscurecido, según vayan bajando los valores irá tendiendo a negro.
En HSB, bajar hacia el valor 0 el slider B.
El valor 255 y 0 corresponden al mismo color Rojo, punto en el que se cerraría el círculo cromático.
Pérdida de saturación color secundario
La herramienta Color Selector del ScriptEditor, ayuda a calcular los valores y ver las relaciones entre los
Se desaturan incrementando el valor de ese tercer componente.
dos modelos, porque al mover los sliders de uno se adjustan también los del otro.
Los colores luz primarios en RGB tienen el máximo valor en su
parámetro correspondiente y 0 en los otros dos.
R=0, G=0, B=255 Azul con máxima luminosidad y saturación.
En HSB, simplemente dsplazar el primer slider (Hue) hasta percibir
el color.
Pérdida de luminosidad colores primarios:
Si los valores son R = 0, G=0, B=128, veremos un azul oscuro por
la pérdida de luminosidad al 50%. Según va bajando el valor del azul
hacia 0, y los otros permanecen igual, se llega al negro. En HSB, ir
bajando el slider B hacia el 0
En el ejemplo anterior, R = 255, G=170, B= 255, es un magenta
desaturado, si los tres alcanzan 255, llegan a blanco. En HSB, bajar
hacia el valor 0 el slider S.
Los colores terciarios surgen al mezclar en la misma proporción un primario y un secundario que no lo
contiene, es decir, con su color complementario al 50%. En este nivel surge el mundo de los marrones,
o tierras, dejando las escalas tímbricas de colores más puros para entrar en las escalas tonales46.
Para traducir estas relaciones a valores RGB, los colores terciarios
sin desaturar y sin pérdida de luminosidad, se obtienen combinando
en proporciones distintas dos componentes del color, dejando el
tercero con un valor 0, o muy diferenciado de los otros. En HSB son
tonos que siempre tienen un descenso de luminosidad.
Para desaturarlos en RGB se incrementa proporcionalmente el valor
de los tres componentes. En HSB se baja el valor de S.
Pérdida de saturación colores primarios:
Volvemos al valor B = 255, conforme G y B van incrementando sus
valores de forma equivalente, el rojo se irá desaturando. Cuando
todos alcancen el valor 255 llegarán al blanco. En HSB, ir bajando
el slider S hacia el 0
102
46 Gillo Dorfles, (1963) El devenir de las artes, México: Fondo de Cultura Económica, pág. 90
Con esta distinción Dorfles aproximó los términos del color a los de la música.. 103
Para reducir la luminosidad se disminuye proporcionalmente el valor
de los dos componentes iniciales. En HSB, bajar el valor de B.
3.5. Azar y probabilidad
Una tirada de dados jamás abolirá el azar
Sthéphane Mallarmé
Si en RGB se mantienen los tres valores semejantes pero no iguales,
se obtienen colores grisaceos con dominate del que tiene, o los dos
que tienen, el valor superior, al incrementarlos proporcionalmente se
desaturan y al reducirlos van perdiendo luminosidad.
El paso de la física determinista a la física de probabilidades implicó un cambio de pensamiento
que ha repercutido más allá de la ciencia. Las relaciones entre orden, caos y aleatoriedad influyeron
fuertemente en el mundo del arte, llegando a ser un motor de creación artística para las propuestas
En Gamuza, el modelo de color HSB se utiliza a través de la clase de openFrameworks of.color().
El proceso es el siguiente:
experimentales de los años 60 y 70, como las composiciones musicales de John Cage, por ejemplo,
quien definió el proceso de creación de la pieza Willian Mix (1953) del siguiente modo:
A través de medios elaborados al azar, determiné previamente cuáles de aquellas categorías tenían
que agruparse, y qué parámetros había que modificar. Se llamó a las categorías A, B, C, D, F; y la
Se vincula una variable global con la clase of.color()
Y en el bloque draw() esa variable establece el puente o traducción de un sistema a otro a través del
método setHsb()
agrupación de estos elementos venía determinada por operaciones al azar del I Ching47.
nombreVariable = of.color()
nombreVariable:setHsb(valor1, valor2, valor3) -- violeta sería(192,255,255)
Después se pone la función habitual para definir el color, pero en sus parámetros se vincula la variable
Esta descripción bien parece un esquema de programación, y como todos los procesos aleatorios,
tiene como particularidad producir formas o sonidos que no pueden conocerse de antemano, pero
dentro el proceso no está dejado al azar en su totalidad, sino que marca un esquema dentro del cual
el azar establece las relaciones.
Azar y aleatoriedad permiten observar cómo la incertidumbre entra en el mundo de las matemáticas,
a .r, .g y .b:
donde la definición de aleatoriedad se expresa como todo es aquello que bajo el mismo conjunto
efecto. Las matemáticas han desarrollado la teoría de la probabilidad y los porcesos estocásticos para
of.setColor(nombreVariable.r, nombreVariable.g, nombreVariable.b)
En los ejemplos de las páginas 86 y 99 se puede comparar el uso de los dos modelos.
aparente de condiciones iniciales, puede presentar resultados diferentes, rompiendo el patrón causacaracterizar las situaciones aleatorias.
En programación, todos los lenguajes contemplan funciones random para representar estas
situaciones. En GAmuza, se puede usar la función of.random(valor 1, valor2) entre el rango
que establecen esos dos valores, el sistema eligirá uno al azar. Esta función suele utilizarse para
generar formas o sonidos menos definidos y que presentan una configuración distinta cada vez que
se activan, pudiendo reflejar un carácter orgánico. En el siguiente ejemplo, un número determinado
de puntos se distribuyen siguiendo una diagonal de 45º de forma uniforme pero fluctúan a un lado y
otro de esa diagonal con una doble aleatoriedad que va incrementando sucesivamente el rango de
fluctuación.
47 Richard Kostelanetz (1973), Entrevista a John Cage, Barcelona: Anagrama, pág. 36.
104
105
/*
GAmuza 0.4.1 examples
--------------------Basics/random_diagonal.ga
diagonal de puntos que fluctúan
of.random(), cuyos valores están a su vez sujetos a la indeterminación de otra función of.random()
que tiende a incrementarlos.
Aunque hagamos un random de random recursivo, la función of.random() produce lo que se conoce
como “una distribución «uniforme» de números”
incrementando el random
Los números aleatorios que recibimos de la función random() no son verdaderamente aleatorios
y por lo tanto, se conoce como “pseudo-aleatorios”. Son el resultado de una función matemática
que simula el azar. Esta función daría lugar a un patrón durante un tiempo, pero ese período de
tiempo es tan largo que para nosotros, parece tan bueno como el azar puro!48
*/
totalPuntos = 800
rango=0
La conjunción de azar y probabilidad busca producir una distribución «no uniforme» de números
function setup()
mismas condiciones.
function draw()
Pensemos de nuevo en la descripción de John Cage. Para trabajar con el azar Cage establece 6
ga.background(0.0,1.0)
of.setColor(255)
rango = 0
for i=1, totalPuntos do
for j = 1, totalPuntos do
if i == j then
of.circle(i + of.random(-rango, rango), j+ of.random(-rango, rango), 1)
rango = rango+ of.random(-1,1.5)
end
end
end
end
La función for tiene sólo dos declaraciones: valor inicial de la variable y test (hasta que i sea menor
o igual a totalPuntos); al no tener la tercera se entiende que es 1, por lo que su acción se reduce a
recorrer todos los valores entre 1 y 800. Cada vez que pasa de un valor a otro, el otro for recorre sus
800 pasos y vuelve el primer for a sumar un punto más... como se vio en la página 96.
categorías para los sonidos: A (sonidos de la ciudad), B (sonidos del campo), C (sonidos electrónicos),
D (sonidos producidos de forma manual), E (sonidos producidos por el viento) y F (“pequeños” sonidos
que deben ser amplificados), y además establece en todos ellos otros parámetros vinculados al tono,
timbre e intensidad. Después tira las monedas del I Ching para que el azar decida la composición a
partir de ese diagrama de relaciones. No se trata de una aleatoriedad uniforme entre todos los sonidos,
sino que opera articulándose con un contexto de relaciones condicionales.
Pero incluso las decisiones que se puedan tomar siguiendo el ejemplo más sencillo del azar, tirar una
moneda al aire, tiene condiciones. En principio existe una equiprobabilidad, es igual de probable que
salga cara o cruz:
1/2 = 50%
Lanzar la moneda una sola vez, nos sitúa ante eventos independientes, cuyo resultado no está
condicionado ni tiene efecto en la probabilidad de que ocurra cualquier otro evento. Pero si lanzamos la
moneda dos veces, la probabilidad de que salga cara en ambos sucesos cambia. Según los principios
básicos de probabilidad, que 2 o más eventos independientes ocurran juntos o en sucesión, es igual
al producto de sus probabilidades marginales:
1/2 * 1/2 = 1/4 el 25%
De todos esos valores, la condicional if desestima las opciones en los valores del primer y segundo
En el caso de tres tiradas (..., el I Ching implica 6 tiradas de 3 monedas cada vez):
siguiendo una línea de 45º.
En la función interna of.circle(), las coordenadas x e y alteran esa distribución uniforme al fluctuar
o no, otro evento.
for no son iguales, por lo que al aplicar los datos que pasan el filtro como coordenadas, se sitúan
un número indeterminado de píxeles a un lado y otro de esa dirección como consecuencia de la función
106
aleatorios, reflejando el hecho de en ningún sistema todos los elementos son iguales, ni tienen las
end
1/2*1/2*1/2 = 1/8 el 12’5%.
Así llegamos a que la probabilidad de que suceda un evento está condicionada a que haya ocurrido,
48 Daniel Shiffman, Nature of code [draft 5.4.2012] pág. 6.
107
Daniel Shiffman propone otro ejemplo particular dentro del campo del azar, el Camino aleatorio,
Este caminante recorre 4 px en cada paso, lo que transforma la opción de puntos en pequeñas líneas
que de algún modo mantiene también relación con las acciones artísticas psicogeográficas de los
endacenadas. El segundo par de coordenadas (xsig, ysig) de cada línea será el primero de la
siguiente, trazando así el recorrido de su deriva.
Situacionistas.
Camino aleatorio (Random Walks) es una formalización matemática de la trayectoria que resulta
de hacer sucesivos pasos aleatorios. Por ejemplo, la ruta trazada por una molécula mientras viaja
por un líquido o un gas, el camino que sigue un animal en su búsqueda de comida, el precio de
una acción fluctuante y la situación financiera de un jugador pueden tratarse como un camino
aleatorio. El término Camino aleatorio fue introducido por Karl Pearson en 1905. Los resultados del
análisis del paseo aleatorio han sido aplicados a muchos campos como la computación, la física,
la química, la ecología, la biología, la psicología o la economía49.
El siguiente ejemplo muestra la programación de un Camino aleatorio tradicional
que se inicia en el centro de la pantalla y a cada paso elige al azar una entre
Como el fondo en GAmuza se dibuja de nuevo en cada frame, para visualizar el recorrido hay que
quitar o comentar la función ga.background().
En esta opción tradicional existe 1/8 = 12,5% de probabilidades de que el punto se traslade a una las
8 posiciones posibles cada vez que se efectúa el random, indistintamente de cuantas veces lo haga.
Daniel Shiffman50 plantea un Random Walker que tiende a moverse hacia una dirección porque,
como mencionaba la defición de este algoritmo, su planteamiento sirve para representar trayectorias,
especialmente en medios fluidos, como el vuelo de las aves, o el movimiento en líquidos o gases,
las 8 opciones, que en coordenadas oscilará entre +1 y -1 tanto para x como
donde la rigidez de la geometría euclideana queda relegada por los flujos o turbulencias, pero más allá
of.randomf(), sin parámetros, porque son esos los que están ya establecidos
están totalmente abiertas sino que marcan una tendencia de dirección. Shiffman regula esta dirección
para y. Por eso, en lugar de utilizar la función of.random(-1, 1) se usa
de la deriva como acción artística que recurre al azar indeterminado, esas trayectorias orgánicas no
por defecto.
de trayectoria por medio de porcentajes, planteando un Random Walker que tiende a la derecha con
las siguiente probabilidades:
/*
GAmuza 0.4.1 examples
--------------------Basics/random_Walker01.ga
Random Walker tradicional
*/
Quedando el código de programación sujeto a condicionales if.
/*
GAmuza 0.4.1 examples
---------------------
x0 = OUTPUT_W/2
Basics/random_Walker02.ga
y0 = OUTPUT_H/2
Random Walker condicionado
step = 4
*/
function draw()
-- ga.background(0.0,1.0)
of.setColor(255)
xsig = x0 + (step * of.randomf())
ysig = y0 + (step * of.randomf())
of.line(x0, y0, xsig, ysig)
x0 = xsig
-- el valor de las dos ultimas coordenadas de la línea
y0 = ysig
-- pasa a las primeras para unir las líneas en recorrido
end
49 Definición Camino aleatorio [enciclopedia on-line] <http://es.wikipedia.org/wiki/Camino_aleatorio> [31.07.2012]
108
Moverse hacia arriba 20%, abajo 20%, izquierda 20%, derecha 40%.
x0 = OUTPUT_W/2
y0 = OUTPUT_H/2
step = 4
xsig = x0-step
ysig = y0-step
function update()
x0 = xsig
y0 = ysig
end
50 Daniel Shiffman, Nature of code [draft 5.4.2012] pág. 8.
109
function draw()
--ga.background(0.0,1.0) el fondo se ha anulado
of.setColor(255)
r = of.random(1)
if
r < 0.4 then
-- 40% hacia derecha
xsig = x0 + step
elseif r < 0.6 then
-- si solo hay un parámetro es entre 0 y ese valor
-- no es 60%, elseif solo actúa si no cabe en if
xsig =x0 - step
elseif r < 0.8 then
ysig = y0 + step
else
/*
GAmuza 0.4.1 examples
--------------------Basics/noise01.ga
modulación del movimiento
ysig = y0 - step
*/
end
v=0
-- parámetro noise
of.line(x0, y0, xsig, ysig)
inc = 0.1
-- incremento
end
function setup()
Sin hacer nunca el mismo camino, siempre que activemos el programa, el recorrido va a la derecha.
end
function draw()
ga.background(0.0,1.0)
of.setColor(255)
of.noFill()
3.5.1. Noise
de la película Tron.
El Ruido Perlin es una función matemática que utiliza interpolación entre un gran número de gradientes
precalculados de vectores que construyen un valor que varía pseudo-aleatoriamente en el espacio
o tiempo. Se parece al ruido blanco, y es frecuentemente utilizado en imágenes generadas por
computadora para simular variabilidad en todo tipo de fenómenos51.
La función of.noise() permite generar formas, texturas y movimientos con una apariencia más
orgánica, porque interpola entre los valores random otros datos para crear transiciones más suaves
que se reflejan como pequeñas irregularidades.
51 Definición de Ruido Perlin [enciclopedia on-line] < http://es.wikipedia.org/wiki/Ruido_Perlin > [01.08.2012]
110
-- n da un valor modulado para y
v=v+inc
uniforme, no uniforme o personalizada, pero son valores que no guardan relación entre sí. La función
proviene de la función matemática Noise Perlin desarrollada por Ken Perlin para generar las texturas
-- i da un valor regular para x
n = of.noise(v)*100.0
of.rect(i, n, 20, 20)
Con la función of.random() se pueden generar series de valores inesperados, con una distribución
of.noise() genera también valores inesperados pero de una forma más controlable. Su nombre
for i=0, OUTPUT_W, 20 do
-- en cada loop del for el valor del parámetro de noise cambia
end
end
La función of.noise() no genera realmente números más relacionados ente sí que la función
of.random(), funciona de manera diferente. El rango de los datos de salida es fijo y siempre devuelve
un valor decimal entre cero y uno. Siempre el mismo valor. Por eso, en el ejemplo, el cálculo se realiza
sobre una variable v que va incrementando su valor paso a paso, v = v + inc. y se multiplica por 100
para escalarlo. Se genera una imagen en movimiento de una cadena de cuadrados que serpentean
ondulatoriamente de forma continua e irregular.
Otra opción es utilizar la función of.map() para mapear los datos. El rango de números decimales
entre 0 y 1 de of.noise() son adaptados por of.map() a través de 6 parámetros:
of.map (valor, inputMin, inputMax, outputMin, outputMax, fijarOut(true o false))
111
3.6. Textos y tipografía
El primer parámetro es el valor que queremos asignar, en el ejemplo es v (el resultado de of.noise());
el segundo y tercero corresponden al rango actual de valores mínimo y máximo obtenidos por
of.noise(), que sabemos son 0 y 1. Los dos siguientes parámetros son el rango al que deseamos
escalar los valores de entrada, en el siguiente ejemplo va a ir de 0 a OUTPUT_W, y el último parámetro
permite fijar los resultados o no, mediante la opción boolenana true o false. Veamos un ejemplo.
Entre los tipos de datos que almacena y con los que opera el software están también las palabras, no
como nombres de variables sino entendidas como caracteres (char), letras, y/o cadena de caracteres
(string) , palabras, pudiendo incorporar texto como imagen, pues las fuentes se convierten en texturas
que se dibujan en la pantalla.
En GAmuza se pueden utilizar las clases of.trueTypeFont() o ofx.trueTypeFontUC()
Para ambas es necesario cargar el tipo de fuente previamente y asociar una variable global a la clase
de openframeworks o de ofx.
/*
GAmuza 0.4.1 examples
---------------------
nombreVariable = of.trueTypeFont()
function setup()
nombreVariable:loadFont(“fonts/Anonymous_Pro_B.ttf”,50, true, true)
Basics/noise_map.ga
modulación del movimiento
Los métodos de vinculan a las variables con el operador “:” (clases y métodos se verán, en la página
*/
136). Los parámetros del método loadFont() son:
• Tipo de fuente (incluyendo la ruta donde está guardada),
v = 0.0
• Tamaño,
inc = 0.01
• Si tiene anti-aliasing (booleano),
• Si la fuente contiene el conjunto completo de caracteres o un subconjunto —ASCII extendido,
que puede incluir diéresis (aunque no acentos) o ASCII normal— también booleano.
function setup()
end
GAmuza crea una carpeta con el mismo nombre que se le ponga al archivo, es en esa carpeta donde
function update()
....
v = v + inc
end
debe guardarse una copia de la fuente a utilizar.
El contenido del texto se dibuja en el bloque draw() con el método drawString() que tiene 3
parámetros: el texto entre comillas “texto entrecomillado” y las coordenadas que definen la
function draw()
ga.background(0.0, 0.1)
of.setColor(255)
x = of.map(of.noise(v),0,1,0,OUTPUT_W, false)
y = OUTPUT_H/2 + of.random(-4, 4)
of.circle(x,180,16,16)
posición de inicio del texto.
nombreVariable: drawString(“texto entrecomillado”, x, y)
Si se va a modificar el tamaño mientras el programa está activo, la función loadFont() se pone en el
bloque draw() o el valor del tamaño vinculado a una variable que se actualiza en el bloque update().
end
112
113
El mundo de la programación es anglosajón, por lo que para trabajar con acentos, ñ..., hay que utilizar
la clase ofx.trueTypeFontUC() para texto Unicode52
Además de los métodos loadFont()
/*
GAmuza 0.4.1 examples
--------------------texto con acentos,
tamaño y posición random
texto = ofx.trueTypeFontUC()
end
function update()
t = of.random(30, 100) -- actualiza el valor del tamaño
end
function draw()
ga.background(0.0,0.5) -- fondo negro 50% transparencia
of.setColor(255, 0, 255) -- color magenta
posX = of.random(50,OUTPUT_W-50)
posY = of.random(50, OUTPUT_H-50)
texto:loadFont(“fonts/verdana.ttf”, t, true, true) -- tamaño variable
-- kerning vinculado a tamaño
texto:drawString(tx, posX ,posY)
end
-- espacio entre palabras
ofx.arcText()
-- para textos con posiciones curvas
ofx.FTGLFont()
-- si requiere openGL
ofx.setSubtitles()
-- trabaja con archivos .srt porpios de subtítulos
-- llama a un archivo .txt para traer el contenido
created by n3m3da | www.d3cod3.org
*/
font = ofx.arcText()
text = “GAmuza - Hybrid Live Coding”
function setup()
of.setCircleResolution(50)
font:loadFont(“fonts/D3Litebitmapism.ttf”,58)
font:setLetterSpacing(1.3)
end
function draw()
ga.background(0.9,1.0)
end
52 “Unicode es un estándar de codificación de caracteres diseñado para facilitar el tratamiento informático, transmisión y visualización
de textos de múltiples lenguajes y disciplinas técnicas, además de textos clásicos de lenguas muertas”. [enciclopedia on-line]
<http://es.wikipedia.org/wiki/Unicode> [30.08.2012]
114
setEspaceSize() /*
GAmuza 0.4.1 examples
--------------------Font/curveText.ga
dibujar texto sobre curva
usando ofx.arcText()54
tx = “Randonée” -- contenido texto
texto:setLetterSpacing(t/50)
-- altura de la línea de texto que se dibuja en pantalla
El siguiente ejemplo está accesible en File/Examples/Font/ , y utiliza la clase ofx.arcText()
-- tamaño fuente
function setup()
setLineHeight() ofx.wordPalette()
*/
drawString(), en el ejemplo se ha utilizado
Existen también otras calses del addon ofx vinculadas a textos y tipografía:
Font/unicode_random.ga
t = 30
y
setLetterSpacing(), que regula el kerning (espaciado entre las letras). Otros métodos posibles son53:
of.setColor(0)
of.pushMatrix()
of.translate(OUTPUT_W/2,OUTPUT_H/2,0)
of.rotateZ(of.getElapsedTimef())
font:drawString(text,0,0,OUTPUT_H/2)
of.popMatrix()
53 Más información en “ofTrueFont” [texto on-line] http://www.openframeworks.cc/documentation/graphics/ofTrueTypeFont.html
[03.08.2012]
54 addon source <https://github.com/companje/ofxArcText> [01.09.2012]
115
Se pueden utilizar texto como formas con la clase of.trueTypeFont(). En el siguiente ejemplo se usan
para ello las siguientes clases, métodos y funciones:
• La clase de openFrameworks of.path()55: crea un path o múltiples path a través de puntos,
generando un vector. Está vinculada con los métodos clear() que borra los puntos y
setFilled() cuyos parámetros true o false establecen si el path es wireframes o relleno.
• La función de Lua string.byte(): devuelve el código numérico interno del carácter que se
ponga como parámetro
• El método getCharacterAsPoints(): obtiene los puntos que definen el carácter y que serán
usados por of.path() para el trazado .
56
/*
GAmuza 0.4.1 examples
--------------------Font/fontShapes.ga
Cómo usar la clase of.trueTypeFont
para dibujar texto desde .ttf o .otf
como formas vectoriales
// draw character as bitmap
font1:drawString(“&”, 50, 250)
// draw the character as shapes
character:setFilled(true)
character:draw(200,250)
character:setFilled(false)
character:draw(350,250)
character:clear()
// draw text as shapes
of.fill()
font2:drawStringAsShapes(“Hello - I am a vector”,50,480)
of.noFill()
font2:drawStringAsShapes(“Hello - I am a vector”,50,550)
end
created by n3m3da | www.d3cod3.org
*/
font1 = of.trueTypeFont()
font2 = of.trueTypeFont()
character = of.path()
letter = string.byte(‘&’)
function setup()
font1:loadFont(“fonts/Anonymous_Pro_B.ttf”,160,true,true,true)
font2:loadFont(“fonts/D3Litebitmapism.ttf”,52,true,true,true)
character = font1:getCharacterAsPoints(letter)
end
function update()
end
function draw()
ga.background(0.0,1.0)
// draw text as bitmap
of.setColor(0,90,60)
font2:drawString(“hello - I am a bitmap”,50,400)
55 ofPath Reference <http://www.openframeworks.cc/documentation/graphics/ofPath.html> [01.09.2012]
56 ofTrueTypeFont Class Reference ver < http://www.undef.ch/uploads/ofDoc/html/classof_true_type_font.html > [01.09.2012]
116
117
3.7. Trigonometría
La trigonometría es una rama de las matemáticas cuyo significado etimológico es “la medición de los
triángulos” y sirve para definir relaciones entre los lados y ángulos de los triángulos. Básicamente es
una extensión del Teorema de Pitágoras Las funciones trigonométricas y las funciones que más se
utilizan son las del seno y coseno, con ellas se generan números repetitivos que pueden ser utilizados
para dibujar ondas, círculos, arcos y espirales.
La unidad de medida angular propia de la trigonometría es el radian, en una circunferencia completa
hay 2π radianes.
Para ver cómo funcionan gráficamente, retomamos un ejemplo de Ben Fry y Casey Reas58, traducido al
lenguaje de programación de GAmuza, porque permite observar qué parámetros controlan la amplitud
y frecuencia de las ondas con los valores del seno, math.sin(), en una estructura for.
Esta unidad puede traducirse a Grado sexagesimal: unidad angular que divide una circunferencia
en 360 grados; o al Grado centesimal: unidad angular que divide la circunferencia en 400 grados
centesimales.
OpenFrameworks cuenta con las siguientes constantes para trabajar con unidades radianes:
PI
TWO_PI
M_TWO_PI
FOUR_PI
HALF_PI
Para convertir grados a radianes y viceversa, pueden utilizarse las funciones de Lua math.deg() y
math.rad() y también las funciones de openFrameworks of.degToRad() y of.radTodeg().
Las funciones math.sin(x) y math.cos(x) se utilizan para determinar el valor del seno y coseno de
un ángulo en radianes. Ambas funciones requieren un parámetro, el ángulo. El siguiente gráfico orienta
los valores del seno y coseno en función de los ángulos57.
57 Más información sobre funciones matemáticas Lua en http://lua-users.org/wiki/MathLibraryTutorial [30.07.2012]
118
/*
GAmuza 0.4.1 examples
--------------------Trigonometria/sin.ga
formas de onda regulables
*/
angle = 0.0
pos = 50.0
amplitud = 35.0
inc = PI/20.0
function draw()
ga.background(0.0,1.0)
for x = 0, OUTPUT_W, 5 do
y = pos + (math.sin(angle) *amplitud)
of.setColor(255)
of.rect(x, y, 2, 4)
angle = angle + inc
end
angle = 0.0
end
58 Casey Reas y Ben Fry, (2007) Processing, a Programming Handbook for Visual Designers and Artist and. Cambridge(MA): The
MIT Press, pág. 119-120.
119
En el siguiente ejemplo se utilizan valores del seno y el coseno para calcular los centros de una espiral
de círculos, haciendo una conversión de grados a radianes
Si en este ejemplo se modifican los valores asignados a las variables se puede observar los cambios
en la frecuencia de la onda. La variable pos define la coordenada Y de la onda, la variable amplitud
controla la altura de la onda, y la variable inc el incremento del ángulo.
Las siguientes imágenes muestran los cambios de frecuencia al modificar esos valores y el ángulo.
pos = 25
/*
GAmuza 0.4.1 examples
--------------------Trigonometria/sin_cos.ga
grados a radianes, espiral
*/
radio = 30
function setup()
of.enableSmoothing()
pos = 75
end
function draw()
ga.background(0.0, 1.0)
amplitud=5.0
of.setColor(255)
radio = 30
for grado = 0, 360*4, 10 do
amplitud=45.0
inc=PI/12.0
angle = math.rad(grado)
x = UTPUT_W/2+ (math.cos(angle) * radio)
y = OUTPUT_H/2+ (math.sin(angle) * radio)
of.circle(x, y, 4)
radio = radio + 1
end
end
inc=PI/90.0
La estructura for recorre cuatro veces los 360º de un círculo de 10 en 10 grados. El resultado de los
grados que se obtiene (10, 20, 30, 40,...) se pasa a radianes mediante la función de Lua math.rad(),
angle=HALF_PI
por ejemplo math.rad(180) = 3.1415926535898, es decir PI.
La espiral crece por el incremento del radio, si se comenta o quita radio=radio+1, el código dibuja
un círculo de círculos.
angle = PI
La repetición del valor inicial de la variable, radio = 30, en el draw() y fuera del for sirve para
detener el crecimiento en loop de su valor.
120
121
3.8. Transformar: traslación, rotación
Una variación del este ejemplo nos lleva a la configuación de obra Rotating Disc de Marcel Duchamp.
En el siguiente apartado volveremos a ella para aplicarle la rotación. De momento analizamos el código
para generar la imagen fija.
/*
GAmuza 0.4.1 examples
--------------------Trigonometria/duchamp_disc.ga
*/
radio = 15
spiralFactor = 15
numCircles = 23
function setup()
of.enableSmoothing()
of.setCircleResolution(50)
end
function update()
Sintaxis:
of.pushMatrix(), of.popMatrix()
of.translate(), of.rotate()
La matriz de pixeles en la que se representan las formas mediante coordenadas, puede transformarse
trasladándola o girándola, es decir, no giramos y trasladamos los objetos sino la textura de salida en
su conjunto.
Por esta particularidad antes de trasladar o girar se deben (se recpmienda) utilizar las funciones
of.pushMatrix(), y of.popMatrix() para controlar ese desplazamiento. Estas funciones siempre
van juntas marcando el inicio y el final del proceso. Es como si se generara una textura paralela sobre
la ventana de salida donde se aplican las funciones of.translate(), of.rotate()
end
function draw()
ga.background(0.0, 1.0)
of.setColor(255)
of.noFill()
of.setLineWidth(3)
radio = 15
for i = 0, numCircles do
angulo = i*TWO_PI/((numCircles/2) +1)
x = (OUTPUT_W/2) + (math.cos(angulo) * spiralFactor)
y = (OUTPUT_H/2) + (math.sin(angulo) * spiralFactor)
of.circle(x, y, radio)
radio = radio + spiralFactor
end
end
La funcion of.translate() mueve la textura de salida desde su coordenada (0, 0, 0) hasta el
punto que se indiquen las coordenadas of.translate(x, y, z), si se está trabajando en 2D la
coordenada z es 0. Pero solo las figuras situadas después de la función se verán afectadas por la
translación.
En las transformaciones con rotacion, of.rotate(), suelen aplicarse tanto las funciones
El centro de todos los circulos está situado en el perímetro de un círculo no dibujado, cada uno de ellos
separado por 45º. La diferencia de sus radios se corresponde al valor de ese mismo circulo invisible
que distribuye la tangencia de los otros, es esa tangencia lo que produce la percepción de una espiral.
122
of.pushMatrix(), y of.popMatrix()como of.translate(), que traslada el punto 0 de la pantalla
al eje de rotación. Se pueden apilar tantas superposiciones de la textura de salida como funciones se
pongan en el código. Retomamos el ejemplo basado en Rotating Disc de Duchamp para ver el uso de
estas funciones.
123
/*
GAmuza 0.4.1 examples
--------------------Basics/disco_giratorio_duchamp.ga
Trigonometry + rotate
created by n3m3da | www.d3cod3.org
*/
radio = 15
spiralFactor = 15
numCircles = 23
radioMax = (radio*(numCircles+1)) + (spiralFactor+1)
inc = 15
counter = 0
function setup()
of.enableSmoothing()
of.setCircleResolution(50)
end
La estructura for que dibuja los círculos está después de las funciones of.pushMatrix(),
of.translate(), of.rotate()que, traducido de forma simplificada es, emula una nueva capa de
textura de salida, traslada su punto cero al centro y gira un número de veces (counter) que se va
incrementando cada vez que el for ha terminado (counter +1), después del for se resitúa la textura
de salida y vuelve a empezar por el loop que hace el bloque draw().
Algunas veces las funciones translate() o rotate() pueden ir sin pushMatrix y popMatrix, e incluso
situarse dentro de un for de modo que la translación se repita en cada paso del loop.
/*
GAmuza 0.4.1 examples
---------------------
Basics/translate_for.ga
repetición de translación en for
*/
function setup()
of.enableSmoothing()
end
function draw()
ga.background(0.0, 1.0)
of.setColor(255)
of.noFill()
of.setLineWidth(3)
of.circle(OUTPUT_W/2,OUTPUT_H/2, radioMax)
radio = 15
of.pushMatrix()
of.translate(OUTPUT_W/2,OUTPUT_H/2, 0.0)
of.rotate(counter)
for i = 0, numCircles do
angulo = i*TWO_PI/((numCircles/2) +1)
x = (math.cos(angulo) * spiralFactor)
y = (math.sin(angulo) * spiralFactor)
of.circle(x, y, radio)
radio = radio + spiralFactor
end
of.popMatrix()
counter = counter + 1
end
124
of.setCircleResolution(50)
function draw()
ga.background(1.0,1.0)
of.setColor (204, 116, 5)
of.noFill()
radio = 0
angulo = 0
radioInc = 0.2
posy = OUTPUT_H/6
amplitud = 5
for i = 0, OUTPUT_W do
of.translate(3, posy, 0.0)
angulo = math.rad(i)
of.circle(radio/2, radio/2, radio)
posy = math.sin(angulo) * amplitud
radio = radio + radioInc
if i== OUTPUT_W/4 then
end
end
radioInc = radioInc * -3
end
125
3.9. Programación orientada a objetos. POO
Esta forma particular de estructurar el código favorece su reutilización al compartimentarse en módulos
independientes. Recordad la cita de Katherine B. McKeithen62 respecto a la importancia de organizar
bien la información para procesarla como grupos significativos, algo así sucede en la POO.
La programación orientada a objetos (POO) es un modelo de programación, una forma particular de
pensar y escribir el código, en la que se utilizan los elementos básicos vistos anteriormente: variables,
expresiones y funciones..., pero organizados de modo más próximo al lenguaje verbal. El hecho de ser
un modelo implica que tiene su propia lógica, y para usarlo no sólo debe comprenderse sino que hay
que pensar el desarrollo del código según ese modelo, para poder aplicar después el lenguaje.
La POO nos hace pensar las cosas de una manera distinta, más abstracta y con una estructura más
Nos centraremos en dos elementos que tienen un papel importante en este juego del pensar diferente,
Tablas [arrays] y Clases; señalando la particularidad de esos elementos en GAmuza, pues la hibridación
de plataformas entre openFrameworks y Lua, plantean otra forma de aproximarse a la programación
orientada a objetos.
En la descripción de algunos ejemplos se ha mencionado ya la presencia de Clases, como
of.trueTypeFont() y de sus métodos. En este apartado se explicará su funcionamiento.
organizada, que sigue un proceso de descomposición del problema en partes bastante particular. Los
métodos tradicionales de programación estructurada descomponen la complejidad en partes más
simples y fáciles de codificar, de manera que cada sub-programa realiza una acción.
Se trata de descomponer el problema en acciones, en verbos [...] por ejemplo el verbo pedir, el
verbo hallar, el verbo comprobar, el verbo calcular…59
3.9.1. Tablas [arrays]
En la POO no se descompone el problema en las acciones que tiene que hacer el programa, sino en
objetos, por lo que debemos pensar “cuál es el escenario real del mismo, y vamos a intentar simular
ese escenario en nuestro programa”60. El elemento básico de esta estructura de programación no
son las funciones sino los objetos, entendidos como la representación de un concepto que contiene
información necesaria (datos) para describir sus propiedades o atributos y las operaciones (métodos)
que describen su comportamiento en ese escenario. Por eso implica una manera distinta de enfocar
los problemas, que empieza por la abstracción, entendida en este caso como la capacidad mental
para representar una realidad compleja en los elementos separados simplificados (objetos), ver
aisladamente sus necesidades de definición y comportamiento, y también sus relaciones (mensajes)
y comportamiento conjunto.
Si nos detenemos a pensar sobre cómo se nos plantea un problema cualquiera en la realidad
podremos ver que lo que hay son entidades (otros nombres que podríamos usar para describir lo
que aquí llamo entidades son “agentes” u “objetos”).
Estas entidades poseen un conjunto de propiedades o atributos, y un conjunto de métodos
mediante los cuales muestran su comportamiento. Y no sólo eso, también podremos descubrir,
a poco que nos fijemos, todo un conjunto de interrelaciones entre las entidades, guiadas por el
intercambio de mensajes; las entidades del problema responden a estos mensajes mediante la
ejecución de ciertas acciones.61
59 Luis R. Izquierdo (2007) “Introducción a la programación orientada a objetos”. Pág. 2 [texto on-line] http://luis.izqui.org/resources/
ProgOrientadaObjetos.pdf [25.07.2012]
60 Ibidem.
61 Ibidem.
126
El término array en programación y matemáticas está vinculado a matriz, y significa un conjunto
ordenado consecutivamente de elementos, del mismo tipo de datos, almacenados bajo el mismo
nombre y para los que el sistema reserva memoria (igual que para las variables, pero aquí como una
serie de variables relacionadas). El orden consecutivo asigna a cada elemento un ID, este ID es una
forma numérica consecutiva que empieza por 0 y lo identifica de manera que se puede acceder a
ese elemento en la programación individualmente. Los datos pueden ser de cualquier tipo pero no se
pueden mezclar distintos tipos en un mismo array.
Hay arrays de una dimensión (lineales) o de dos dimensiones (matrices) que podemos visualizarlo
como una fila de contenedores que acogen cada uno de ellos un dato. En el siguiente ejemplo vemos
como un array de 20 elementos se ordena hasta la posición 19 porque empieza a contar desde 0:
Los arrays de dos dimensiones constituyen una matriz de filas y columnas. Por ejemplo, la ventana de
salida podemos verla como un array cuyo número de elementos es igual a los píxeles de la imagen y
62 Katherine B. McKeithen et al., “Knowledge Organization and Skill Differences in Computer Programmers” Cognitive Psychology
13(3) Pág. 307. [Texto on-line] [Consultado: 12/05/2012] http://hdl.handle.net/2027.42/24336
127
function draw()
ga.background(0.0,1.0)
of.setColor(255,0,0)
-- color rojo
of.noFill()
-- no rellenar
for i = 0, 100 do
-- dibuja los 100 círculos
of.circle(myTable[i].x, myTable[i].y, myTable[i].diam)
end
end
su dimensión es el resultado de multiplicar el ancho por
el alto. Al igual que los array lineales, empieza a contar
por cero y el primer elemento tiene el ID [0,0]
Teniendo en mente este concepto, vamos a ver cómo
GAmuza no usa exactamente arrays, sino lo que en
el lenguaje Lua se denominan tablas (librería table de
Lua), pero puede hacer las mismas operaciones con
mayor flexibilidad porque las tablas permiten utilizar
La variable i de la estructura for va adoptando consecutivamente el ID de cada circulo de la tabla.
datos de diferente tipo y simplifican mucho el proceso
de programación. Además, las tablas en Lua no se entienden como lineales o de dos dimensiones,
sino que una tabla lineal puede albergar múltiples dimensiones de datos. La sintaxis para declarar una
tabla es:
Después de crearla con myTable[i] = {}, no necesita establecer nuevos arrays para cada uno de
los parámetros de la función of.circle, simplemente en el mismo for va asignando esos valores
utilizando el operador “.” junto al código que representa cada dato de la tabla: myTable[i].
En la función draw(), además de las funciones internas para el color y no relleno, otra estructura
nombreTabla {}
for dibuja todos los círculos recogiendo los datos de la tabla. No hay función update() porque en
Para crearla pueden enumerarse los elementos que la constituyen entre {}, definir cual es el número
de elementos por medio de una variable, o simplemente crear la tabla y todos los objetos utilizando
el ejemplo las formas están fijas, no hay comportamiento. Sí se incluye en el siguiente ejemplo en el
que se incrementan las propiedades de cada uno de los objetos de la tabla que vuelven a ser círculos.
una expresión for que recorrerá la tabla y asignará valores a todos los datos. Pasamos a describirlo
comentado el código de algunos ejemplos.
/*
GAmuza 0.4.1 examples
--------------------Basics/tabla_circulosFijos.ga
Cómo declarar una tabla y asignar
valores a sus elementos
created by n3m3da | www.d3cod3.
org
*/
myTable = {}
function setup()
of.setCircleResolution(60)
for
i
=
0,
100
do
-- establece nº objetos del array
myTable[i] = {}
myTable[i].x = of.randomuf()*OUTPUT_W
myTable[i].y = of.randomuf()*OUTPUT_H
myTable[i].diam = of.random(0,OUTPUT_W/2)
end
end
128
-----
crea la tabla
asigna valores a posición x
asigna valores a posición y
valores a diámetros
/*
GAmuza 0.4.1 examples
--------------------Basics/tabla_circulosRebotan.ga
asignar comportamiento a los
objetos de una tabla
*/
129
circulos ={} maxCirculos = 20 -- se declara la tabla
-- número máximo de objetos
function setup()
of.enableSmoothing()
of.setCircleResolution(50)
for i = 0, maxCirculos-1 do -- recorre todos los objetos
circulos[i] = {}
-- crea tabla y asigna propiedades
circulos[i].posX = of.random(30, OUTPUT_W) -- coordenadas X al azar
circulos[i].posY = of.random(OUTPUT_H/2)
-- coordenadas Y al azar
circulos[i].diam = of.random(15, 100)
-- diámetro círculos
circulos[i].velX = 0.000000
-- velocidad X
circulos[i].velY = 0.000000
-- velocidad Y
circulos[i].gY = 0.00184562
-- gravedad Y
circulos[i].gX = of.random(-0.018326, 0.044326) -- gravedad X
circulos[i].color= of.random(80, 255)
-- gris azar cada objeto
circulos[i].transp = 220 --transparencia
end
end
function update()
for i=0, maxCirculos-1 do
circulos[i].posX = circulos[i].posX + circulos[i].velX -- posición + velocidad
circulos[i].posY = circulos[i].posY + circulos[i].velY
circulos[i].velX = circulos[i].velX + circulos[i].gX -- velocidad + gravedad
circulos[i].velY = circulos[i].velY + (circulos[i].gY*circulos[i].diam)
if circulos[i].posX <= 0 or circulos[i].posX >= OUTPUT_W-10 then
circulos[i].velX = circulos[i].velX * -0.972773
end
-- invierte dirección al tocar los bordes
if circulos[i].posY >= OUTPUT_H or circulos[i].posY <= 0 then
circulos[i].velY = circulos[i].velY * -0.962722
end
end
end
function draw()
ga.background(0.0, 1.0) for i= 0, maxCirculos-1 do -- dibuja todos los círculos
of.setColor(circulos[i].color, circulos[i].transp - circulos[i].diam)
dibujaCirculos(circulos[i].posX, circulos[i].posY, circulos[i].diam)
end
-- dibuja círculos usando la función de abajo
end
En el bloque del setup() se asignan las propiedades del objeto utilizando el operador “.” junto al
nombre de la tabla y el identificador del array de objetos que contiene [i]
nombreTabla[i].Propiedad
El for recorre el array, reserva la memoria que el sistema necesita para estos objetos y les asigna las
propiedades definidas, que en este caso son: posición X y posición Y (para localizar el centro de cada
circulo), radio (tamaño), velocidad X y velocidad Y (para el movimiento de los círculos) gravedad X y
gravedad Y (para representar los rebotes y un movimiento menos lineal), color y transparencia.
Los valores de i van desde la posición 0 a la que define la variable maxCirculos-1, porque empieza a
cotar desde 0, y el objeto 20 está en el contenedor con ID 19. Los valores de las propiedades que se
asignan pueden cambiar, pues un objeto puede tener distintos valores en momentos diferentes, pero
siempre es el mismo objeto. Así, a las propiedades de velocidad, gravedad y transparencia se le han
asignado inicialmente unos valores y después cambian.
Los comportamientos se establecen en la función update(), donde se actualizan los datos de las
variables que definen las propiedades. Con un nuevo for , a las coordenadas de posición de cada
objeto se le suman las de velocidad, y a las de velocidad, las de gravedad en la coordenada de las
X y las de gravedad por el diámetro del círculo en la coordenada Y, este incremento produce un
movimiento más físico de peso del círculo. Después se ajustan los rebotes a los límites de la ventana
mediante bloques condicionales if, invirtiendo la dirección del movimiento al multiplicar el valor de su
velocidad por un número negativo con muchos decimales que no llega a 1.
La función dibujaCirculos() define la forma de los objetos, en este caso los parámetros son los
mismos que los de la función interna del circulo of.circle(), pero como vimos en el ejemplo anterior,
no siempre es así.
El siguiente ejemplo, más complejo, está basado en la noción de Random Walker, utiliza varios arrays
y la función of.noise() vista en la página 108.
function dibujaCirculos (posX, posY, diam)
of.circle(posX, posY, diam)
-- función que define la forma de los objetos
end
130
131
function draw()
/*
GAmuza 0.4.1 examples
--------------------Basics/tabla_noiseWalk.ga
Basado en Daniel Shiffman - Nature Of Code
created by n3m3da | www.d3cod3.org
*/
walkers = {}
noiseTimeX = {}
noiseTimeY = {}
stepX = {}
stepY = {}
numW = 300
function setup()
for
i = 0,numW-1 do
walkers[i] = {}
walkers[i].x = OUTPUT_W/2
walkers[i].y = OUTPUT_H/2
noiseTimeX[i] = of.random(0,10000)
noiseTimeY[i] = of.random(7000,14000)
stepX[i] = of.random(0.001,0.003)
stepY[i] = of.random(0.001,0.003)
end
end
function update()
for i=0,numW-1 do
mapX = of.map(of.noise(noiseTimeX[i]),0.15,0.85,0,OUTPUT_W,true)
mapY = of.map(of.noise(noiseTimeY[i]),0.15,0.85,0,OUTPUT_H,true)
walkers[i].x = mapX
walkers[i].y = mapY
132
noiseTimeX[i] = noiseTimeX[i] + stepX[i]
noiseTimeY[i] = noiseTimeY[i] + stepY[i]
end
end
ga.background(0.0,0.01)
of.noFill()
for i=0,numW-1 do
if math.fmod(i,7) == 0 then -- Devuelve el resto de la división de i por 7
-- y redondea el cociente a cero.
of.setColor(255)
else
of.setColor(0)
end
of.rect(walkers[i].x,walkers[i].y,1,1)
end
end
Algunas funciones internas vinculadas a las tablas63
table.getn(myTable)
Para saber el número de elementos de una tabla
table.foreach(myTable, MyFunction)
Recorre cada índice de la tabla y le asigna la función (el segundo parámetro dentro del
corchete).
table.insert(myTable, [position], value) -- ejemplo (myTable, 5, true)
Esta función añade un valor al final de la tabla. Si se señala una posición exacta, para
colocar el valor los índices siguientes se desplazan en consecuencia.
table.remove(myTable, [pos])
-- ejemplo (myTable, 3)
Elimina un elemento de una tabla y mueve hacia arriba los índices restantes si es
necesario. Si no se asigna posición borra el último elemento.
63 Más información en “Lua for Beginers” [texto on-line] http://lua.gts-stolberg.de/en/table.php [29.07.2012]
133
3.9.2. Clases y objetos
En una clase, el concepto más destacado es el de objeto, representa cualquier cosa, real o abstracta,
(componente conceptual del problema planteado). En la programación, un objeto se define en dos
partes: 1) Constructor: una serie de datos que constituyen el estado particular (atributos o propiedades)
del objeto y que se formalizan mediante un conjunto de variables. 2) Update: comportamiento propio de
los objetos que se formaliza mediante métodos (funciones de objetos) relacionados con las variables.
Como se ha visto en los ejemplos anteriores, el objeto círculo tiene una serie propiedades declaradas
con variables según lo que requiera la situación planteada: coordenadas del centro, radio o diámetro,
color, transparencia, grosor del trazo..., de ellas, las que sean necesarias para definir el objeto serán
los parámetros del constructor.
El comportamiento quedará regulado por los métodos que programemos para que esos objetos
circulo situen sus coordenadas fijas o en movimiento, sigan una dirección de movimiento u otra,
reboten con los límites de la ventana, etc.,
Definición de Clase
Estableciendo una relación algo simplista podemos entender las clases aludiendo a la Teoría de las
ideas (o Teoría de las formas) de Platón. Las clases se corresponderían al mundo inteligible donde
están las estructuras o modelos (las ideas) en las cuales se basan las cosas físicas concretas (los
objetos) que podemos percibir en el mundo sensible.
Por ejemplo, la clase círculos puede contener todos los objetos circulares, con sus distintos tamaños,
colores, etc., y sus distintos comportamientos. El objeto círculo es una instancia de la clase círculos.
Cada objeto círculo tiene un estado particular independiente, pero todos tienen en común el hecho
de tener una variable color, radio, etc. E igualmente deben tener en común la posibilidad de adoptar
determinados comportamientos, por lo que la clase debe declarar o implementar los métodos que
regulan el comportamiento de los objetos que contiene.
En resumen, una clase es como una plantilla que define las variables y los métodos que son comunes
para todos los objetos que agrupa, en esta plantilla debe haber siempre un bloque dedicado al
constructor que lleva el mismo nombre que la clase y define los parámetros necesarios para crear o
instanciar un objeto de la clase.
Herencia
Es fácil comprender que la clase círculos pertenece a una clase mayor que alberga las figuras
geométricas planas. Si en nuestro trabajo planteamos ambos niveles, un círculo concreto debe
134
responder tanto a las propiedades de la clase círculos como a la de la clase figuras_planas, por lo
que compartirá esos atributos y comportamientos con objetos de otras posibles clases, como la clase
triángulos o la clase cuadrados.
Esta herencia no limita las posibilidades
de particularización de la clase círculos,
más bien el orden de pensamiento es
inverso al establecido aquí. La herencia
permite definir nuevas clases partiendo
de las existentes, de modo que heredan
todos los comportamientos programados
en la primera y pueden añadir variables y
comportamientos propios que la diferencian
como clase derivada o subclase. Y así se
puede establecer un árbol de herencias tan
ramificado como se necesite.
Mensajes
En la imagen anterior, además de ver un diagrama de herencia también muestra en una de las
flechas que va de la clase triángulos a la clase rectángulos como se establece un mensaje. Es a
través de los mensajes como se produce la interacción entre los objetos, permitiendo así programar
comportamientos más complejos.
Por ejemplo, cuando un objeto triángulo cumple una determinada condición, puede enviar un
mensaje a un objeto rectángulo para que realice alguno de los comportamientos que su clase (la del
rectángulo) tiene definidos, en el mensaje se pueden incorporar determinados parámetros para ajustar
el comportamiento.
Un mismo mensaje puede generar comportamientos diferentes al ser recibido por objetos diferentes.
A esta característica se le denomina polimorfismo.
Es conveniente hacer diagramas de las clases con los atributos y comportamientos de los objetos
antes de empezar a escribir el código, para respondernos a las preguntas:
–
¿Cuántas clases necesitamos definir y que herencia se establece entre ellas?
–
¿Dónde definimos cada propiedad?
–
¿Dónde definimos cada método?
–
¿Dónde implementamos cada método?
135
3.9.3. Clases en GAmuza
La herencia se implementada utilizando el concepto de metatablas, que actúan como superclases, y la
función setmetatable(). El código __index almacena la metatabla de la tabla. En el siguiente código
la tabla Rectangulo deriva de la tabla Formas65:
Lua does not have a class system, but its powerful metaprogramming facilities makes defining
classic objects straightforward.64
Rectangulo = {}
setmetatable(Rectangulo, {__index = Formas})
En el lenguaje Lua, la programación orientada a objetos (POO) puede realizarse a través de tablas.
Una tabla, además de funcionar como un array, también puede hacerlo como un objeto, porque las
tablas tienen un estado y una identidad (self) que es independiente de sus valores, como hemos
Algunos ejemplos comentados de clases simples.
mencionado antes, dos objetos con el mismo valor son objetos diferentes, un objeto puede tener
distintos valores en momentos diferentes, pero siempre es el mismo objeto. Al igual que los objetos,
las tablas tienen un ciclo vital que es independiente de aquello que lo creó, o donde se crearon. Hemos
visto en el apartado arrays como en una tabla se asignan propiedades a cada elemento mediante el
operador “.”, ahora veremos como se asocian métodos (funciones de objetos) a los objetos de una
clase mediante el operador “:”.
La sintaxis para las clases en GAmuza es
class ‘nombreClase’
Se hace el constructor con una función que lleva el nombre de la clase y se inicializa con
function nombreClase:__init (parametro1, parámetro2,...)
Después del nombre de la clase van dos puntos “:” y dos guiones bajos “__” seguidos de init y los
parámetros que definen la construcción del objeto, entre paréntesis y separados por “,”.
La clase tiene su propio método update() que se escribe:
function nombreClase:update()
donde se pone el código para actualizar los valores de las variables y programar el comportamiento
de los objetos.
Y su método draw() que contiene el código de las formas que va a dibujar.
function nombreClase:draw()
Después, se crean los objetos de la clase dándole los valores concretos a los parámetros definidos en
el constructor.
ob1 = nombreClase(valorParametro1, valorParámetro2,...)
64 Lua-users wiki: Simple Lua Classes [texto on-line] < http://lua-users.org/wiki/SimpleLuaClasses > [25.07.2012]
136
/*
GAmuza 0.4.1 examples
--------------------Basics/classExample.ga
Este ejemplo muestra el código básico para construir una clase.
created by mj
*/
class ‘foco’
---constructor
function foco:__init(x, d, s, g)
--define parámetros y propiedades del objeto
self.posX = x
-- posición Y
self.diam = d
-- diámetro
self.speed = s
-- velocidad
self.grav = g
-- gravedad
end
65 Marcelo da Silva Gomes, “The Shape Example in Lua” [texto on-line] <http://onestepback.org/articles/poly/gp-lua.html>
[25.07.2012]
137
function foco:update() -- actualiza parámetros para el comportamiento
self.posX = self.posX + self.speed
self.speed = self.speed + (self.grav*self.diam)
-- condicionales: cuando llegue a los topes cambia de dirección
if self.posX > OUTPUT_W - self.diam/2
then
self.speed = self.speed * -0.999722
end
if self.posY < 0 + self.diam/2 then
self.speed = self.speed * -0.999722
end
Después de declarar la clase: class ‘foco’; se define el constructor, es decir, ya sabemos los
parámetros que definen las propiedades concretas de los objetos que queremos crear. El código
function nombreClase:__init (parametro1, parámetro2,...) en el ejemplo corresponde a:
function foco:__init(x, d, s, g), y en esta función (constructor), utilizando el operador “.”, se
define el estado de las propiedades para la identidad (self) de cada objeto.
Las clases, además del self, tienen sus propios métodos update() y draw() que se asocian a la
clase mediante el operador “:”
function foco:update()
function foco:draw()
En la primera define las funciones del comportamiento: suma el valor de la posición X a la velocidad,
suma el valor de la velocidad al de la gravedad; establece las condiciones para cambiar el sentido de la
end
velocidad cuando la coordenada X llega a los límites de la ventana. La segunda, contiene las funciones
function foco:draw() -- función para dibujar la forma del objeto
of.circle(self.posX, OUTPUT_H/2, self.diam)
end
internas que dibujan la forma.
Después de definir la clase se crean el objeto u objetos concretos, dando valores específicos a los
parámetros determinados en el constructor. En este caso, los parámetros (y, d, s, g) para el objeto
-------- crear 2 objetos de la clase foco
foco1 = circulo(25, 50, 3.5, 0.00184562)
foco2 = foco(125, 30, 1.5, 0.00184562)
----------------------------------------function setup()
of. enableSmoothing()
of.setCircleResolution(50)
end
foco1 son (25, 50, 3.5, 0.00184562), es decir, el objeto aparece en la coordenada y = 25, tiene
un diámetro de 50 píxeles, se mueve a una velocidad de 3.5 y con una gravedad de 0.00184562.
En las funciones habituales de un programa en GAmuza, el código llama a los métodos de la clase.
En function update()
foco1:update()
En function draw()
foco1:draw()
function update()
foco1:update()
foco2:update()
Es importante observar las diferencias entre clases y array, cuando una tabla funciona como array las
end
propiedades se definen en el setup() por el ID del array [i] utilizando un for para recorrer todos
function draw()
función update() y dibuja las formas en la función draw() del programa.
los objetos. Además el array no tiene métodos propios, por lo que actualiza su comportamiento en la
ga.background(0.0, 1.0)
of.setColor(255)
foco1:draw()
foco2:draw()
Según el tipo de planteamiento a resolver es mejor estructurarlo por arrays o por clases. El siguiente
ejemplo utiliza clases y arrays.
end
138
139
if blackout then
c:set(0,0,0,24)
else
c:set(255,255,255,24)
end
end
-- hacer filamentos blancos
-- hacer filamentos negros
function Particle:update()
self.xx = self.x
self.yy = self.y
-- posición x’= a la de x
-- posición y’= a la de y
self.x = self.x + self.vx
self.y = self.y + self.vy
self.vx = self.vx + (of.randomf()/2)
self.vy = self.vy + (of.randomf()/2)
/*
GAmuza 0.4.1 examples
--------------------Artists/binaryRing.ga
This example is from Binary Ring66 piece by Jared Tarbel, 2004.
created by n3m3da | www.d3cod3.org
*/
c = of.color()
blackout = false
kaons = {}
numKaons = 1000
class ‘Particle’
-- hacer filamentos blancos o negros -- declara la tabla
-- declara la Clase
function Particle:__init(Dx,Dy,r)
self.Dx = Dx
self.Dy = Dy
self.r = r
self.ox = OUTPUT_W/2
self.oy = OUTPUT_H/2
self.x = math.ceil(self.ox-self.Dx)
self.y = math.ceil(self.oy-self.Dy)
self.xx = 0
self.yy = 0
self.vx = 2*math.cos(self.r)
self.vy = 2*math.sin(self.r)
self.age = of.random(0,200)
----------
posición x círculo
posición y círculo
posición x
posición y
posición x’
posición y’
velocidad x
velocidad y
edad
66 Este ejemplo retoma el trabajo del artista Jared Tarbell y lo realiza en GAmuza. Código original en:
http://www.complexification.net/gallery/machines/binaryRing/appletm/BinaryRing_m.pde [29.07.2012]
140
self.age = self.age + 1
if self.age > 200 then
local t = of.random(TWO_PI)
self.x = 3*math.sin(t)
self.y = 3*math.cos(t)
self.xx = 0
self.yy = 0
self.vx = 0
self.vy = 0
self.age = 0
-- posición x = x + velocidad x
-- posición y = y + velocidad y
-- velx = velx + random(-1,1)/2
-- vely = vely + random(-1,1)/2
-- cada vuelta tienen más edad
-- si llegan al valor 200
if blackout then
c:set(0,0,0,24)
else
c:set(255,255,255,24)
end
end
end
function Particle:draw()
of.noFill()
of.setColor(c)
-- define los parámetros de las lineas
of.line(self.ox+self.xx,self.oy+self.yy,self.ox+self.x,self.oy+self.y)
of.line(self.ox-self.xx,self.oy+self.yy,self.ox-self.x,self.oy+self.y)
end
function setup()
ga.background(0.0, 1.0)
for i=0,numKaons-1 do
-- define los elementos de la tabla
local emitx = math.ceil(3*math.sin(TWO_PI*i/numKaons)+OUTPUT_W/2)
local emity = math.ceil(3*math.cos(TWO_PI*i/numKaons)+OUTPUT_H/2)
local r = PI*i/numKaons
kaons[i] = Particle(emitx,emity,r)
-- los vincula con la clase
end
end
function update()
141
for i=0,numKaons-1 do kaons[i]:update()
-- a cada elemento de la tabla da el update de la clase
end
local r = of.randomuf()
if r > 0.9991 then
blackout = not blackout
end
end
4. Interactividad
4.1. Definiciones de interactividad
function draw()
--ga.background(0.0,1.0)
for i=0,numKaons-1 do
kaons[i]:draw()
-- a cada elemento de la tabla da el draw de la clase
…I do think I can interact with a cat. That’s a feeling I have. But not with an ant, for example…
Jim Campbell67
end
end
function mouseReleased()
blackout = not blackout
end
Todos las acciones perceptivas implican un grado de interactividad con los estímulos que las generan y
su entorno. A través de los sentidos recogemos datos (inputs), nuestra mente los codifica y/o reflexiona
sobre ellos (procesa) y como resultado pueden modificar nuestro conocimiento, comportamiento,
estado de salud, ánimo, etc., (output). Pero desde el contexto de los medios digitales se ha generado
un nuevo enfoque del término interactividad que tiene que ver con ese mismo proceso, pero restringe el
ámbito a la relación humano-máquina. En nuestro caso vamos a restringir un poco más para analizarlo
sólo en la relación que se produce entre espectadores y piezas en el arte interactivo, si bien para
analizarlo en ese contexto recurriremos a veces a su consideración más general.
Con la siguiente selección de definiciones y argumentos queremos aportar una panorámica amplia de
las distintas posiciones que artistas y teóricos del arte han adoptado en este tema. Algunas son muy
extensas, sí, pero dibujan bien el cambio que se ha producido desde los pioneros hasta la actualidad.
Myron W. Krueger:
[…] observando a los participantes que interactuaban con las piezas, he desarrollado una fuerte
intuición sobre lo que la gente puede llegar a entender de lo que está haciendo y lo que quieren que
suceda. Mi idea de interacción surgió de esta observación de los participantes, más que de ideas
preconcebidas, evitando la creación de un arte que suena muy impresionante cuando se describe
por escrito, pero que no tiene éxito con su público. Esto fue poco después de las instalaciones
originales, tras dieciséis años de desarrollar las capacidades de la visión por ordenador necesarias
para que el trabajo empezara a ser autónomo. Todo el trabajo posterior se ha basado en una
estética de los interactivos aprendida en las primeras piezas:
El arte debe ser divertido y accesible.
67 Richard Whittaker (1999) Jim Campbell: Frames of Reference [texto on-line] <http://www.conversations.org/story.php?sid=30>
[28.08.2012]
142
143
La interacción física es una nueva dimensión que debe ser explorada. Aunque nuestra cultura
sólo permite a los adultos modos limitados de movimiento físico, el arte interactivo puede inducir
a moverse en nuevas formas.
Stephen Wilson
La interactividad es a menudo considerada el rasgo distintivo de los medios basados en el
ordenador. El público está invitado a actuar para influir en el curso de los acontecimientos, o para
navegar por el hiperespacio de datos. Al principio, esta relación entre público y obra se consideró
una aportación bastante radical, que transformaba a artista y público en co-creadores lo que
incrementaba las probabilidades de un compromiso intelectual, espiritual y estético. A medida que
el campo ha madurado, tanto artistas como teóricos han tratado de deconstruir la interactividad.69
Las pantallas deben dominar el campo de visión de los participantes para que se sumerjan en la
experiencia interactiva.
La imagen de los participantes es un ingrediente útil en la pantalla visual. La gente considera su
imagen como una extensión de su identidad. ¿Qué pasa con él, que les pasa. Qué tocan, ellos
sienten.
Las respuestas del ordenador deben ser obvias. Siempre debe haber un nivel superficial, que la
gente pueda entender en pocos segundos. En un mundo en el que las experiencias interactivas
compiten con muchas otras Alternativas, una pieza que no es aprehendida casi de inmediato se
abandona rápidamente.
Todos los estímulos generados por el ordenador deben ser una respuesta a las acciones de los
participantes. Cuando el equipo inicia estímulos gratuitos, la capacidad de los participantes para
comprender lo que está pasando se ve amenazada.
1. No es necesario el realismo gráfico para una interacción convincente. De hecho, los entornos
gráficos realistas suelen aportar confusión y son menos claros que las posibilidades interactivas
que el mundo virtual ofrece.
2. La interacción entre el participante y el mundo virtual debe ser fluida y sin problemas. Esto
significa que las respuestas debe ser instantáneas, tal como lo serían en el mundo real. Así
como un taxi que corre por una pista de despegue, pero no se mueven lo suficientemente
rápido como para despegar no es un avión, una experiencia interactiva en la que el participante
es consciente de un desfase entre su acción y la respuesta de la pieza no es interactiva.
3. Dando a la audiencia muchas interacciones diferentes para elegir los mantienes interesados
por más tiempo.
4. Si se ofrece un lienzo, pincel y pinturas de óleo en un lugar público, muy poca gente tratará de
crear arte, pero cuando se enfrentan a la posibilidad de utilizar un medio en el que las reglas
son desconocidas y con el que las posibilidades de éxito estético son Altas, la mayoría de la
gente moverán sus cuerpos para crear un resultado que les agrade. De hecho, la exploración
estética ofrece una nueva razón para mover el cuerpo.
5. Idealmente, una pieza debería hacer algo que tenga sentido en todas las condiciones de
exposición: lleno frente vacío, ruidosa frente silenciosa, individuos aislados frente pequeños
grupos.
6. Mientras que los videojuegos se basan en los resultados para motivar la participación en
experiencias muy estructuradas, la participación física permite desarrollar otros estilos de
interacción.
7. Cargar con dispositivos como head-mounted displays distancia al participante de la experiencia
virtual y aún no son suficientemente buenos para utilizarlos.68
68 Myron W. Krueguer, ‘Towards Interactive Aesthetics’, en Ars Electronica Katalogartikel <http://90.146.8.18/en/archives/festival_
archive/festival_catalogs/festival_artikel.asp?iProjectID=12978> [20.02.2012].
144
Joshua Nobel
Hacer arte interactivo es muy diferente de hacer arte no interactivo porque el verdadero objeto de
arte interactivo es la situación. En pintura, el objeto es la propia pintura, en escultura, es el objeto y
el espacio que lo rodea, en una pieza de vídeo, el objeto es la proyección de vídeo. En una obra de
arte interactivo, el objeto de arte es realmente la interacción entre el observador y el sistema que el
artista ha creado. Ese sistema puede ser muy complejo tecnológicamente, puede tener un único
elemento técnicamente simple, o puede tener ninguno. 70
[…] La interactividad es un concepto que tiende a utilizarse para evadir las descripciones de los
mecanismos tecnológicos de los medios, y como resultado, con demasiada frecuencia elude una
atención analítica y crítica sostenida71.
Erkki Huhtamo,
[…] la tecnología interactiva soporta una gran promesa. Bien podría subvertir las prácticas de
media art predominantes y sustituirlas con formas más versátiles, amigables y “democráticas”.
Sin embargo, dirigirse solo al desarrollo de hardware, diseño de interfaz y curvas de ventas no
será suficiente para lograr este objetivo. La tecnología digital han de ser valorada en un contexto
más amplio que abarca no sólo el espectro completo de las prácticas contemporáneas sociales
e ideológicas, sino la historia también. Este artículo ha tratado de demostrar -aunque a través de
muestreo muy selectivo- que las obras de arte interactivas pueden tener un papel fundamental en
este proceso, manteniendo un metadiálogo continuo sobre la interactividad. Esto no es una tarea
fácil. Como Andy Darley ha dicho de manera sucinta: «Las posibilidades de formas constructivas
igualitarias, más democráticas, que ofrezcan nuevas formas del interacción, conocimiento y
comprensión puede ser mejorada por la capacidad novedosa de las nuevas tecnologías. Y más
que nunca, tienen que esforzarse en ello».72
Estas referencias señalan algunas características del arte interactivo, y su transformación desde la
interactividad directa y casi mimética de los pioneros, muy vinculada a la relación humano-máquina
69 Stephen Wilson, (2002) Information Arts: Intersections of Art, Science, and Technology (Cambridge (MA): MIT Press), pág. 653.
70 Joshua Noble, Programming Interactivity. A Designer’s Guide to Processing, Arduino, and openFrameworks (Sebastopol (CA):
O’Reilly, 2009), pág. 14.
71 Ibidem, pág. 87.
72 Erkki Huhtamo, (1992) ‘Seeking Deeper Contact. Interactive Art as Metacommentary’, [texto on-line] <http://www.kenfeingold.
com/seekingdeeper.html> [17.06.2012].
145
(human computer interaction73), la interactividad indirecta, hasta el metalenguaje interactivo que señala
Siempre he pensado que el sentido que se le da al término interactividad en el trabajo con
Huhtamo.
ordenadores estaba equivocado. Me refiero a que el sentido histórico de la “interactividad” siempre
En la interactividad directa, la experiencia del espectador habitualmente se debate ante el desafío de
encontrar los mecanismos de interacción (su funcionamiento técnico) y lo que la obra quería transmitir,
llegando a tener una experiencia satisfactoria semejante a la que se alcanza cuando consigues superar
nivel en un videojuego, pero a veces distante al tipo de fruición y reflexión propios del arte.
A finales de los 90’s algunas propuestas empezaron a cuestionar el sentido de la interactividad en
el arte digital, mostrando dos disyuntivas: por una parte, la interactividad directa entre el espectador
y la pieza, en la que el rol del espectador se aproximaba al performer; por otra parte, el contenido
de la obra se configura a través de la interactividad del los mecanísmos técnicos de la pieza con
datos obtenidos del entorno físico o del flujo da datos de la red. Con ello se desplazaba la noción de
interactividad desde la relación espectador/obra [humano-máquina] hacia entorno/obra pudiendo el
ha estado vinculado a un suceso de comunicación mutua, recíproco. Tal como lo veo, lo que
realmente se establece con los ordenadores es control. Se les controla para hacer algo [o se
controla al espectador para hacer algo]. Las piezas dedicadas a Heisenberg sirven para mostrar
estos problemas de una forma directa: cuanto más se quiere ver algo, más se intenta controlar la
situación, pero entonces se ve menos y cuando menos lo controlas, más posibilidades tienes de
ver. Por ejemplo, en la pieza “Sin título para Heisenberg” cuando se camnia haacia la cama, tienes
la imagen cada vez más cerca, pero nunca se verán los poros de la piel, lo que se ve son píxeles.
Cuando estás más lejos se puede ver a los dos amantes, pero por el hecho de aproximarte no
puedes ver más. La pieza del Buda responde de forma similar. Desde la distancia se puede ver la
estatua de Buda, pero a medida que te acercas no ves más que su sombra. ¿Qué estás viendo?
Ambas piezas haacen referencia al principio de Heisenberg. ¿Lo conoces?75
espectador participar en los datos que proporciona el entorno, o no.
En el año 2002, la obra Listening Post74, de Ben Rubin y Mark Hansen, subrayó ese desplazamiento
del concepto de interactividad, hacia otro tipo de relación entre:
inputs -- procesamiento - output = obra en continuo proceso
La salida, la configuración de la obra, subraya aun más el valor del proceso. La pieza combina de forma
sugerente la relación de entrada dinámica de datos en tiempo real con el debate de espacio privado/
publico en la red. Esa entrada dinámica de datos está constituida por la selección de fragmentos de
texto en tiempo real de miles de salas de chat de Internet no restringidas, tablones de anuncios y
otros foros públicos en la red. El procesamiento de esos datos tiene como resultado que los textos
seleccionados son cantados por un sintetizador de voz, y al mismo tiempo se muestran a través de
más de doscientas pantallas electrónicas pequeñas que construyen una membrana reticular curva.
La participación de los espectadores es secundaria y su tarea es interpretar la instalación, su función
y concepto, a través de una experiencia con el ambiente casi ceremonioso que genera la obra y su
alusión ritualizada sobre el flujo de información de las redes sociales.
Por último retomamos otro fragmento de la entrevista a Jim Campbell que inicia este apartado:
73 Interacción persona-ordenador: Es la disciplina que estudia el intercambio de información mediante software entre las personas
y las computadoras. Ésta se encarga del diseño, evaluación e implementación de los aparatos tecnológicos interactivos,
estudiando el mayor número de casos que les pueda llegar a afectar. El objetivo es que el intercambio sea más eficiente:
minimizar errores, incrementar la satisfacción, disminuir la frustración y, en definitiva, hacer más productivas las tareas que
rodean a las personas y los computadores. [enciclopedia on-line] http://es.wikipedia.org/wiki/Interaccion_persona-computador
[05.07.2012]
74 Listening Post - Ear Studio < http://earstudio.com/2010/09/29/listening-post/> [04.09.2012]
146
75 Richard Whittaker (1999) Jim Campbell: Frames of Reference [texto on-line] <http://www.conversations.org/story.php?sid=30>
[28.08.2012]
147
4.2. Código para interactividad. Eventos de ratón
El objetivo es plantear sistemas interactivos más complejos y conceptuales, menos directos, pero para
llegar hasta ellos hay que recorrer los primeros pasos, conocer la base interactiva de las interfaces
gráficas. Los dispositivos más comunes para interactuar con elementos gráficos en la pantalla son el
ratón y el teclado. Tras un breve repaso se plantearan otras opciones más próximas al “metadiálogo
La relación inversa entre la dimensión de la ventana de salida respecto a la posición del ratón hace que
el movimiento responda a direcciones con sentido contrario.
También puede aplicarse el valor de las coordenadas X,Y del ratón a las dimensiones de las formas que
cambian de tamaño con el movimiento del ratón.
function setup()
sobre la interactividad” que señala Huhtamo, pero hay que empezar a andar.
Situados ante la pnatalla, para el diseño de interactividad con el ratón, los datos que el sistema necesita
function update()
conocer son las coordenadas X e Y de su posición, si se ha movido, si algún botón está presionado,
ha sido soltado o es arrastrado. Las funciones que nos dan esos datos son:
ga.mouseX(), ga.mouseY()
-- coordenadas x e y de la posición del ratón
Posición del ratón
Cuando el ratón está en el lado izquierdo de la pantalla su coordenada es 0, y se incrementa conforme
se desplaza hacia la derecha. Cuando el ratón está en el lado superior de la pantalla, el valor de la
end
end
function draw()
se pone en marcha la posición del ratón es (0,0) y el código escrito en el bloque setup()solo lo lee
una vez. Usualmente se establecen relaciones interactivas entre la posición del ratón y la ubicación de
formas, como en:
-- color amarillo
of.setLineWidth(20)
-- ancho línea 20px
of.line(ga.mouseX(), ga.mouseY(), 200, 200) -- la línea tiene una coordenada fija
-- color verde
of.noFill()
-- no rellenar
of.circle(OUTPUT_W/2, OUTPUT_H/2, ga.mouseX()/2) end
relación como de bombeo flexible, al estirar la línea el círculo crece.
ga.background(0.0, 0.5)
of.setColor(255)
of.circle(mouseX(), mouseY(), 50) -- el centro de círculo está
GAmuza articula los eventos de ratón a través de bloques de función que permiten programar acciones
-- en la posición del ratón
que serán efectuadas cuando esos eventos sucedan.
function mouseDragged()
-- Mover el ratón con el botón apretado (arrastrar)
function mouseMoved() -- Movimiento del ratón
end
Pueden establecerse relaciones menos evidentes si se combinan operadores matemáticos que
aumenten o disminuyan determinados valores para que las relaciones visuales que se producen entre
las formas y la posición del ratón sean indirectas, por ejemplo:
function draw()
ga.background(0.0, 0.5)
of.setColor(255)
of.circle(OUTPUT_W-mouseX(), mouseY()- OUTPUT_H, 50);
end 148
-- y otra en la posición del ratón
of.setColor(0,255,0)
Los cambios entre la línea y el círculo están vinculados a la posición del ratón estableciendo una
function draw()
end
ga.background(0.0,1.0)
of.setColor(255,255,0) coordenada y es 0 y se incrementa conforme va bajando. Estos datos NO los da el sistema si las
funciones ga.mouseX()y ga.mouseY() se sitúan en el bloque setup() porque cuando el programa
of.setCircleResolution(50)
end
function mousePressed()
end
-- Botón del ratón apretado
function mouseReleased() -- Botón del ratón soltado
end
El siguiente ejemplo responde al movimiento del ratón - mouseMoved()- que equivale a tamaño de las
formas vinculado a su posición y clicar el botón, mousePressed()
149
/*
GAmuza 0.4.1 examples
--------------------Basics/flutua_dispersa.ga
Interactividad mouseDragged
y mouseMoved
*/
x = OUTPUT_W/2
En este caso se utiliza la función mouseMoved() para modificar el valor de las variables fluctua y
dispersa según se mueva el ratón por la ventana de salida. La variable fluctua controla el límite de
repeticiones de una estructura for (el número de circulos pequeños que construyen el anillo) y la variable
dispersa controla el radio del anillo de círculos generado por el for. Con la función mousePressed()
se desplaza el centro del anillo a la zona de la ventana de salida donde clique el ratón. Tras clicar en
cualquier punto de la ventana de salida, si se mueve el ratón diagonalmente se verán los cambios. La
transparencia del fondo permite ver el rastro de los cambios.
y = OUTPUT_H/2
r = 2
angle = 0.0
En el siguiente ejemplo se establecen 5 opciones de composión formal diferentes cuyo cambio está
fluctua = 20
vinculado a la acción de pulsar el botón del ratón
dispersa = 5
/*
GAmuza 0.4.1 examples
--------------------ReasMcWilliamsLUST_FORM+CODE/EmbeddedIteration.ga
function setup()
of.enableSmoothing()
end
function draw()
ga.background(0.0, 0.2)
of.setColor(255)
for i = 0, fluctua do
angle = of.random(TWO_PI)
dispX = x + math.cos(angle)*dispersa
dispY = y + math.sin(angle)*dispersa
of.circle(dispX, dispY, r*2)
end
end
function mousePressed()
x = ga.mouseX()
y = ga.mouseY()
end
Repeat: Embedded Iteration
from Form+Code in Design, Art, and Architecture
by Casey Reas, Chandler McWilliams, and LUST
Princeton Architectural Press, 2010
http://formandcode.com
created by n3m3da | www.d3cod3.org
*/
option = 1 -- variable global function setup()
of.enableSmoothing()
end
function draw()
ga.background(0.0,1.0)
of.setColor(245,151,176)
if option==1 then
function mouseMoved()
dispersa = ga.mouseX()*0.5
fluctua = ga.mouseY()*0.5
-- stitches
for x=50, OUTPUT_W-50, 20 do
for y=50, OUTPUT_H-50, 20 do
of.line(x-5,y-5,x+5,y+5)
of.line(x+5,y-5,x-5,y+5)
end
end
end
150
151
elseif option == 2 then
-- perspectiva
for y=50, OUTPUT_H-50, 20 do
of.line(x,y,OUTPUT_W/2,OUTPUT_H/2)
end
elseif option == 3 then
-- círculos superpuestos
of.noFill()
for x = 50, OUTPUT_W-50, 20 do
for y = 50, OUTPUT_H-50, 20 do
end
of.ellipse(x,y,40,40)
end
elseif option==4 then
-- arcos girando
for x = 50, OUTPUT_W-50, 20 do
for y = 50, OUTPUT_H-50, 20 do
of.line(x-5,y-5,x+5,y+5)
end
elseif option == 5 then
-- grupos de cinco
for x = 50, OUTPUT_W-50, 20 do
for y = 50, OUTPUT_H-50, 20 do
for i = 1, 16, 4 do
of.line(x+i,y,x+i,y+12)
end
of.line(x,y,x+12,y+12)
end
señal de entrada al sistema que tiene como respuesta (salida) la impresión de caracteres en el monitor.
código. Vamos a ver un ejemplo en el que el teclado genera sonidos en lugar de palabras.
/*
GAmuza 0.4.1 examples
--------------------Audio/keyboardSynth.ga
Este ejemplo transforma el teclado en un sintetizador de audio random (muy básico)
Comprobar que está activado un canal de salida de audio en el Setting Manager
created by n3m3da | www.d3cod3.org
*/
function setup()
ga.wave(GA_TRI,120)
end
end
El teclado es el dispositivo habitual para escribir texto en el ordenador. Cada tecla presionada es una
Esa señal de entrada (input) puede utilizarse para interactuar con las acciones programadas en el
end
4.3. Eventos de teclado
for x=50, OUTPUT_W-50, 20 do
end
function update()
end
function draw()
ga.background(0.0,1.0)
end
function keyReleased()
end
ga.waveFrequency(0,(ga.key()/3)*ga.nToF(RE_0))
end
function mouseReleased()
if option >= 5 then
ga.waveVolume(0,of.randomuf()/4)
end
option = 1
else
-- cada vez que se suelta el botón del ratón
option = option + 1 -- va sumando 1 a la variable option
end
end
152
153
Descargar