We are about to switch to a new forum software. Until then we have removed the registration on this forum.
I'm working on a boids flocking project. My goal is to have several draggable objects which have to be avoided by the boids. There are several different flocks with a different starting position.
I managed to get the boids to avoid one draggable object. But I can't seem to make them avoid all. (using a for loop)
I really can't figure out why this won't do the trick..
I hope you could give me some suggestions.
the code:
int initBoidNum = 100; //amount of boids to start the program with
BoidList flock1,flock2,flock3;
Draggable draggable;
NullDraggableObject nullDraggableObject;
ArrayList draggables;
int id;
float[] xposs= new float[10];
float[] yposs= new float[10];
String turn;
void setup()
{
size(1000,700);
//create and fill the list of boids
flock1 = new BoidList(150,0, 10, 100);
flock2 = new BoidList(150,255, 10,200);
flock3 = new BoidList(150,150, 10,300);
turn = "turn";
nullDraggableObject = new NullDraggableObject();
draggables = new ArrayList();
for(int i = 0; i < 10; i++)
draggables.add(new DraggableObject(random(width), random(height/2)));
}
void draw()
{
background(100, 60);
flock1.run();
flock2.run();
flock3.run();
stroke(255);
noFill();
draggable = nullDraggableObject;
for(id = 0; id < draggables.size(); id++)
{
Draggable d = (Draggable)draggables.get(id);
d.draw();
if(d.isBeingMouseHovered())
draggable = d;
}
}
void mousePressed() {
draggable.mousePressed();
}
void mouseDragged() {
draggable.mouseDragged();
}
void mouseReleased() {
draggable.mouseReleased();
}
interface Draggable{
boolean isBeingMouseHovered();
boolean inside(float ix, float iy);
void draw();
void mousePressed();
void mouseDragged();
void mouseReleased();
}
class NullDraggableObject implements Draggable{
boolean isBeingMouseHovered(){ return false;}
boolean inside(float ix, float iy){return false;}
void draw(){}
void mousePressed(){}
void mouseDragged(){}
void mouseReleased(){}
}
public class DraggableObject implements Draggable {
float XX, YY;
float radius;
boolean drag;
float dragX, dragY;
DraggableObject(float _x, float _y) {
XX = _x; YY = _y;
radius = 50;
drag = false;
dragX = 0;
dragY = 0;
}
boolean isBeingMouseHovered()
{
return inside(mouseX, mouseY);
}
boolean inside(float ix, float iy) {
return (dist(XX, YY, ix, iy) < radius);
}
void draw() {
ellipseMode(CENTER);
ellipse(XX, YY, 2*radius, 2*radius);
String space = "__";
println(id); println(XX); println(YY);
xposs[id] = XX;
yposs[id] = YY;
// String yy = "y:";
// String xx = "x:";
// println(xx);
// println(xposs);
// println(yy);
// println(yposs);
}
void mousePressed() {
drag = inside(mouseX, mouseY);
if (drag) {
dragX = mouseX - XX;
dragY = mouseY - YY;
}
}
void mouseDragged() {
if (drag) {
XX = mouseX - dragX;
YY = mouseY - dragY;
}
}
void mouseReleased() {
drag = false;
}
}
class Boid
{
//fields
PVector pos, vel, acc, ali, coh, sep; //pos, velocity, and acceleration in a vector datatype
float neighborhoodRadius; //radius in which it looks for fellow boids
float maxSpeed = 1; //maximum magnitude for the velocity vector
float maxSteerForce = .05; //maximum magnitude of the steering vector
float sMod, aMod, cMod; //modifiers for the three forces on the boid
float h; //hue
//constructors
Boid(PVector inPos)
{
pos = new PVector();
pos.set(inPos);
vel = new PVector(random(-1, 1), random(-1, 1));
acc = new PVector(0, 0);
neighborhoodRadius = 20;
sMod = 1;
aMod = 1;
cMod = 4;
}
Boid(PVector inPos, PVector inVel, float r)
{
pos = new PVector();
pos.set(inPos);
vel = new PVector();
vel.set(inVel);
acc = new PVector(0, 0);
neighborhoodRadius = r;
}
void run(ArrayList bl)
{
//println(xposs[1]);
//println(yposs[1]);
for (int i =0; i < 10; i++){
acc.add(attract(new PVector(width/2, height/2), true));
acc.add(avoid(new PVector(xposs[i], yposs[i]), true));
if (i == 10)
i = 0;
}
if (pos.x>width-10)acc.add(bounce(new PVector(width, pos.y), true));
if (pos.x<10) acc.add(bounce(new PVector(0, pos.y), true));
;
if (pos.y>height-10) acc.add(bounce(new PVector(pos.x, height), true));
;
if (pos.y<10) acc.add(bounce(new PVector(pos.x, 0), true));
;
ali = alignment(bl);
coh = cohesion(bl);
sep = seperation(bl);
for (int i =0; i < 10; i++) {
if (PVector.dist(new PVector(xposs[i], yposs[i]), pos)>180)
{
acc.add(PVector.mult(ali, aMod));
acc.add(PVector.mult(coh, cMod));
acc.add(PVector.mult(sep, sMod));
}
if (PVector.dist(new PVector(xposs[i], yposs[i]), pos)<80)
maxSpeed = 1000;
if (i == 10)
i = 0;
}
if (PVector.dist(new PVector(width, height), pos)<60)
maxSpeed = 1000;
//println(turn);
if (PVector.dist(new PVector(0, 0), pos)<50)
maxSpeed = 1000;
//////
else
maxSpeed = 1;
move();
checkBounds();
render();
}
void move()
{
vel.add(acc); //add acceleration to velocity
vel.limit(maxSpeed); //make sure the velocity vector magnitude does not exceed maxSpeed
pos.add(vel); //add velocity to position
acc.mult(0); //reset acceleration
}
void checkBounds()
{
// if(pos.x>width) pos.x=0;
// if(pos.x<0) pos.x=width;
// if(pos.y>height) pos.y=0;
// if(pos.y<0) pos.y=height;
}
void render()
{
pushMatrix();
translate(pos.x, pos.y);
rotate(atan2(vel.y, vel.x)); //rotate drawing matrix to direction of velocity
stroke(0);
noFill();
ellipse(0,0,neighborhoodRadius/2,neighborhoodRadius/2);
noStroke();
fill(h);
//draw triangle
beginShape(TRIANGLES);
rect(0,0,6,2);
// vertex(6, 0);
//vertex(-6, 2);
//vertex(-6, -2);
endShape();
popMatrix();
}
//steering. If arrival==true, the boid slows to meet the target. Credit to Craig Reynolds
PVector steer(PVector target, boolean arrival)
{
PVector steer = new PVector(); //creates vector for steering
if (!arrival)
{
steer.set(PVector.sub(target, pos)); //steering vector points towards target (switch target and pos for avoiding)
steer.limit(maxSteerForce); //limits the steering force to maxSteerForce
} else
{
PVector targetOffset = PVector.sub(target, pos);
float distance=targetOffset.mag();
float rampedSpeed = maxSpeed*(distance/100);
float clippedSpeed = min(rampedSpeed, maxSpeed);
PVector desiredVelocity = PVector.mult(targetOffset, (clippedSpeed/distance));
steer.set(PVector.sub(desiredVelocity, vel));
}
return steer;
}
//avoid. If weight == true avoidance vector is larger the closer the boid is to the target
PVector avoid(PVector target, boolean weight)
{
PVector steer = new PVector(); //creates vector for steering
steer.set(PVector.sub(pos, target)); //steering vector points away from target
if (weight)
steer.mult(1/sq(PVector.dist(pos, target)));
//steer.limit(maxSteerForce); //limits the steering force to maxSteerForce
return steer;
}
PVector attract(PVector target, boolean weight)
{
PVector steer = new PVector(); //creates vector for steering
steer.set(PVector.sub(target, pos)); //steering vector points away from target
if (weight)
steer.mult(1/sq(PVector.dist(target, pos)));
//steer.limit(maxSteerForce); //limits the steering force to maxSteerForce
return steer;
}
PVector bounce(PVector target, boolean weight)
{
PVector steer = new PVector(); //creates vector for steering
steer.set(PVector.sub(pos, target)); //steering vector points away from target
if (weight)
steer.mult(1/sq(PVector.dist(pos, target)));
//steer.limit(maxSteerForce); //limits the steering force to maxSteerForce
return steer;
}
PVector seperation(ArrayList boids)
{
PVector posSum = new PVector(0, 0);
PVector repulse;
for (int i=0; i<boids.size (); i++)
{
Boid b = (Boid)boids.get(i);
float d = PVector.dist(pos, b.pos);
if (d>0&&d<=neighborhoodRadius)
{
repulse = PVector.sub(pos, b.pos);
repulse.normalize();
repulse.div(d);
posSum.add(repulse);
}
}
return posSum;
}
PVector alignment(ArrayList boids)
{
PVector velSum = new PVector(0, 0);
int count = 0;
for (int i=0; i<boids.size (); i++)
{
Boid b = (Boid)boids.get(i);
float d = PVector.dist(pos, b.pos);
if (d>0&&d<=neighborhoodRadius)
{
velSum.add(b.vel);
count++;
}
}
if (count>0)
{
velSum.div((float)count);
velSum.limit(maxSteerForce);
}
return velSum;
}
PVector cohesion(ArrayList boids)
{
PVector posSum = new PVector(0, 0);
PVector steer = new PVector(0, 0);
int count = 0;
for (int i=0; i<boids.size (); i++)
{
Boid b = (Boid)boids.get(i);
float d = dist(pos.x, pos.y, b.pos.x, b.pos.y);
if (d>0&&d<=neighborhoodRadius)
{
posSum.add(b.pos);
count++;
}
}
if (count>0)
{
posSum.div((float)count);
}
steer = PVector.sub(posSum, pos);
steer.limit(maxSteerForce);
return steer;
}
}
class BoidList
{
ArrayList boids; //will hold the boids in this BoidList
float h; //for color
BoidList(int n,float ih, int xstart, int ystart)
{
boids = new ArrayList();
h = ih;
for(int i=0;i<n;i++)
boids.add(new Boid(new PVector(xstart,ystart)));
}
void run()
{
for(int i=0;i<boids.size();i++) //iterate through the list of boids
{
Boid tempBoid = (Boid)boids.get(i); //create a temporary boid to process and make it the current boid in the list
tempBoid.h = h;
tempBoid.run(boids); //tell the temporary boid to execute its run method
}
}
}
Answers
Still struggling with this.. Is the check just to slow somehow? It now tried killing boid instances on hitting one of the draggable objects. This however seems to work partly only. So some are killed, some go trough unharmed.
Would anyone have suggestions on how to make boids bounce of the draggable objects instead of avoiding them? I have been trying to increase maxSteerForce on approaching an object. This makes it look a lot more like bouncing of boids but its the boid directions seem quite unpredictable. Sometimes it just goes trough, very fast instead of bouncing of.