Concept
For my Week 9 assignment, I developed a dynamic flocking system that illustrates the principles of autonomous agents through morphing shapes. This project was inspired by fond memories of teaching my younger siblings about shapes, using games where they would fit various geometric shapes into corresponding holes, like cubes with different cutouts. It’s interesting how my journey started with flocking and boids, but the morphing aspect allowed me to create something truly engaging. While it’s playful, it’s also educational, as I was able to design fundamental shapes like circles, squares, rectangles, and triangles, making it a fun way to learn about geometry!
Embedded Sketch
Key Features
- Engaging Flocking Behavior: The particles demonstrate natural flocking behavior, moving cohesively as they navigate towards their target shapes, which creates an immersive experience that captivates the audience.
- Dynamic Shape Morphing: As the particles morph into various geometric formations—such as circles, squares, rectangles, and triangles—they provide a visually stunning display that keeps viewers intrigued and encourages exploration of fundamental shapes.
- Interactive Learning Experience: Each shape transition introduces an element of surprise, making learning about geometry enjoyable and interactive, as viewers can appreciate the beauty of shapes while observing the playful interactions of the particles.
Piece of Code That I’m Proud Of
While the concept is simple, implementing this code has been challenging due to the complex interactions between particles that mimic flocking behavior, requiring a solid understanding of vector mathematics. It’s tricky to ensure that the particles move toward their target points and morph seamlessly between shapes, and managing the timing for shape transitions while keeping everything smooth, especially with many particles, adds another layer of complexity.
One aspect I’m particularly proud of is the code for the shape transformations, which handles transitions smoothly and captivates my siblings’ attention. This showcases my ability to blend creativity with programming logic, making it a standout feature of my project. Their joy in watching the shapes dance across the screen highlights the impact of this code and its educational value.
let particles = []; let numParticles = 100; let shapeIndex = 0; // Current shape index let shapePoints = []; // Array to hold shape points let morphingDuration = 3000; // 3 seconds for morphing let lastUpdateTime = 0; // Last time the shape was updated function setup() { createCanvas(windowWidth, windowHeight); // Initialize particles for (let i = 0; i < numParticles; i++) { particles.push(new Particle(random(width), random(height))); } // Define shape points for morphing shapes shapePoints.push(getCirclePoints()); shapePoints.push(getSquarePoints()); shapePoints.push(getTrianglePoints()); shapePoints.push(getRectanglePoints()); } function draw() { background(51); // Get the target shape points based on the shapeIndex let targetPoints = shapePoints[shapeIndex]; // Update each particle to move toward the target points with flocking behavior for (let i = 0; i < particles.length; i++) { particles[i].update(targetPoints[i]); particles[i].show(); } // Check if the time elapsed is greater than the morphing duration if (millis() - lastUpdateTime > morphingDuration) { if (areParticlesClose(targetPoints)) { shapeIndex = (shapeIndex + 1) % shapePoints.length; // Cycle through shapes lastUpdateTime = millis(); // Reset the timer } } } function areParticlesClose(targetPoints) { for (let i = 0; i < particles.length; i++) { let d = dist(particles[i].position.x, particles[i].position.y, targetPoints[i].x, targetPoints[i].y); if (d > 10) return false; // Allow some tolerance } return true; // All particles are close to their target points } // Functions to generate shape points omitted for brevity... class Particle { constructor(x, y) { this.position = createVector(x, y); this.velocity = createVector(random(-1, 1), random(-1, 1)); this.acceleration = createVector(); this.size = 8; this.colors = [color(255, 0, 0), color(0, 255, 0), color(0, 0, 255), color(255, 255, 0)]; // Different colors this.color = this.colors[shapeIndex]; // Set color based on shape index } update(target) { // Calculate flocking forces let cohesionForce = this.cohesion(); let separationForce = this.separation(); this.acceleration.add(cohesionForce); this.acceleration.add(separationForce); // Move towards target shape point let desired = p5.Vector.sub(target, this.position); desired.setMag(2); // Set maximum speed let steering = p5.Vector.sub(desired, this.velocity); steering.limit(0.5); // Increase steering limit for faster response this.acceleration.add(steering); // Update velocity and position this.velocity.add(this.acceleration); this.velocity.limit(4); // Limit maximum velocity this.position.add(this.velocity); this.acceleration.mult(0); // Reset acceleration // Update color based on shape index this.color = this.colors[shapeIndex]; } show() { fill(this.color); noStroke(); ellipse(this.position.x, this.position.y, this.size); } // Cohesion and separation functions omitted for brevity... }
Future Work and Improvements
Moving forward, I plan to introduce more complex geometric shapes to deepen the learning experience and challenge understanding. Additionally, I aim to enhance interactivity by incorporating elements that allow users to manipulate shapes and observe immediate changes, fostering a hands-on learning approach. To further reinforce their learning in an engaging manner, I will implement educational features such as quizzes or prompts that encourage users to identify shapes or predict transformations.