Skip to content

Instantly share code, notes, and snippets.

@Craigson
Created February 6, 2015 23:52
Show Gist options
  • Select an option

  • Save Craigson/ba9acf4f2431b6902fa3 to your computer and use it in GitHub Desktop.

Select an option

Save Craigson/ba9acf4f2431b6902fa3 to your computer and use it in GitHub Desktop.
Movers with the ability to steer and a mutual repulsion force, traveling through regions in which a drag force is applied
Mover [] movers;
Patch [] patches;
float count = 0;
void setup() {
size(1200, 675);
movers = new Mover[150]; //create an array of movers
patches = new Patch[10]; //create an array of friction patches
for (int i = 0; i < movers.length; i++) {
movers[i] = new Mover();
}
for (int j = 0; j < patches.length; j++) {
patches[j] = new Patch();
}
}
void draw() {
background(255);
PVector mouse = new PVector(mouseX, mouseY); //create a vector that stores the mouse location
for (int i = 0; i < patches.length; i++) {
patches[i].display();
}
//check every mover against every other mover. Apply the force that's determined
//by the repel() method for every mover so that the movers repel one another
//and don't bunch together as they follow the mouse
for (int j = 0; j < movers.length; j++) {
for (int l = 0; l < movers.length; l++) {
if (j!=l) { //mover musn't check against itself
PVector force = movers[l].repel(movers[j]);
movers[j].applyForce(force);
//println(force);
}
}
//loop through both each patch to check if the mover is over the patch,
//if it is, execute the calcDrag method and apply the drag force
for (int k = 0; k < patches.length; k++) {
if (patches[k].isInside(movers[j]) == true) {
movers[j].applyForce(patches[k].calcDrag(movers[j]));
movers[j].k = color(100, 200, 100); //change the colour if the mover is over the patch
} else {
movers[j].applyForce(movers[j].initForce); //if the mover is not within
//the drag zone, apply the initial force assigned in the constructor
}
}
movers[j].seek(mouse); //the seek() method takes the mouse position as a paramet and
//ensures that the movers steer towards the mouse
movers[j].update();
movers[j].checkEdges();
movers[j].display();
}
println(frameRate);
}
class Mover {
PVector loc, vel, acc, initForce;
float mass;
float rad;
float maxSpeed, maxForce;
color k;
float g;
Mover() {
loc = new PVector(random(width),random(height));
vel = new PVector(0, 0);
mass = random (0.1,0.5);
acc = new PVector(0,0);
rad = mass*20;
k = color (0);
initForce = new PVector(random(-0.002,0.002),random(-0.002,0.002)); //give the mover an initial velocity
maxSpeed = 3; //speed to which to limit the mover's velocity
maxForce = 0.05; //maximum force steering force to be applied
g = 50; //gravitational constant
}
void update() {
vel.add(acc);
vel.limit(maxSpeed); //limit the velocity of the mover
loc.add(vel);
acc.mult(0); //reset the acceleration at the end of every frame
}
void applyForce(PVector force) {
PVector f = PVector.div(force, mass); //creace a copy of the original force
acc.add(f);
}
void display() {
float theta = vel.heading() + PI/2; //the triangle is drawn upright, so rotate by 90degrees
fill(k);
//draw the triangle for the mover
pushMatrix();
translate(loc.x,loc.y);
rotate(theta);
beginShape();
vertex(0, -rad*1.3);
vertex(-rad, rad*1.3);
vertex(rad, rad*1.3);
endShape(CLOSE);
popMatrix();
noFill();
k = 0; //reset the colour to black at the end of every frame, this ensures
//that the colour changes back to black when the movers leave the patch.
}
// ellipse(loc.x,loc.y,rad*2,rad*2);
// k = 0;
void checkEdges(){
if (loc.x < 0){
loc.x += width;
} else if (loc.x > width){
loc.x -= width;
}
if (loc.y < 0){
loc.y += height;
} else if (loc.y > height){
loc.y -= height;
}
}
void seek(PVector target){
//create a new vector by subtracting the mover's location from the mouse's location
//this is the direction in which the mover "would like to travel"
PVector desired = PVector.sub(target,loc);
desired.setMag(maxSpeed); //set the magnitude according to the predefined maxspeed variable
//create a new vector by subtracting the desired location from the current
//velocity. The resultant force will steer the mover toward the target location
PVector steer = PVector.sub(desired,vel);
steer.limit(maxForce); //limit the magnitude of the resultant vector for smoother/ more realistic motion
applyForce(steer);
}
//the repel method causes the mover to apply a repulsion force to every mover in
//the environment
PVector repel(Mover m){
PVector force = PVector.sub(loc,m.loc); //create a copy of the vector and get the direction
float d = force.mag(); //get the magnitude of the computed vector
//d = constrain(d,5.0,25.0);
force.normalize(); //reduce it to a unit vector
force.mult(-1); //reverse the direction for a repulsive force
//the force strenght is determined by the universal strength of attraction
float strength = (g * mass * m.mass) / (d * d);
force.mult(strength); //multiply the unit vector by the computed strength
return force;
}
}
class Patch{
float rad;
PVector loc; //PVector to store the objects location
float c; //co-efficient of drag
Patch(){
rad = random(10,75); //assign a random radius
loc = new PVector(random(width),random(height)); //draw the patch in a random location
c = random(0.01,0.05); //initialise it to a random value
}
//pass patch p into the function
PVector calcDrag(Mover m){
float speed = m.vel.mag(); //speed is the scalar value of the mover's velocity
float dragMag = c*speed*speed; //the magnitude of the drag force is equivalent to the patch's
//coefficient of friction multiplied by the square of the movers speed
PVector drag = m.vel.get(); //get a copy of the movers direction
drag.normalize(); //normalize to get the unit vector
drag.mult(-1); //reverse the direction
drag.mult(dragMag); //multiply the unit vector by the magnitude of the force
return drag; //apply the new drag force to 'this' mover
}
boolean isInside(Mover m){
PVector l = m.loc;
float d = dist(loc.x,loc.y,l.x,l.y);
//if the distance between the centers is less than the sum of the radii
//the mover must be inside the patch
if (d < rad + m.rad){
return true;
} else {
return false;
}
}
void display(){
fill(0,20);
noStroke();
ellipse(loc.x,loc.y,rad*2,rad*2);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment