Week 9- Morphed

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.

Leave a Reply

Your email address will not be published. Required fields are marked *