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:
anglecontrols the phase of the sine function,amplitudedetermines the height of oscillation, andxandytrack the position of the ellipse. - Sinusoidal Movement: The
yvalue oscillates based on thesin(angle), creating an up-and-down motion. - Horizontal Movement:
xmoves horizontally, influenced byxSpeedfor varied speeds, giving it a dynamic feel. - Color Dynamics: The
fillfunction assigns random colors to each circle.
Failures and Successes:
- Initial versions used static speeds, resulting in uniform movement. Adding
randomimproved 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 forxandy. - Mapping: The
map()function constrains the noise values to a specific range. - Color Change: Colors change dynamically when
morngo 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
800x600pixels. - Creates an array of
numCirclescircle objects, each with:- Random initial position (
x,y). - Random
radiussize. - Random starting
angle. - Random
speedof 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
circlesarray. - Position Calculation:
xandyare calculated usingcos()andsin()functions respectively, based on the circle’sangleandradiusOffset.
- 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
angleto move it along its circular path. - Adds a small random value to
c.xandc.yto 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.
