Lerp flow field and attractor

Hello forum, I am looking for help on an issue where only one object is being affected by an attractor. I am building on top of different tutorials I have found on YouTube. The sketch basically has a noise field that is providing values for drawing points. I’ve called these points v1 in my comments in the code. I then took that code and made a class where I am attempting to interpolate between the noise values and values generated from vector math related to an attractor point. My goal is to be able to vary the interpolation between the two computations (noise & attractor). I have gotten stuck trying to figure out why only one point is being attracted.

The points that are not being attracted are from the same class as the point that is being attracted. They are the blue points and I have named them flow points although they are the ones that should also be affected by the attractor. I might give them a better name later.

These blue flow points have a method that generates values based on a target vector within the drawing which is the red point that I have named attractor. All of the flow points should be attracted to this target vector. This code is mostly an adaptation from one of Dan Shiffman’s Coding Train challenges on attraction and repulsion. Maybe the problem might be related to the fact that in the challenge he uses p5js and I am using Processing.

If you run the sketch you will see how it partially works. The problem of only one flow point orbitting around the attractor point becomes visible after about 10s of letting the sketch run. This is not the behavior I am aiming for. I want all the blue flow points to be influenced by the attractor point’s position. Currently the attractor point is positioned at the center of the canvas.

Like I mentioned previously, only one blue flow point is moving in a way that shows it is attracted by the attractor. All the other blue points seem to be attracted to the 0,0 coordinate even though there is no attractor point at that location. I don’t understand why all the other blue flow points are being attracted to coordinate 0,0. I suspect that something is wrong with how I structured the code within the FlowPts class or maybe how the vector math is ordered or how the class methods are being called inside the draw loop. I don’t know. Thanks for the help.

//flowing lines and attractors
//initial flowfield code reference follows Barney Codes YT tut
//initial attractor code based on coding traing challenge 56 attraction & repulsion

//number of initial points that flow along noise field
int numPts = 3;

//arraylist of PVector type for stroing points that flow
ArrayList<PVector> pts = new ArrayList<PVector>(numPts);
ArrayList<FlowPts> flpts = new ArrayList<FlowPts>(numPts);

//PVector object to act as attractor
PVector attractor;

//variable for changing scale of noise field
float nScale = 0.01;

//variable for increasing or decreasing the speed or rate
//that the points flow along noise field
float increase = 0.15;

//--------------------------------------------------------------------------------------------//
//
//--------------------------------------------SETUP-------------------------------------------//
void setup(){
    size(800,800);

    //initialize data to attractor PVector type
    //attractor = new PVector(width/2,height/2);
    //stroke(200,0,0);
    //point(attractor.x, attractor.y);

    //initialize points into arraylist give them random locations
    for (int i = 0; i < numPts; ++i) {
        float x = random(0, width);
        float y = random(0, height);
        pts.add(new PVector(x,y));
        flpts.add(new FlowPts(x,y));
        printArray("pts ArrayList: "+pts);
        printArray("flpts ArrayList: "+flpts);
    }
}

//--------------------------------------------------------------------------------------------//
//
//--------------------------------------------DRAW--------------------------------------------//
void draw(){

    attractor = new PVector(width/2,height/2);
    stroke(200,0,0);
    point(attractor.x, attractor.y);

    //draw a "background" with low transparency
    if(frameCount % 15 == 0){   
        fill(200,5);
        noStroke();  
        rect(0,0,width,height);
    }

    //draw points v1
    for(int i = 0; i < numPts; i++){
        PVector tempPt = pts.get(i);
        
        float n = noise(tempPt.x * nScale, tempPt.y * nScale);
        float a = TWO_PI * n;
        tempPt.x += cos(a) + increase;
        tempPt.y += sin(a) + increase;

        stroke(0,200,0,20); //green color
        strokeWeight(random(1,15)); 
        point(tempPt.x, tempPt.y);

        //my solution to when pts are outside of canvas
        //barney codes uses a different solution
        if(tempPt.x < 0){tempPt.x = width; tempPt.y = random(0,height);}
        if(tempPt.x > width){tempPt.x = 0; tempPt.y = random(0, height);}
        if(tempPt.y < 0){tempPt.y = height; tempPt.x = random(0, width);}
        if(tempPt.y > height){tempPt.y = 0; tempPt.x = random(0, width);}

        }//end for loop that draws green pts

        //draw points v2 
        int i = 0;
        for (FlowPts flpt : flpts){
        i++;
        push();
            //blue
            stroke(0,0,255,120);

            //FlowPts flpt = flpts.get(i);
           
            //FlowPts flpt = new FlowPts(_x,_y);

            //println("flpt: "+flpt.xP());
            
            //call methods from FlowPts class
            flpt.attracted(attractor);
            flpt.move();
            flpt.show();
            
            //for debugging which pt is being attracted
            if(frameCount % 60 == 0){
                push();
                fill(0);
                textSize(12);
                text(i,flpt.xP(),flpt.yP());
                pop();
            }

            //for repositioning
            PVector tempV = new PVector();
            tempV.x = flpt.xP();
            tempV.y = flpt.yP();
            if(!onCanvas(tempV)){
                flpt.reposition();
            }

        pop();
        }
    //println("frameRate: "+frameRate);
}//end draw


//--------------------------------------------------------------------------------------------//
//
//--------------------------------FLOW PONTS CLASS--------------------------------------------//
class FlowPts {

    PVector flPtpos = new PVector();
    PVector flPtvel = new PVector(random(-5,5),random(5,-5));
    PVector flPtacc = new PVector();
    
    //constructor
    FlowPts (float tempX, float tempY) {
        flPtpos.x = tempX;
        flPtpos.y = tempY;
    }
    
    //I don't know if I need these two methos xP and yP
    float xP(){
        return flPtpos.x;
    }

    float yP(){
        return flPtpos.y;
    }

    void move(){
        
        float rand0 = random (-2,2);//random value to give some jitter
        
        //chatgpt suggection for fixing blue points not orbiting around attractor
        //reset the acceleration //did not fix issue of only one blue orbiting 
        //flPtacc.set(0,0);
        flPtacc.mult(0.1);
        //flPtacc.normalize();

        //next four lines of code form the flowfield values
        float n = noise(flPtpos.x * nScale, flPtpos.y * nScale);
        float a = TWO_PI * n + rand0;
        flPtpos.x += cos(a) + increase;
        flPtpos.y += sin(a) + increase;

        //create a verctor that will be used for
        //interpolating between flowfield vectors
        //and attractor vectors
        PVector lerpFlAtt = new PVector();
        lerpFlAtt.add(flPtpos);
        
        //next two lines make vectors be influenced by attractor
        flPtpos.add(flPtvel);
        flPtvel.add(flPtacc);

        //next line makes an interpolation between
        //flowfield values and attractor values
        flPtpos.lerp(lerpFlAtt, 0.5);
    }

    void show(){
        //blue color
        stroke(0,0,200,60);
        strokeWeight(random(1,5));
        point(flPtpos.x,flPtpos.y);
    }

    //this method was a solution provided by chatgpt when I was stuck
    void reposition(){
        flPtpos.x = random(0,width);
        flPtpos.y = random(0,height);
        flPtvel.set(0.1,0.1); //this keeps the points from getting too fast
        //flPtacc.set(0.1,0.1); 
    }

    //this method generates the values for making points
    //be attracted to the attractor
    void attracted(PVector target){
        PVector force = target.sub(flPtpos);
        float dsq = force.magSq();
        dsq = constrain(dsq, 5, 50);
        float G = 5;
        float strength = G / dsq;
        force.setMag(strength);
        flPtacc = force.mult(5);//this reduces the attractor's force
    }
    
}

//this function is based on the Barney Codes video about flowfields
boolean onCanvas(PVector v){
        return v.x >= 0 && v.x <= width && v.y >= 0 && v.y <= height;
        //println("flPtpos off canvas");
    }

Figured it out. Placing the attractor inside the loop that is drawing the blue points makes all the points have the attraction.

1 Like