We are about to switch to a new forum software. Until then we have removed the registration on this forum.
As the title says I'm trying to create an ArrayList of SinOsc objects. When I click the mouse I want it to add a new SinOsc object to the ArrayList which will play a sine wave. The sin wave will differ in frequency and amplitude based on its x and y location on the screen. When I remove the SinOsc object from the ArrayList I want the sound to stop as well. These sinOsc objects will also be dynamically moving around the screen based on Boids behaviours that are already defined in this code. So ideally when the mouse is clicked both a boid object (which will be displayed on the screen) and a SinOsc object will be created and the same ones removed when needed. I'm having trouble making this work. Any help is appreciated!
//importing sine sound and declaring array
import processing.sound.*;
ArrayList<SinOsc> sine;
ArrayList<Boid> boids;
float globalScale = .91;
float eraseRadius = 20;
String tool = "boids";
// boid control
float maxSpeed;
float friendRadius;
float crowdRadius;
float avoidRadius;
float coheseRadius;
boolean option_friend = true;
boolean option_crowd = true;
boolean option_avoid = true;
boolean option_noise = true;
boolean option_cohese = true;
// gui crap
int messageTimer = 0;
String messageText = "";
void setup () {
size(700, 700); //3508 pixels x 4961 1754x2480 877, 1240 , just some sizes
textSize(16);
recalculateConstants();
boids = new ArrayList<Boid>();
//sine is new Arraylist with SinOsc sounds in it
sine = new ArrayList<SinOsc>();
}
void recalculateConstants () {
maxSpeed = 2.1 * globalScale;
friendRadius = 60 * globalScale;
crowdRadius = (friendRadius / 1.3);
avoidRadius = 90 * globalScale;
coheseRadius = friendRadius;
}
void draw () {
noStroke();
colorMode(HSB);
fill(0, 100);
rect(0, 0, width, height);
if (tool == "erase") {
noFill();
stroke(0, 100, 260);
rect(mouseX - eraseRadius, mouseY - eraseRadius, eraseRadius * 2, eraseRadius *2);
if (mousePressed) {
erase();
}
} else if (tool == "avoids") {
noStroke();
fill(0, 200, 200);
ellipse(mouseX, mouseY, 15, 15);
}
for (int i = 0; i <boids.size(); i++) {
Boid current = boids.get(i);
current.go();
current.draw();
}
}
void keyPressed () {
if (key == 'q') {
tool = "boids";
} else if (key == 'e') {
tool = "erase";
} else if (key == '-') {
globalScale *= 0.8;
} else if (key == '=') {
globalScale /= 0.8;
} else if (key == '1') {
option_friend = option_friend ? false : true;
} else if (key == '2') {
option_crowd = option_crowd ? false : true;
} else if (key == '3') {
option_avoid = option_avoid ? false : true;
} else if (key == '4') {
option_cohese = option_cohese ? false : true;
} else if (key == '5') {
option_noise = option_noise ? false : true;
}
recalculateConstants();
// screen shot
// if (key == 'p') {
// saveFrame("boidsMaster-######.png");
// }
}
String s(int count) {
return (count != 1) ? "s" : "";
}
String on(boolean in) {
return in ? "on" : "off";
}
void mousePressed () {
switch (tool) {
case "boids":
boids.add(new Boid(mouseX, mouseY));
//adding new sine object/ particle to arraylist
//sine.add(new SinOsc());
//does not recognise play as a function
//sine.play();
break;
}
}
void erase () {
for (int i = boids.size()-1; i > -1; i--) {
Boid b = boids.get(i);
if (abs(b.pos.x - mouseX) < eraseRadius && abs(b.pos.y - mouseY) < eraseRadius) {
boids.remove(i);
//remove sin particle from array
sine.remove(i);
//does not recognise stop as a function
//sine.stop(i);
}
}
}
class Boid {
// main fields
PVector pos;
PVector move;
float shade;
ArrayList<Boid> friends;
// timers
int thinkTimer = 0;
Boid (float xx, float yy) {
move = new PVector(0, 0);
pos = new PVector(0, 0);
pos.x = xx;
pos.y = yy;
thinkTimer = int(random(10));
shade = random(255);
friends = new ArrayList<Boid>();
}
void go () {
increment();
wrap();
if (thinkTimer ==0 ) {
// update our friend array (lots of square roots)
getFriends();
}
flock();
pos.add(move);
}
void flock () {
PVector allign = getAverageDir();
PVector avoidDir = getAvoidDir();
PVector avoidObjects = getAvoidAvoids();
PVector noise = new PVector(random(2) - 1, random(2) -1);
PVector cohese = getCohesion();
allign.mult(1);
if (!option_friend) allign.mult(0);
avoidDir.mult(1);
if (!option_crowd) avoidDir.mult(0);
avoidObjects.mult(3);
if (!option_avoid) avoidObjects.mult(0);
noise.mult(0.1);
if (!option_noise) noise.mult(0);
cohese.mult(1);
if (!option_cohese) cohese.mult(0);
stroke(0, 255, 160);
move.add(allign);
move.add(avoidDir);
move.add(avoidObjects);
move.add(noise);
move.add(cohese);
move.limit(maxSpeed);
shade += (random(2) - 1) ;
shade = (shade + 255) % 255; //max(0, min(255, shade));
}
void getFriends () {
ArrayList<Boid> nearby = new ArrayList<Boid>();
for (int i =0; i < boids.size(); i++) {
Boid test = boids.get(i);
if (test == this) continue;
if (abs(test.pos.x - this.pos.x) < friendRadius &&
abs(test.pos.y - this.pos.y) < friendRadius) {
nearby.add(test);
}
}
friends = nearby;
}
PVector getAverageDir () {
PVector sum = new PVector(0, 0);
//int count = 0;
for (Boid other : friends) {
float d = PVector.dist(pos, other.pos);
// If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
if ((d > 0) && (d < friendRadius)) {
PVector copy = other.move.copy();
copy.normalize();
copy.div(d);
sum.add(copy);
//count++;
}
//if (count > 0) {
// sum.div((float)count);
//}
}
return sum;
}
PVector getAvoidDir() {
PVector steer = new PVector(0, 0);
int count = 0;
for (Boid other : friends) {
float d = PVector.dist(pos, other.pos);
// If the distance is greater than 0 and less than an arbitrary amount (0 when you are yourself)
if ((d > 0) && (d < crowdRadius)) {
// Calculate vector pointing away from neighbor
PVector diff = PVector.sub(pos, other.pos);
diff.normalize();
diff.div(d); // Weight by distance
steer.add(diff);
count++; // Keep track of how many
}
}
if (count > 0) {
//steer.div((float) count);
}
return steer;
}
PVector getAvoidAvoids() {
PVector steer = new PVector(0, 0);
//int count = 0;
return steer;
}
PVector getCohesion () {
PVector sum = new PVector(0, 0); // Start with empty vector to accumulate all locations
int count = 0;
for (Boid other : friends) {
float d = PVector.dist(pos, other.pos);
if ((d > 0) && (d < coheseRadius)) {
sum.add(other.pos); // Add location
count++;
}
}
if (count > 0) {
sum.div(count);
PVector desired = PVector.sub(sum, pos);
return desired.setMag(0.05);
} else {
return new PVector(0, 0);
}
}
void draw () {
noStroke();
fill(255);
pushMatrix();
translate(pos.x, pos.y);
ellipse(0, 0, 5, 5);
popMatrix();
float freqMy = map(pos.y,height,0,0,500);
float ampMy = map(pos.y,0,height,0,1);
float panMx = map(pos.x,0,width,-1,1);
float add= 0;
//sine.set(freqMy,ampMy,add,panMx);
}
// update all those timers!
void increment () {
thinkTimer = (thinkTimer + 1) % 5;
}
void wrap () {
pos.x = (pos.x + width) % width;
pos.y = (pos.y + height) % height;
}
}
class SinOsc {
SinOsc(){
}
}
Answers
There is a new forum you want to post in as well
See processing main page, link to forum please
sine in line 128 is your entire array. You want to stop the current Osc so you need sine.get(i).stop() the same for play on 116.
However, having two parallel arrays like this is asking for trouble. Better to add the SinOsc to the boid class so every boid has an osc
@lanelps Please, don't forget to cross-link your posts so people can track the answers and assist more efficiently.
Kf