From b56c57a5348872c26ce27747ec318ca596f59e2a Mon Sep 17 00:00:00 2001
From: hannahilea
Date: Thu, 9 May 2024 12:27:42 -0400
Subject: [PATCH 1/7] initial commit empty
---
projects/flock-chorus/index.html | 43 ++++++++++++++++++++++++++++++++
projects/flock-chorus/sketch.js | 33 ++++++++++++++++++++++++
projects/index.html | 5 ++++
3 files changed, 81 insertions(+)
create mode 100644 projects/flock-chorus/index.html
create mode 100644 projects/flock-chorus/sketch.js
diff --git a/projects/flock-chorus/index.html b/projects/flock-chorus/index.html
new file mode 100644
index 0000000..a1c2c25
--- /dev/null
+++ b/projects/flock-chorus/index.html
@@ -0,0 +1,43 @@
+
+
+
+
+ Sketch: Flock chorus
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Details
+ A creative coding excercise (prompt: TODO), co-created with TODO
+ while at the Recurse Center
+ Usage: When prompted, grant microphone access, then TODO.
+
+
+
+
+
+
+
diff --git a/projects/flock-chorus/sketch.js b/projects/flock-chorus/sketch.js
new file mode 100644
index 0000000..4a1fa66
--- /dev/null
+++ b/projects/flock-chorus/sketch.js
@@ -0,0 +1,33 @@
+// TODO: edit this blurb!
+// Original p5 sketch {{ co-created with FOO+link}}
+// as a creative coding project while at the
+// Recurse Center (www.recurse.com/)
+
+let mic;
+
+const params = {
+ micSensitivity: 4.0,
+};
+
+const gui = new GUI();
+gui.add(params, 'micSensitivity', 0.01, 30, 2);
+
+function setup() {
+ createCanvas(windowWidth, windowHeight)
+
+ // Create an Audio input
+ mic = new p5.AudioIn();
+
+ // start the Audio Input.
+ // By default, it does not .connect() (to the computer speakers)
+ mic.start();
+}
+
+function windowResized() {
+ resizeCanvas(windowWidth, windowHeight);
+}
+
+function draw() {
+ // https://stackoverflow.com/questions/55026293/google-chrome-javascript-issue-in-getting-user-audio-the-audiocontext-was-not
+ getAudioContext().resume();
+}
diff --git a/projects/index.html b/projects/index.html
index b933f3e..2b7470d 100644
--- a/projects/index.html
+++ b/projects/index.html
@@ -58,6 +58,11 @@ Virtual Gallery
One-off creative coding projects, often small and interactive.
+ -
+ Flock chorus
+
+
TODO-description
+
-
Chrome extension: Cat Friend!
From 0d58224632eecffc4593ff163acebcb89825546e Mon Sep 17 00:00:00 2001
From: hannahilea
Date: Thu, 9 May 2024 12:37:01 -0400
Subject: [PATCH 2/7] set up project
---
projects/flock-chorus/index.html | 7 ++++---
projects/flock-chorus/sketch.js | 5 +----
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/projects/flock-chorus/index.html b/projects/flock-chorus/index.html
index a1c2c25..ea6be1e 100644
--- a/projects/flock-chorus/index.html
+++ b/projects/flock-chorus/index.html
@@ -30,10 +30,11 @@
--> -->
+ Created by modifying the p5 flocking demo.
+ Usage: Drag on screen to loose flocks of birds. Make sure your computer sound is on. May not yet work on mobile.
diff --git a/projects/flock-chorus/sketch.js b/projects/flock-chorus/sketch.js
index 4a1fa66..fbee929 100644
--- a/projects/flock-chorus/sketch.js
+++ b/projects/flock-chorus/sketch.js
@@ -1,7 +1,4 @@
-// TODO: edit this blurb!
-// Original p5 sketch {{ co-created with FOO+link}}
-// as a creative coding project while at the
-// Recurse Center (www.recurse.com/)
+// Built off of p5 flocking demo sketch https://p5js.org/examples/simulate-flocking.html
let mic;
From 3a7540c4f2c50ac0841cb8b45c75e1909ed47503 Mon Sep 17 00:00:00 2001
From: hannahilea
Date: Thu, 9 May 2024 12:44:05 -0400
Subject: [PATCH 3/7] copy in initial flocking demo
---
projects/flock-chorus/index.html | 4 +-
projects/flock-chorus/sketch.js | 222 +++++++++++++++++++++++++++++--
2 files changed, 214 insertions(+), 12 deletions(-)
diff --git a/projects/flock-chorus/index.html b/projects/flock-chorus/index.html
index ea6be1e..5502b89 100644
--- a/projects/flock-chorus/index.html
+++ b/projects/flock-chorus/index.html
@@ -32,8 +32,8 @@ Created by modifying the p5 flocking demo.
+ while at the Recurse Center -->
+ Built on top of the p5 flocking demo.
Usage: Drag on screen to loose flocks of birds. Make sure your computer sound is on. May not yet work on mobile.
diff --git a/projects/flock-chorus/sketch.js b/projects/flock-chorus/sketch.js
index fbee929..163468c 100644
--- a/projects/flock-chorus/sketch.js
+++ b/projects/flock-chorus/sketch.js
@@ -1,23 +1,23 @@
// Built off of p5 flocking demo sketch https://p5js.org/examples/simulate-flocking.html
-let mic;
+let flock;
const params = {
- micSensitivity: 4.0,
+ // micSensitivity: 4.0,
};
const gui = new GUI();
-gui.add(params, 'micSensitivity', 0.01, 30, 2);
+// gui.add(params, 'micSensitivity', 0.01, 30, 2);
function setup() {
createCanvas(windowWidth, windowHeight)
- // Create an Audio input
- mic = new p5.AudioIn();
-
- // start the Audio Input.
- // By default, it does not .connect() (to the computer speakers)
- mic.start();
+ flock = new Flock();
+ // Add an initial set of boids into the system
+ for (let i = 0; i < 100; i++) {
+ let b = new Boid(width / 2, height / 2);
+ flock.addBoid(b);
+ }
}
function windowResized() {
@@ -26,5 +26,207 @@ function windowResized() {
function draw() {
// https://stackoverflow.com/questions/55026293/google-chrome-javascript-issue-in-getting-user-audio-the-audiocontext-was-not
- getAudioContext().resume();
+ // getAudioContext().resume();
+
+ background(51);
+ flock.run();
+}
+
+// Add a new boid into the System
+function mouseDragged() {
+ flock.addBoid(new Boid(mouseX, mouseY));
+}
+
+// The Nature of Code
+// Daniel Shiffman
+// http://natureofcode.com
+
+// Flock object
+// Does very little, simply manages the array of all the boids
+
+function Flock() {
+ // An array for all the boids
+ this.boids = []; // Initialize the array
+}
+
+Flock.prototype.run = function () {
+ for (let 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);
+}
+
+// The Nature of Code
+// Daniel Shiffman
+// http://natureofcode.com
+
+// Boid class
+// Methods for Separation, Cohesion, Alignment added
+
+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;
+ this.maxspeed = 3; // Maximum speed
+ this.maxforce = 0.05; // Maximum steering force
+}
+
+Boid.prototype.run = function (boids) {
+ this.flock(boids);
+ this.update();
+ this.borders();
+ this.render();
+}
+
+Boid.prototype.applyForce = function (force) {
+ // We could add mass here if we want A = F / M
+ this.acceleration.add(force);
+}
+
+// We accumulate a new acceleration each time based on three rules
+Boid.prototype.flock = function (boids) {
+ let sep = this.separate(boids); // Separation
+ let ali = this.align(boids); // Alignment
+ let 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);
+ // 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) {
+ let 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
+ let steer = p5.Vector.sub(desired, this.velocity);
+ steer.limit(this.maxforce); // Limit to maximum steering force
+ return steer;
+}
+
+Boid.prototype.render = function () {
+ // Draw a triangle rotated in the direction of velocity
+ let theta = this.velocity.heading() + radians(90);
+ fill(127);
+ stroke(200);
+ push();
+ translate(this.position.x, this.position.y);
+ rotate(theta);
+ beginShape();
+ vertex(0, -this.r * 2);
+ vertex(-this.r, this.r * 2);
+ vertex(this.r, this.r * 2);
+ endShape(CLOSE);
+ pop();
+}
+
+// Wraparound
+Boid.prototype.borders = function () {
+ if (this.position.x < -this.r) this.position.x = width + this.r;
+ if (this.position.y < -this.r) this.position.y = height + this.r;
+ if (this.position.x > width + this.r) this.position.x = -this.r;
+ if (this.position.y > height + this.r) this.position.y = -this.r;
+}
+
+// Separation
+// Method checks for nearby boids and steers away
+Boid.prototype.separate = function (boids) {
+ let desiredseparation = 25.0;
+ let steer = createVector(0, 0);
+ let count = 0;
+ // For every boid in the system, check if it's too close
+ for (let i = 0; i < boids.length; i++) {
+ let 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
+ let 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) {
+ let neighbordist = 50;
+ let sum = createVector(0, 0);
+ let count = 0;
+ for (let i = 0; i < boids.length; i++) {
+ let 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);
+ let 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) {
+ let neighbordist = 50;
+ let sum = createVector(0, 0); // Start with empty vector to accumulate all locations
+ let count = 0;
+ for (let i = 0; i < boids.length; i++) {
+ let 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);
+ }
}
From 5a1e4fc4bc6d8b0debbace7cdb5db2a8b9d70525 Mon Sep 17 00:00:00 2001
From: hannahilea
Date: Thu, 9 May 2024 12:52:18 -0400
Subject: [PATCH 4/7] add world wrapping param
---
projects/flock-chorus/index.html | 2 +-
projects/flock-chorus/sketch.js | 10 ++++++++--
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/projects/flock-chorus/index.html b/projects/flock-chorus/index.html
index 5502b89..a6a06a0 100644
--- a/projects/flock-chorus/index.html
+++ b/projects/flock-chorus/index.html
@@ -5,7 +5,7 @@
Sketch: Flock chorus
-
+
diff --git a/projects/flock-chorus/sketch.js b/projects/flock-chorus/sketch.js
index 163468c..683d5cb 100644
--- a/projects/flock-chorus/sketch.js
+++ b/projects/flock-chorus/sketch.js
@@ -3,11 +3,11 @@
let flock;
const params = {
- // micSensitivity: 4.0,
+ worldWraps: true,
};
const gui = new GUI();
-// gui.add(params, 'micSensitivity', 0.01, 30, 2);
+gui.add(params, 'worldWraps').name("Wrap world");
function setup() {
createCanvas(windowWidth, windowHeight)
@@ -53,6 +53,12 @@ Flock.prototype.run = function () {
for (let i = 0; i < this.boids.length; i++) {
this.boids[i].run(this.boids); // Passing the entire list of boids to each boid individually
}
+ if (!params.worldWraps) {
+ // If the world doesn't wrap, remove all boids that have flown off screen
+ this.boids = this.boids.filter((b) => {
+ return b.position.x <= windowWidth && b.position.x >= 0 && b.position.y <= windowHeight && b.position.y >= 0;
+ });
+ }
}
Flock.prototype.addBoid = function (b) {
From 2d3e5b8b21f1875f451a10d99d310ccc3d3ae3f1 Mon Sep 17 00:00:00 2001
From: hannahilea
Date: Thu, 9 May 2024 16:08:50 -0400
Subject: [PATCH 5/7] wip working
---
projects/flock-chorus/index.html | 3 ++-
projects/flock-chorus/sketch.js | 24 +++++++++++++++++++-----
2 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/projects/flock-chorus/index.html b/projects/flock-chorus/index.html
index a6a06a0..0cb7e19 100644
--- a/projects/flock-chorus/index.html
+++ b/projects/flock-chorus/index.html
@@ -5,7 +5,8 @@
Sketch: Flock chorus
-
+
+
diff --git a/projects/flock-chorus/sketch.js b/projects/flock-chorus/sketch.js
index 683d5cb..98554ba 100644
--- a/projects/flock-chorus/sketch.js
+++ b/projects/flock-chorus/sketch.js
@@ -3,14 +3,22 @@
let flock;
const params = {
- worldWraps: true,
+ worldWraps: false,
+ maxspeed: 2,
+ maxforce: 0.05, // Maximum steering force
+ radius: 3,
};
const gui = new GUI();
gui.add(params, 'worldWraps').name("Wrap world");
+const guiFolder = gui.addFolder( 'Settings for spawned boids' );
+guiFolder.add(params, 'maxspeed', 0, 8, .5).name("Max speed");
+guiFolder.add(params, 'maxforce', 0, .1, .01).name("Max steering force");
+guiFolder.add(params, 'radius', .1, 10, .3).name("Size");
function setup() {
createCanvas(windowWidth, windowHeight)
+ // Tone.start();
flock = new Flock();
// Add an initial set of boids into the system
@@ -26,7 +34,7 @@ function windowResized() {
function draw() {
// https://stackoverflow.com/questions/55026293/google-chrome-javascript-issue-in-getting-user-audio-the-audiocontext-was-not
- // getAudioContext().resume();
+ getAudioContext().resume();
background(51);
flock.run();
@@ -76,9 +84,10 @@ 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;
- this.maxspeed = 3; // Maximum speed
- this.maxforce = 0.05; // Maximum steering force
+ this.r = params.radius;
+ this.maxspeed = params.maxspeed; // Maximum speed
+ this.maxforce = params.maxforce; // Maximum steering force
+ // this.synth = new Tone.Synth().toDestination();
}
Boid.prototype.run = function (boids) {
@@ -187,7 +196,12 @@ Boid.prototype.separate = function (boids) {
steer.mult(this.maxspeed);
steer.sub(this.velocity);
steer.limit(this.maxforce);
+
+ // Play collision sound!
+ // console.log(this, "ping", steer.mag())
+ // this.synth.triggerAttackRelease("C4", "8n")
}
+
return steer;
}
From 6d75554f009ad5f4462c1a565639a3a0e7b8a235 Mon Sep 17 00:00:00 2001
From: hannahilea
Date: Thu, 9 May 2024 17:47:11 -0400
Subject: [PATCH 6/7] presented version
---
projects/flock-chorus/index.html | 22 +++++++++++++------
projects/flock-chorus/sketch.js | 37 ++++++++++++++++++++++----------
projects/index.html | 4 ++--
3 files changed, 44 insertions(+), 19 deletions(-)
diff --git a/projects/flock-chorus/index.html b/projects/flock-chorus/index.html
index 0cb7e19..ee018cc 100644
--- a/projects/flock-chorus/index.html
+++ b/projects/flock-chorus/index.html
@@ -4,9 +4,8 @@
Sketch: Flock chorus
-
-
+
@@ -20,6 +19,19 @@
}
+
@@ -31,13 +43,11 @@ @hannahilea > projects > Sk
Details
-
Built on top of the p5 flocking demo.
Usage: Drag on screen to loose flocks of birds. Make sure your computer sound is on. May not yet work on mobile.
+
-
+
diff --git a/projects/flock-chorus/sketch.js b/projects/flock-chorus/sketch.js
index 98554ba..159c8a2 100644
--- a/projects/flock-chorus/sketch.js
+++ b/projects/flock-chorus/sketch.js
@@ -1,31 +1,35 @@
// Built off of p5 flocking demo sketch https://p5js.org/examples/simulate-flocking.html
-
+console.log("Access to tone module?", Tone)
let flock;
const params = {
worldWraps: false,
- maxspeed: 2,
+ maxspeed: .5, //2,
maxforce: 0.05, // Maximum steering force
radius: 3,
+ targetFreqHz: 440,
+ maxStartOffsetHz: 100,
};
const gui = new GUI();
gui.add(params, 'worldWraps').name("Wrap world");
const guiFolder = gui.addFolder( 'Settings for spawned boids' );
+guiFolder.add(params, 'targetFreqHz', 27, 2350, 5).name("Target freq (Hz)");
+guiFolder.add(params, 'maxStartOffsetHz', 0, 100, 1);
guiFolder.add(params, 'maxspeed', 0, 8, .5).name("Max speed");
guiFolder.add(params, 'maxforce', 0, .1, .01).name("Max steering force");
guiFolder.add(params, 'radius', .1, 10, .3).name("Size");
function setup() {
createCanvas(windowWidth, windowHeight)
- // Tone.start();
+ Tone.start();
flock = new Flock();
// Add an initial set of boids into the system
- for (let i = 0; i < 100; i++) {
- let b = new Boid(width / 2, height / 2);
- flock.addBoid(b);
- }
+ // for (let i = 0; i < 100; i++) {
+ // let b = new Boid(width / 2, height / 2);
+ // flock.addBoid(b);
+ // }
}
function windowResized() {
@@ -34,14 +38,14 @@ function windowResized() {
function draw() {
// https://stackoverflow.com/questions/55026293/google-chrome-javascript-issue-in-getting-user-audio-the-audiocontext-was-not
- getAudioContext().resume();
+ // getAudioContext().resume();
background(51);
flock.run();
}
// Add a new boid into the System
-function mouseDragged() {
+function mouseClicked() {
flock.addBoid(new Boid(mouseX, mouseY));
}
@@ -87,7 +91,11 @@ function Boid(x, y) {
this.r = params.radius;
this.maxspeed = params.maxspeed; // Maximum speed
this.maxforce = params.maxforce; // Maximum steering force
- // this.synth = new Tone.Synth().toDestination();
+ this.targetFreqHz = params.targetFreqHz;
+ this.synth = new Tone.PolySynth().toDestination();
+ this.synth.volume.value = -12
+ this.currentFreqHz = this.targetFreqHz + params.maxStartOffsetHz; //TODO: allow negative, randomize idff
+ this.synth.triggerAttack(this.currentFreqHz)
}
Boid.prototype.run = function (boids) {
@@ -187,6 +195,14 @@ Boid.prototype.separate = function (boids) {
// Average -- divide by how many
if (count > 0) {
steer.div(count);
+ // console.log(count,this.currentFreqHz, this.targetFreqHz)
+ if (this.currentFreqHz > this.targetFreqHz) {
+ this.currentFreqHz = this.currentFreqHz - 1;
+ // this.synth.triggerRelease()
+ this.synth.triggerAttack(this.currentFreqHz, Tone.now())
+ this.synth.releaseAll()
+ console.log("OK")
+ }
}
// As long as the vector is greater than 0
@@ -199,7 +215,6 @@ Boid.prototype.separate = function (boids) {
// Play collision sound!
// console.log(this, "ping", steer.mag())
- // this.synth.triggerAttackRelease("C4", "8n")
}
return steer;
diff --git a/projects/index.html b/projects/index.html
index 2b7470d..a68e7d1 100644
--- a/projects/index.html
+++ b/projects/index.html
@@ -58,11 +58,11 @@ Virtual Gallery
One-off creative coding projects, often small and interactive.