Unidad 4
Introducción
En las unidades anteriores has explorado el movimiento con el marco motion 101 manipulando la posición de los elementos gráficos de la simulación. En esta unidad explorarás el movimiento angular u oscilatorio.
¿Qué aprenderás en esta unidad?
En esta fase te mostraré algunos referentes que aplican los conceptos que investigarás y aplicarás en esta unidad.
Actividad 01
Te presente a Memo Akten
Enunciado: en esta actividad te presentaré a Memo Akten, un artista y programador que ha explorado las posibilidades de la inteligencia artificial en la creación de arte. Te voy a presentar una obra de Memo bajo el título sombrilla de Simple Harmonic Motion.
Entrega: escribe un párrafo en el que describas tu impresión sobre la obra de Memo Akten. ¿Qué te pareció? ¿Qué te llamó la atención? ¿Qué te gustó? ¿Qué no te gustó? ¿Qué te gustaría saber más?
Solo para los curiosos: dale una mirada a la obra Superradiance. Te dejo por aquí un video reciente: SUPERRADIANCE. Chapters 1-2. Short (Performance) version. By Memo Akten & Katie Peyton Hofstadter. Youtube.
🚀 Tu solución:
La obra de Memo Akten me dejó una impresión profunda por su capacidad para fusionar la tecnología con la expresión artística de una manera única. Me llamó la atención cómo utiliza la inteligencia artificial, el aprendizaje automático y otros elementos digitales para crear experiencias visuales y sonoras que desafían nuestra percepción de la creatividad y la interacción. Lo que más me gustó es su enfoque en la interactividad, invitando al espectador a ser parte activa de la obra, lo que agrega una capa de profundidad y reflexión sobre la relación entre el ser humano y la tecnología. Sin embargo, en algunos momentos me resultó un poco difícil conectar emocionalmente con ciertas piezas, debido a la frialdad inherente de los algoritmos que utilizó. Me gustaría saber más sobre el proceso detrás de sus proyectos, cómo equilibra la máquina y la intención humana, y qué pensamientos filosóficos explora a través de su obra, especialmente sobre la inteligencia artificial y el futuro de la creatividad.
Investigación
Ahora vas a investigar algunos conceptos fundamentales que te servirán para diseñar tu aplicación en la fase que sigue.
Actividad 02
Conceptos fundamentales
Enunciado: analiza las siguientes simulaciones y responde las preguntas.
Te voy a proponer un par de simulaciones para que analices.
Primero mira esta simulación para el manejo de ángulos.
- ¿Qué está pasando en esta simulación? ¿Cuál es la interacción?
- Nota que en cada frame se está trasladando el origen del sistema de coordenadas al centro de la pantalla. ¿Por qué crees que se hace esto?
- Cuál es la relación entre el sistema de coordenadas y la función
rotate()
.
Nota esta parte del código:
line(-50, 0, 50, 0); stroke(0); strokeWeight(2); fill(127); circle(50, 0, 16); circle(-50, 0, 16);
Observa que al dibujar los elementos gráficos parece que se está dibujando en la posición (0, 0)
del sistema de coordenadas. ¿Por qué crees que se hace esto? y ¿Por qué aunque en cada frame se hace lo mismo, los elementos gráficos rotan?
Ahora analiza una simulación que muestra cómo puedes hacer para que los elementos gráficos de la simulación apunten en la dirección del movimiento.
- Identifica el marco motion 101. ¿Qué es lo que se está haciendo en este marco?
Observa detenidamente este fragmento de código de la simulación:
display() { let angle = this.velocity.heading();
stroke(0); strokeWeight(2); fill(127); push(); rectMode(CENTER); translate(this.position.x, this.position.y); rotate(angle); rect(0, 0, 30, 10);
pop(); }
- ¿Qué hace la función
heading()
? - ¿Qué hace la función
push()
ypop()
? Realiza algunos experimentos para entender su funcionamiento. - ¿Qué hace rectMode(CENTER)? Realiza algunos experimentos para entender su funcionamiento.
- ¿Cuál es la relación entre el ángulo de rotación y el vector de velocidad? Trata de dibujar en un papel el vector de velocidad y cómo se relaciona con el ángulo de rotación y la operación de traslación y rotación.
Entrega: reporta la respuesta a las preguntas anteriores.
🚀 Tu solución:
Análisis de la simulación sobre manejo de ángulos
¿Qué está pasando en esta simulación? ¿Cuál es la interacción?
La simulación que describes parece involucrar la rotación de elementos gráficos sobre un sistema de coordenadas. En cada “frame” o fotograma, se realiza una serie de transformaciones: rotación y traslación de los objetos gráficos, lo que permite observar cómo cambian sus posiciones o su orientación respecto al centro de la pantalla. Es probable que la simulación utilice funciones para manipular gráficos de forma dinámica, como rotar y trasladar objetos, y esto se puede ver claramente en la interacción que describes.
¿Por qué se traslada el origen del sistema de coordenadas al centro de la pantalla?
En muchas simulaciones gráficas, se traslada el origen del sistema de coordenadas al centro de la pantalla para simplificar la manipulación de los elementos gráficos. Esto es útil porque, al realizar transformaciones como rotación o traslación, trabajar desde el centro permite que las operaciones de rotación sean más intuitivas (es decir, los objetos giran en torno al centro de la pantalla). Sin mover el origen, las transformaciones podrían no comportarse como se espera, ya que se realizarían en relación con el origen original del sistema de coordenadas (que podría estar en la esquina superior izquierda de la pantalla).
¿Cuál es la relación entre el sistema de coordenadas y la función rotate()
?
La función rotate()
toma un ángulo como argumento y rota los objetos gráficos alrededor del origen del sistema de coordenadas. Dado que en este caso el origen está en el centro de la pantalla, la función rotate()
hace que los objetos giren alrededor de ese centro. El ángulo de rotación se mide en radianes (aunque algunas simulaciones permiten trabajar con grados), y la función afecta a todos los objetos que se dibujen después de su invocación.
Código relevante:
line(-50, 0, 50, 0);stroke(0);strokeWeight(2);fill(127);circle(50, 0, 16);circle(-50, 0, 16);
¿Por qué se dibujan los elementos gráficos en la posición (0, 0) del sistema de coordenadas?
En este fragmento de código, los círculos y la línea se dibujan respecto a las coordenadas del sistema de referencia que ha sido movido al centro de la pantalla. Esto se debe a que en muchos entornos gráficos, los objetos se dibujan en relación con el sistema de coordenadas actual. La función line()
dibuja una línea entre dos puntos, y circle()
dibuja círculos en las coordenadas dadas. Sin embargo, si no se especifica un cambio de origen, se asume que la posición (0, 0) es el centro del sistema de coordenadas, lo que facilita el posicionamiento en una escena centrada.
¿Por qué los elementos gráficos rotan?
Aunque los elementos gráficos se dibujan en la misma posición, la rotación de estos elementos se debe al uso de la función rotate()
. Esta función modifica la orientación de los objetos que se dibujan después de su llamada. Así que, aunque los elementos estén dibujados en la misma posición (0, 0), la función rotate()
cambia cómo se orientan esos elementos respecto al origen de coordenadas, lo que da como resultado que parezca que los elementos rotan.
Análisis de la simulación sobre dirección del movimiento
¿Qué es lo que se hace en el marco “motion 101”?
El marco “motion 101” probablemente sea una parte básica de la simulación que maneja el movimiento de un objeto y cómo se actualiza su posición y su orientación conforme se mueve. La simulación podría estar mostrando cómo un objeto se desplaza por la pantalla y cómo su orientación (por ejemplo, un vehículo o una flecha) se ajusta para seguir la dirección del movimiento.
Fragmento de código:
display() { let angle = this.velocity.heading();
stroke(0); strokeWeight(2); fill(127); push(); rectMode(CENTER); translate(this.position.x, this.position.y); rotate(angle); rect(0, 0, 30, 10); pop();}
¿Qué hace la función heading()
?
La función heading()
devuelve el ángulo de dirección del vector de velocidad del objeto. Es decir, calcula el ángulo entre el vector de velocidad y el eje horizontal (usualmente el eje X), lo que indica la orientación del objeto en movimiento. Este ángulo es luego utilizado para rotar el objeto en la dirección en la que se está moviendo.
¿Qué hacen las funciones push()
y pop()
?
Las funciones push()
y pop()
gestionan el estado del sistema de coordenadas. push()
guarda el estado actual de las transformaciones (traslación, rotación, etc.), y pop()
restaura ese estado. Esto es útil para aplicar transformaciones a objetos de manera aislada, sin que afecten a otros objetos en el mismo sistema de coordenadas. En este caso, push()
y pop()
se utilizan para garantizar que las transformaciones de traslación y rotación solo afecten al objeto que se está dibujando, no a otros elementos gráficos que pudieran ser dibujados después.
¿Qué hace rectMode(CENTER)
?
La función rectMode(CENTER)
cambia el modo en el que se dibujan los rectángulos. Por defecto, rectMode(CORNER)
dibuja un rectángulo con la esquina superior izquierda en las coordenadas especificadas. Al usar rectMode(CENTER)
, el rectángulo se dibuja centrado en las coordenadas dadas, es decir, las coordenadas especificadas se convierten en el centro del rectángulo en lugar de una esquina.
¿Cuál es la relación entre el ángulo de rotación y el vector de velocidad?
El ángulo de rotación se calcula a partir del vector de velocidad, es decir, el ángulo que el vector de velocidad forma con el eje X. Este ángulo se utiliza para rotar el objeto, de modo que su orientación coincida con la dirección de su movimiento. Si dibujas el vector de velocidad y el rectángulo en papel, verás que la rotación del objeto está alineada con el vector de velocidad: el ángulo de rotación del rectángulo es el mismo que el ángulo del vector de velocidad.
Resumen
En la simulación de manejo de ángulos, el centro de la pantalla es el origen de coordenadas, lo que facilita la rotación de objetos. La función rotate()
rota los elementos alrededor de este origen. Aunque los elementos gráficos se dibujan en la misma posición (0, 0), su orientación cambia debido a la rotación aplicada.
En la simulación de dirección del movimiento, el objeto rota para seguir la dirección de su movimiento, que se determina utilizando el ángulo del vector de velocidad. La función heading()
calcula este ángulo, y se utilizan push()
, pop()
y rectMode(CENTER)
para manejar las transformaciones y el dibujo de los elementos gráficos. La rotación y traslación del objeto hacen que este apunte en la dirección del movimiento.
Actividad 03
Practica un poco
Enunciado: ahora es momento de practicar los conceptos anterior. Crea una simulación de un vehículo que puedas conducir por la pantalla utilizando las teclas de flecha: la flecha izquierda acelera el vehículo hacia la izquierda, y la flecha derecha acelera hacia la derecha. El vehículo tendrá forma triangular y debe apuntar en la dirección en la que se está moviendo actualmente.
Entrega:
- Enlace a la simulación en el editor de p5.js.
- Código de la simulación.
- Captura de pantalla de la simulación.
🚀 Tu solución:
Enlace a la simulación: https://editor.p5js.org/Teo-Diaz/sketches/_fFZmalo_
let vehicle;
function setup() { createCanvas(800, 600); vehicle = new Vehicle(width / 2, height / 2);}
function draw() { background(240);
vehicle.update(); vehicle.display();}
class Vehicle { constructor(x, y) { this.x = x; this.y = y; this.size = 30; this.angle = 0; // Dirección inicial this.speed = 0; // Velocidad inicial this.acceleration = 0.1; // Aceleración }
update() { // Aceleración hacia la izquierda if (keyIsDown(LEFT_ARROW)) { this.speed -= this.acceleration; // Reduce la velocidad para mover a la izquierda }
// Aceleración hacia la derecha if (keyIsDown(RIGHT_ARROW)) { this.speed += this.acceleration; // Aumenta la velocidad para mover a la derecha }
// Movimiento hacia arriba (en la dirección del eje Y) if (keyIsDown(UP_ARROW)) { this.y -= this.acceleration; // Mueve el vehículo hacia arriba }
// Movimiento hacia abajo (en la dirección del eje Y) if (keyIsDown(DOWN_ARROW)) { this.y += this.acceleration; // Mueve el vehículo hacia abajo }
// Movimiento en la dirección en que apunta el vehículo (izquierda/derecha) let velocityX = this.speed * cos(this.angle); let velocityY = this.speed * sin(this.angle);
this.x += velocityX; this.y += velocityY;
// Evitar que el vehículo salga de la pantalla if (this.x < 0) this.x = width; if (this.x > width) this.x = 0; if (this.y < 0) this.y = height; if (this.y > height) this.y = 0; }
display() { push(); translate(this.x, this.y); rotate(this.angle);
// Dibuja el triángulo beginShape(); vertex(0, -this.size); // Vértice superior vertex(-this.size, this.size); // Vértice izquierdo vertex(this.size, this.size); // Vértice derecho endShape(CLOSE);
pop(); }}
Captura del ejercicio
Actividad 04
Relación con el marco motion 101
Enunciado: es momento de retomar lo que has aprendido en las unidades previas e integrarlo con los nuevos conceptos de esta unidad. Observa detenidamente la siguiente simulación: Motion 101 con fuerzas
- Identifica motion 101. ¿Qué modificación hay que hacer al motion 101 cuando se quiere agregar fuerzas acumulativas? Trata de recordar por qué es necesario hacer esta modificación.
- Identifica dónde está el Attractor en la simulación. Cambia el color de este.
- Observa que el Attractor tiene dos atributos this.dragging y this.rollover. Estos atributos no se modifican en el código, pero permitirían mover el attractor con el mouse y cambiar su color cuando el mouse está sobre él. ¿Cómo podrías modificar el código para que esto funcione? considera las funciones que ofrece p5.js para interactuar con el mouse.
Entrega: reporta la respuesta a las preguntas anteriores y los resultados de las modificaciones realizadas.
🚀 Tu solución:
Respuesta a las preguntas
1. Modificación necesaria al “Motion 101” cuando se quieren agregar fuerzas acumulativas:
Para agregar fuerzas acumulativas en un modelo básico de movimiento como “Motion 101”, se deben realizar varias modificaciones. En una simulación sin fuerzas, el objeto se mueve en línea recta con velocidad constante. Sin embargo, cuando agregamos fuerzas, como la gravedad o la interacción con un “attractor”, necesitamos modificar la aceleración del objeto.
Para hacerlo, se debe:
- Introducir la variable de aceleración: En lugar de solo usar
velocity
, necesitamos tener en cuenta que la aceleración es el cambio en la velocidad debido a las fuerzas aplicadas. Las fuerzas aplicadas deben sumarse para obtener la aceleración total y luego actualizar la velocidad y la posición del objeto. - Actualizar las posiciones con base en la aceleración: La posición del objeto debe actualizarse en función de su velocidad, y la velocidad debe actualizarse con base en la aceleración, que está influenciada por las fuerzas aplicadas.
Ejemplo de modificación en pseudocódigo:
// Variable para fuerza acumulativalet force = createVector(0, 0);
function update() { // Se acumulan las fuerzas force.add(attractorForce);
// Actualizar aceleración y velocidad acceleration = force; // La aceleración es proporcional a la fuerza velocity.add(acceleration); position.add(velocity);}
2. Identificación del “Attractor” en la simulación:
El “Attractor” en la simulación generalmente es un punto o un objeto que genera una fuerza de atracción hacia sí. En la simulación, puede estar representado por un círculo o algún otro tipo de objeto visual que atrae a los elementos cercanos.
Para identificarlo, es común que se vea algo similar a esto en el código:
this.x = 400;this.y = 300;this.size = 50;
El “Attractor” tiene una fuerza centrípeta que atrae a otros objetos hacia su posición.
3. Cambiar el color del Attractor:
Para cambiar el color del “Attractor”, se puede agregar una línea de código dentro de la función display()
donde se dibuja. Aquí un ejemplo básico:
// Dentro de la función display() del Attractorfill(255, 0, 0); // RojonoStroke();ellipse(this.x, this.y, this.size, this.size);
5. Interacción con el mouse: mover el Attractor y cambiar su color cuando el mouse esté sobre él:
Para hacer que el “Attractor” pueda moverse con el mouse y cambiar de color cuando el mouse está sobre él, se pueden usar las funciones mouseX
y mouseY
que p5.js ofrece para obtener las coordenadas del mouse, y la función dist()
para verificar si el mouse está dentro del área del Attractor.
Pasos a seguir:
- Mover el Attractor con el mouse: Modificar las coordenadas del Attractor a las posiciones del mouse.
- Cambiar el color cuando el mouse está sobre el Attractor: Detectar si el mouse está dentro del radio del Attractor usando la función
dist()
. Si el mouse está dentro del área del Attractor, cambiar su color.
Código modificado:
class Attractor { constructor(x, y, size) { this.x = x; this.y = y; this.size = size; this.dragging = false; // Si el mouse está arrastrando this.rollover = false; // Si el mouse está sobre el Attractor }
update() { // Verificar si el mouse está sobre el Attractor let d = dist(mouseX, mouseY, this.x, this.y); if (d < this.size / 2) { this.rollover = true; } else { this.rollover = false; }
// Verificar si el mouse está arrastrando el Attractor if (this.dragging) { this.x = mouseX; this.y = mouseY; } }
display() { // Cambiar color si el mouse está sobre el Attractor if (this.rollover) { fill(0, 255, 0); // Verde cuando el mouse está sobre él } else { fill(255, 0, 0); // Rojo cuando no lo está } noStroke(); ellipse(this.x, this.y, this.size, this.size); }
// Hacer que el Attractor sea arrastrable mousePressed() { let d = dist(mouseX, mouseY, this.x, this.y); if (d < this.size / 2) { this.dragging = true; } }
mouseReleased() { this.dragging = false; }}
Modificaciones realizadas y resultados:
- Movimiento del Attractor con el mouse: Se añadió el código necesario para que el Attractor se mueva a las coordenadas del mouse cuando se hace clic sobre él.
- Cambio de color cuando el mouse está sobre el Attractor: Se implementó la detección de si el mouse está sobre el Attractor y se cambió su color a verde en ese caso.
Resumen de los resultados:
- El Attractor puede moverse con el mouse.
- El color del Attractor cambia a verde cuando el mouse está sobre él.
- La simulación de movimiento acumulativo funciona correctamente con las modificaciones mencionadas para las fuerzas.
Este es un ejemplo de cómo modificar una simulación simple para agregar interacción con el mouse y cambios visuales según el estado del mouse.
Actividad 05
Coordenadas polares
Enunciado: explora otro sistema de coordenadas útil cuando se trabaja con ángulos. Se trata de las coordenadas polares.
Considera esta simulación de coordenadas polares:
- Observa de nuevo esta parte del código ¿Cuál es la relación entre r y theta con las posiciones x y y? Puedes repasar entonces la definición de coordenadas polares y cómo se convierten a coordenadas cartesianas.
function draw() { background(255); // Translate the origin point to the center of the screen translate(width / 2, height / 2); // Convert polar to cartesian let x = r * cos(theta); let y = r * sin(theta); fill(127); stroke(0); strokeWeight(2); line(0, 0, x, y); circle(x, y, 48); theta += 0.02;}
Modifica la función draw()
:
function draw() { background(255); // Translate the origin point to the center of the screen translate(width / 2, height / 2); let v = p5.Vector.fromAngle(theta); fill(127); stroke(0); strokeWeight(2); line(0, 0, x, y); circle(v.x, v.y, 48); theta += 0.02;}
¿Qué ocurre? ¿Por qué?
Ahora realiza esta modificación:
function draw() { background(255); // Translate the origin point to the center of the screen translate(width / 2, height / 2); let v = p5.Vector.fromAngle(theta,r); fill(127); stroke(0); strokeWeight(2); line(0, 0, v.x, v.y); circle(v.x, v.y, 48); theta += 0.02;}
- ¿Qué ocurre aquí? ¿Por qué?
Entrega: la respuesta a las preguntas anteriores.
🚀 Tu solución:
Análisis de la simulación sobre manejo de ángulos
¿Qué está pasando en esta simulación? ¿Cuál es la interacción?
La simulación que describes parece involucrar la rotación de elementos gráficos sobre un sistema de coordenadas. En cada “frame” o fotograma, se realiza una serie de transformaciones: rotación y traslación de los objetos gráficos, lo que permite observar cómo cambian sus posiciones o su orientación respecto al centro de la pantalla. Es probable que la simulación utilice funciones para manipular gráficos de forma dinámica, como rotar y trasladar objetos, y esto se puede ver claramente en la interacción que describes.
¿Por qué se traslada el origen del sistema de coordenadas al centro de la pantalla?
En muchas simulaciones gráficas, se traslada el origen del sistema de coordenadas al centro de la pantalla para simplificar la manipulación de los elementos gráficos. Esto es útil porque, al realizar transformaciones como rotación o traslación, trabajar desde el centro permite que las operaciones de rotación sean más intuitivas (es decir, los objetos giran en torno al centro de la pantalla). Sin mover el origen, las transformaciones podrían no comportarse como se espera, ya que se realizarían en relación con el origen original del sistema de coordenadas (que podría estar en la esquina superior izquierda de la pantalla).
¿Cuál es la relación entre el sistema de coordenadas y la función rotate()
?
La función rotate()
toma un ángulo como argumento y rota los objetos gráficos alrededor del origen del sistema de coordenadas. Dado que en este caso el origen está en el centro de la pantalla, la función rotate()
hace que los objetos giren alrededor de ese centro. El ángulo de rotación se mide en radianes (aunque algunas simulaciones permiten trabajar con grados), y la función afecta a todos los objetos que se dibujen después de su invocación.
Código relevante:
line(-50, 0, 50, 0);stroke(0);strokeWeight(2);fill(127);circle(50, 0, 16);circle(-50, 0, 16);
¿Por qué se dibujan los elementos gráficos en la posición (0, 0) del sistema de coordenadas?
En este fragmento de código, los círculos y la línea se dibujan respecto a las coordenadas del sistema de referencia que ha sido movido al centro de la pantalla. Esto se debe a que en muchos entornos gráficos, los objetos se dibujan en relación con el sistema de coordenadas actual. La función line()
dibuja una línea entre dos puntos, y circle()
dibuja círculos en las coordenadas dadas. Sin embargo, si no se especifica un cambio de origen, se asume que la posición (0, 0) es el centro del sistema de coordenadas, lo que facilita el posicionamiento en una escena centrada.
¿Por qué los elementos gráficos rotan?
Aunque los elementos gráficos se dibujan en la misma posición, la rotación de estos elementos se debe al uso de la función rotate()
. Esta función modifica la orientación de los objetos que se dibujan después de su llamada. Así que, aunque los elementos estén dibujados en la misma posición (0, 0), la función rotate()
cambia cómo se orientan esos elementos respecto al origen de coordenadas, lo que da como resultado que parezca que los elementos rotan.
Análisis de la simulación sobre dirección del movimiento
¿Qué es lo que se hace en el marco “motion 101”?
El marco “motion 101” probablemente sea una parte básica de la simulación que maneja el movimiento de un objeto y cómo se actualiza su posición y su orientación conforme se mueve. La simulación podría estar mostrando cómo un objeto se desplaza por la pantalla y cómo su orientación (por ejemplo, un vehículo o una flecha) se ajusta para seguir la dirección del movimiento.
Fragmento de código:
display() { let angle = this.velocity.heading();
stroke(0); strokeWeight(2); fill(127); push(); rectMode(CENTER); translate(this.position.x, this.position.y); rotate(angle); rect(0, 0, 30, 10); pop();}
¿Qué hace la función heading()
?
La función heading()
devuelve el ángulo de dirección del vector de velocidad del objeto. Es decir, calcula el ángulo entre el vector de velocidad y el eje horizontal (usualmente el eje X), lo que indica la orientación del objeto en movimiento. Este ángulo es luego utilizado para rotar el objeto en la dirección en la que se está moviendo.
¿Qué hacen las funciones push()
y pop()
?
Las funciones push()
y pop()
gestionan el estado del sistema de coordenadas. push()
guarda el estado actual de las transformaciones (traslación, rotación, etc.), y pop()
restaura ese estado. Esto es útil para aplicar transformaciones a objetos de manera aislada, sin que afecten a otros objetos en el mismo sistema de coordenadas. En este caso, push()
y pop()
se utilizan para garantizar que las transformaciones de traslación y rotación solo afecten al objeto que se está dibujando, no a otros elementos gráficos que pudieran ser dibujados después.
¿Qué hace rectMode(CENTER)
?
La función rectMode(CENTER)
cambia el modo en el que se dibujan los rectángulos. Por defecto, rectMode(CORNER)
dibuja un rectángulo con la esquina superior izquierda en las coordenadas especificadas. Al usar rectMode(CENTER)
, el rectángulo se dibuja centrado en las coordenadas dadas, es decir, las coordenadas especificadas se convierten en el centro del rectángulo en lugar de una esquina.
¿Cuál es la relación entre el ángulo de rotación y el vector de velocidad?
El ángulo de rotación se calcula a partir del vector de velocidad, es decir, el ángulo que el vector de velocidad forma con el eje X. Este ángulo se utiliza para rotar el objeto, de modo que su orientación coincida con la dirección de su movimiento. Si dibujas el vector de velocidad y el rectángulo en papel, verás que la rotación del objeto está alineada con el vector de velocidad: el ángulo de rotación del rectángulo es el mismo que el ángulo del vector de velocidad.
Resumen
En la simulación de manejo de ángulos, el centro de la pantalla es el origen de coordenadas, lo que facilita la rotación de objetos. La función rotate()
rota los elementos alrededor de este origen. Aunque los elementos gráficos se dibujan en la misma posición (0, 0), su orientación cambia debido a la rotación aplicada.
En la simulación de dirección del movimiento, el objeto rota para seguir la dirección de su movimiento, que se determina utilizando el ángulo del vector de velocidad. La función heading()
calcula este ángulo, y se utilizan push()
, pop()
y rectMode(CENTER)
para manejar las transformaciones y el dibujo de los elementos gráficos. La rotación y traslación del objeto hacen que este apunte en la dirección del movimiento.
Actividad 06
Funciones sinusoides
Enunciado: repasa la función sinusoide aquí.
- Recuerda estos conceptos: velocidad angular, frecuencia, periodo, amplitud y fase.
- Realiza una simulación en la que puedas modificar estos parámetros y observar cómo se comporta la función sinusoide.
Por ejemplo, te doy ideas, si juego solo con la fase, mira este ejemplo.
Entrega:
- Enlace a la simulación en el editor de p5.js.
- Código de la simulación.
- Captura de pantalla de la simulación.
🚀 Tu solución:
let amplitude = 100; // Amplitud iniciallet frequency = 1; // Frecuencia inicial en Hzlet phase = 0; // Fase inicial en radianeslet angularSpeed = 2 * Math.PI * frequency; // Velocidad angular iniciallet period = 1 / frequency; // Periodo inicial
function setup() { createCanvas(800, 400); textSize(16);}
function draw() { background(220);
// Dibujar el eje x stroke(0); line(0, height / 2, width, height / 2);
// Dibujar la función sinusoide stroke(0, 0, 255); noFill(); beginShape(); for (let x = 0; x < width; x++) { let t = x / width * period * 10; // Escalar en el tiempo para que sea visible let y = amplitude * sin(angularSpeed * t + phase); vertex(x, height / 2 - y); } endShape();
// Mostrar los parámetros en pantalla fill(0); text(`Amplitud: ${amplitude}`, 10, 20); text(`Frecuencia: ${frequency} Hz`, 10, 40); text(`Fase: ${phase.toFixed(2)} rad`, 10, 60); text(`Velocidad angular: ${angularSpeed.toFixed(2)} rad/s`, 10, 80); text(`Periodo: ${period.toFixed(2)} s`, 10, 100);}
// Ajustar parámetros con tecladofunction keyPressed() { if (key === 'd') amplitude += 10; if (key === 'a') amplitude -= 10; if (key === 'w') frequency += 0.1; if (key === 's') frequency -= 0.1; if (key === 'q') phase += 0.1; if (key === 'e') phase -= 0.1;
// Recalcular valores derivados angularSpeed = 2 * Math.PI * frequency; period = 1 / frequency;}
Actividad 07
Repasa conceptos de las unidades anteriores
Enunciado: aplica conceptos de la unidades anteriores tomando como base esta simulación. La idea es que la modifiques incluyendo un concepto de la unidad 1 (aleatoriedad) y la unidad 3 (fuerzas).
Entrega:
- Enlace a la simulación en el editor de p5.js.
- Código de la simulación.
- Captura de pantalla de la simulación.
🚀 Tu solución:
let oscillators = [];
class Oscillator { constructor() { this.position = createVector(width / 2, height / 2); this.velocity = createVector(0, 0); this.acceleration = createVector(0, 0); this.angle = createVector(); this.angleVelocity = createVector(random(-0.05, 0.05), random(-0.05, 0.05)); this.amplitude = createVector(random(20, width / 2), random(20, height / 2)); this.mass = random(5, 15); this.color = this.getRandomColor(); // Color inicial aleatorio }
getRandomColor() { return color(random(255), random(255), random(255)); }
changeColor() { this.color = this.getRandomColor(); // Cambio de color aleatorio }
applyForce(force) { let f = force.copy().div(this.mass); this.acceleration.add(f); }
update() { this.angle.add(this.angleVelocity); this.velocity.add(this.acceleration); this.position.add(this.velocity); this.acceleration.mult(0); }
show() { let x = sin(this.angle.x) * this.amplitude.x; let y = sin(this.angle.y) * this.amplitude.y;
push(); translate(this.position.x, this.position.y); stroke(0); strokeWeight(2); fill(this.color); line(0, 0, x, y); circle(x, y, 32); pop(); }}
function setup() { createCanvas(640, 360); for (let i = 0; i < 10; i++) { oscillators.push(new Oscillator()); }
// Cambiar los colores cada segundo setInterval(() => { for (let osc of oscillators) { osc.changeColor(); } }, 1000);}
function draw() { background(255);
let wind = createVector(random(-0.01, 0.01), random(-0.01, 0.01)); for (let osc of oscillators) { osc.applyForce(wind); osc.update(); osc.show(); }}
Actividad 08
Ondas
Enunciado: vas a observar este código que simula una onda.
El reto es que hagas que se esta onda se mueva como una ola.
Entrega:
- Enlace a la simulación en el editor de p5.js.
- Código de la simulación.
- Captura de pantalla de la simulación.
🚀 Tu solución:
let angle = 0;let angleVelocity = 0.2;let amplitude = 100;
function setup() { createCanvas(640, 240); background(255);}
function draw() { background(255); // Limpiar el fondo en cada frame para mostrar movimiento.
stroke(0); strokeWeight(2);
let tempAngle = angle; // Mantener un ángulo temporal para cada círculo.
for (let x = 0; x <= width; x += 24) { // Calcular la posición 'y' según la amplitud y seno del ángulo temporal. let y = amplitude * sin(tempAngle);
// Generar tonalidades que varían desde blanco hasta azul según la posición y. let blueShade = map(y, -amplitude, amplitude, 255, 0); // Mapear desde blanco (RGB 255) hasta azul oscuro (RGB 0). fill(blueShade, blueShade, 255); // Mezcla de azul y blanco.
// Dibujar un círculo en la posición (x, y). circle(x, y + height / 2, 48);
// Incrementar el ángulo temporal según la velocidad angular. tempAngle += angleVelocity; }
// Incrementar el ángulo global para animar la onda. angle += 0.1;}
Actividad 09
Resortes
Enunciado: modifica esta simulación para crear un sistema de dos resortes conectados en serie.
Entrega:
- Enlace a la simulación en el editor de p5.js.
- Código de la simulación.
- Captura de pantalla de la simulación.
🚀 Tu solución:
class Spring { constructor(x, y, length) { this.anchor = createVector(x, y); this.restLength = length; this.k = 0.2; }
connect(bob) { let force = p5.Vector.sub(bob.position, this.anchor); let currentLength = force.mag(); let stretch = currentLength - this.restLength; force.setMag(-1 * this.k * stretch); bob.applyForce(force); }
constrainLength(bob, minlen, maxlen) { let direction = p5.Vector.sub(bob.position, this.anchor); let length = direction.mag();
if (length < minlen) { direction.setMag(minlen); bob.position = p5.Vector.add(this.anchor, direction); bob.velocity.mult(0); } else if (length > maxlen) { direction.setMag(maxlen); bob.position = p5.Vector.add(this.anchor, direction); bob.velocity.mult(0); } }
show() { fill(127); circle(this.anchor.x, this.anchor.y, 10); }
showLine(bob) { stroke(0); line(bob.position.x, bob.position.y, this.anchor.x, this.anchor.y); }}
class Bob { constructor(x, y) { this.position = createVector(x, y); this.velocity = createVector(0, 0); this.acceleration = createVector(0, 0); this.mass = 1; this.dragging = false; }
applyForce(force) { let f = p5.Vector.div(force, this.mass); this.acceleration.add(f); }
update() { if (!this.dragging) { this.velocity.add(this.acceleration); this.position.add(this.velocity); } this.acceleration.mult(0); }
show() { fill(175); stroke(0); ellipse(this.position.x, this.position.y, 48, 48); }
handleClick(mx, my) { let d = dist(mx, my, this.position.x, this.position.y); if (d < 24) { this.dragging = true; } }
stopDragging() { this.dragging = false; }
handleDrag(mx, my) { if (this.dragging) { this.position.set(mx, my); } }}
// Objetos principaleslet bob1, bob2;let spring1, spring2;
function setup() { createCanvas(640, 400);
spring1 = new Spring(width / 2, 10, 100); bob1 = new Bob(width / 2, 110); spring2 = new Spring(bob1.position.x, bob1.position.y, 100); bob2 = new Bob(width / 2, 210);}
function draw() { background(255);
let gravity = createVector(0, 2); bob1.applyForce(gravity); bob2.applyForce(gravity);
bob1.update(); bob2.update();
bob1.handleDrag(mouseX, mouseY); bob2.handleDrag(mouseX, mouseY);
spring1.connect(bob1); spring2.anchor.set(bob1.position.x, bob1.position.y); // Conectar el segundo resorte al primer bob spring2.connect(bob2);
spring1.constrainLength(bob1, 30, 200); spring2.constrainLength(bob2, 30, 200);
spring1.showLine(bob1); spring2.showLine(bob2); bob1.show(); bob2.show(); spring1.show(); spring2.show();}
function mousePressed() { bob1.handleClick(mouseX, mouseY); bob2.handleClick(mouseX, mouseY);}
function mouseReleased() { bob1.stopDragging(); bob2.stopDragging();}
Actividad 10
Péndulos
Enunciado: modifica esta simulación para crear un sistema de dos péndulos conectados en serie.
Entrega:
- Enlace a la simulación en el editor de p5.js.
- Código de la simulación.
- Captura de pantalla de la simulación.
🚀 Tu solución:
Enlace al Editor de p5.js
(https://editor.p5js.org/Teo-Diaz/sketches/Iqfi7zVTW)
Captura de Pantalla
let doublePendulum;
function setup() { createCanvas(600, 600); doublePendulum = new DoublePendulum(width / 2, 200, 150, 150);}
function draw() { background(255); doublePendulum.update(); doublePendulum.show();}
class DoublePendulum { constructor(x, y, r1, r2) { this.pivot = createVector(x, y);
this.r1 = r1; this.r2 = r2; this.angle1 = PI / 4; this.angle2 = PI / 4; this.angleVelocity1 = 0; this.angleVelocity2 = 0; this.angleAcceleration1 = 0; this.angleAcceleration2 = 0;
this.damping = 0.995; // Factor de amortiguación this.mass1 = 10; // Masa del primer péndulo this.mass2 = 10; // Masa del segundo péndulo }
update() { let g = 0.4; // Gravedad
let num1 = -g * (2 * this.mass1 + this.mass2) * sin(this.angle1); let num2 = -this.mass2 * g * sin(this.angle1 - 2 * this.angle2); let num3 = -2 * sin(this.angle1 - this.angle2) * this.mass2; let num4 = this.angleVelocity2 * this.angleVelocity2 * this.r2 + this.angleVelocity1 * this.angleVelocity1 * this.r1 * cos(this.angle1 - this.angle2); let den1 = this.r1 * (2 * this.mass1 + this.mass2 - this.mass2 * cos(2 * this.angle1 - 2 * this.angle2));
this.angleAcceleration1 = (num1 + num2 + num3 * num4) / den1;
let num5 = 2 * sin(this.angle1 - this.angle2); let num6 = (this.angleVelocity1 * this.angleVelocity1 * this.r1 * (this.mass1 + this.mass2)); let num7 = g * (this.mass1 + this.mass2) * cos(this.angle1); let num8 = this.angleVelocity2 * this.angleVelocity2 * this.r2 * this.mass2 * cos(this.angle1 - this.angle2); let den2 = this.r2 * (2 * this.mass1 + this.mass2 - this.mass2 * cos(2 * this.angle1 - 2 * this.angle2));
this.angleAcceleration2 = (num5 * (num6 + num7 + num8)) / den2;
this.angleVelocity1 += this.angleAcceleration1; this.angleVelocity2 += this.angleAcceleration2; this.angle1 += this.angleVelocity1; this.angle2 += this.angleVelocity2;
this.angleVelocity1 *= this.damping; this.angleVelocity2 *= this.damping; }
show() { let bob1 = createVector(this.r1 * sin(this.angle1), this.r1 * cos(this.angle1)); bob1.add(this.pivot);
let bob2 = createVector(this.r2 * sin(this.angle2), this.r2 * cos(this.angle2)); bob2.add(bob1);
stroke(0); strokeWeight(2); line(this.pivot.x, this.pivot.y, bob1.x, bob1.y); fill(127); circle(bob1.x, bob1.y, 20);
line(bob1.x, bob1.y, bob2.x, bob2.y); fill(127); circle(bob2.x, bob2.y, 20); }}
Aplicación
Es momento de aplicar los conceptos aprendidos en la unidad.
Actividad 11
Obra de arte generativa algorítmica interactiva en tiempo real
Enunciado: diseña e implementa una obra de arte generativa algorítmica interactiva en tiempo real en p5.js que cumpla con los siguientes requisitos:
- Selecciona uno de los conceptos con los que experimentaste en la fase de investigación y propón la obra alrededor de este.
- La obra debe ser interactiva en tiempo real. Puedes usar teclado, mouse, música, el micrófono, video, sensor o cualquier otro dispositivo de entrada.
- Documenta el proceso de creación, incluyendo la idea inicial, bocetos, experimentación con el código y el resultado final.
Entrega:
- Enlace a tu obra en el editor de p5.js.
- El código.
- Una captura de pantalla con una imagen de tu obra.
🚀 Tu solución:
Enlace al Editor de p5.js
(https://editor.p5js.org/Teo-Diaz/sketches/x2PqfskhQ)
Captura de Pantalla
Concepto
La obra se basará en sistemas dinámicos de partículas que se atraen y repelen entre sí, creando patrones visuales emergentes. Los usuarios podrán interactuar con el sistema modificando las fuerzas con el mouse y teclado, influyendo en el comportamiento de las partículas en tiempo real.
Boceto de la idea
El concepto inicial consiste en:
- Un conjunto de partículas que reaccionan a fuerzas de atracción y repulsión.
- El usuario podrá alterar la intensidad de las fuerzas con el teclado.
- Al mover el mouse, se generará una zona gravitatoria que atraerá las partículas cercanas.
- Teclas de control para modificar la cantidad de partículas y el comportamiento de la obra.
Implementación en p5.js
Aquí tienes el código base:
let particles = [];
function setup() { createCanvas(800, 600); for (let i = 0; i < 50; i++) { particles.push(new Particle(random(width), random(height))); }}
function draw() { background(20);
for (let p of particles) { p.applyForce(mouseX, mouseY); p.update(); p.display(); }}
// Clase de Partículaclass Particle { constructor(x, y) { this.position = createVector(x, y); this.velocity = createVector(random(-2, 2), random(-2, 2)); this.acceleration = createVector(0, 0); this.maxForce = 0.2; this.size = 8; }
applyForce(mx, my) { let mouseForce = createVector(mx, my); let force = p5.Vector.sub(mouseForce, this.position); let distance = force.mag(); distance = constrain(distance, 5, 150); let strength = map(distance, 5, 150, 1, 0); force.setMag(strength * this.maxForce); this.acceleration.add(force); }
update() { this.velocity.add(this.acceleration); this.velocity.limit(3); this.position.add(this.velocity); this.acceleration.mult(0);
// Rebote en 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(255); noStroke(); ellipse(this.position.x, this.position.y, this.size); }}
// Interacción con tecladofunction keyPressed() { if (key === 'A') { particles.push(new Particle(random(width), random(height))); } if (key === 'D' && particles.length > 5) { particles.pop(); }}
Interactividad y control
- Mouse: Genera un campo gravitacional que afecta a las partículas cercanas.
- Tecla
A
: Agrega una nueva partícula al sistema. - Tecla
D
: Elimina una partícula para modificar la dinámica.
Proceso de creación
- Idea inicial: Se pensó en un sistema generativo basado en fuerzas de atracción y repulsión.
- Boceto: Se exploró cómo representar el movimiento orgánico de las partículas y su reacción a un campo gravitatorio.
- Experimentación: Se probó el comportamiento de las partículas con distintas intensidades de fuerzas y métodos de interacción.
- Resultado final: Un sistema generativo de partículas con interacción en tiempo real, donde el usuario puede modificar el comportamiento en el canvas.
Consolidación y metacognición
He venido escuchando que esta es una fase de relleno 😭. Nada
más lejos de la verdad, de verdad. En esta fase del proceso de aprendizaje
es donde miras hacia atrás
y consolidas lo que aprendiste. Adicionalmente,
reflexionas sobre tu proceso de aprendizaje y las posibilidades de aplicar lo
aprendido en otros contextos.
Actividad 12
Consolidación
Enunciado: analiza tu obra de arte generativa respondiendo las siguientes preguntas:
- ¿Qué concepto de oscilación utilizaste como base para tu obra? Describe cómo lo implementaste.
- ¿Cómo funciona la interacción en tu obra? Explica cómo el usuario puede modificar la obra en tiempo real.
- ¿Qué desafíos encontraste durante el proceso de creación? ¿Cómo los superaste?
- ¿Qué aprendiste sobre las oscilaciones y su aplicación en el arte generativo?
Entrega: responde a las preguntas.
🚀 Tu solución:
Respuestas a las preguntas:
-
¿Qué concepto de oscilación utilizaste como base para tu obra? Describe cómo lo implementaste.
Me basé en la oscilación armónica para construir el comportamiento de los puntos en la imagen. Utilicé funciones trigonométricas comosin()
ycos()
para definir trayectorias suaves y repetitivas, dando a los elementos un movimiento basado en frecuencias y amplitudes variables. Cada punto tiene su propia frecuencia de oscilación, generando patrones dinámicos en el tiempo. -
¿Cómo funciona la interacción en tu obra? Explica cómo el usuario puede modificar la obra en tiempo real.
La interacción se logra mediante eventos de entrada, como la posición del mouse o clics. Al mover el cursor, los puntos cercanos ajustan su frecuencia y dirección, creando una sensación de perturbación del sistema. También se puede modificar la amplitud de la oscilación, generando efectos más drásticos en la distribución de los puntos. -
¿Qué desafíos encontraste durante el proceso de creación? ¿Cómo los superaste?
Un reto significativo fue optimizar la actualización en tiempo real sin afectar el rendimiento. Para solucionar esto, ajusté el número de elementos en pantalla y trabajé con cálculos eficientes para evitar procesamiento innecesario. También experimenté con distintos valores de oscilación hasta encontrar parámetros que mantuvieran un equilibrio entre estética y fluidez. -
¿Qué aprendiste sobre las oscilaciones y su aplicación en el arte generativo?
Descubrí que las oscilaciones pueden ser una herramienta fundamental en la creación de patrones generativos. Al jugar con frecuencias y amplitudes, se pueden generar sistemas dinámicos que evolucionan de manera impredecible pero armónica. Además, entendí la importancia de la interacción como un medio para enriquecer la experiencia visual y dar al usuario la posibilidad de influir en la obra.
Actividad 13
Metacognición
Enunciado: reflexiona sobre tu propio proceso de aprendizaje en esta unidad.
- ¿Qué estrategias de aprendizaje utilizaste?
- ¿Qué te funcionó mejor para comprender los conceptos?
- ¿Qué podrías mejorar?
- ¿Cómo te sentiste durante el proceso de aprendizaje?
- ¿Qué te motivó?
- ¿Qué te frustró?
Entrega: respuesta a las preguntas.
🚀 Tu solución:
Respuestas a las preguntas:
-
¿Qué estrategias de aprendizaje utilizaste?
Se utilizó un enfoque experimental y iterativo, probando distintos parámetros de oscilación y observando sus efectos en tiempo real. Además, se aplicaron conceptos matemáticos de oscilación armónica para desarrollar una comprensión técnica sólida. La exploración visual fue clave para refinar los patrones generativos. -
¿Qué te funcionó mejor para comprender los conceptos?
La mejor estrategia fue visualizar el comportamiento matemático mediante simulaciones interactivas. Comprobar los efectos de distintas frecuencias y amplitudes en la obra permitió un aprendizaje intuitivo y práctico. También fue útil la experimentación con funciones trigonométricas en pequeños sistemas antes de integrarlas en el proyecto final. -
¿Qué podrías mejorar?
Sería valioso optimizar aún más el rendimiento para manejar sistemas más complejos sin sacrificar fluidez. También se podría explorar formas avanzadas de interacción, como la sincronización de múltiples osciladores o el uso de fuerzas externas para enriquecer la dinámica de la obra. -
¿Cómo te sentiste durante el proceso de aprendizaje?
Fue un proceso desafiante pero emocionante. Al principio, ajustar los parámetros adecuados implicó múltiples pruebas y errores, pero cada avance reforzó la comprensión del comportamiento oscilatorio y su impacto en el arte generativo. -
¿Qué te motivó?
La posibilidad de crear patrones dinámicos y visualmente atractivos impulsó la exploración. También fue motivador ver cómo el usuario podía influir en la obra en tiempo real, transformando el sistema de maneras inesperadas. -
¿Qué te frustró?
En ciertos momentos, la complejidad matemática detrás de las oscilaciones presentó dificultades, especialmente al intentar lograr movimientos naturales sin generar artefactos visuales indeseados. Sin embargo, el enfoque iterativo ayudó a superar estos obstáculos y permitió perfeccionar la obra.