Putting a gradient influence instead of range on agents and attractors?
in
Contributed Library Questions
•
1 years ago
Currently I have a predator/prey based flocking algorithm where the mouse is used to chase a flock of agents by a series of predators guided by the mouse. When the predators are within a certain range the agents velocity killed and they stop moving. As the predator moves away the agent begins to flock again. The velocity is scaled by a function that take the sin of the distance from the predator and scales it down if it is within the predators range. However I would like the prey to be more influenced the closer to the predators and less if far away. More of a gradient influence than an either or situation is what I am basically looking for. In the sketch the prey are referred to as agents in the population arraylist and the predators as attractorfood in the attractorfoodpop arraylist. Anything would help.
- import toxi.processing.*;
- import toxi.geom.*;
- ArrayList population;
- ArrayList attractFoodPop;
- void setup(){
- colorMode(HSB, 160);
- size(700,700);
- population = new ArrayList();
- attractFoodPop = new ArrayList();
- for(int i = 0; i < 500; i++){
- Vec3D p = new Vec3D(random(0,width),random(0,height),0);
- Vec3D v = new Vec3D(random(-1,1), random(-1,1), random(-1,1));
- agent a = new agent(p,v, random(2,4), random(0.1, 0.3));
- population.add(a);
- }
- for(int i = 0; i < 5; i++) {
- Vec3D p = new Vec3D(random(0,width),random(0,height),0);
- Vec3D v = new Vec3D(random(-1,1), random(-1,1), random(-1,1));
- attractFoodPop.add(new attractorFood(p,v,random(1,2), random(0.1, 0.3))); // p, v, mv, mf
- }
- }
- void draw(){
- background(0,0,255);
- for(int i = 0; i < population.size(); i++){
- agent a = (agent) population.get(i);
- a.update(attractFoodPop);
- a.render();
- }
- for(int i = 0; i < attractFoodPop.size(); i++) {
- attractorFood a = (attractorFood) attractFoodPop.get(i);
- a.update();
- a.render();
- }
- }
- class agent{
- // states - global variables
- Vec3D pos;
- Vec3D vel;
- float scaleVel = 1;
- float maxVel;
- float maxForce;
- // constructor
- agent(Vec3D p, Vec3D v, float mv, float mf){
- pos = p.copy();
- vel = v.copy();
- maxVel = mv;
- maxForce = mf;
- }
- // behaviors
- void update(ArrayList attPop){
- this.attractorFood(attPop, 60);
- Vec3D acc = new Vec3D();
- // call the vector functions
- Vec3D ste = steer(new Vec3D(random(0,width),random(0,height),0));
- Vec3D ali = alignment(population, 30);
- Vec3D coh= cohesion (population, 30);
- Vec3D sep= separation (population, 30);
- // weight or scale vectors
- ste.scaleSelf(2.0);//0
- ali.scaleSelf(2.0);//0
- coh.scaleSelf(2.0);//5
- sep.scaleSelf(2.0);//3
- // add vectors to acc
- acc.addSelf(ste);
- acc.addSelf(ali);
- acc.addSelf(coh);
- acc.addSelf(sep);
- // vel = vel + acc
- vel.addSelf(acc);
- vel.scaleSelf(scaleVel);
- vel.limit(maxVel);
- // pos = pos + vel
- pos.addSelf(vel);
- }
- void attractorFood(ArrayList attPop, float range) {
- float sumSin = 0;
- int count = 0;
- float minDist = 50000000;
- //loop thru all the attractors
- for(int i = 0; i < attPop.size(); i++) {
- attractorFood a = (attractorFood) attPop.get(i);
- //get the distance to the attractor
- float Attdist = a.pos.distanceTo(this.pos);
- if (Attdist<minDist){
- minDist = Attdist;
- }
- }
- //if distance < range of attractor
- if(minDist < range) {
- sumSin = sumSin + sin(0.126*minDist);//sumSin = sumSin + (sin(0.06*Attdist))*(100/Attdist);
- //sumCos = sumCos + cos(0.06*Attdist);
- }else{sumSin = 1;}
- // }
- //scaleCoh = sumSin;
- scaleVel = sumSin; //scaleVel = 1/sumSin;
- }
- Vec3D steer(Vec3D target){
- // make a vector from the pos to the target: vec = target - pos
- Vec3D vec = target.sub(pos);
- float d = vec.magnitude();
- if(d > 0){
- // normalize the vector - magnitude of 1
- vec.normalize();
- // scale to length of maxVel: vec = vec x maxVel
- vec.scaleSelf(maxVel);
- // subtract vel
- vec.subSelf(vel);
- // limit by maxForce
- vec.limit(maxForce);
- }else{
- vec = new Vec3D(); // 0,0,0
- }
- // return the vector
- return vec;
- }
- Vec3D alignment(ArrayList pop, float range){
- Vec3D sum = new Vec3D(); // 0,0,0
- int count = 0;
- // loop through each agent in pop
- for(int i = 0; i < pop.size(); i++){
- agent a = (agent) pop.get(i);
- // find the distance between the current agent and the other agent
- float d = pos.distanceTo(a.pos);
- // if distance < range
- if( (d < range) && (d > 0) ){ //(d>0)
- // sum = sum + other agents vel
- sum.addSelf(a.vel);
- // count = count + 1
- count++;
- }
- }
- // find the average: sum/count: sum = sum x 1/count
- if(count > 0){
- sum.scaleSelf(1/(float)count);
- // limit the average vector to maxForce
- sum.limit(maxForce);
- }
- // return the limited vector
- return sum;
- }
- Vec3D cohesion(ArrayList pop, float range){
- // make 0 vector sum, 0 int count
- Vec3D sum = new Vec3D();
- int count = 0;
- // loop through all agents
- for(int i = 0; i < pop.size(); i++){
- // get one agent out of the arraylist
- agent a = (agent) pop.get(i);
- // calculate distance from pos to the other agent pos
- float d = pos.distanceTo(a.pos);
- // if distance < range && other agent is not this agent
- if( (d < range) && (a != this) ){
- // add other agent pos to sum, add 1 to count: sum = sum + a.pos
- sum.addSelf(a.pos);
- count++;
- }
- }
- // find the average pos: sum/count: sum = sum x 1/count
- if(count > 0){
- sum.scaleSelf(1/(float)count); // sum is now the average pos
- // steer toward the average pos
- sum = steer(sum);
- }
- // return that vector
- return sum;
- }
- Vec3D separation(ArrayList pop, float range){
- // make 0 vector
- Vec3D sum = new Vec3D(0,0,0);
- // loop through each agent
- for(int i = 0; i < pop.size(); i++){
- // get an agent out of the arrayList
- agent a = (agent) pop.get(i);
- // calculate distance to the agent
- float d = pos.distanceTo(a.pos);
- // if distance is less than range
- if( (d < range) && ( a != this) ){
- // make a vector between the other agent and this agent
- Vec3D vec = pos.sub(a.pos);
- // scale vector by 1/distance
- vec.scaleSelf(1/d);
- // add the vector to sum
- sum.addSelf(vec);
- }
- }
- // limit to maxForce
- sum.limit(maxForce);
- // return vector
- return sum;
- }
- void render(){
- noStroke();
- fill(155,0,0,40);
- ellipse(pos.x, pos.y, 2, 2);
- // x, y, w, h
- }
- }
- class attractorFood {
- Vec3D pos;
- Vec3D vel;
- float maxVel;
- float maxForce;
- float mag = 100;
- //float range = 50;
- attractorFood(Vec3D p, Vec3D v, float mv, float mf){
- pos = p.copy();
- vel = v.copy();
- maxVel = mv;
- maxForce = mf;
- }
- void update(){
- Vec3D acc = new Vec3D();
- // call the vector functions
- Vec3D ste = steer(new Vec3D(mouseX,mouseY,0)); //steer(new Vec3D(mouseX,mouseY,0));
- Vec3D ali = alignment(attractFoodPop, 30); //steer(new Vec3D(random(0,width),random(0,height),0));
- Vec3D coh= cohesion (attractFoodPop, 30);
- Vec3D sep= separation (attractFoodPop, 30);
- // weight or scale vectors
- ste.scaleSelf(.5);//0.1
- ali.scaleSelf(2.0);//1.0
- coh.scaleSelf(2.0);//2.0
- sep.scaleSelf(2.0);//5.0
- // add vectors to acc
- acc.addSelf(ste);
- acc.addSelf(ali);
- acc.addSelf(coh);
- acc.addSelf(sep);
- // vel = vel + acc
- vel.addSelf(acc);
- vel.limit(maxVel);
- // pos = pos + vel
- pos.addSelf(vel);
- torusSpace();
- }
- Vec3D steer(Vec3D target){
- // make a vector from the pos to the target: vec = target - pos
- Vec3D vec = target.sub(pos);
- float d = vec.magnitude();
- if(d > 0){
- // normalize the vector - magnitude of 1
- vec.normalize();
- // scale to length of maxVel: vec = vec x maxVel
- vec.scaleSelf(maxVel);
- // subtract vel
- vec.subSelf(vel);
- // limit by maxForce
- vec.limit(maxForce);
- }else{
- vec = new Vec3D(); // 0,0,0
- }
- // return the vector
- return vec;
- }
- Vec3D alignment(ArrayList pop, float range){
- Vec3D sum = new Vec3D(); // 0,0,0
- int count = 0;
- // loop through each agent in pop
- for(int i = 0; i < attractFoodPop.size(); i++){
- attractorFood a = (attractorFood) pop.get(i); ///attractorFood a = (attractorFood)
- // find the distance between the current agent and the other agent
- float d = pos.distanceTo(a.pos);
- // if distance < range
- if( (d < range) && (d > 0) ){ //(d>0)
- // sum = sum + other agents vel
- sum.addSelf(a.vel);
- // count = count + 1
- count++;
- }
- }
- // find the average: sum/count: sum = sum x 1/count
- if(count > 0){
- sum.scaleSelf(1/(float)count);
- // limit the average vector to maxForce
- sum.limit(maxForce);
- }
- // return the limited vector
- return sum;
- }
- Vec3D cohesion(ArrayList pop, float range){
- // make 0 vector sum, 0 int count
- Vec3D sum = new Vec3D();
- int count = 0;
- // loop through all agents
- for(int i = 0; i < attractFoodPop.size(); i++){
- // get one agent out of the arraylist
- attractorFood a = (attractorFood) pop.get(i);
- // calculate distance from pos to the other agent pos
- float d = pos.distanceTo(a.pos);
- // if distance < range && other agent is not this agent
- if( (d < range) && (d > 0) ){
- // add other agent pos to sum, add 1 to count: sum = sum + a.pos
- sum.addSelf(a.pos);
- count++;
- }
- }
- // find the average pos: sum/count: sum = sum x 1/count
- if(count > 0){
- sum.scaleSelf(1/(float)count); // sum is now the average pos
- // steer toward the average pos
- sum = steer(sum);
- }
- // return that vector
- return sum;
- }
- Vec3D separation(ArrayList pop, float range){
- // make 0 vector
- Vec3D sum = new Vec3D(0,0,0);
- // loop through each agent
- for(int i = 0; i < attractFoodPop.size(); i++){
- // get an agent out of the arrayList
- attractorFood a = (attractorFood) pop.get(i);
- // calculate distance to the agent
- float d = pos.distanceTo(a.pos);
- // if distance is less than range
- if( (d < range) && (d > 0) ){
- // make a vector between the other agent and this agent
- Vec3D vec = pos.sub(a.pos);
- // scale vector by 1/distance
- vec.scaleSelf(1/d);
- // add the vector to sum
- sum.addSelf(vec);
- }
- }
- // limit to maxForce
- sum.limit(maxForce);
- // return vector
- return sum;
- }
- void torusSpace(){
- if(pos.x > width) pos.x = pos.x - width;
- if(pos.y > height) pos.y = pos.y - height;
- if(pos.x < 0) pos.x = pos.x + width;
- if(pos.y < 0) pos.y = pos.y + height;
- }
- void render() {
- noStroke();
- fill(155,0,0,50);
- ellipse(pos.x, pos.y, 10, 10);
- }
- }
1