[Solved] Creating chain, need help?

I know there is a code for chain simulation in processing but I want to create my own code using my logic but somehow it not working as expected. Can anyone of you help me?

thanks in advance :)

Point P1, P2;
int len = 50;
float sx=0, sy=0;
void setup() {
  size(400, 400);
  P1 = new Point();
  P2 = new Point();
}

void draw() {
  background(-1);
  P1.move(mouseX, mouseY);
  P1.display(#F20055);
  float theta = atan2(mouseY-sy, mouseX-sx);
  sx = mouseX + len*cos(theta);
  sy = mouseY + len*sin(theta);
  P2.move(sx, sy);
  P2.display(#C5F200);
  stroke(0);
  line(P1.x, P1.y, P2.x, P2.y);
}


class Point {
  float x, y;

  void display(color c) {
    fill(c);
    noStroke();
    ellipse(x, y, 10, 10);
  }
  void move(float x, float y) {
    this.x = x; 
    this.y = y;
  }
}

Answers

  • Because its not working "as expected" its very hard to fix as I don't know what you expected. What do you want your chain to be like?

  • @DCRaven I wanted it like to one ellipse follow other and I would like to expand it to more than two.

    Also it would be great if you can explain me the problem.

    Thanks again :)

  • edited March 2014

    This is an adaptation to an example to have an unlimited amount of links in the chain and structured it a bit closer to how I would've. :)

    ArrayList links = new ArrayList();
    float gravity = 9.0, mass = 3.0, radius = 20, stiffness = 0.3, damping = 0.75;
    
    void setup() {
      size(640, 360);
      fill(255, 126);
      for (int i = 0; i <= 7; i++) {
        links.add(new Link(0.0, width/2, mass, gravity));
      }
    }
    void draw() {
      background(0);
      for (int i = 0; i < links.size(); i++) {
        Link l = (Link) links.get(i);
        if (i == 0) {
          l.update(mouseX, mouseY);
        }
        else {
          Link l2 = (Link) links.get(i-1);
          l.update(l2.x, l2.y);
        }
      }
    }
    class Link {
      float vx, vy, x, y;
      Link(float xpos, float ypos, float m, float g) {
        x = xpos;
        y = ypos;
        mass = m;
        gravity = g;
      }
      void update(float targetX, float targetY) {
        float forceX = (targetX - x) * stiffness;
        float ax = forceX / mass;
        vx = damping * (vx + ax);
        x += vx;
        float forceY = (targetY - y) * stiffness;
        forceY += gravity;
        float ay = forceY / mass;
        vy = damping * (vy + ay);
        y += vy;
        display(targetX, targetY);
      }
      void display(float targetX, float targetY) {
        noStroke();
        ellipse(x, y, radius*2, radius*2);
        stroke(255);
        line(x, y, targetX, targetY);
      }
    }
    

    The problem with your code (or at least my problem with it) is I would've structured it completely differently. First off you will need an array or arraylist (I personally would go for an arraylist) and store your class in it. Another problem you would have found with this structure is that you will need to put your physics inside the class rather than having a shell of a class that you control from a draw loop. Last thing that I can think of at the moment is that the mouseX & mouseY are like the fist link in the chain. Instead of having it centered (like you did) you should provide each like with the previous link's positions to join to (mouseX & mouseY being for the first link as there is no other to attach to)

  • edited March 2014

    Oh wow it posted twice. Anyway I hope that works for you :D

  • edited March 2014

    @DCRaven ..... Thanks a lot :) for your code and explanation. :D But sorry I wanted to simulate this code [illustrated below] using my logic [illustrated above]. It is an example code from processing which works as expected and I wanted to do the same using class but I am not able to get my head around.

    I had tried removing y directional force in your code and it worked but the only problem was it gets collapsed which I don't want. I have also teased stiffness and damping but then it started behaving weird.

    /**
     * Follow 3  
     * based on code from Keith Peters. 
     * 
     * A segmented line follows the mouse. The relative angle from
     * each segment to the next is calculated with atan2() and the
     * position of the next is calculated with sin() and cos().
     */
    
    float[] x = new float[20];
    float[] y = new float[20];
    float segLength = 18;
    
    void setup() {
      size(640, 360);
      strokeWeight(9);
      stroke(255, 100);
    }
    
    void draw() {
      background(0);
      dragSegment(0, mouseX, mouseY);
      for(int i=0; i<x.length-1; i++) {
        dragSegment(i+1, x[i], y[i]);
      }
    }
    
    void dragSegment(int i, float xin, float yin) {
      float dx = xin - x[i];
      float dy = yin - y[i];
      float angle = atan2(dy, dx);  
      x[i] = xin - cos(angle) * segLength;
      y[i] = yin - sin(angle) * segLength;
      segment(x[i], y[i], angle);
    }
    
    void segment(float x, float y, float a) {
      pushMatrix();
      translate(x, y);
      rotate(a);
      line(0, 0, segLength, 0);
      popMatrix();
    }
    

    So can you help me to implement it ? and thank you so much for time ....

  • edited March 2014 Answer ✓

    And a bit of physics later this appears!

    float[] x = new float[20];
    float[] y = new float[20];
    float[] accelX = new float[20];
    float segLength = 10, grav = 0.5, dampening = 0.002;
    
    void setup() {
      size(640, 360);
      strokeWeight(15);
      stroke(255, 100);
      strokeCap(PROJECT);
    }
    
    void draw() {
      background(0);
      dragSegment(0, mouseX, mouseY);
      for(int i=0; i<x.length-1; i++) {
        dragSegment(i+1, x[i], y[i]);
      }
    }
    
    void dragSegment(int i, float xin, float yin) {
      float dx = xin - x[i];
      float dy = yin - y[i];
      accelX[i] += dx;
      float angle = atan2(dy, dx);  
      x[i] = xin - (cos(angle)-(accelX[i]*dampening)) * segLength;
      y[i] = yin - (sin(angle)-grav) * segLength;
      segment(x[i], y[i], angle);
    }
    
    void segment(float x, float y, float a) {
      pushMatrix();
      translate(x, y);
      rotate(a);
      line(0, 0, segLength, 0);
      popMatrix();
    }
    

    Is this what you want? its 12:03 am so i'm gonna sleep now I'll make changes tommorow if need be :D

  • edited March 2014 Answer ✓

    Here is the my attempt. You can find code in action here

    Points[] P = new Points[50];
    int len = 50;
    void setup() {
      size(400, 400);
      for (int i=0;i<P.length;i++) {
        P[i] = new Points();
      }
    }
    
    void draw() {
      background(-1, 20);
      P[0].move(mouseX, mouseY);
      P[0].display(#F20055);
      for (int i=1;i<P.length;i++) {
        float t = atan2(P[i].y-P[i-1].y, P[i].x-P[i-1].x);
        float sx = P[i-1].x + len*cos(t);
        float sy = P[i-1].y + len*sin(t);
       // sx+=0.2; // for fluidic motion
       // sy+=0.5; // for fluidic motion
        P[i].move(sx, sy);
        P[i].display(#C5F200);
        //stroke(0);
        //line(P[i].x, P[i].y, P[i-1].x, P[i-1].y);
      }
    }
    
    
    class Points {
      float x=0, y=0;
      void display(color c) {
        fill(c);
        noStroke();
        ellipse(x, y, 5, 5);
      }
      void move(float x, float y) {
        this.x = x; 
        this.y = y;
      }
    }
    
  • @Blyk Thanks for the code. This is what exactly what I wanted :) @DCRaven : Thanks for your effort and time .... highly appreciated :) :)

  • edited April 2014

    Oh I thought you wanted it physicsified :/ Still my one is cooler... good luck on whatever project you have planned with a chain!

  • @DCRaven: I am really sorry if I was rude. I just wanted to use my logic (class implementation) to create the same effect that comes with processing.

    Certainly your code was awesome :) because it has physics but I was trying some basics first :)

    Thanks.

Sign In or Register to comment.