Unidad 3
Introducción
En esta unidad, explorarás el concepto de fuerzas y cómo se aplican en la creación de sistemas interactivos dinámicos. Partiendo de la manipulación de la aceleración vista en la unidad anterior, aprenderás a utilizar las leyes de Newton para simular el movimiento de objetos en un entorno virtual. A través de ejercicios prácticos, comprenderás cómo las fuerzas influyen en la aceleración, velocidad y posición de los elementos visuales, y cómo modelar diferentes tipos de fuerzas, incluyendo la fricción, la resistencia y la gravedad. Además, explorarás la narrativa como un elemento clave para dar sentido y propósito a las interacciones entre los elementos de la simulación. Finalmente, integrarás la interactividad del usuario para enriquecer la experiencia y el control sobre el sistema.
¿Qué aprenderás en esta unidad?
En esta fase inicial, establecerás las bases para comprender las fuerzas en sistemas interactivos. Despertarás la curiosidad y establecerás conexiones con conocimientos previos.
Actividad 01
Explorando las Fuerzas en el Mundo Real
Enunciado: observa a tu alrededor e identifica cinco ejemplos de fuerzas en acción. Describe cada ejemplo y explica qué tipo de fuerza está actuando (ej. gravedad, fricción, empuje). ¿Cómo se manifiesta visualmente cada fuerza?
Por ejemplo, considera un libro sobre una mesa:
- Fuerza en acción: gravedad.
- Descripción: la gravedad tira del libro hacia abajo, pero la mesa ejerce una fuerza de reacción normal que evita que caiga.
- Manifestación visual: el libro permanece en reposo sobre la mesa sin moverse.
¿Cómo conectamos esto con el arte y diseño generativo? Por ejemplo, una simulación de equilibrio y gravedad. En una simulación de arte generativo podrías pensar en algoritmos de simulación de cuerpos rígidos que calculan la estabilidad de estructuras apiladas. Como inspiración visual se podrían analizar obras que exploran la gravedad y el equilibrio, como las esculturas de Alexander Calder (móviles que juegan con la estabilidad y el contrapeso). Esto lo podrías aplicar a una simulación de un sistema generativo donde las formas geométricas se apilan siguiendo un modelo de fuerzas de reacción y colisión.
Entrega: una lista de cinco ejemplos de fuerzas del mundo real, con descripciones detalladas de cada fuerza, su manifestación visual y qué te inspira en términos de arte/diseño generativo algorítmico?
🚀 Tu solución:
EJEMPLOS
1. Un termo sostenido desde su agarradera
- Fuerza en acción: Gravedad y tensión
- Descripción: La gravedad tira del termo hacia abajo, pero la mano ejerce una fuerza de tensión a través de la agarradera para sostenerlo.
- Manifestación visual: El termo permanece suspendido en el aire sin caer. Si la mano se mueve, el termo puede oscilar ligeramente debido a su peso.
- Inspiración en arte/diseño generativo: Se puede simular una cuerda o resorte con un sistema de partículas que reacciona a la gravedad y la tensión. Un ejemplo visual sería un sistema de péndulos acoplados o una simulación de cuerpos suspendidos con deformaciones según la carga.
2. Dos manos entrelazadas
- Fuerza en acción: Fuerza de contacto, fricción y presión
- Descripción: Cada mano ejerce presión sobre la otra para mantenerse sujetas. La fricción evita que las manos se deslicen fácilmente.
- Manifestación visual: Se observa un leve hundimiento en la piel por la presión aplicada, y las manos permanecen unidas a pesar de movimientos sutiles.
- Inspiración en arte/diseño generativo: Esto podría inspirar un sistema de partículas conectadas que representan la interacción de fuerzas en estructuras flexibles, como en simulaciones de tejidos o redes dinámicas de conexión.
3. Una silla de escritorio rodando
- Fuerza en acción: Fuerza de empuje, fricción y resistencia del aire
- Descripción: Un empuje inicial (de una persona o fuerza externa) pone la silla en movimiento. La fricción con el suelo y la resistencia del aire gradualmente reducen su velocidad hasta detenerla.
- Manifestación visual: La silla se mueve suavemente hasta desacelerar y detenerse por completo.
- Inspiración en arte/diseño generativo: Un sistema de partículas con fricción y resistencia al movimiento puede generar simulaciones de desplazamiento realista. Se pueden diseñar interacciones basadas en colisiones y trayectorias con pérdida de energía progresiva.
4. Un proyector situado en lo alto de un techo
- Fuerza en acción: Gravedad y fuerza de reacción del soporte
- Descripción: La gravedad tira del proyector hacia abajo, pero el soporte ejerce una fuerza de reacción igual y opuesta para mantenerlo en equilibrio.
- Manifestación visual: El proyector permanece fijo sin moverse.
- Inspiración en arte/diseño generativo: Se podría usar en simulaciones de equilibrio estructural, como modelos de arquitectura generativa que calculan la distribución de peso y fuerzas en estructuras suspendidas.
5. Las ramas de un árbol muy grande
- Fuerza en acción: Gravedad, tensión interna y fuerza del viento
- Descripción: La gravedad tira de las ramas hacia abajo, pero el tronco y los tejidos internos ejercen una fuerza de tensión para mantenerlas en su lugar. Si hay viento, este ejerce una fuerza adicional, provocando oscilaciones.
- Manifestación visual: Las ramas pueden doblarse ligeramente hacia abajo o moverse de un lado a otro con el viento.
- Inspiración en arte/diseño generativo: Esto se puede modelar con sistemas de simulación de dinámica de fluidos y oscilaciones, como un algoritmo de ruido de Perlin para simular el movimiento de ramas o estructuras flexibles.
Actividad 02
Explorando Posibilidades
Enunciado: te voy a presentar el estudio de diseño SOSO. Observa el proyecto Data Structure.
Tomando como inspiración el proyecto de Data Structure, explora cómo las experiencias digitales pueden manifestarse en el mundo físico. Esto puede lograrse mediante la creación de instalaciones interactivas que fusionen elementos digitales y físicos, utilizando técnicas como la proyección, la realidad aumentada y la fabricación digital.
Por ejemplo, se podría desarrollar una instalación donde los jugadores interactúen con proyecciones en superficies físicas, creando una experiencia de juego que trascienda la pantalla tradicional. Otra posibilidad es diseñar esculturas cinéticas controladas por algoritmos generativos, donde la animación digital influya directamente en el movimiento físico de la obra.
Entrega: un texto donde propongas una idea concreta, asociada con tus intereses o línea de énfasis, acerca de cómo difuminar la línea entre lo digital y lo tangible, ofreciendo experiencias inmersivas que involucren al espectador de manera multisensorial.
🚀 Tu solución:
Idea
- Cuando era pequeña solía ir con mi familia a un lugar llamado “El parque del agua” en Bucaramanga, cuando era diciembre todo parecía mágico porque habían luces por todos lados y podías ver a los peces a través de canalizaciones situadas a los lados de los caminos por los que se transitaban. Hace un tiempo vi a una chica en TikTok que usando Touchdesigner realizó un video mapping en su habitación con dos platos llenos de agua. La proyección era un pez animado que nadaba en círculos. Sería muy divertido poder recrear esto agregando efectos sonoros y una superficie más amplia para que las personas puedan “sostener con sus manos” a los peces aunque sean proyecciones. Incluso pensándolo ahora sería una gran alternativa a los acuarios, tener a los animales en un lugar seguro, monitoreado y tranquilo mientras los usuarios interactúan solo con sus proyecciones en tiempo real.
Investigación
En esta fase, profundizarás en la comprensión de las leyes de Newton y cómo se aplican en la simulación de fuerzas. Analizarás ejemplos de código y resolverás problemas para afianzar el conocimiento.
Actividad 03
Lectura Inicial Exploratoria
Enunciado: comienza dando una lectura inicial exploratoria a la unidad 2 del libro The nature of code. NO OLVIDES: inicial exploratoria (la idea es dedicarle solo 30 minutos). Mira de que se trata. Observa los ejemplos y lee las partes que más te llamen la atención.
Entrega: un texto donde:
- Expliques qué fue lo más te llamó la atención de la unidad
- ¿Por qué?
- ¿Qué relación observas entre la unidad anterior y esta en relación con el marco Motion 101?
🚀 Tu solución:
¿Qué fue lo más te llamó la atención de la unidad?
- Lo que más me llamó la atención de esta unidad fue darme cuenta de cómo el uso de fuerzas hace que los movimientos en una simulación se sientan más naturales y realistas. Antes, usaba estos conceptos de manera más técnica en ejercicios de modelamiento, donde aplicaba ecuaciones y ajustes precisos, pero sin enfocarme tanto en cómo estos principios pueden hacer que una simulación se sienta más viva. Ahora veo que al aplicar fuerzas, los objetos reaccionan de manera más fluida y creíble dentro de una simulación.
¿Por qué?
- Me gusta la idea de aplicar esto en proyectos interactivos, como simulaciones donde los objetos respondan a su entorno de manera más natural. Por ejemplo, hacer que una partícula caiga como si realmente tuviera peso o que un personaje se mueva de manera más dinámica dependiendo de las fuerzas que actúan sobre él.
¿Qué relación observas entre la unidad anterior y esta en relación con el marco Motion 101?
- Motion 101 proporciona el modelo básico de actualización de movimiento con posición, velocidad y aceleración. Las fuerzas afectan la aceleración, lo que a su vez modifica la velocidad y, finalmente, la posición del objeto. Las fuerzas agregan realismo al modificar la aceleración de forma dinámica. Con este enfoque podemos simular fenómenos físicos como gravedad, fricción, viento, rebotes o resortes.
Actividad 04
Marco Motion 101
Entrega: ¿Recuerdas el marco motion 101 de la unidad anterior? Regresa y dale una mirada rápida si es del caso. Luego considera lo siguiente:
let mover;
function setup() { createCanvas(640, 240); mover = new Mover();}
function draw() { background(255); mover.show(); mover.update(); mover.checkEdges();}
...
update() {
// Aquí calculo la aceleración . . . this.velocity.add(this.acceleration); this.velocity.limit(this.topSpeed); this.position.add(this.velocity);}...
Mira bien el código. ¿Dónde está el marco motion 101?
- En la unidad anterior tu definías la aceleración mediante algún algoritmo. ¿Cuáles eran? Muestra ejemplos de código de la unidad anterior (solo la parte donde se define la aceleración).
- En esta unidad tu vas a calcular la aceleración. ¿Qué tiene que ver esto con las leyes de movimiento de Newton?
Entrega: texto y fragmentos de código donde des respuesta a cada una de las preguntas anteriores.
🚀 Tu solución:
Recordando el Marco Motion 101
En el código de ejemplo: ¿Dónde está el marco motion 101?
En la función Update() puedo identificar un patrón característico del Motion 101, en donde la aceleración afecta la velocidad y esta a su vez modifica la posición.
update() { this.velocity.add(this.acceleration); this.velocity.limit(this.topSpeed); this.position.add(this.velocity);}
En la unidad anterior tu definías la aceleración mediante algún algoritmo. ¿Cuáles eran? Muestra ejemplos de código de la unidad anterior (solo la parte donde se define la aceleración).
Aceleración constante
update() { this.velocity.add(this.acceleration); this.velocity.limit(this.topSpeed); this.position.add(this.velocity); }
Aceleración aleatoria
update() { this.acceleration = p5.Vector.random2D(); this.velocity.add(this.acceleration); this.velocity.limit(this.topSpeed); this.position.add(this.velocity);}
Aceleración dependiendo de la posición del mouse
update() { let mouse = createVector(mouseX, mouseY); // Step 1: Compute the direction. let dir = p5.Vector.sub(mouse, this.position); // Step 2: Normalize. dir.normalize(); // Step 3: Scale. dir.mult(0.2); //{!1} Step 4: Accelerate. this.acceleration = dir; this.velocity.add(this.acceleration); this.velocity.limit(this.topSpeed); this.position.add(this.velocity); }
En esta unidad tu vas a calcular la aceleración. ¿Qué tiene que ver esto con las leyes de movimiento de Newton?
En la unidad anterior definiamos la aceleración de manera arbitraría per ahora debemos aplicar fuerzas al objeto en movimiento basándonos en la segunda ley de Newton.
F= m*a---> a=F/m
¿Cómo se aplicaría en código?
applyForce(force) { let f = p5.Vector.div(force, this.mass); // a = F/m this.acceleration.add(f);}
-
applyForce(force)—> Convierte una fuerza en una aceleración dividiéndola por la masa del objeto.
-
Cada fuerza aplicada afectará la aceleración, que a su vez modificará la velocidad y la posición, permitiendo simulaciones más realistas.
Actividad 05
¿Y qué relación tiene esto de las leyes de Newton con al arte generativo?
Enunciado: analiza con detenimiento la siguiente idea.
Antes de comenzar, disfruta esta simulación donde puedes experimentar de manera creativa las leyes de la atracción. Ahora si, volviendo al lío de Monte Pío (pero no tanto).
La ecuación vectorial de la segunda ley de Newton se expresa como:
Donde:
-
La fuerza neta o la sumatoria de todas las fuerzas que actúan sobre un objeto:
-
Masa del objeto:
-
Aceleración del objeto:
Nota entonces que:
Y lo siguiente lo dejaré a tu criterio, finalmente tu eres quien toma las decisiones en tu mundo de arte generativo ¿Qué tal si la masa es igual a 1? Yo no veo por qué no, finalmente, en el mundo de los pixeles el artista manda (¿O no?) 😉.
Entonces ya tenemos la relación. En la unidad anterior tu definías en cada frame de la simulación un algoritmo para la aceleración. Ahora, la aceleración en cada frame la calcularemos como la influencia de todas las fuerzas sobre nuestros elementos gráficos 😹.
Si volvemos a nuestro texto guía: The Nature of code, verás que un elemento gráfica que se mueva en el canvas tendrá mínimo estas propiedades:
class Mover { constructor() { this.position = createVector(); this.velocity = createVector(); this.acceleration = createVector(); }}
Ahora, considera que en un frame actúan sobre este elemento dos fuerzas: viento y gravedad. Por tanto, en ese frame aplicarás las dos fuerzas:
mover.applyForce(wind);
y luego:
mover.applyForce(gravity);
Finalmente, en el método applyForce
de la clase Mover
tendrás algo como:
applyForce(force) { this.acceleration = force;}
Y listo ¿Cierto?
Entrega: ¿Qué problema le ves a este planteamiento? ¿Qué solución propones? ¿Cómo lo implementarías en p5.js?
Nota: no olvides que queremos calcular la aceleración en cada frame como la sumatoria de todas las fuerzas que actúan sobre un objeto.
🚀 Tu solución:
Planteamiento inicial:
class Mover { constructor() { this.position = createVector(); this.velocity = createVector(); this.acceleration = createVector(); }
update() { mover.applyForce(wind); mover.applyForce(gravity); }
applyForce(force) { this.acceleration = force; }
}
¿Qué problema le ves a este planteamiento?
- En el método applyForce(force) la aceleración se está sobreescribiendo en cada llamada en lugar de acumularse con cada fuerza que se aplica sobre el objeto. Es decir, cuando llamamos a la fuerza del viento y después a la fuerza de gravedad, esta última reemplaza a la primera en lugar de sumarse a ella y es por ello que se elimina “el efecto de viento”.
¿Qué solución propones?
- Para evitar que se sobreescriban las fuerzas, es necesario sumar la nueva fuerza a la aceleración acumulada por la anterior, permitiendo que hayan varias fuerzas que influyan en un mismo movimiento.
¿Cómo lo implementarías en p5.js?
applyForce(force) { this.acceleration.add(force); // Se suma en lugar de reemplazar}
Actividad 06
La fuerza neta debe ser acumulativa
Enunciado: ya te diste cuenta entonces que la fuerza neta es la sumatoria de todas las fuerzas que actúan sobre un objeto. Ahora, ¿Qué pasa si en un frame actúan sobre un objeto dos fuerzas? ¿Cómo calculas la aceleración resultante?
mover.applyForce(wind);mover.applyForce(gravity);...
applyForce(force) { // Segunda ley de Newton, pero con acumulación de fuerza, sumando todas las fuerzas de entrada a la aceleración this.acceleration.add(force);}
⚠️
Te diste cuenta qué pasó aquí con respecto a la actividad anterior? Vuelve a mirar.
Entonces en cada frame, la aceleración se calcula como la sumatoria de todas las fuerzas que actúan sobre un objeto:
mover.applyForce(wind);mover.applyForce(gravity);mover.update();
Y en el método update() se actualiza la velocidad y la posición del objeto:
update() { this.velocity.add(this.acceleration); this.position.add(this.velocity); this.acceleration.mult(0);}
Pero calma 🧘. Notaste algo raro al final de update()?
- ¿Por qué es necesario multiplicar la aceleración por cero en cada frame?
- ¿Por qué se multiplica por cero justo al final de update()?
Entrega: un texto donde expliques por qué es necesario multiplicar la aceleración por cero al final de cada frame.
🚀 Tu solución:
¿Por qué es necesario multiplicar la aceleración por cero al final de cada frame?
El orden de los cálculos que se realizan en el método update() es: primero se usan todas las fuerzas aplicadas para actualizar la velocidad y la posición; luego, se borra la aceleración (this.acceleration.mult(0)) para evitar que se acumule en el siguiente frame. Finalmente, se vuelven a aplicar las fuerzas y se recalcula la aceleración desde cero.
Así se asegura que el objeto responde correctamente a las fuerzas en cada frame sin errores de acumulación no deseada.
Actividad 07
En mi mundo los pixeles si tienen masa
Enunciado:
Como en tu mundo los pixeles tienen masa, entonces, ¿Qué pasa si en un frame actúan sobre un objeto dos fuerzas? ¿Cómo calculas la aceleración resultante?
mover.applyForce(wind);mover.applyForce(gravity);
applyForce(force) { // Asume que la masa es 10 force.div(10); this.acceleration.add(force);}
¿Y listo cierto? Pues ¡No! 🤣
¿Qué ves raro?
Entrega: un texto donde expliques qué problema le ves a este planteamiento y qué solución propones. ¿Cómo lo implementarías en p5.js?
Nota: recuerda, ¿Cuándo se pasa algo a un función por valor y cuándo por referencia? En este caso, force es objeto de la clase p5.Vector, es decir, es un objeto que se pasa por referencia. ¿Qué implica esto?
🚀 Tu solución:
Planteamiento inicial
¿Qué pasa si en un frame actúan sobre un objeto dos fuerzas? ¿Cómo calculas la aceleración resultante?
mover.applyForce(wind);mover.applyForce(gravity);----------------applyForce(force) { // Asume que la masa es 10 force.div(10); this.acceleration.add(force);}
¿Qué problema le ves a este planteamiento y qué solución propones?
- El problema en este planteamiento es que force, al ser un objeto de la clase p5.Vector, se pasa por referencia en la función applyForce().
Esto significa que cualquier modificación dentro de la función afectará el objeto original fuera de ella.
En este caso, al dividir force por 10 en la primera llamada, el cambio también impacta en la siguiente fuerza aplicada, lo que genera un resultado incorrecto en la simulación. Lo que realmente queremos es modificar la fuerza solo dentro de la función, sin alterar su valor original. La solución es crear una copia del vector antes de hacer cualquier operación, usando force.copy(), para asegurarnos de que cada fuerza se aplique de manera independiente. Así, en lugar de modificar directamente el argumento recibido, trabajamos con una copia que se ajusta y luego se suma a la aceleración. De esta manera, cada llamada a applyForce() procesa la fuerza correctamente sin afectar las demás, asegurando una simulación más precisa y coherente en p5.js.
¿Cómo lo implementarías en p5.js?
applyForce(force) { let f = force.copy(); // Crear una copia del vector para no modificar el original f.div(10); // Dividir por la masa this.acceleration.add(f); // Sumar a la aceleración}
Actividad 08
Paso por valor y paso por referencia
Enunciado:
En el siguiente código:
let friction = this.velocity.copy();let friction = this.velocity;
- ¿Cuál es la diferencia entre las dos líneas?
- ¿Qué podría salir mal con let friction = this.velocity;
De nuevo, toca repasar. ¿Cuál es la diferencia entre copiar por VALOR y por REFERENCIA?
- En el fragmento de código ¿Cuándo es por VALOR y cuándo por REFERENCIA.
Entrega: un texto donde expliques la diferencia entre paso por valor y paso por referencia. ¿Qué implica esto en el fragmento de código?
🚀 Tu solución:
¿Cuál es la diferencia entre las dos líneas?
let friction = this.velocity.copy();
- En esta primera línea se está pasando por valor, ya que copy() crea una nueva instancia del vector con los mismos valores que this.velocity, pero sin compartir la referencia.
- friction es ahora un objeto independiente de this.velocity, por lo que modificar friction no afectará this.velocity.
- this.velocity.copy(); → Crea un nuevo objeto independiente (valor).
let friction = this.velocity;
- En la segunda línea, sí se usa el valor por referencia, porque friction y this.velocity apuntan al mismo objeto en memoria. Cualquier cambio en friction afectará también a this.velocity.
- this.velocity; → Apunta al mismo objeto (referencia).
¿Qué podría salir mal con let friction = this.velocity;
Estaríamos modificando this.velocity directamente en lugar de solo modificar friction. Esto puede generar comportamientos inesperados en la simulación, ya que la velocidad del objeto cambiaría de forma no deseada.
Diferencia entre paso por valor y paso por referencia.
- El paso por valor crea una copia independiente del valor original para no afectarlo y se usa para datos de tipo primitivos (número, booleanos, string, etc…), sin embargo, si queremos pasar un vector (objeto en p5.js) por valor se debe crear una copia del mismo usando copy() como el ejemplo anterior en la primera línea. Cuando queremos pasar un dato por referencia se copia la referencia en memoria y al modificarla afecta a la variable original por lo que suele usarse para objetos y arrays. En resumen, si asignas un objeto a otra variable ambas apuntaran al mismo objeto en memoria. Si queremos una copia independiente, se crea una nueva instancia con .copy() para no modificar la variable original.
Actividad 09
Creando fuerzas en tu mundo de pixeles
Enunciado:
En tu mundo de pixeles tu puedes crear las fuerzas o las puedes modelar.
Vamos a probar con lo segundo, modelar una fuerza. Ve a la sección Modeling forces del texto guía. Lee con detenimiento y responde:
Dada una fuerza que desees modelar para usar en tu simulación ¿Qué pasos hay que seguir?
Entrega: un texto donde expliques los pasos a seguir para modelar una fuerza en tu simulación.
🚀 Tu solución:
¿Cómo modelar una fuerza para una simulación?
1. Entendder el concepto detrás de una fuerza: Una fuerza es una interacción que puede cambiar el estado de movimiento de un objeto. Las fuerzas pueden ser resultado de distintas interacciones como la gravedad, la fricción, el empuje, etc.
2. Descomponer la fórmula de la fuerza en dos partes:
- Dirección de la fuerza: La dirección de una fuerza indica hacia dónde se aplica. Por ejemplo, la gravedad siempre actúa hacia abajo.
- Magnitud de la fuerza: La magnitud de una fuerza indica cuánta fuerza se aplica. Puede calcularse usando fórmulas específicas para cada tipo de fuerza.
3. Representar la fuerza como un vector: En programación, una fuerza se representa como un vector, que tiene una dirección y una magnitud. En “Nature of Code”, se utilizan las clases PVector o Vector para representar fuerzas.
4. Crear una clase que represente el objeto en movimiento: En esta clase, define propiedades como posición, velocidad y aceleración, que también son vectores. Además, deberás incluir una propiedad de masa, que afectará cómo se aplica la fuerza al objeto.
5. Aplicar la fuerza al objeto: Para aplicar una fuerza a un objeto, utiliza la segunda ley de Newton: 𝐹=𝑚*𝑎. Esto significa que la fuerza es igual a la masa del objeto multiplicada por su aceleración. Para obtener la aceleración, divide la fuerza por la masa del objeto.
6. Actualizar el estado del objeto: En cada frame de la simulación, actualiza la posición y la velocidad del objeto sumando la aceleración a la velocidad y la velocidad a la posición.
7. Implementar la función de dibujo: Crea una función que dibuje el objeto en la pantalla, utilizando su posición actualizada.
8. Añadir las fuerzas adicionales: Si quieres simular otras fuerzas, como la fricción o el arrastre, simplemente crea funciones adicionales que calculen esas fuerzas y aplícalas al objeto de la misma manera que aplicaste la fuerza inicial.
Aplicación
En esta fase, aplicarás los conceptos aprendidos para crear simulaciones interactivas que involucren diferentes tipos de fuerzas.
Actividad 10
Modelando fuerzas
Enunciado: diseña varias simulaciones interactivas que muestren cómo modelar fuerzas en tu mundo de pixeles.
Las fuerzas que puedes modelar son las siguientes:
- Fricción.
- Resistencia del aire y de fluidos.
- Atracción gravitacional.
Entrega: el código de cada una de las simulaciones y un texto donde expliques cómo modelaste cada fuerza. Adicionalmente, no olvides incluir un enlace a cada simulación en el editor de p5.js. Para hacer esto recuerda que debes estar logueado en el editor de p5.js y que debes hacer clic en el botón “Save” para guardar los cambios. De esta manera, el enlace a tu simulación se actualizará en la barra de direcciones de tu navegador.
🚀 Tu solución:
Modelamiento de fuerzas
Enlace a la simulación aquí
let mover;let select;let liquid;let attractor;let attracting = false;
function setup() { createCanvas(600, 400); mover = new Mover(50, 200, 2); attractor = new Attractor(width / 2, height / 2, 20);
select = createSelect(); select.position(10, 10); select.option('Fricción'); select.option('Resistencia del aire'); select.option('Resistencia de fluidos'); select.option('Atracción gravitacional'); select.changed(resetMover);
liquid = new Liquid(0, height / 2, width, height / 2, 0.1);}
function draw() { background(220); let selectedForce = select.value();
if (selectedForce === 'Resistencia de fluidos') { liquid.show(); }
if (selectedForce === 'Atracción gravitacional') { attractor.display(); if (attracting) { let attraction = attractor.attract(mover); mover.applyForce(attraction); } }
let gravity = createVector(0, 0.2 * mover.mass); mover.applyForce(gravity);
if (selectedForce === 'Fricción' && mover.velocity.mag() > 0) { let friction = mover.calculateFriction(0.1); mover.applyForce(friction); }
if (selectedForce === 'Resistencia del aire') { let airResistance = mover.calculateAirResistance(0.02); mover.applyForce(airResistance); }
if (selectedForce === 'Resistencia de fluidos' && liquid.contains(mover)) { let fluidResistance = liquid.drag(mover); mover.applyForce(fluidResistance); }
mover.update(); mover.edges(); mover.display();}
function resetMover() { mover = new Mover(50, 200, 2);}
function mousePressed() { if (select.value() === 'Atracción gravitacional') { attracting = true; }}
function mouseReleased() { attracting = false;}
class Mover { constructor(x, y, m) { this.position = createVector(x, y); this.velocity = createVector(2, 0); this.acceleration = createVector(0, 0); this.mass = m; }
applyForce(force) { let f = p5.Vector.div(force, this.mass); this.acceleration.add(f); }
calculateFriction(mu) { let friction = this.velocity.copy(); friction.normalize(); friction.mult(-1); let normalForce = this.mass * 0.2; friction.setMag(mu * normalForce); return friction; }
calculateAirResistance(c) { let airResistance = this.velocity.copy(); airResistance.normalize(); airResistance.mult(-1); let speedSq = this.velocity.magSq(); airResistance.setMag(c * speedSq); return airResistance; }
update() { this.velocity.add(this.acceleration); this.position.add(this.velocity); this.acceleration.mult(0); }
edges() { if (this.position.y >= height - 10) { this.position.y = height - 10; this.velocity.y *= -0.5; } if (this.position.x <= 0) { this.position.x = 0; this.velocity.x *= -0.5; } if (this.position.x >= width) { this.position.x = width; this.velocity.x *= -0.5; } if (this.position.y <= 0) { this.position.y = 0; this.velocity.y *= -0.5; }
}
display() { fill(0); ellipse(this.position.x, this.position.y, this.mass * 10, this.mass * 10); }}
class Liquid { constructor(x, y, w, h, c) { this.x = x; this.y = y; this.w = w; this.h = h; this.c = c; }
contains(m) { return m.position.y > this.y; }
drag(m) { let speed = m.velocity.mag(); let dragMagnitude = this.c * speed * speed; let dragForce = m.velocity.copy().mult(-1).normalize().mult(dragMagnitude); return dragForce; }
show() { fill(0, 0, 255, 100); noStroke(); rect(this.x, this.y, this.w, this.h); }}
class Attractor { constructor(x, y, m) { this.position = createVector(x, y); this.mass = m; }
attract(m) { let force = p5.Vector.sub(this.position, m.position); let distance = force.mag();
// Evitar una distancia muy pequeña para evitar una fuerza infinita distance = constrain(distance, 5, 25);
let strength = (0.4 * this.mass * m.mass) / (distance * distance); force.setMag(strength); return force; }
display() { fill(255, 0, 0); ellipse(this.position.x, this.position.y, this.mass * 2); }}
Explicación de la aplicación de fuerzas
1. Gravedad: se modeló como una fuerza constante dirigida hacia abajo. Su magnitud es proporcional a la masa del objeto, siguiendo la ecuación: Fg= m*g y asegurando que el objeto experimente una aceleración hacia abajo proporcional a su masa.
En el código, esto se representa mediante un vector de fuerza aplicado en cada iteración del ciclo draw():
let gravity = createVector(0, 0.2 * mover.mass);mover.applyForce(gravity);
2. Fricción: se modeló como una fuerza opuesta a la dirección del movimiento. Su magnitud depende de la fuerza normal y el coeficiente de fricción: Fr= μ * N, en este caso la fuerza normal es el peso del objeto, por lo que se aproxima a N= m * g
calculateFriction(mu) { let friction = this.velocity.copy(); friction.normalize(); friction.mult(-1); let normalForce = this.mass * 0.2; friction.setMag(mu * normalForce); return friction;}
Se asegura que la fricción tenga la dirección opuesta a la velocidad del objeto y se aplique solo si el objeto se está moviendo.
3.1 Resistencia del aire: se consideró que su magnitud depende del cuadrado de la velocidad del objeto-> Fa= c * v^2
calculateFriction(mu) { let friction = this.velocity.copy(); friction.normalize(); friction.mult(-1); let normalForce = this.mass * 0.2; friction.setMag(mu * normalForce); return friction;}
Se normaliza la dirección de la velocidad para invertirla y se ajusta la magnitud de la fuerza en función del coeficiente c y el cuadrado de la velocidad.
3.2 Resistencia de fluidos: Esta fuerza actúa solo cuando el objeto está dentro de un área de fluido y se basa en la misma fórmula que la resistencia del aire—> F = c * v^2. Se verifica si el objeto está dentro del fluido y luego se aplica la fuerza de arrastre
El código verifica si el objeto está dentro del fluido y luego aplica la fuerza de arrastre:
if (liquid.contains(mover)) { let fluidResistance = liquid.drag(mover); mover.applyForce(fluidResistance);}
Luego se calcula la fuerza dentro de la función drag ()
drag(m) { let speed = m.velocity.mag(); let dragMagnitude = this.c * speed * speed; let dragForce = m.velocity.copy().mult(-1).normalize().mult(dragMagnitude); return dragForce;}
4. Atracción gravitacional: para modelar la atracción gravitacional entre el objeto y un punto específico (Attractor), se usó la ecuación de la ley de gravitación universal de Newton. Se evita que la distancia sea demasiado pequeña para prevenir fuerzas excesivamente grandes.
La dirección de la fuerza apunta hacia el attractor, creando una atracción que se activa cuando se presiona el mouse.
attract(m) { let force = p5.Vector.sub(this.position, m.position); let distance = force.mag(); distance = constrain(distance, 5, 25); let strength = (0.4 * this.mass * m.mass) / (distance * distance); force.setMag(strength); return force;}
Actividad 11
El problema de los n-cuerpos
Enunciado: vas a diseñar una simulación interactiva, en la que se muestre el problema de los n-cuerpos. En el texto guía tienes una sección que te puede ayudar a entender cómo modelar este problema, pero la idea es que uses tu creatividad para crear algo diferente basado en ese concepto. ¿Qué tal si te inspiras en las esculturas cinéticas de Alexander Calder?
Entrega:
- El código de tu simulación
- Un texto donde expliques cómo modelaste el problema de los n-cuerpos.
- No olvides incluir un enlace a tu simulación en el editor de p5.js.
- Adicionalmente, captura una imagen del resultado.
🚀 Tu solución:
Simulación del problema de los n-cuerpos
Enlace a la simulación aquí
let bodies = [];const G = 1;const numBodies = 10;
function setup() { createCanvas(600, 600); for (let i = 0; i < numBodies; i++) { let x = randomGaussian(width / 2, width / 6); let y = randomGaussian(height / 2, height / 6); let mass = abs(randomGaussian(10, 5)); let vx = randomGaussian(0, 1); let vy = randomGaussian(0, 1); bodies.push(new Body(x, y, vx, vy, mass)); }}
function draw() { background(220); for (let body of bodies) { body.update(bodies); body.display(); }}
class Body { constructor(x, y, vx, vy, mass) { this.position = createVector(x, y); this.velocity = createVector(vx, vy); this.acceleration = createVector(0, 0); this.mass = mass;
// Aplicamos distribución normal para el color this.color = color( randomGaussian(50, 50), // Rojo (media 50, desviación estándar 50) randomGaussian(100, 50), // Verde (media 100, desviación estándar 50) randomGaussian(200, 50) // Azul (media 200, desviación estándar 50) ); this.color = constrainColor(this.color); // Aseguramos que los valores de color estén dentro de los límites }
applyForce(force) { let f = p5.Vector.div(force, this.mass); this.acceleration.add(f); }
update(bodies) { for (let other of bodies) { if (other !== this) { let force = this.calculateAttraction(other); this.applyForce(force); } }
this.velocity.add(this.acceleration); this.position.add(this.velocity); this.acceleration.mult(0);
// Rebotar las partículas en los bordes del canvas this.checkEdges(); }
calculateAttraction(other) { let force = p5.Vector.sub(other.position, this.position); let distance = constrain(force.mag(), 5, 50); let strength = (G * this.mass * other.mass) / (distance * distance); force.setMag(strength); return force; }
checkEdges() { // Rebotar al llegar a los bordes del canvas if (this.position.x < 0 || this.position.x > width) { this.velocity.x *= -1; } if (this.position.y < 0 || this.position.y > height) { this.velocity.y *= -1; } }
display() { fill(this.color); noStroke(); ellipse(this.position.x, this.position.y, this.mass * 2); }}
// Función para garantizar que los valores del color estén dentro del rango válido [0, 255]function constrainColor(c) { return color( constrain(red(c), 0, 255), constrain(green(c), 0, 255), constrain(blue(c), 0, 255) );}
- El problema de los n-cuerpos trata sobre cómo varios cuerpos interactúan entre sí debido a la gravedad. En el código, este problema se modela mediante partículas que se atraen gravitacionalmente. Cada partícula tiene propiedades como posición, velocidad, masa y aceleración. La fuerza gravitacional entre dos partículas se calcula usando la ley de gravitación de Newton, que depende de sus masas y la distancia entre ellas. En cada ciclo de la simulación, se calculan las fuerzas gravitacionales entre todas las partículas. Estas fuerzas actualizan la aceleración, velocidad y posición de cada partícula, lo que hace que se muevan en el espacio. Además, se simula el rebote de las partículas en los bordes del lienzo, evitando que se salgan de la pantalla. Este modelo simplificado simula cómo las partículas interactúan y se mueven bajo la gravedad, ofreciendo una versión básica del problema de los n-cuerpos en 2D.
Consolidación y metacognición
En esta fase final, reflexionarás sobre el proceso de aprendizaje y consolidarás los conocimientos adquiridos.
Actividad 12
Análisis de resultados
Enunciado: revisa los resultados de las actividades de la fase APPLY. ¿Qué desafíos encontraste al aplicar los conceptos aprendidos? ¿Qué aprendiste de estos desafíos?
Entrega: descripción de los desafíos encontrados y las lecciones aprendidas durante la fase APPLY. No olvides incluir ejemplos concretos de tu experiencia.
🚀 Tu solución:
Desafíos encontrados y lecciones aprendidad
- Durante la primera actividad, en la que modelé tres fuerzas, el proceso fue un poco más largo y tradado porque ya estaba aplicando las fórmulas y principios básicos a un ejemplo múltiple.
- Para la segunda actividad pude hacerlo más rápido pero fue más complejo por la cantidad de partículas con las que tuve que trabajar, sin embargo, apliqué la ley de gravitación de Newton y pude cear un borrador muy básico de la simulación de las partículas.
- En la actividad de exploración de fuerzas quise hacer un solo código que integrara todas las simulaciones y eso me permitió compararlas pero también fue complejo integrar la parte de fluidos porque tocó ubicar una capa que actuara como un shader para que se aplicara la fuerza.
Actividad 13
Conexión con Diseño de Entretenimiento Digital
Enunciado: describe cómo los conceptos de esta unidad pueden ser utilizados en el diseño de videojuegos, experiencias interactivas o animaciones. Da ejemplos concretos.
Entrega: descripción de al menos tres aplicaciones de los conceptos aprendidos en el diseño de entretenimiento digital, con ejemplos concretos.
🚀 Tu solución:
Aplicaciones de fuerzas en simulaciones para Ingeniería en Diseño de Entretenimiento Digital
-
DISEÑO DE VIDEOJUEGOS
- Fricción y resistencia del aire/fluidos: se puede usar la fricción para controlar el movimiento de personajes o vehículos en un entorno, como en un juego de carreras donde los coches disminuyen su velocidad al frenar. La resistencia del aire puede ser crucial para simular el vuelo de aviones o proyectiles en juegos de acción o simulación.
- Atracción gravitacional: es muy común en juegos de simulación espacial, donde puedes usar la ley de la gravedad para crear órbitas realistas o colisiones entre asteroides y planetas. También se puede aplicar en juegos de plataformas con gravedad que afecte a los personajes y objetos en el mundo del juego.
- Problema de los n cuerpos: este modelo es muy útil en simulaciones de sistemas estelares o juegos de simulación espacial. Se puede aplicar para crear entornos donde varios cuerpos celestes interactúan entre sí, afectando el movimiento de naves, planetas o asteroides.
-
DISEÑO DE EXPERIENCIAS INTERACTIVAS
- Fricción y resistencia del aire: en una experiencia interactiva, la fricción y la resistencia pueden afectar cómo los usuarios interactúan con el entorno. Por ejemplo, si están moviendo objetos virtuales, puedes hacer que la experiencia se sienta más dinámica y responsiva, dependiendo de las condiciones del entorno.
- Gravedad: se pueden aplicar diferentes fuerzas gravitacionales según el espacio en el que se encuentre el usuario. Por ejemplo, si el usuario está en una simulación de otro planeta, la gravedad puede ser diferente y eso afectará cómo interactúa con los objetos.
- Problema de los n cuerpos: esta simulación se puede usar para crear sistemas interactivos complejos, como simulaciones científicas, donde los usuarios puedan observar y manipular múltiples cuerpos que interactúan entre sí.
-
ANIMACIONES
- Fricción: en animación, la fricción puede usarse para darle un toque de realismo al movimiento de objetos, como cuando una pelota rueda y eventualmente se detiene debido a la resistencia al movimiento. Esta animación puede hacerse gradual, ajustando la velocidad con cada fotograma.
- Resistencia del aire: si se anima algo como una caída libre, la resistencia del aire será importante para suavizar la aceleración de un objeto que cae, dándole un movimiento más realista que no sea simplemente un “caer en línea recta”.
- Gravedad: la animación de cuerpos cayendo, saltando o flotando puede beneficiarse de la gravedad. Además, se puede experimentar con la gravedad en planetas con diferentes fuerzas gravitacionales para crear efectos visuales interesantes.
Actividad 14
Reflexión sobre el proceso de aprendizaje
Enunciado: reflexiona sobre tu propio proceso de aprendizaje durante esta unidad. ¿Qué estrategias te resultaron más efectivas para comprender los conceptos? ¿Qué podrías mejorar en futuras unidades?
Entrega:
- Descripción de las estrategias de aprendizaje utilizadas y su efectividad. No olvides mencionar de manera explícita en qué punto del proceso aplicaste estas estrategias, ilustrando con ejemplos concretos de tu trabajo en la unidad.
- Planteamiento de mejoras para futuras unidades.
🚀 Tu solución:
Estrategias de aprendizaje
- Comprender la aplicación de la fuerza en la vida real antes de visualizarla en el código: desde que inició la unidad fui muy consciente de la importancia de comprender con exactitud cómo funciona la fuerza en la vida real y ya después aplicarla en el código. Fue muy útil en la actividad 10 en la que tuve que modelar tres fuerzas para poder relacionar lo que he experimentado en la vida real con lo que sucedía en el código.
- Regresar a los conceptos que he aprendido en las unidades anteriores para integrarlos con los que estoy aprendiendo: en la actividad 11 con el ejercicio de los n cuerpos pude aplicar distribuciones gaussianas y el movimiento de Lévy para darle más dinamismo y vida a mi simulación.
- Esta unidad me pareció que estaba muy bien organizada porque el paso de una actividad a otra me parecía natural y por ejemplo en la actividad 9 definimos los pasos a seguir para realizar la simulación de una fuerza y ya simplemente siguiéndolos logramos completar la actividad 10 que aunque era extensa me permitió aplicar todo lo anterior, finalmente, en el problema de los n cuerpos pude experimentar su aplicación con lo que creía que funcionaría e incluso pude agregar conceptos de unidades anteriores para refrescar mi memoria.
Actividad 15
Autoevaluación
Enunciado: evalúa tu nivel de comprensión de los conceptos de la unidad en una escala del 1 al 5 (1: Nada de comprensión, 5: Dominio completo). Justifica tu autoevaluación con ejemplos concretos de tu trabajo en la unidad. Identifica áreas donde necesitas reforzar tu aprendizaje.
Entrega:
- Autoevaluación con justificación y ejemplos concretos de tu trabajo que sustenten.
- Identificación de áreas de mejora.
🚀 Tu solución:
Autoevaluación sobre comprensión de conceptos
- Leyes de Newton y el arte generativo—> 5—Son temas que no son nuevos en cuanto a las ecuaciones, volver a leer sobre ellos refrescó mi memoria para poder modelarlo en código.
- Acumulación de la fuerza neta—> 5—EDl orden de los cálculos importan por lo que es necesario asegurar que los objetos responden correctamente a las fuerzas de cada frame.
- Paso por valor y paso por referencia—> 5---Aprender a diferencia la manera en la que le enviamos el valor de otra variable a una nueva y el cómo se puede afectar el original es súper importante y me pareció el tema más divertido porque la solución a muchos problemas es simplementee crear copias de los vectores para manipularlos libremente.
- Modelamiento de fuerzas para simulaciones—> 4---Realicé el modelamiento de estas fuerzas pero de manera muy sencilla y me gustaría pulir un poco más las simulaciones en diferentes contextos.
- El problema de los n-cuerpos—> 4----Me pareció muy divertido aplicar el problema y ver la interacción entre partículas pero al igual que con el tema anterior, quisiera explorar más el concepto en ejemplos más realistas como la interacción de planetas pero ya eso será un proyecto más grande a futuro.
Areas de mejora identificadas
- Mi gran talón de Aquiles siempre será la implementación en código de las ideas y conceptos pero gracias a las nuevas herramientas de IA he podido dejar de lado estas barreras.