Mini Project 3: Generative Motion
Project Link
Sketch 1: https://editor.p5js.org/King-Raphael/sketches/W1yWhF780
Sketch 2: https://editor.p5js.org/King-Raphael/sketches/SRvTRY2wZ
Sketch 3: https://editor.p5js.org/King-Raphael/sketches/XAmtepc77
Brief Description and Concept
In this project, I explored different generative motion techniques using the p5.js. The goal was to create dynamic animations with various shapes and movements. Each sketch demonstrates unique types of motion influenced by noise functions, trigonometric calculations, and interactive elements.
Visual Documentation
Coding
Sketch 1
let shapes = []; let currentShapeIndex = 0; function setup() { createCanvas(800, 600); // Initialize shapes with different directions for (let i = 0; i < 4; i++) { shapes.push({ x: random(width), y: random(height), size: random(30, 60), speedX: random(-3, 3), speedY: random(-3, 3), shapeType: i, // Each shape has a different type (0 to 3) }); } } function draw() { background(0, 65); for (let i = 0; i < shapes.length; i++) { let s = shapes[i]; // Update position s.x += s.speedX; s.y += s.speedY; // Check for boundaries and reverse direction if necessary if (s.x < 0 || s.x > width) s.speedX *= -1; if (s.y < 0 || s.y > height) s.speedY *= -1; // Set random color noStroke(); fill(random(255), random(255), 200, 150); // Draw shapes based on shapeType if (s.shapeType === 0) { ellipse(s.x, s.y, s.size, s.size); } else if (s.shapeType === 1) { rect(s.x, s.y, s.size, s.size); } else if (s.shapeType === 2) { triangle( s.x, s.y - s.size / 2, s.x - s.size / 2, s.y + s.size / 2, s.x + s.size / 2, s.y + s.size / 2 ); } else if (s.shapeType === 3) { beginShape(); vertex(s.x, s.y - s.size / 2); vertex(s.x + s.size / 4, s.y - s.size / 4); vertex(s.x + s.size / 2, s.y); vertex(s.x + s.size / 4, s.y + s.size / 4); vertex(s.x, s.y + s.size / 2); vertex(s.x - s.size / 4, s.y + s.size / 4); vertex(s.x - s.size / 2, s.y); vertex(s.x - s.size / 4, s.y - s.size / 4); endShape(CLOSE); } } } // Change shape types with mouse press function mousePressed() { // Change the shapeType of each shape to the next type for (let i = 0; i < shapes.length; i++) { shapes[i].shapeType = (shapes[i].shapeType + 1) % 4; } }
Inner Workings:
- Variables:
angle
controls the phase of the sine function,amplitude
determines the height of oscillation, andx
andy
track the position of the ellipse. - Sinusoidal Movement: The
y
value oscillates based on thesin(angle)
, creating an up-and-down motion. - Horizontal Movement:
x
moves horizontally, influenced byxSpeed
for varied speeds, giving it a dynamic feel. - Color Dynamics: The
fill
function assigns random colors to each circle.
Failures and Successes:
- Initial versions used static speeds, resulting in uniform movement. Adding
random
improved the dynamic nature. - Color transitions were initially jarring; applying semi-transparent fills enhanced the blending effect.
Alternative Approach:
Use cos()
for y
and sin()
for x
to reverse the directional oscillation. This would create a different, yet harmonious, wave motion:
Sketch 2
let xoff = 0; let yoff = 1000; let r, g, b; function setup() { createCanvas(600, 600); } function draw() { noStroke(); background(255,40); let x = noise(xoff) * width; let m = map(x, 100, 500, 0, 600); let y = noise(yoff) * height; let n = map(y, 100, 500, 0, 600); fill(r, g, b, 80); ellipse(m, n, 50, 50); xoff += 0.01; yoff += 0.01; if(m > 550 || m < 50){ // xoff = -xoff; r = random(0, 255); g = random(0, 255); b = random(0, 255); } if(n > 550 || n < 50){ // yoff = -yoff; r = random(0, 255); g = random(0, 255); b = random(0, 255); } console.log(m,n); }
Inner Workings:
- Noise Function:
noise()
is used to generate smooth, organic movements forx
andy
. - Mapping: The
map()
function constrains the noise values to a specific range. - Color Change: Colors change dynamically when
m
orn
go beyond set boundaries, creating a vibrant effect.
Failures and Successes:
- The initial attempt used only
random()
for movement, which resulted in erratic behavior. Switching tonoise()
provided smoother transitions. - The boundary conditions sometimes led to abrupt color changes, which were softened by adjusting the alpha values in
fill()
.
Alternative Approach:
Instead of changing colors when boundaries are crossed, modify the speed of noise increment (xoff
and yoff
). This would slow down or speed up the motion dynamically, giving a different pace to the movement.
Sketch 3
let numCircles = 10; let circles = []; function setup() { createCanvas(800, 600); // Initialize circles with random properties for (let i = 0; i < numCircles; i++) { let newCircle = { x: random(width), y: random(height), radius: random(20, 50), angle: random(TWO_PI), speed: random(0.01, 0.05), radiusOffset: random(50, 150), color: [random(255), random(255), random(255), 150] // Random color with alpha }; circles.push(newCircle); } } function draw() { background(255); noStroke(); for (let i = 0; i < circles.length; i++) { let c = circles[i]; // Calculate new position based on angle and radius offset let x = c.x + cos(c.angle) * c.radiusOffset; let y = c.y + sin(c.angle) * c.radiusOffset; // Set the circle color fill(c.color); ellipse(x, y, c.radius * 2, c.radius * 2); // Update angle to move the circle c.angle += c.speed; // Update the center position to create a linear movement effect c.x += random(-1, 1); c.y += random(-1, 1); // Reset position if the circle moves out of the canvas if (c.x < 0 || c.x > width || c.y < 0 || c.y > height) { c.x = random(width); c.y = random(height); } } }
- Variables:
numCircles
: Specifies the number of circles to be created.circles
: An array to store circle objects, each with its own properties.
setup()
Function:- Initializes the canvas to
800x600
pixels. - Creates an array of
numCircles
circle objects, each with:- Random initial position (
x
,y
). - Random
radius
size. - Random starting
angle
. - Random
speed
of rotation, determining how fast the circle moves along its path. - Random
radiusOffset
, determining the size of the circular path. - A random color stored as an array
[r, g, b, alpha]
.
- Random initial position (
- Initializes the canvas to
draw()
Function:- Sets the background color to white with
background(255);
. - Iterates over each circle object in the
circles
array. - Position Calculation:
x
andy
are calculated usingcos()
andsin()
functions respectively, based on the circle’sangle
andradiusOffset
.
- Color and Shape:
- Sets the fill color to the circle’s stored color (
fill(c.color);
). - Draws the circle using the
ellipse()
function at the calculated position.
- Sets the fill color to the circle’s stored color (
- Movement:
- Updates the circle’s
angle
to move it along its circular path. - Adds a small random value to
c.x
andc.y
to make the center of the circle drift slightly, giving a more dynamic movement.
- Updates the circle’s
- Boundary Check:
- If the circle’s center moves outside the canvas bounds, it is repositioned randomly within the canvas.
- Sets the background color to white with
Findings / Lessons Learned
- Core Takeaways: Mastery of the
noise()
function and its applications in creative coding can lead to more sophisticated visual outputs. The integration of interactive features (mouse and keyboard inputs) opens new avenues for dynamic designs. - Challenges: The main challenge was balancing randomness with smooth motion. Ensuring the sketches were visually appealing yet distinct required iterative tuning of parameters.
Reflection Prompts
- The project challenged me to think beyond simple movements and explore complex interactions between shapes, motion, and user inputs.
- Tuning parameters like speed and amplitude to get the desired movement patterns was time-consuming and required multiple iterations.
- It strengthened my grasp of generative art principles and the synergy between coding and creativity.