agusman_adev_Final_Project

sketch

var angle = 0; //tree branch angle
var mic; //internal microphone
var forest = []; //holds trees
var iInc; //branch incriment
var ns = 10; //stars
var p; //moon curve variable
var q; //moon curve variable
var curveSize; //moon curve constraint

function setup() {
	createCanvas(480, 280);
	background(51);

	mic = new p5.AudioIn(); //create mic
	mic.start(); //activate mic

	//push 3 trees into array
	var tree1 = new Branch(87,10);
	forest.push(tree1);
	var tree2 = new Branch(70,70);
	forest.push(tree2);
	var tree3 = new Branch(40, 300);
	forest.push(tree3);

	flock = new Flock();

	//creating and pushing stars into an array
	for (var i = 0; i < ns; i++) {
		var p = makeStar(-10, -10,random(-50, 50), random(-50, 50));
		stars.push(p);
	}

	frameRate(10);

}

function draw() {
	background(51, 7.5);
	stroke(255,5);

	//get volume from mic (trees, stars, moon)
	var micLevel = mic.getLevel()*200;
	angle = micLevel/40;
	
	//call the function
	flock.run();

	//get volume from mic (flowy energy)
	var vol = mic.getLevel()*15;

		//if the volume is above a certain threshold, add a new flock of boids to the scene
		if (vol > 2) {
		flock.addBoid(new Boid(0, height/2)); 
		}
   
	pop(); 
	background(51,51,51,255*.2); //redrawing the background to give ghostly layering effect

		//Trees
		for(var i = 0; i < forest.length; i++){ //create multiple trees
			push();
			var xPos = forest[i].x;
			translate(xPos, height);
			forest[i].display();
			pop();
		}

		//Stars
		//if the volume exceeds a certain threshold, new stars are drawn
		if (micLevel > 10) {
			var newS = makeStar(random(10, width), random(10, height/3*2), random(-0.5, 0.5), random(-0.5, 0.5));
			stars.push(newS);
		}

		//store newly created stars
	 	newStars = []; 
		for (var i = 0; i < stars.length; i++) {
			var p = stars[i];
			p.draw();
			
			if (p.age < 200) {
				newStars.push(p);
			}
		}
   
	stars = newStars;

	//Moon
   
   	//map volume threshold to moon curve formula
	p = map (micLevel, 0, 100, 0, 100); 
	q = map (micLevel, 0, 100, 0, 130);

	curveSize = map (micLevel, 0, width, 20, 20);

	//curve formula 
	var k = p/q;
	push();
	translate (380, 70);
	iInc = map (micLevel, 0, height, 0.05, 1.5); 

		for (var i = 0; i < TWO_PI * q ; i+= iInc*1.2) {
		var r = curveSize * cos (k*i);
		var x = r * cos(i);
		var y = r * sin(i);
		fill(189, 207 , 253, 10);
		strokeWeight(iInc*5);
		point (x, y);
		fill(255);
	}  
}

//Completing the tree objects
function Branch(len, xTrans){
	this.originalTall = len;
	this.x = xTrans;
	
	this.display = function(){
		push();
		translate(50);
		branching(this.originalTall);
		pop();
	}
	
}

//Making the recursive tree
function branching(len){
	line(0,0,0,-len);
	translate(0,-len);
	stroke(255);
	if(len > 4) {
		push();
		rotate(angle);
		branching(len * 0.67);
		pop();

		push();
		rotate(-angle);
		branching(len * 0.67);
		pop();
	}
}

//Making the stars
function starDraw() {
	fill(255);
	point(this.x + random (0.1, -0.1), this.y + random(-0.1, 0.1));
}

//create the star
function makeStar(sx, sy) {
	p = {x: sx +random(-0.1, 0.1), y: sy + (-0.1, 0.1),
		 age: 0,
		 draw: starDraw
		}
	return p;
}

var stars = [];

// Starting here:
// Flocking Behavior algorithm sampled from Daniel Shiffman, "The Nature of Code" 
// http://natureofcode.com

function Flock() {
  // An array for all the boids
  this.boids = []; // Initialize boids array
}

Flock.prototype.run = function() {
  for (var i = 0; i < this.boids.length; i++) {
	this.boids[i].run(this.boids);  // Passing the entire list of boids to each boid individually
  }
}

Flock.prototype.addBoid = function(b) {
  this.boids.push(b); //
}

// Separation, Cohesion, and Alignment forces added

//defining the boid object
function Boid(x,y) {
  this.acceleration = createVector(0,0);
  this.velocity = createVector(random(-1,1),random(-1,1));
  this.position = createVector(x,y);
  this.r = 3.0; //radius of boid
  this.maxspeed = 2;    // Maximum speed
  this.maxforce = 0.05; // Maximum steering force

// Starting here:
// Our own original code

  var rr = random(70, 90); 
  var gg = random(70, 90); 
  var bb = random(80, 100); 
  this.rcolor = rr; 
  this.gcolor = gg; 
  this.bcolor = bb; 

  // Keep track of old x y coordinates of boid
  this.history = []; 
}

// Our own original code
// Ending here:

// Continuing here:
// Flocking Behavior algorithm sampled from Daniel Shiffman, "The Nature of Code" 
// http://natureofcode.com

Boid.prototype.run = function(boids) {
  this.flock(boids);
  this.update();
  this.borders();
  this.render();
}

Boid.prototype.applyForce = function(force) {
  this.acceleration.add(force);
}

// We accumulate a new acceleration each time based on three rules
Boid.prototype.flock = function(boids) {
  var sep = this.separate(boids);   // Separation
  var ali = this.align(boids);      // Alignment
  var coh = this.cohesion(boids);   // Cohesion

  // Arbitrarily weight these forces
  sep.mult(1.5);
  ali.mult(1.0);
  coh.mult(1.0);
  
  // Add the force vectors to acceleration
  this.applyForce(sep);
  this.applyForce(ali);
  this.applyForce(coh);
}

// Method to update location
Boid.prototype.update = function() {
  // Update velocity
  this.velocity.add(this.acceleration);
  // Limit speed
  this.velocity.limit(this.maxspeed);
  this.position.add(this.velocity);

  // update the property that stores old positions
  var v = [this.position.x, this.position.y]; //AG
  this.history.push(v); //AG

  // Reset accelertion to 0 each cycle
  this.acceleration.mult(0);
}

// A method that calculates and applies a steering force towards a target
// STEER = DESIRED MINUS VELOCITY
Boid.prototype.seek = function(target) {
  var desired = p5.Vector.sub(target,this.position);  // A vector pointing from the location to the target
  // Normalize desired and scale to maximum speed
  desired.normalize();
  desired.mult(this.maxspeed);
  // Steering = Desired minus Velocity
  var steer = p5.Vector.sub(desired,this.velocity);
  steer.limit(this.maxforce);  // Limit to maximum steering force
  return steer;
}

//Starting Here:
//Heavily modified perameters by us

Boid.prototype.render = function() {
  // Draw a triangle rotated in the direction of velocity
  var theta = this.velocity.heading() + radians(90);
  noFill();
  noStroke();
  push();
  translate(this.position.x,this.position.y);
  rotate(theta);
  beginShape();
  vertex(0, -this.r);
  vertex(-this.r, this.r*6); //boid size
  vertex(this.r, this.r*6); //boid size
  endShape(CLOSE);
  pop();

// Starting here:
// Our own original code

	// Displays path of old locations
	for (var i = 0; i < this.history.length; i++) { 
	  var posx = this.history[i][0]; 
	  var posy = this.history[i][1];
	  fill(this.rcolor, this.gcolor, this.bcolor, 90); 
	  ellipse(posx, posy, 5, 5);
	}
}
// Our own original code
// Ending here:

// Starting here:
// Separation, Alignment and Cohesion force algorithms sampled from Daniel Shiffman, "The Nature of Code" 
// http://natureofcode.com

// Border Constraints
Boid.prototype.borders = function() { 
  if (this.position.x < 0) {
	  this.velocity.x = -this.velocity.x; 
  }
  if (this.position.y > height) { 
	  this.velocity.y = -this.velocity.y;
  }
  if (this.history.length > 10) { 
	  this.history.shift(); 
  }
}

// Separation
// Method checks for nearby boids and steers away
Boid.prototype.separate = function(boids) {
  var desiredseparation = 25.0;
  var steer = createVector(0,0);
  var count = 0;

  // For every boid in the system, check if it's too close
  for (var i = 0; i < boids.length; i++) {
	var d = p5.Vector.dist(this.position,boids[i].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
	  var diff = p5.Vector.sub(this.position,boids[i].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(count);
  }

  // As long as the vector is greater than 0
  if (steer.mag() > 0) {

	// Implement Reynolds: Steering = Desired - Velocity
	steer.normalize();
	steer.mult(this.maxspeed);
	steer.sub(this.velocity);
	steer.limit(this.maxforce);
  }
  return steer;
}

// Alignment
// For every nearby boid in the system, calculate the average velocity
Boid.prototype.align = function(boids) {
  var neighbordist = 50;
  var sum = createVector(0,0);
  var count = 0;
  for (var i = 0; i < boids.length; i++) {
	var d = p5.Vector.dist(this.position,boids[i].position);
	if ((d > 0) & (d < neighbordist)) {
	  sum.add(boids[i].velocity);
	  count++;
	}
  }
  if (count > 0) {
	sum.div(count);
	sum.normalize();
	sum.mult(this.maxspeed);
	var steer = p5.Vector.sub(sum,this.velocity);
	steer.limit(this.maxforce);
	return steer;
  } else {
	return createVector(0,0);
  }
}

// Cohesion
// For the average location (i.e. center) of all nearby boids, calculate steering vector towards that location
Boid.prototype.cohesion = function(boids) {
  var neighbordist = 50;
  var sum = createVector(0,0);   // Start with empty vector to accumulate all locations
  var count = 0;
  for (var i = 0; i < boids.length; i++) {
	var d = p5.Vector.dist(this.position,boids[i].position);
	if ((d > 0) & (d < neighbordist)) {
	  sum.add(boids[i].position); // Add location
	  count++;
	}
  }
  if (count > 0) {
	sum.div(count);
	return this.seek(sum);  // Steer towards the location
  } else {
	return createVector(0,0);
  }
}

Anna Gusman and I created a therapeutic garden landscape that grows when it’s sung to. We chose to collaborate on this project because we were both super eager to explore p5’s comprehensive and lauded sound library. We thought that sonic interactions and audiovisual expressions would be great domains to explore by utilizing this tool.

Initially, we brainstormed ways by which people could see themselves “reflected” in a dynamic digital environment. By activating and scaling properties of the internal mic, we could poise the voice of an audience as the actuator of a captivating and therapeutic experience. The scene we designed contains four dynamic elements: recursion, flocking behavior, algorithmic curves and a particle system. Respectively, these would inform the emergence of natural objects like trees, wind, the moon and stars. Each of these dynamic elements are initiated by a singing voice and continue to grow as the viewer continues to sing! While some elements with more exposure to sound multiply, others express continued metamorphosis within themselves.

Leave a Reply