This started as a travel in New York and Boston in November 2017. The travel was realized thanks to Fuorirotta, who supported me with a crowdfunding campaign.
The travel was conceived to record a series of audio-interviews on science, creativity and how they mix to engage the public.
It started and never progressed up to the point when suddenly, it did. How was that possible? The boredom of letting things uncompleted got the best of me, unbelievable but true
The travel was conceived to record a series of audio-interviews on science, creativity and how they mix to engage the public.
It started and never progressed up to the point when suddenly, it did. How was that possible? The boredom of letting things uncompleted got the best of me, unbelievable but true
show code
// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com
// Demonstration of Craig Reynolds' "Flocking" behavior
// See: http://www.red3d.com/cwr/
// Rules: Cohesion, Separation, Alignment
// Click mouse to add boids into the system
PShape boh,me;
Flock flock;
float gravity=3;
float mass=2;
int life;
public static float bound=90;
//public static float BBound=50;
void setup() {
size(900,200);
flock = new Flock();
boh = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/boh.svg");
// PShape MARIO = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/MARIO.svg");
PShape Anonimo = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/Anonimo.svg");
// PShape Martino = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/Martino.svg");
PShape Nathan = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/Nathan.svg");
// PShape LALLA = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/LALLA.svg");
// PShape aldo = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/aldo.svg");
// PShape matto = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/matto.svg");
// PShape parrot = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/parrot.svg");
// PShape piero = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/piero.svg");
// PShape nada = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/nada.svg");
// PShape cactolo = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/cactolo.svg");
// PShape magolo = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/magolo.svg");
// PShape genio = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/genio.svg");
// PShape next = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/next.svg");
// PShape pollo = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/pollo.svg");
// PShape hoho = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/hoho.svg");
// PShape zorro = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/zorro.svg");
me = loadShape("http://sciencelasagna.org/wp-content/uploads/2019/08/me.svg");
life=-1; // this way never goes to zero
// Add an initial set of boids into the system
flock.addBoid(new Boid(random(width),random(height), me,80,gravity,mass,life));
// flock.addBoid(new Boid(random(width),random(height), MARIO,80,gravity,mass,life));
// flock.addBoid(new Boid(random(width),random(height), Anonimo,80,gravity,mass,life));
// flock.addBoid(new Boid(random(width),random(height), Martino,80,gravity,mass,life));
// flock.addBoid(new Boid(random(width),random(height), Nathan,80,gravity,mass,life));
// flock.addBoid(new Boid(random(width),random(height), LALLA,80,gravity,mass,life));
// flock.addBoid(new Boid(random(width),random(height), aldo,80,gravity,mass,life));
// flock.addBoid(new Boid(random(width),random(height), matto,80,gravity,mass,life));
// flock.addBoid(new Boid(random(width),random(height), parrot,80,gravity,mass,life));
// flock.addBoid(new Boid(random(width),random(height), piero,80,gravity,mass,life));
// flock.addBoid(new Boid(random(width),random(height), nada,80,gravity,mass,life));
// flock.addBoid(new Boid(random(width),random(height), cactolo,80,gravity,mass,life));
// flock.addBoid(new Boid(random(width),random(height), magolo,80,gravity,mass,life));
// flock.addBoid(new Boid(random(width),random(height), genio,80,gravity,mass,life));
// flock.addBoid(new Boid(random(width),random(height), next,80,gravity,mass,life));
// flock.addBoid(new Boid(random(width),random(height), pollo,80,gravity,mass,life));
// flock.addBoid(new Boid(random(width),random(height), hoho,80,gravity,mass,life));
// flock.addBoid(new Boid(random(width),random(height), zorro,80,gravity,mass,life));
for (int i = 0; i < 2; i++) {
Boid b = new Boid(width/2,height/2, boh,20,gravity,mass,life);
flock.addBoid(b);
}
}
void draw() {
background(255);
stroke(175);
noFill();
rectMode(CENTER);
//rect(width/2, height/2, width-bound*2, height-bound*2);
//rect(width/2, height/2, width-BBound*2, height-BBound*2);
PVector mouse = new PVector(mouseX, mouseY);
flock.run(mouse);
// Instructions
fill(0);
//text("Clicca per mescolare il raguDrag the mouse to generate new boids.",10,height-16);
}
//Add a new boid into the System
void mouseDragged() {
if (keyPressed == true) {
life=1000;
flock.addBoid(new Boid(mouseX,mouseY,boh,20,gravity,mass,life));
}
}
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// @@@@@@@@@@@@@@start Boid@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com
// Boid class
// Methods for Separation, Cohesion, Alignment added
class Boid {
PVector position;
PVector velocity;
PVector acceleration;
float r;
float maxforce; // Maximum steering force
float maxspeed; // Maximum speed @@@ posso farla anche random!!
PShape boh;
PVector mouse;
boolean moreaway;
float gravity; //gravity variable
float mass; //mass variable
int life;
float dist;
int rFig;
Boid(float x, float y, PShape tboh, int trFig,float tgravity,float tmass,int tlife) {
life=tlife;
rFig=trFig;
acceleration = new PVector(0,0);
boh=tboh;
gravity=tgravity;
mass=tmass;
velocity = new PVector(random(-1,1),random(-1,1));
position = new PVector(x,y);
r = 3.0;
maxspeed = 3;
maxforce = 0.02;
}
void run(ArrayList<Boid> boids, PVector tmouse) {
if (life!=0) {//checking if it is still alive
life=life-1;
}
mouse=tmouse;
flock(boids);
//checkEdges();
update();
render();
}
void applyForce(PVector force) {
// We could add mass here if we want A = F / M
acceleration.add(force);
}
// We accumulate a new acceleration each time based on three rules
void flock(ArrayList<Boid> boids) {
PVector sep = separate(boids); // Separation
PVector ali = align(boids); // Alignment
PVector coh = cohesion(boids); // Cohesion
PVector mescola = new PVector(0,0);
PVector mouse = new PVector(mouseX,mouseY);
PVector diff = PVector.sub(position,mouse);
if ((mousePressed== true)&&(keyPressed == false)&&(diff.mag()>20) ) {
mescola = mix(mouseX,mouseY);
}
// Arbitrarily weight these forces
sep.mult(0.2);
ali.mult(0.1);
coh.mult(0.1);
mescola.mult(0.2);
// Add the force vectors to acceleration
applyForce(sep);
applyForce(ali);
applyForce(coh);
applyForce(mescola);
}
// Method to update position
void update() {
// Update velocity
velocity.add(acceleration);
// Limit speed
velocity.limit(maxspeed);
// questo lo metto qui perchè prima voglio aver calcolato la velocità x o y complessiva (che uso in boundaries)
PVector away = boundaries(); // check the proximity to boundaries of this boid
if (away!=null) {
//if (moreaway==false) {
away.mult(0.8);
//else {away.mult(2.5);}
applyForce(away);
// REUpdate velocity
velocity.add(acceleration);
// RELimit speed
velocity.limit(maxspeed);
}
position.add(velocity);
// Reset accelertion to 0 each cycle
acceleration.mult(0);
}
// A method that calculates and applies a steering force towards a target
// STEER = DESIRED MINUS VELOCITY
PVector seek(PVector target) {
PVector desired = PVector.sub(target,position); // A vector pointing from the position to the target
//@@@ steering force = desired velocity - current velocity
// Normalize desired and scale to maximum speed
desired.normalize();
desired.mult(maxspeed);
// Steering = Desired minus Velocity
PVector steer = PVector.sub(desired,velocity);
steer.limit(maxforce); // Limit to maximum steering force
return steer;
}
void render() {
// Draw a triangle rotated in the direction of velocity
float theta = velocity.heading2D() + radians(90);
fill(175);
stroke(0);
pushMatrix();
translate(position.x,position.y);
rotate(theta);
beginShape();
shape(boh, 0,0, rFig, rFig);
//ellipse(0,0,20, 20);
// vertex(0, -r*2);
// vertex(-r, r*2);
// vertex(r, r*2);
endShape();
popMatrix();
}
// Wraparound
//void borders() {
// if (position.x < -r) position.x = width+r;
// if (position.y < -r) position.y = height+r;
// if (position.x > width+r) position.x = -r;
// if (position.y > height+r) position.y = -r;
//}
// Separation
// Method checks for nearby boids and steers away
PVector separate (ArrayList<Boid> boids) {
float desiredseparation = 25.0f;
PVector steer = new PVector(0,0,0);
int count = 0;
// For every boid in the system, check if it's too close
for (Boid other : boids) {
float d = PVector.dist(position,other.position);
// If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
if ((d > 0) && (d < desiredseparation)) {
// Calculate vector pointing away from neighbor
PVector diff = PVector.sub(position,other.position);
diff.normalize();
diff.div(d); // Weight by distance
steer.add(diff);
count++; // Keep track of how many
}
}
// Average -- divide by how many
if (count > 0) {
steer.div((float)count);
}
// As long as the vector is greater than 0
if (steer.mag() > 0) {
// Implement Reynolds: Steering = Desired - Velocity
steer.normalize();
steer.mult(maxspeed);
steer.sub(velocity);
steer.limit(maxforce);
}
return steer;
}
// Alignment
// For every nearby boid in the system, calculate the average velocity
PVector align (ArrayList<Boid> boids) {
float neighbordist = 50;
PVector sum = new PVector(0,0);
int count = 0;
for (Boid other : boids) {
float d = PVector.dist(position,other.position);
if ((d > 0) && (d < neighbordist)) {
sum.add(other.velocity);
count++;
}
}
if (count > 0) {
sum.div((float)count);
sum.normalize();
sum.mult(maxspeed);
PVector steer = PVector.sub(sum,velocity);
steer.limit(maxforce);
return steer;
} else {
return new PVector(0,0);
}
}
// Cohesion
// For the average position (i.e. center) of all nearby boids, calculate steering vector towards that position
PVector cohesion (ArrayList<Boid> boids) {
float neighbordist = 50;
PVector sum = new PVector(0,0); // Start with empty vector to accumulate all positions
int count = 0;
for (Boid other : boids) {
float d = PVector.dist(position,other.position);
if ((d > 0) && (d < neighbordist)) {
sum.add(other.position); // Add position
count++;
}
}
if (count > 0) {
sum.div(count);
return seek(sum); // Steer towards the position
} else {
return new PVector(0,0);
}
}
PVector boundaries() {
PVector steer = null;
moreaway=false;
PVector desired = null;
if (position.x < bound) {
desired = new PVector(maxspeed, velocity.y);
}
else if (position.x > width -bound) {
desired = new PVector(-maxspeed, velocity.y);
}
if (position.y < bound) {
desired = new PVector(velocity.x, maxspeed);
}
else if (position.y > height-bound) {
desired = new PVector(velocity.x, -maxspeed);
}
if (desired != null) {
desired.normalize();
desired.mult(maxspeed);
steer = PVector.sub(desired, velocity);
steer.limit(maxforce);
//applyForce(steer);
}
return(steer);
}
//math for attraction and repulsion forces
//tx and ty are the co-ordinates attraction/repulsion will be applied to
PVector mix(float tx, float ty){
PVector targetLoc = new PVector(tx, ty); //creating new vector for attractive/repulsive x and y values
PVector dir = PVector.sub(position, targetLoc); //calculate the direction between a particle and targetLoc
dist = dir.mag(); //calculate how far away the particle is from targetLoc
dir.normalize(); //convert the measurement to a unit vector
//calculate the strength of the force by factoring in a gravitational constant and the mass of a particle
//multiply by distance^2
float force = (gravity*mass) / (dist*dist);
//if the mouse is pressed, turn on repulsion by multiplying direction by 1
//if(mousePressed){
dir.mult(-1);
//}
//else multiply the direction by -1 to switch the direction the particle travels in (attraction)
//else{
// dir.mult(-1);
//}
//apply directional vector
//applyRepulsion(dir);
dir.div(mass);
return(dir);
}
//method to apply a force vector to the particle
//void applyRepulsion(PVector force){
//force.div(mass);
//acc.add(force);
//}
//
//void checkEdges() { if (position.x > width) {
// position.x = width;
// }
// else if (position.x < 0) {
// position.x = 0;
// }
// if (position.y > height) {
// position.y = height;
// }
// else if (position.y < 0) { position.y = 0;
// }
// }
}
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// @@@@@@@@@@@@@@start Flock@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// The Nature of Code
// Daniel Shiffman
// http://natureofcode.com
// Flock class
// Does very little, simply manages the ArrayList of all the boids
class Flock {
ArrayList<Boid> boids; // An ArrayList for all the boids
ArrayList<Boid> toremove;
Flock() {
boids = new ArrayList<Boid>(); // Initialize the ArrayList
}
void run(PVector tmouse) {
toremove=new ArrayList<Boid>(0);
for (Boid b : boids) {
b.run(boids,tmouse);
if (b.life==0) {
toremove.add(b);
}
// Passing the entire list of boids to each boid individually
}
for (Boid b : toremove) {
boids.remove(b);
}
}
void addBoid(Boid b) {
boids.add(b);
}
}
After the campaign, I drew a few simple shapes, one for each supporter, and after the travel I drew new ones, one for each people I interviewed. I let them simmer and interact in this space, which I envision as virtual ragu’ sauce, the key ingredient for a great lasagna.
Be First to Comment