Yesterday we attended a lecture by professor Neil Leach who talked about AI intelligence, its effect and progression on humanity, as well as the future that we should expect with its expansion. Something that I found really interesting was the quote that said “what we know how to do, machines will do better than us” because this was a fear that’s been nestled within my mind especially with the growing loss of job availabilities for young adults from our generation. While we only have ourselves to blame, — after all, we are the creators of machines and AI in the first place — it’s also important to remember that we won’t be “outdated” or “useless” because I’m a firm believer in the thought that there will always be a characteristic, skill, or an idea that can only be generated from a human. Overall, it was a really interesting lecture that helped me reflect on technology and our relationship on a day-to-day basis and what to be mindful of when utilizing these technological resources.
Month: November 2023
Lecture Reflection
The talk made me think about how AI is not inherently good or bad. The dark side of AI only comes from its capabilities and probably doesn’t realise what bad it is doing. It also makes me think about the way AI thinks, whether AI is conscious or if it does think for itself the way we do or metaphorically.
AI is always seen as more to do with actual knowledge but we can also apply AI capabilities towards design and our future cities. A lot of AI is already in use even before ChatGPT but it’s just ‘invisible’ and I think more people need to understand the spectrum of AI.
Neil also talks about how with current AI such as self driving cars, humans won’t care about driving and I think that links with the idea that humans are inherently lazy and selfish.
I think this lecture just made me realise that more than ever before, professionals across multiple disciplines need to start working together to learn how to live with this new intelligence.
Alien Intelligence Talk Reflection – Abdelrahman Mallasi
In a future where AI replaces various occupations, it pushes us to shift our focus from capitalistic, economically-driven values to our inherent human qualities. This shift places greater emphasis on interpersonal and soft skills than technical abilities that are likely to be automated. This leads to an existential question: How will we define our identities in the absence of conventional professions? We may end up needing to seek alternative methods to derive a sense of achievement and intelligence, or maybe reassess our dependence on such emotions for happiness. Ultimately, as Professor Leach mentioned, AI can act as a mirror to understand humans.
Assignment Week #9 – Flocking Simulation with Obstacle Avoidance
Concept:
In this project, I aimed to create an immersive simulation that showcases the collective behavior of a group of boids, as they navigate through an environment that can be filled with obstacles. The focus was to mimic the natural flocking behavior observed in birds or fish, incorporating obstacle avoidance to enhance the realism of their movement.
Implementation:
- Boid Behavior: Each boid follows three primary rules – alignment, cohesion, and separation – to simulate natural flocking behavior.
- Dynamic Interaction: Boids react to user input, moving towards the mouse pointer when a specific key is pressed. Pressing ‘a’ makes the boids get attracted toward the cursor. In addition, when clicking on two points on the canvas, it spawns a line that acts as an obstacle for the boids.
- Obstacle Avoidance: Boids dynamically detect and steer clear of line obstacles in their environment, enhancing the realism of their movement patterns.
- Visual Aesthetics: The boids change colors dynamically, creating a visually captivating display that reflects their speed and movement.
Sketch:
Code:
display() { // Calculate the size based on velocity let speed = this.velocity.mag(); let size = map(speed, 0, this.maxSpeed, 2, 10); // Map speed to a reasonable size range // Calculate hue for color let time = millis() / 1000; let timeFactor = (sin(time + this.color) + 1) / 2; let velFactor = speed / this.maxSpeed; let hue = (this.color + 360 * timeFactor + 180 * velFactor) % 360; // Set color and size colorMode(HSB, 360, 100, 100); stroke(hue, 80, 90); strokeWeight(size); // Draw the boid push(); translate(this.position.x, this.position.y); point(0, 0); pop(); colorMode(RGB, 255); }
- The steering forces that direct the boids’ movement towards alignment, cohesion, and separation as well as additional forces for obstacle avoidance and attraction towards the mouse pointer.
avoidObstacles(obstacles) { let steer = createVector(0, 0); let count = 0; let safeDistance = 30; // Increase safe distance for early avoidance obstacles.forEach(obstacle => { let closestPoint = this.closestPointOnLine(this.position, obstacle.start, obstacle.end); let d = p5.Vector.dist(this.position, closestPoint); if (d < safeDistance) { let diff = p5.Vector.sub(this.position, closestPoint); diff.normalize(); diff.div(d); // Stronger weighting by distance steer.add(diff); count++; } }); if (count > 0) { steer.div(count); steer.setMag(this.maxSpeed * 1.5); // Increase the magnitude of the steering force steer.sub(this.velocity); steer.limit(this.maxForce * 1.5); // Increase the maximum force limit } return steer; }
- Obstacles are represented as lines, and a specialized algorithm calculates the closest point on these lines to each boid, triggering avoidance maneuvers.
Challenges:
- Obstacle Avoidance Algorithm: Crafting an effective method for boids to avoid line-shaped obstacles requires careful consideration of the forces required to allow the boids to avoid obstacles properly.
Future Improvements:
- Enhanced User Interaction: Exploring more complex user interactions, such as allowing users to create and modify obstacles in real time. making the obstacles possibly move or experience forces.
- Environmental Complexity: Adding more environmental elements like varying wind currents or areas of attraction and repulsion could create more dynamic scenarios for the boids.
Coding Assignment #9 – Nematodes
Concept & Inspiration:
For this week’s assignment, I tried to recreate a microscopic view of nematodes (parasitic species that feed on plants and are found in soil environments) using flocking behaviors (alignment, cohesion, separation). Nematodes have smooth unsegmented bodies similar to worms, as shown in the following picture:
In the sketch, there is a circle in the middle representing the view from the microscope oculars (eyepieces), and starts with a smooth fade in animation as if the light of the microscope was turned on.
Sketch:
Code Walkthrough:
https://editor.p5js.org/bdr/sketches/n0c4DAM2S
Nematode (vehicle) Class:
Flocking – Separation: to cause nematodes to steer away from all the others.
separate() { let desiredSeparation = 25; let steer = createVector(0, 0); let count = 0; for (let i = 0; i < Nematodes.length; i++) { let d = p5.Vector.dist(this.position, Nematodes[i].position); if (d > 0 && d < desiredSeparation) { let diff = p5.Vector.sub(this.position, Nematodes[i].position); diff.normalize(); diff.div(d); steer.add(diff); count++; } } if (count > 0) { steer.div(count); } if (steer.mag() > 0) { steer.normalize(); steer.mult(this.maxspeed); steer.sub(this.velocity); steer.limit(this.maxforce); } return steer; }
Flocking – Cohesion: to cause nematodes to steer towards the center of mass – the average position of the nematodes within the circle.
// Flocking - Cohesion cohere() { let neighborDistance = 50; let sum = createVector(0, 0); let count = 0; for (let i = 0; i < Nematodes.length; i++) { let d = p5.Vector.dist(this.position, Nematodes[i].position); if (d > 0 && d < neighborDistance) { sum.add(Nematodes[i].position); count++; } } if (count > 0) { sum.div(count); return this.seek(sum); } else { return createVector(0, 0); } }
Flocking – Alignment: to cause the nematodes to line up with others close by.
align() { let neighborDistance = 40; let sum = createVector(0, 0); let count = 0; for (let i = 0; i < Nematodes.length; i++) { let d = p5.Vector.dist(this.position, Nematodes[i].position); if (d > 0 && d < neighborDistance) { sum.add(Nematodes[i].velocity); count++; } } if (count > 0) { sum.div(count); sum.normalize(); sum.mult(this.maxspeed); let steer = p5.Vector.sub(sum, this.velocity); steer.limit(this.maxforce); return steer; } else { return createVector(0, 0); } }
Trail: FrameRate animation: To get a smooth animation, I used frame rates.
frameRate(30) // Add a trail if (frameCount % 20 == 0) { fill(160, 160, 45, 15); } ellipse(width/2, height/2, 440, 440);
Improvements:
One of the next steps would be to add user interactions using the mouse, i.e. creating an obstacle when the user clicks within the bounds of the circle, add food to the nematodes to consume that would help increase their speed/behavior…
Coding Assignment Week #9 – Biology Much?
INSPIRATION & CONCEPT
I have been exploring a lot of physics and math, haven’t I? So I wanted to explore biology for this assignment, something way beyond my comfort zone… But thankfully I do not need to know biology for that, only coding!
So, I have often been fascinated with cells and tissues and those diagrams were few of my favourites to draw in school. I also researched a bit more into molecular biology and viewed some designs / images for more perspective. Then, I tried to model these through code using the flocking simulation as the base – yes!
The main idea or intention behind my work this week was to create patterns and designs using the flocking that do not intrinsically look like the behaviour of the flocking system. And I guess I was successful in that to some extent 🙂 I am very happy with my work.
Mood Board
THE PROCESS
As one can see in the above images, circular objects almost appear everywhere. Even in the neuron-like strands, one can htink of those strands either avoiding or circling around certain points. Hence, I started with adding a bunch of circles with random radii, which I called holes, to the canvas. The logic of the code is that the flocking system tries to avoid or circle around these circles to create desired results.
I started by writing a hole class as follows:
class Hole { constructor(x, y, r) { this.pos = createVector(x, y); this.r = r; } show() { push(); noFill(); circle(this.pos.x, this.pos.y, this.r*2); pop(); } }
and then creating the hole objects which are passed to the flocking system. Each boid tries to avoid this circle using a custom avoid() method I write inspired by our evade() and flee() methods.
let holes = []; // make holes for neurons for (let i = 0; i < 10; i++) { holes.push(new Hole(random(width), random(height), random(20,80))); } for (let i = 0; i < holes.length; i ++) { holes[i].show(); flock.avoid(holes[i]); }
The avoid method is as follows:
// in the flock.js class avoid(hole) { for (let boid of this.boids) { // let obstacle = createVector(width/2, height/2); let d = p5.Vector.dist(boid.position, hole.pos); if (d > 0 && d < hole.r) { boid.avoid(hole); } } } // in the boid.js class avoid(hole) { let desired = p5.Vector.sub(this.position, hole.pos); desired.setMag(this.maxspeed); // Steering = Desired minus velocity let steer = p5.Vector.sub(desired, this.velocity); steer.mult(this.maxforce); // Limit to maximum steering force this.applyForce(steer); }
THE SKETCHES
As you can see above, the boids try to avoid the the circles and flee away from it.
Then I further played around with values and fine-tuned the parameters to achieve varying results.
A bit of a honey-comb effect:
To create certain knots at places, I also decided to add a few holes that would be attractors. I added more weight to this so it would attract more than the holes taht repel. This creates a very different kind of design – something that one would see though a microscope.
OUTPUT
All my lovely outputs of the code above can be seen in the below gallery!! Hope you all like them 🙂
FURTHER DEVELOPMENT
Try creating patterns with different kinds of shapes – thin rectangles, triangles and polygons to try and mimic other kinds of tissues and cells. One of the patterns that I really want to try and did not achieve in this attempt is the neurological one, neurons vein like here and there (the last 3 in my inspiration gallery). They would require some other kind of factors to attract and diffuse in a line kind if format and that is something I would like to try out in the future.
Scurrying Ants – Week 9
Inspiration
For my inspiration this week, I wanted to replicate the ants that always scurry around with each other and sometimes if they find food or something they want, they tend to move in a herd.
I first had the images on the background to represent dirt in some way and to have the ant image.
After the graphics aspect was done, I wanted to implement the actual motion and have the ants be represented as circles for now. I needed to work on two particular functions, separate and align.
For the separate function, I needed to create a vector and have the separation movement be coded within that vector.
separate(ants) { let steer = createVector(); let count = 0; for (let other of ants) { let d = dist( this.pos.x, this.pos.y, other.pos.x, other.pos.y ); if (other != this && d < this.desiredSeparation) //make sure the ant is not comparing with isteld and within certain distance { let diff = p5.Vector.sub(this.pos, other.pos); diff.normalize(); diff.div(d); steer.add(diff); count++; } } if (count > 0) { steer.div(count); } if (steer.mag() > 0) { steer.setMag(this.maxSpeed); steer.sub(this.vel); steer.limit(this.maxForce); } return steer; }
For the align function, it is the same structure as the separate function ,but we use addition instead of subtraction.
align(ants) { let sum = createVector(); let count = 0; let perceptionRadius = 50; for (let other of ants) { let d = dist( this.pos.x, this.pos.y, other.pos.x, other.pos.y ); if (other !== this && d < perceptionRadius) { sum.add(other.vel); count++; } } if (count > 0) { sum.div(count); sum.setMag(this.maxSpeed); let steer = p5.Vector.sub(sum, this.vel); steer.limit(this.maxForce); return steer; } else { return createVector(); } }
This was the output with circles and I wanted the head of my ant to always point the way in the direction it was going.
display() { push(); translate(this.pos.x, this.pos.y); rotate(this.vel.heading()); image(this.img, 0, 0, 15, 15); pop(); // circle(this.pos.x, this.pos.y, 10); }
This is my final output and I would want to add more interactivity next time by making the user have something ‘sweet’ as the mouse movement, so the ants move towards the mouse.
Xiaozao Assignment #9
Project title: Dark Side of the Moon
https://editor.p5js.org/Xiaozao/sketches/eqtX3a2Cv
This week’s assignment is inspired by the surface of the moon. It is covered with craters large and small, and the sand is being blown among the surface.
I wanted to create a more dynamic movement of the boids, that’s why I applied a sine value to the separate, align, and cohere functions and made the distance limitation change over time.
flock(boids) { time_off += 0.01; let sin_value = sin(time_off); let separate_control = map(sin_value, -1, 1, 1, 50); let align_control = map(sin_value, -1, 1, 30, 0); let cohere_control = map(sin_value, -1, 1, 50, 500); let sep = this.separate(boids, separate_control); // Separation let ali = this.align(boids, align_control); // Alignment let coh = this.cohere(boids, cohere_control); // Cohesion
To create the craters on the moon’s surface, I placed several “obstacles” around the canvas, and made the boids near the obstacles flee from them. I adjusted the parameters to make some of the boids go across the obstacles while the others bounce back. This creates a more natural feeling.
// main for (let i = 0; i < obstacles.length; i ++) { let obstacle = obstacles[i]; // circle(obstacle.x, obstacle.y, 10); flock.avoid(obstacle); } // flock class avoid(obstacle) { for (let boid of this.boids) { let d = p5.Vector.dist(boid.position, obstacle); if (d > 0 && d < 100) { boid.avoid(obstacle); } } } // boid class avoid(obstacle) { let desired = p5.Vector.sub(this.position, obstacle); desired.setMag(this.maxspeed); // Steering = Desired minus velocity let steer = p5.Vector.sub(desired, this.velocity); steer.mult(0.02); // Limit to maximum steering force this.applyForce(steer); }
Finally, I set the blend mode to “add” which makes the patterns more aesthetic.
Possible improvements:
Maybe I can draw lines between each pair of boids that are close enough to each other, or try other kinds of blend modes.
Week 9 Assignment – Flocking Behavior
Concept:
I was listening to one of my favorite songs called “Good-bye days” by a Japanese singer called YUI when I got the inspiration for this sketch. This song always reminded me of a summer night when the sun is starting to set and people chilling in an endless green field while trying to catch fireflies, and I thought this might be a fun idea to try to recreate using flocking.
Process/Highlight:
I used all three of the main skills that we learned in class by referring to our class slides as well as the Coding Train’s tutorial, which are:
- Alignment — I used this to align boids to their neighboring boids, so that they will all match velocities and also the direction of their movement instead of dispersing.
- Cohesion — this feature was what held the boids somewhat loosely together in a group so that they won’t be too spread out and will still somehow manage to stay close to each other.
- Separation — this was necessary because while I still wanted my boids to stay close to each other and move in a cohesive way towards a certain direction, I also didn’t want them to clash into each other because in real life, fireflies keep their distances from each other. This added a sort of “repelling” behavior amongst the boids.
A special feature I added was limiting the space of where the boids can travel to, which I did so by adding the “constrainToArea” function within the “Boid” class. At first, I made the area so that boids will only be able to travel in the upper half of the canvas, but this seemed too rectangular because the boid particles were very specifically outlining the rectangular area, so I modified it so that they’ll be active in 2/3 of the canvas area.
constrainToArea(x1, y1, x2, y2) { this.position.x = constrain(this.position.x, x1, x2); this.position.y = constrain(this.position.y, y1, y2); } ...
Then I adjusted the following code elements in class Boid so that the boids were behaving in a way I wanted them to:
class Boid { constructor() { this.position = createVector(random(width), random(height)); this.velocity = p5.Vector.random2D(); this.velocity.setMag(random(2, 4)); this.acceleration = createVector(); this.maxForce = 0.6; this.maxSpeed = 10; this.repulsionRange = 70; // Distance to start separation this.alignmentRange = 90; // Distance for alignment this.cohesionStrength = 0.8; // Strength of cohesion behavior this.separationStrength = 1; // Strength of separation behavior }
For example, adjusting the this.maxForce and this.maxSpeed by increasing their values helped the particles to show their repulsion from the mouse cursor much clearer, as well as increasing the this.repulsionRange and this.alignementRange.
I was happy with the above values because they showed my desired picture when I simulated it, so I decided to stick with them. Then I simply added a background image that I got from this link to show that blue sky, summer night background, and changed the color of my boids to yellow so that they will be like fireflies.
Final Sketch:
And here’s the final sketch. Click on the sketch screen once and then feel free to move your mouse cursor around to observe how the boids repel from it!
Reflection:
Next time I’d like to add a character to the mouse cursor so that it’ll be like a character chasing down the fireflies but the fireflies just flying away from her, just like a scene that could be in a Ghibli movie!
Additional Change:
After hearing professor’s feedback in class about adding trails to show the “glow” of the fireflies better, I added the below snippet of code:
class Boid { ... this.history = []; // New property to store position history ... // Store the current position in history this.history.push(createVector(this.position.x, this.position.y)); // Limit the history length to control the trail length if (this.history.length > 50) { this.history.shift(); } ... show() { noStroke(); fill(255, 255, 102, 24); // Adjust the alpha value for transparency for (let pos of this.history) { ellipse(pos.x, pos.y, 6, 6); // Adjust the size of the ellipse } } ... }
I adjusted the size and the transparency of the ellipse trail as I saw fit, and I’m really pleased with the outcome!
Coding Assignment – Week #9
Concept
For this week’s assignment, I did not specifically want to simulate a real-life system but rather focus on creating an interesting visual piece. As instructed, I started from the dynamic flocking system as the base. I experimented with different values of distances for separation, cohesion, and alignment. I wanted to create something more chaotic than the base: I wanted the cohesion to be stronger, and alignment to be less prominent. In general, I wanted the flocking to be more aggressive if that makes sense. Although I experimented without a goal to mimic a particular system, the end result sort of reminds me of fireworks at certain stages. Here is the sketch:
Implementation:
The most altered part from the base was the show function. In the show() method, the visual effect is achieved by manipulating the ‘pulsation’ variable, creating a dynamic look for each element. The dynamic size of the circles is based on a sine function. Additionally, I added a fading trail effect by initializing a trail list for every boid, and storing the last 15 previous positions as vectors and constantly updating them (I created an extended class so that I would not mess up the base too much, and at some point the boids reminded me of fireflies so that’s where the naming comes from).
show() { // manipulating pulsation and alpha value let glow_size = 1 + 10 * sin(this.pulsation / 1.2); let alpha_value = map(glow_size, 1, 10, 100, 200); // drawing the trail for (let i = 0; i < this.trail.length; i++) { let trail_alpha = map(i, 0, this.trail.length, 0, 180); // Fade out the trail fill(255, 255, 200, trail_alpha); ellipse(this.trail[i].x, this.trail[i].y, glow_size, glow_size); } // Draw the current firefly noStroke(); fill(255, 255, 25, alpha_value); ellipse(this.position.x, this.position.y, glow_size, glow_size); // Update pulsation for the next frame this.pulsation += this.pulsation_speed; // updating the trail array this.trail.push(createVector(this.position.x, this.position.y)); if (this.trail.length > 15) { this.trail.shift(); // keeping the trail length limited } }
Improvements
If I were to follow the fireworks theme as my inspiration, I think switches in colors would be an interesting field of exploration. Perhaps it would even be possible to make the flocking orientated more toward the vertical path and create a firing-like effect . Additionally, I believe another direction could be taking inspiration from specific microorganisms and creating a more defined system that stabilizes a little more over time.
what I meant when I said that I was reminded of fireworks: