Saltearse al contenido

Unidad 6

Introducción 📜

¿Qué aprenderás en esta unidad? 💡

Actividad 01

Inspiración en agentes y comportamiento emergente

👣 Pasos:

  1. Observa “Arrels”: dedica tiempo a mirar imágenes o videos de “Arrels”. Fíjate en las estructuras que se forman. ¿Parecen seguir reglas? ¿Cómo interactúan las diferentes “ramas” o elementos?
  2. Observa “encuentros”: explora la obra “Encuentros”. Observa los "Outputs finales"¿Qué tipo de movimiento o trayectoria siguen las entidades? ¿Parecen evitarse, seguirse o ignorarse? ¿Qué reglas simples podrían generar estos caminos complejos?
  3. Reflexiona sobre la autonomía: Para ambas obras (“Arrels” y “Encuentros”), reflexiona sobre estas preguntas:
    • ¿Qué reglas o comportamientos autónomos crees que podrían estar programados en los agentes (sean ramas, líneas, partículas) para generar estas formas y patrones?
    • ¿Cómo se percibe la “vida”, la “agencia” o el comportamiento emergente (complejidad no programada explícitamente) en estas obras?
  4. (Opcional) Si viste el video de Blender: ¿Cómo se relaciona el concepto de flow field mostrado en Blender con las ideas de agentes siguiendo reglas en un entorno? ¿Qué posibilidades creativas te sugiere para la animación?

🚀 Tu solución:

Agentes autónomos y Comportamiento emergente

  • En cuanto a la obra “arrels” noto que las ramas siguen un comportamiento de agente autónomo, es decir, como tal no están dirigidas por una planificación central, sino que siguen reglas individuales de crecimiento, colisión o curvatura, adaptándose a su entorno visual surgiendo de los márgenes y evitando las demás raíces. A medida que se expanden, evitan superponerse o cambiar de dirección, generando un patrón visual orgánico y complejo, además, al estar llegando a su longitud final, se van encogiendo, para dar ese efecto de punta.

    Ahora, respecto a la obra de “encuentros”, me parece que su nombre da un indicio bastante acertado de qué es lo que hacen las figuras mostradas en la obra, y es que hay tanto campos de flujo, como figuras geométricas, colores, tamaños, etc, todo esto llega un punto en que se empieza a combinar, según la descripción de su propio creador “mediante un sistema numérico hexadecimal”, pero como tal lo principal es comprender que el encuentro entre los campos de flujo y la geometría es lo que produce la composición final, en ese orden de ideas, lo que vemos en esta obra es un comportamiento emergente más que nada, ya que como tal, los agentes autónomos que componen la obra, logran los resultados vistos en los outputs mediante una regla principal que es la combinación, o en este caso, un “encuentro”.

  • Nuevamente lo haré por partes, en el caso de “arrels” se percibe vida, se percibe crecimiento, interacción, un ciclo, las ramas surgen, crecen, pierden fuerza, tamaño, y finalmente su ciclo termina, quedando plasmadas en la obra pero sin una interacción posterior a esta, ya cumplieron su ciclo de vida al llegar a la punta, y quedan detrás dando lugar a otras ramas que nuevamente van a volver a experimentar este corto y aunque comprensible, impredecible ciclo visual.

    Ahora, respecto a la obra de “encuentros”, siento que como ya mencioné anteriormente, es un comportamiento emergente en base a la regla principal que tiene la visualización, que es la colisión, el encuentro y la combinación de los agentes autónomos (Campos de flujo, geometría, colores) que componen esta obra, es cierto que tiene sus debidas reglas cada uno de ellos, y de hecho tienen de base ciertas retículas o “grids” para tener un flujo de trabajo y generación organiado, sin embargo, lo que hace que esta obra se vea como se ve, y sea como es, es principalmente el comportamiento emergente de la misma, el cual, insisto, es en esencia un encuentro.

Investigación 🔎

Actividad 02

Analizando los campos de flujo (flow fields)

👣 Pasos:

  1. Ejecuta el ejemplo: ejecuta el código del ejemplo principal de Flow Fields de TNoC en p5.js. Observa el comportamiento de los vehículos/agentes.
  2. Identifica la estructura del campo: en el código (usualmente en una clase FlowField), localiza cómo se almacena el campo de flujo. ¿Qué estructura de datos se usa (ej: un array 2D)? ¿Qué representa cada elemento de esa estructura? ¿Cómo se calcula inicialmente el vector en cada punto?
  3. Analiza el comportamiento del agente: en el código de la clase del vehículo/agente (Vehicle), encuentra la función follow(). Explica con tus palabras:
    • ¿Cómo determina el agente qué vector del campo de flujo debe seguir basándose en su posición actual? (pista: implica mapear la posición a índices de la cuadrícula).
    • Una vez que tiene el vector deseado del campo, ¿cómo lo utiliza para calcular la fuerza de dirección (steering force)? (pista: implica calcular la diferencia con la velocidad actual y limitar la fuerza).
  4. Identifica parámetros clave: Localiza en el código las variables que controlan aspectos importantes como:
    • La resolución del campo de flujo (el tamaño de las celdas de la cuadrícula).
    • La velocidad máxima (maxspeed) y la fuerza máxima (maxforce) de los agentes.
  5. Experimenta con modificaciones: realiza al menos una de las siguientes modificaciones en el código, ejecuta y describe el efecto observado en el comportamiento de los agentes:
    • Cambia significativamente la forma en que se generan los vectores del campo (ej: usa una fórmula matemática diferente en lugar de noise(), o cambia drásticamente los parámetros de noise()).
    • Modifica sustancialmente la resolución del campo de flujo (hazla mucho más fina o mucho más gruesa).
    • Altera considerablemente maxspeed o maxforce de los agentes.

🚀 Tu solución:

Análisis de campos de flujo

  • Estructura del campo de flujo

    El campo de flujo se construye como una matriz bidimensional de vectores (p5.Vector) que representan direcciones en cada casilla del canvas. Esta matriz se define según el ancho y alto de la pantalla dividido por la resolución, lo que determina cuántas columnas y filas tendrá el campo. Para rellenarla, se utiliza ruido de Perlin, que permite generar direcciones suaves y coherentes entre sí. En cada celda, se genera un ángulo a partir del ruido y se convierte en un vector de dirección, logrando así una red de vectores que simula un flujo natural, como el de viento o corrientes.

  • Comportamiento del agente Cada agente (o vehículo) sigue el campo de flujo buscando el vector correspondiente a su posición actual dentro de la matriz. Este vector indica la dirección deseada en la que debería moverse. El agente lo escala a su velocidad máxima (maxspeed), y luego calcula una fuerza de giro (steering) restando su velocidad actual a la dirección deseada. Esta fuerza se limita por su capacidad máxima de giro (maxforce) y se aplica como aceleración, haciendo que el agente poco a poco se alinee con el flujo, en lugar de cambiar bruscamente de dirección. Esto da lugar a movimientos suaves y naturales.

  • Parámetros que controlan el comportamiento Los tres parámetros principales que afectan el comportamiento de los vehículos son la resolución del campo, la velocidad máxima (maxspeed) y la fuerza máxima de giro (maxforce). La resolución determina el tamaño de las celdas del campo: una resolución baja crea más detalle y más cambios en las direcciones del flujo, mientras que una alta simplifica el movimiento. La velocidad máxima define qué tan rápido puede moverse un agente, y la fuerza máxima de giro limita qué tan bruscamente puede cambiar de dirección. Estos parámetros trabajan en conjunto para balancear entre un movimiento fluido, controlado y natural o uno más brusco y reactivo.

  • Modificación de código

    Se modificaron los parámetros del noise() para hacerlo dinámico en el tiempo usando frameCount, lo que genera un campo de flujo en constante cambio, como si el entorno fluyera o respirara. Además, se hizo la resolución del campo más fina (de 20 a 10), duplicando la cantidad de vectores y haciendo que los vehículos reaccionen a cambios más detallados en su entorno. Finalmente, se aumentaron los valores de maxspeed y maxforce, lo que hace que los agentes se muevan más rápido y hagan giros más bruscos, resultando en trayectorias más agitadas, sensibles y caóticas.

Modificación de campos de flujo

image image

class FlowField {
constructor(cols, rows) {
this.cols = cols;
this.rows = rows;
this.field = Array.from({ length: cols }, () =>
Array.from({ length: rows }, () => createVector(0, 0))
);
this.init();
}
// Generación de vectores usando noise animado
init() {
let scale = 0.2; // más frecuencia = más detalle
for (let i = 0; i < this.cols; i++) {
for (let j = 0; j < this.rows; j++) {
let angle = map(noise(i * scale, j * scale, frameCount * 0.01), 0, 1, 0, TWO_PI);
this.field[i][j] = p5.Vector.fromAngle(angle);
}
}
}
show() {
for (let i = 0; i < this.cols; i++) {
for (let j = 0; j < this.rows; j++) {
let w = width / this.cols;
let h = height / this.rows;
let v = this.field[i][j].copy();
v.setMag(w * 0.5);
let x = i * w + w / 2;
let y = j * h + h / 2;
strokeWeight(1);
stroke(180, 100, 200); // Color HSB
line(x, y, x + v.x, y + v.y);
}
}
}
lookup(position) {
let column = constrain(floor(position.x / (width / this.cols)), 0, this.cols - 1);
let row = constrain(floor(position.y / (height / this.rows)), 0, this.rows - 1);
return this.field[column][row].copy();
}
}
class Vehicle {
constructor(x, y) {
this.position = createVector(x, y);
this.velocity = p5.Vector.random2D();
this.acceleration = createVector(0, 0);
this.r = 4;
this.maxspeed = 7; // ← Aumentado
this.maxforce = 0.4; // ← Aumentado
}
run() {
this.update();
this.borders();
this.show();
}
follow(flow) {
let desired = flow.lookup(this.position);
desired.mult(this.maxspeed);
let steer = p5.Vector.sub(desired, this.velocity);
steer.limit(this.maxforce);
this.applyForce(steer);
}
applyForce(force) {
this.acceleration.add(force);
}
update() {
this.velocity.add(this.acceleration);
this.velocity.limit(this.maxspeed);
this.position.add(this.velocity);
this.acceleration.mult(0);
}
borders() {
if (this.position.x < -this.r) this.position.x = width + this.r;
if (this.position.y < -this.r) this.position.y = height + this.r;
if (this.position.x > width + this.r) this.position.x = -this.r;
if (this.position.y > height + this.r) this.position.y = -this.r;
}
show() {
let theta = this.velocity.heading();
fill(127);
stroke(0);
strokeWeight(2);
push();
translate(this.position.x, this.position.y);
rotate(theta);
beginShape();
vertex(this.r * 2, 0);
vertex(-this.r * 2, -this.r);
vertex(-this.r * 2, this.r);
endShape(CLOSE);
pop();
}
}
// Variables globales
let debug = true;
let flowfield;
let vehicles = [];
function setup() {
createCanvas(640, 640);
colorMode(HSB, 255); // ← Para ver mejor el campo si quieres usar color
// Campo más fino: más columnas y filas
let cols = 80;
let rows = 60;
flowfield = new FlowField(cols, rows);
for (let i = 0; i < 120; i++) {
vehicles.push(new Vehicle(random(width), random(height)));
}
}
function draw() {
background(255);
flowfield.init(); // ← Campo animado frame a frame
if (debug) flowfield.show();
for (let i = 0; i < vehicles.length; i++) {
vehicles[i].follow(flowfield);
vehicles[i].run();
}
}
function keyPressed() {
if (key === ' ') {
debug = !debug;
}
}
function mousePressed() {
flowfield.init();
}

Actividad 03

Analizando el comportamiento de enjambre (Flocking)

👣 Pasos:

  1. Ejecuta el ejemplo: ejecuta el código del ejemplo principal de Flocking de TNoC en p5.js. Observa el movimiento colectivo de los “boids” (agentes).
  2. Identifica las tres reglas: en el código de la clase del agente (ej: Boid), localiza las funciones que implementan las tres reglas fundamentales del Flocking:
    • Separación (Separation): evitar el hacinamiento con vecinos cercanos.
    • Alineación (Alignment): dirigirse en la misma dirección promedio que los vecinos cercanos.
    • Cohesión (Cohesion): moverse hacia la posición promedio de los vecinos cercanos.
  3. Explica las Reglas: para cada una de las tres reglas, explica con tus propias palabras:
    • ¿Cuál es el objetivo de la regla?
    • ¿Cómo calcula el agente la fuerza de dirección correspondiente? (describe la lógica general, ej: “Calcula un vector apuntando lejos de los vecinos demasiado cercanos”).
  4. Identifica parámetros clave: localiza en el código las variables que controlan:
    • El radio (o distancia) de percepción (perceptionRadius o similar) que define quiénes son los “vecinos”. A veces también hay un ángulo de percepción.
    • Los pesos o multiplicadores que determinan la influencia relativa de cada una de las tres reglas al combinarlas.
    • La velocidad máxima (maxspeed) y la fuerza máxima (maxforce) de los agentes (similar a Flow Fields).
  5. Experimenta con modificaciones: realiza al menos una de las siguientes modificaciones en el código, ejecuta y describe el efecto observado en el comportamiento colectivo del enjambre:
    • Cambia drásticamente el peso de una de las reglas (ej: pon la cohesión a cero, o la separación muy alta).
    • Modifica significativamente el radio de percepción (hazlo muy pequeño o muy grande).
    • Introduce un objetivo (target) que todos los boids intenten seguir (usando una fuerza de seek) además de las reglas de flocking, y ajusta su influencia.

🚀 Tu solución:

Comportamiento de Enjambre

  • Objetivo y lógica de las reglas de Flocking

    El comportamiento de enjambre o Flocking simula cómo se mueven animales como aves o peces en grupo. Se basa en tres reglas principales que cada boid sigue de forma autónoma.

    1. La separación evita que los boids choquen entre sí. Cada uno se aleja de los que estén demasiado cerca. Se calcula con una fuerza que empuja en dirección contraria a los vecinos cercanos.
    2. La alineación permite que un boid copie la dirección promedio de los que lo rodean. Esto hace que todos se muevan en la misma dirección y forma.
    3. La cohesión empuja a cada boid hacia el centro del grupo. Se calcula usando la posición promedio de los vecinos cercanos, ayudando a que se mantengan juntos.

    Estas reglas combinadas crean un movimiento grupal fluido y realista, sin necesidad de un líder.


  • Parámetros clave

    Uno de los parámetros clave es el radio de percepción. En el código original, su valor es de aproximadamente 50 píxeles. Esto significa que cada boid solo tiene en cuenta a los demás que se encontraban dentro de ese radio. Este parámetro es crucial, ya que define con cuántos vecinos interactúa cada boid para aplicar las reglas de flocking.

    Los pesos de las reglas también juegan un papel fundamental. En el comportamiento original, los tres comportamientos (separación, alineación y cohesión) tienen un peso equilibrado. Esto permite que los boids se mantengan juntos sin aglomerarse demasiado, alineándose suavemente con los demás y manteniendo una distancia apropiada.

    El parámetro maxSpeed controla la velocidad máxima de cada boid. En su configuración original, esta velocidad es moderada, permitiendo un movimiento natural sin que los boids se dispersen demasiado rápido. A su vez, maxForce limita la fuerza máxima de cambio de dirección. Con un valor bajo, los giros y ajustes de trayectoria son suaves, evitando movimientos bruscos.


  • Cambios en el código y efecto observado

    Se aumentó el tamaño del canvas a 800x800 píxeles y se cambió el fondo a un azul claro para que el enjambre se vea mejor.

    Los boids ahora persiguen el cursor del mouse como si fuera un objetivo. Esto hace que todo el grupo reaccione hacia donde el usuario mueve el puntero.

    La alineación y la cohesión se aumentaron considerablemente. La separación se redujo a 10, para que los boids se acerquen mucho entre sí, lo que favorece la formación de grupos apretados. Los pesos de las reglas se ajustaron así:

    • Separación: 0.3 (poco efecto)
    • Alineación: 1.0 (efecto medio)
    • Cohesión: 2.0 (muy influyente)

    Como resultado, el enjambre forma grupos compactos, muy unidos, que se mueven con fluidez. Parecen una sola entidad, que sigue el mouse en conjunto.

    Ejambre Modificado

    image image


  • El fragmento del código que contiene las modificaciones clave es el siguiente:

createCanvas(800, 800); // Canvas más grande
background('#cceeff'); // Fondo azul claro
sep.mult(0.3); // Separación baja
ali.mult(1.0); // Alineación media
coh.mult(2.0); // Cohesión alta
let desiredSeparation = 10;
let neighborDist = 120; // Alineación
let neighborDist = 150; // Cohesión
// Movimiento hacia el mouse
seekMouse() {
let mouse = createVector(mouseX, mouseY);
let steer = this.seek(mouse);
steer.mult(0.5);
this.applyForce(steer);
}
// Círculo en el cursor
ellipse(mouseX, mouseY, 20, 20);

Aplicación 🛠

Actividad 04

Aplicación creativa e inesperada de agentes autónomos

👣 Pasos:

  1. Elige un algoritmo: decide si trabajarás con Flow Fields o Flocking.
  2. Conceptualiza la aplicación inesperada: brainstorming: ¿Cómo puedes usar la lógica de ese algoritmo para representar algo diferente? ¿Qué fenómeno visual, natural o abstracto podrías simular de forma no convencional? Define tu concepto.
  3. Diseña la implementación:
    • ¿Cómo adaptarás el algoritmo base a tu nuevo concepto? ¿Qué representarán los “agentes”? ¿Qué significará el “campo” o las “reglas de enjambre” en tu contexto?
    • ¿Qué aspecto visual tendrán tus agentes o el resultado del proceso?
    • ¿Qué tipo de interacción incluirás? (ej: el mouse influye en el flow field, un clic añade/quita agentes, teclas cambian parámetros, micrófono, etc).
  4. Implementa tu sketch: escribe el código en p5.js. Empieza adaptando el código base del algoritmo elegido e introduce gradualmente los cambios para tu concepto, los nuevos visuales y la interacción.
  5. Prueba y refina: ejecuta, prueba la interacción y refina los parámetros y el aspecto visual hasta que logres una pieza coherente con tu concepto inesperado.

🚀 Tu solución:

Aplicación de agentes autónomos

Comportamiento de la sociedad

En este caso lo que haré será integrar ambos conceptos, los campos de flujo y el comportamiento de enjambre, para mostrar una representación de cómo funciona la sociedad, de como en un principio a las personas se nos guía por un camino específico, en conjunto, pero que a medida que crecemos, y tomamos nuestras propias decisiones a pesar de ser individuos con metas específicas, nuestra necesidad de pertenecer a algo, y también por el hecho de ser seres sociales, nos vamos formando en grupos, siguiendo a aquellos cuyas ideas se conectan con las nuestras, esas conexiones son más fuertes que cualquier otra influencia externa, pues al final del día nos alineamos con aquello que nos llena más, que nos hace más feliz, aquello para lo que “estamos hechos”.

Esta pequeña reflexión fue resultado directo de ver ambos comportamientos, y es que me parece que es una analogía interesante, el sistema está organizado de tal manera que hasta cierto punto de nuestra vida todos tenemos en general experiencias bastante similares, estudiamos, pasamos por cambios en nuestro cuerpo, llegan las críticas sociales y la expectativa de nuestros familiares, y eventualmente tomamos la decisión, si queremos hacer algo bueno, algo malo, estudiar una cosa u otra, trabajar en un lugar u otro, y es entonces cuando todos esos campos de flujo (la educación, la familia y la sociedad) se convierten en comportamientos de enjambres (las carreras universitarias, los puestos de trabajo, los equipos de deporte, etc).

Así que lo que haré será una obra que integre eso de una forma visual, lo que se me ocurre es un comportamiento de campos de flujo en que seamos un boid, uno específico, tendremos la posibilidad de controlarlo con las flechas, y aunque seremos atraídos por los campos de flujo y eventualmente por el comportamiento de enjambre, seremos nosotros quienes trataremos de encajar en uno o en otro, es decir, estando en la fase de campos de flujo, decidiremos a cuál entrar, y aunque en un principio nuestro color sea negro, al entrar en uno u otro adquiriremos el color que estos tengan, adicionalmente habrá un interruptor en la parte superior, el cual al presionarlo, estos voids dejarán de seguir los campos de flujo (desaparecerán) y empezarán a comportarse como enjambre, formándose nuevamente en distintos enjambres de colores (como el código original, pero con 4 colores limitados (Azul,Verde,Rojo y Morado), cada uno representando realidades sociales istintas), y nuevamente tendremos la oportunidad de encajar en uno o en otro, de movernos a nuestra merced entre ellos, pero si nos metemos en alguno y nos dejamos de mover, seremos parte de ese sistema, debido a su evidente atracción.


Documentación de proceso

  • Algoritmo elegido

    Para esta pieza decidí combinar los dos algoritmos estudiados: Flow Fields y Flocking. Me interesa cómo ambos pueden representar aspectos distintos pero complementarios del comportamiento social: uno como estructura invisible que guía, y otro como la respuesta colectiva que emerge de los individuos.

  • Concepto de aplicación inesperada

    Mi propuesta representa el comportamiento de la sociedad humana desde una perspectiva simbólica. En lugar de simular fluidos o criaturas, uso los algoritmos para explorar cómo las personas buscan pertenecer a grupos, influenciadas por contextos sociales invisibles. El flujo representa fuerzas externas como educación, familia o cultura. El flocking representa la forma en que nos alineamos con otros, en búsqueda de identidad y conexión.

  • Adaptación de la lógica del algoritmo

    Los campos de flujo guían los movimientos de todos los agentes en la escena, simulando esa estructura social que muchas veces no vemos, pero que nos empuja a movernos en ciertas direcciones. Al mismo tiempo, los agentes siguen un comportamiento de enjambre (flocking), buscando alinearse con otros cercanos. Cuando un agente entra en una zona de color, su comportamiento cambia: adquiere un nuevo color (representando una identidad) y se alinea con agentes del mismo color, reforzando esa identidad grupal.

  • Interacción implementada

    El usuario controla un agente individual con las flechas del teclado. Este agente puede desplazarse libremente por los campos de flujo, pero al entrar en las “zonas de identidad” , adopta un nuevo comportamiento e identidad visual. A partir de ahí, se comporta como parte del grupo con el que se alineó. La pieza permite explorar activamente cómo tomamos decisiones y cómo estas decisiones nos convierten en parte de una estructura mayor.


”Código Final”

Comportamiento Social

Niñez1 Niñez2 Adultez1 Adultez2

Nota: Se aumentó la velocidad para poder ver la simulación de manera rápida, pero la idea es bajar la velocidad de los agentes para poder tener un comportamiento social más acorde al esperado

class Boid {
constructor(x, y, isPlayer) {
this.position = createVector(x, y);
this.velocity = p5.Vector.random2D();
this.velocity.setMag(random(1, 2));
this.acceleration = createVector();
this.maxForce = 0.08;
this.maxSpeed = isPlayer ? 3 : 2;
this.isPlayer = isPlayer;
this.r = isPlayer ? 10 : 6;
this.group = floor(random(numGroups));
this.setBaseColor();
}
setBaseColor() {
if (this.isPlayer) {
this.baseColor = color(0);
} else {
this.baseColor = mode === 'adultez'
? groupColors[this.group]
: color(random(255), random(255), random(255));
}
this.currentColor = this.baseColor;
}
applyForce(force) {
this.acceleration.add(force);
}
update() {
this.velocity.add(this.acceleration);
this.velocity.limit(this.maxSpeed);
this.position.add(this.velocity);
this.acceleration.mult(0);
}
edges() {
if (this.position.x < 0) this.position.x = width;
else if (this.position.x > width) this.position.x = 0;
if (this.position.y < 0) this.position.y = height;
else if (this.position.y > height) this.position.y = 0;
}
followFlowField(flowfield, cols) {
let x = floor(this.position.x * flowfieldScale);
let y = floor(this.position.y * flowfieldScale);
let index = x + y * cols;
let force = flowfield[index];
this.applyForce(force);
}
flock(boids) {
let perceptionRadius = 80;
let alignment = createVector();
let cohesion = createVector();
let separation = createVector();
let groupCenter = createVector();
let total = 0;
let sameGroupCount = Array(numGroups).fill(0);
for (let other of boids) {
let d = dist(this.position.x, this.position.y, other.position.x, other.position.y);
if (other != this && d < perceptionRadius) {
alignment.add(other.velocity);
cohesion.add(other.position);
let diff = p5.Vector.sub(this.position, other.position);
diff.div(d * d);
separation.add(diff);
sameGroupCount[other.group]++;
if (other.group === this.group) {
groupCenter.add(other.position);
}
total++;
}
}
if (total > 0) {
alignment.div(total);
alignment.setMag(this.maxSpeed);
alignment.sub(this.velocity);
alignment.limit(this.maxForce);
cohesion.div(total);
cohesion.sub(this.position);
cohesion.setMag(this.maxSpeed);
cohesion.sub(this.velocity);
cohesion.limit(this.maxForce);
separation.div(total);
separation.setMag(this.maxSpeed);
separation.sub(this.velocity);
separation.limit(this.maxForce);
this.applyForce(alignment);
this.applyForce(cohesion.mult(1.5));
this.applyForce(separation.mult(1.0));
let maxGroup = this.group;
let maxCount = 0;
for (let i = 0; i < numGroups; i++) {
if (sameGroupCount[i] > maxCount) {
maxCount = sameGroupCount[i];
maxGroup = i;
}
}
this.group = maxGroup;
let targetColor = groupColors[this.group];
if (this.isPlayer) {
if (maxCount > 0) {
groupCenter.div(maxCount);
let dir = p5.Vector.sub(groupCenter, this.position);
dir.setMag(this.maxForce * 1.8);
this.applyForce(dir);
}
this.currentColor = lerpColor(this.currentColor, lerpColor(this.baseColor, targetColor, 0.5), 0.015);
} else {
this.currentColor = lerpColor(this.currentColor, targetColor, 0.07);
}
}
}
display() {
noStroke();
fill(this.currentColor);
ellipse(this.position.x, this.position.y, this.r);
}
}
let boids = [];
let player;
let flowfield;
let mode = 'niñez';
let flowfieldScale = 0.05;
let cols, rows;
let zoff = 0;
let switchButton;
let groupColors = [];
let numGroups = 4;
let boidCount = 300;
function setup() {
createCanvas(800, 800);
colorMode(RGB);
background(100);
cols = floor(width * flowfieldScale);
rows = floor(height * flowfieldScale);
flowfield = new Array(cols * rows);
groupColors = [
color(255, 0, 0),
color(0, 255, 0),
color(0, 0, 255),
color(255, 0, 255)
];
for (let i = 0; i < boidCount; i++) {
let b = new Boid(random(width), random(height), false);
b.r = 6;
boids.push(b);
}
player = new Boid(width / 2, height / 2, true);
player.r = 10;
boids.push(player);
switchButton = createButton('Cambiar a adultez');
switchButton.position(10, 10);
switchButton.mousePressed(toggleMode);
}
function toggleMode() {
mode = (mode === 'niñez') ? 'adultez' : 'niñez';
switchButton.html(`Cambiar a ${mode === 'niñez' ? 'adultez' : 'niñez'}`);
for (let b of boids) {
if (!b.isPlayer) {
b.setBaseColor();
}
}
}
function draw() {
background(100);
if (mode === 'niñez') {
updateFlowField();
}
maintainGroupBalance();
for (let boid of boids) {
if (mode === 'niñez') {
boid.followFlowField(flowfield, cols);
} else {
boid.flock(boids);
}
boid.update();
boid.edges();
boid.display();
}
handlePlayerInput();
}
function updateFlowField() {
let xoff = 0;
for (let x = 0; x < cols; x++) {
let yoff = 0;
for (let y = 0; y < rows; y++) {
let index = x + y * cols;
let angle = noise(xoff, yoff, zoff) * TWO_PI * 1.5;
let v = p5.Vector.fromAngle(angle);
v.setMag(0.4);
flowfield[index] = v;
yoff += 0.1;
}
xoff += 0.1;
}
zoff += 0.003;
}
function handlePlayerInput() {
let force = createVector(0, 0);
if (keyIsDown(LEFT_ARROW)) force.x = -0.5;
if (keyIsDown(RIGHT_ARROW)) force.x = 0.5;
if (keyIsDown(UP_ARROW)) force.y = -0.5;
if (keyIsDown(DOWN_ARROW)) force.y = 0.5;
player.applyForce(force);
}
function maintainGroupBalance() {
let groupCounts = Array(numGroups).fill(0);
for (let b of boids) {
groupCounts[b.group]++;
}
for (let i = 0; i < numGroups; i++) {
if (groupCounts[i] < 5) {
let candidates = boids.filter(b => !b.isPlayer);
for (let j = 0; j < 5 - groupCounts[i]; j++) {
let b = random(candidates);
if (b) {
b.group = i;
b.setBaseColor();
}
}
}
}
}

Consolidación y metacognición 🤔

Actividad 05

Comparando algoritmos y consolidando conceptos

👣 Pasos:

Reflexiona sobre los dos algoritmos y tu experiencia:

  1. Diferencias fundamentales: ¿Cuál dirías que es la diferencia principal en cómo Flow Fields y Flocking logran el movimiento coordinado o dirigido de los agentes? (piensa en dónde reside la “inteligencia” o las reglas: ¿En el entorno o en las interacciones entre agentes?).
  2. Tipos de comportamiento emergente: basado en tu análisis y aplicación, ¿Qué tipo de comportamiento colectivo o patrón visual crees que es más fácil o natural lograr con Flow Fields? ¿Y con Flocking? Da ejemplos.
  3. Ventajas y desventajas: en tu opinión, ¿Cuáles podrían ser las ventajas o desventajas de usar uno u otro algoritmo para ciertos tipos de efectos visuales o simulaciones?
  4. El agente autónomo: ¿Cómo te ayudaron estos dos ejemplos (Flow Fields y Flocking) a entender mejor el concepto de “agente autónomo”? ¿Qué características definen a un agente en estos sistemas?
  5. Emergencia: ¿En qué momento observaste “comportamiento emergente” (complejidad o patrones no programados explícitamente) al trabajar con estos algoritmos?

🚀 Tu solución:

Comparación de Algoritmos

    1. La diferencia principal entre Flow Fields y Flocking está en que la “Inteligencia” reside en un lugar diferente dependiendo del tipo de simulación, en uno es en el entorno, y en otro en los agentes como tal. En Flow Fields, las reglas están en el entorno; los agentes siguen vectores predefinidos que guían su movimiento. En cambio, en Flocking, la inteligencia está en las interacciones entre los agentes mismos, quienes se coordinan con sus vecinos para mantener separación, alineación y cohesión.
    1. Con Flow Fields es más fácil lograr patrones visuales uniformes y controlados, como corrientes de partículas que fluyen en una dirección definida, similar a un río o viento. En Flocking, los comportamientos colectivos como bandadas de aves o cardúmenes de peces resultan más naturales, donde cada agente se adapta a los movimientos de los otros generando formas fluidas y dinámicas. O por ejemplo como en el caso de mi código, en patrones de simulación de multitudes o grupos que se conectan entre sí por uno u otro motivo, en este caso, metafóricamente, ideologías más que nada.
    1. Flow Fields es ventajoso cuando se quiere un control claro y direccional del movimiento, útil para efectos como humo, agua o flujos de tráfico. Sin embargo, puede parecer menos orgánico. Flocking es ideal para simular grupos con comportamiento autónomo y flexible, pero puede ser más complejo y menos predecible, aparte, otra desventaja es que Flocking puede ser más costoso computacionalmente y más difícil de controlar en detalles específicos.
    1. Estos ejemplos me ayudaron a entender que un agente autónomo es una entidad que toma decisiones basadas en reglas simples y su percepción local, sin un control central. Sus características principales son la capacidad de percibir el entorno o a otros agentes, y de actuar en consecuencia para lograr un comportamiento colectivo emergente.
    1. El comportamiento emergente lo noté cuando, sin programar movimientos específicos para el grupo, los agentes empezaron a formar patrones complejos como formaciones o agrupaciones en Flocking, y flujos suaves y ordenados en Flow Fields, mostrando cómo reglas simples pueden generar comportamientos complejos sin control directo, o bueno, un poco indirecto en el caso del “comportamiento social”.

Actividad 06

Autoevaluación del aprendizaje

👣 Pasos:

Considera tu experiencia personal en esta unidad y responde con honestidad:

  1. Comprensión conceptual: ¿Qué tan claros te resultaron los conceptos de agente autónomo, emergencia, flow fields y flocking? ¿Qué fue lo más fácil y lo más difícil de entender?
  2. Análisis de algoritmos: ¿Te resultó útil analizar los ejemplos de TNoC y experimentar con modificaciones para entender cómo funcionaban los algoritmos? ¿Qué dificultades encontraste en esta fase?
  3. Aplicación creativa: ¿Qué tan "exitoso" te sientes al aplicar uno de los algoritmos a un contexto inesperado? ¿Lograste plasmar tu idea? ¿Qué fue lo más desafiante de esta actividad?
  4. Conexión con TNoC: ¿Cómo se conectan los conceptos de esta unidad (agentes, sistemas, fuerzas) con lo que has aprendido en unidades anteriores?
  5. Exploración futura: ¿Hay algún aspecto de los agentes autónomos, flow fields, flocking u otros comportamientos de sistemas que te gustaría explorar más a fondo después de esta unidad?

🚀 Tu solución:

Autoevaluación del aprendizaje

    1. En general, los conceptos me parecieron bastante claros. Lo más fácil fue entender cómo se dan los comportamientos de los agentes y qué reglas los generan. Lo que me costó un poco más fue captar bien el concepto de emergencia, cómo algo tan simple puede generar patrones complejos inesperados, y es que realmente pasó bastante, a veces en los flowfields parecía que seguían todos los agentes una misma ruta, en ocasiones se hacían intersecciones, todo esto era bastante interesante, en cuanto al flocking más de lo mismo, me pasó en varias ocasiones que aunque quería tener grupos separados, se terminaban juntando eventualmente.
    1. Sí, claro que analizar los ejemplos de TNoC y probar cambios me ayudó mucho a entender mejor cómo funcionan los algoritmos. La dificultad principal fue que al principio cambiaba muchos parámetros al mismo tiempo y eso confundía los resultados porque realmente no terminaba de entender qué era lo que estaba cambiando y cómo esto afectaba directamente o en ocasiones indirectamente el comportamiento, así que tuve que ser más metódico para comprender mejor cada variable, empezar a cambiar una por una y ver qué era lo que pasaba, y ahí si empezar a combinar cambios y de esa forma pude comprender mejor.
    1. Siento que logré plasmar mi idea en el contexto, aunque visualmente creo que podría mejorar mucho más, el problema en este caso y en este contexto es que a decir verdad no estoy muy seguro de cómo hacerlo en un entorno de programación, aún siento que me falta experiencia técnica para enriquecerlo más en ese aspecto, se me ocurren mil ideas en animación, y quizá trate de aprender a integrar ambas cosas, para poder sacarle el jugo a este trabajo, pero como tal aquí me limitan bastante mis capacidades técnicas.
    1. Veo que los conceptos de esta unidad conectan con lo aprendido antes, especialmente con el uso de vectores para dirigir a los agentes específicamente en el caso de los flow fields, fuerzas de varios tipos en el caso de flocking, claramente esto para hacer que los agentes se acerquen entre sí, es más que evidente que ahí había atracción y al final del día esto también es una fuerza, movimiento con el marco 101 porque obviamente todos estos agentes tenían una velocidad, dirección, en algunos casos aceleración, y claro que siempre en todo hay algo de aleatoriedad (O mucha). Es como juntar varias piezas que ya conocía para crear sistemas que funcionan en conjunto, no solo elementos aislados, en esencia seguir acumulando conceptos para que todo sea cada vez más complejo.
    1. Me interesa profundizar más en el flocking porque creo que tiene un gran potencial para simulaciones complejas y realistas, o metafóricas, aunque haciendo código en un momento tuve un resultado muy curioso, el cual parecía simular las neuronas en el cerebro, los procesos sinápticos, me parece que en este caso se aplica más que nada los flow fields, pero si tuviera que quedarme con uno y estudiarlo más a fondo, sería el flocking. Me gustaría explorar cómo se puede usar para crear efectos visuales más naturales y con comportamientos emergentes interesantes, es algo que si se controla solo hasta cierta parte puede general naturalmente efectos visuales bastante únicos e impactantes.

Actividad 07

Retroalimentación para mejorar la unidad

👣 Pasos:

Reflexiona sobre cómo fue tu experiencia personal al cursar esta unidad específica y responde:

  1. Claridad y enfoque: ¿Te pareció claro el objetivo de la unidad y la conexión entre las actividades (inspiración, análisis, aplicación)?
  2. Actividades de introducción e investigación: ¿Fueron útiles los referentes artísticos (SET) para introducir el tema? ¿Fueron efectivas las actividades de análisis de algoritmos para tu comprensión? ¿Sugerirías algún cambio?
  3. Actividad de aplicación: ¿Te gustó el desafío de la aplicación inesperada? ¿Fue demasiado difícil, demasiado fácil o adecuado? ¿Necesitabas más orientación o ejemplos para esta parte?
  4. Recursos: ¿Fueron suficientes los enlaces a TNoC y los ejemplos? ¿Necesitaste buscar muchos recursos adicionales por tu cuenta?
  5. Ritmo y carga de trabajo: ¿Cómo sentiste el ritmo y la carga de trabajo de esta unidad en comparación con las anteriores?
  6. Sugerencia principal: Si pudieras hacer una sugerencia principal para mejorar la experiencia de aprendizaje en esta unidad sobre agentes autónomos, ¿Cuál sería?

🚀 Tu solución:

Retroalimentación de la unidad

    1. Sí claro, en la unidad siento que lo principal era entender cómo funcionaban estos algoritmos, y cómo estas simulaciones quedaban bien en entornos naturales, en el caso de los campos de flujo, como corrientes de partículas, rios, ese tipo de cosas, claro que se puede aplicar a temas más complejos de partículas y bueno, una infinidad de cosas, pero ya eso es cuestión del alcance creativo de cada artista, lo importante es entender lo básico, y lo mismo con el flocking, el cual me pareció aún más claro de entender puesto que las comparaciones que se usan para entender este concepto son mucho más claras y fáciles de entender, incluso nosotros como especie “compleja” en muchísimos de nuestros comportamientos tenemos tendencia a seguir a la mayoría, en todo caso lo importante es que sí, si me pareció claro, si me parece que el enfoque estuvo bien explicado, los recursos disponibles y las actividades propuestas logran el objetivo de hacer entender bien los conceptos y propician esa innovación, las ganas de proponer y desarrollar formas nuevas de aplicar esto.
    1. Sí, los referentes fueron muy útiles, de hecho, me hubiera gustado hacer algo similar a las ramificaciones de “Arrels”, era algo que realmente daba una impresión verlo ya que todo parecía muy orgánico, y es muy loco pensar que todo eso se logra codificando, con patrones, con parámetros, con algoritmos, y con un conjunto de reglas que aunque limitan hasta cierto punto los patrones, por otro lado, también hacen que hayan resultados inesperados y visualmente muy interesantes.
    1. Me gustó, pero realmente me parece que si hubiera estado bien más ejemplos para esta parte, siento que nos dejaron un poco a la suerte y aunque ya estaban claros los conceptos, fue un poco raro entender cómo podríamos combinarlos para hacer algo “diferente”, ya que por mi parte creo que lo que hizo de mi aplicación algo diferente fue la forma en que se mostró, pero al pensar en flocking y flow fields esa fue una de las tantas cosas que se me vino a la cabeza, a lo que voy es que no sé qué tan innovador se puede ser ya que no tuve claro qué ejemplos había ya, y de donde partir aparte de lo que se explicó al principio sobre “corrientes”, “grupos de aves”, etc.
    1. Los enlaces y recursos fueron suficientes hasta que se trató de innovar ya que me parece que puede darse el caso de que algún estudiante piense en una idea y le parezca innovadora y sea algo que hacen muy comúnmente pero que no puede parecer tan obvio, de hecho, nadie quita que ese sea mi caso, realmente es probable, y no tengo forma de saberlo, ya que a decir verdad no me dediqué tan de lleno a buscar nuevos recursos, me limité a los que tenía disponibles y esto puede jugar en contra de la innovación, que es lo que se buscaba en la actividad que menciono.
    1. Me pareció bien, realmente la última y esta fueron bastante similares, menos actividades, pero más cargadas, no es algo malo, tampoco es algo bueno, simplemente me pareció una forma diferente de proponer la unidad, pero como ya mencioné, la unidad anterior me pareció igual así que no la sentí ni muy pesada ni muy liviana, simplemente diferente, pero de manera positiva.
    1. Quiero insistir en los recursos de referencia para la idea innovadora, en el caso de la actividad 4, soy muy consciente de que la idea es innovar, usar la cabeza, ser creativos y “pensar fuera de la caja” pero a muchos este proceso se les dificulta bastante, y las referencias al final del día son recursos necesarios para nosotros los artistas, nos inspiran de muchas maneras, y está a criterio de cada uno ver en qué tanto se basan en una o en otra, quizá esto haya sido a propósito para evitar precisamente esto, pero me parece que quizá se deba tener en cuenta y dar un poquito más de recursos, así sea limitados, sobre referencias para trabajar esa parte, esa actividad 4, me parece que haría que el proceso de muchos sea mucho más digerible, enriquecedor e incluso más divertido de hacer.