How to animate ball path?

edited January 2017 in Questions about Code

I need some direction how to implement something like that (link) into processing.

This is my code right now:

ArrayList xPositions = new ArrayList();
ArrayList yPositions = new ArrayList();

void setup() {
  size(640, 360);

  xPositions.add((int) width / 2);
  yPositions.add((int) height / 2);
}

void draw() {
  background(0, 0, 255);
  ball();
}

void mousePressed() {
  xPositions.add( mouseX );
  yPositions.add( mouseY );
}

void ball() {
  
  int ballSize = 8;
  connectingBallLine();

  // Balls parameters
  strokeWeight(1);
  stroke(0);
  fill(255);

  for ( int i = 0; i < xPositions.size(); i++) 
    ellipse( (int) xPositions.get(xPositions.size()-1), (int) yPositions.get(xPositions.size()-1), ballSize, ballSize);
}

void connectingBallLine() {
  for ( int i = 0; i < xPositions.size()-1; i++) { 
    arrow((int) xPositions.get(xPositions.size()-2), (int) yPositions.get(yPositions.size()-2), (int) xPositions.get(xPositions.size()-1), (int) yPositions.get(yPositions.size()-1), 8);
  }
}

// Function for creating arrow
void arrow(float x1, float y1, float x2, float y2, float s) {

  strokeWeight(1);
  stroke(0);
  line(x1, y1, x2, y2);

  pushMatrix();
  translate(x2, y2);
  float a = atan2(x1-x2, y2-y1); // 70, 360
  rotate(a);
  line(0, 0, -s, -s);
  line(0, 0, s, -s);
  popMatrix();
}

So instead of an arrow I would like to have animation just like in the video above. Can you guys give me some clues or tips how to do that?

Tagged:

Answers

  • Look at lerp

    When you increase your amt (in lerp) slowly in draw, you see a smooth transition from a to b

  • You mean lerp function yeah? I will look at this, thanks again @Chrisir :-bd

  • edited January 2017

    I like this better. Try it-

    public static final int ALPHA_VAL = 5;//fine-tune yourself for best result
    void setup(){
      size(1280, 720);
      background(0);
      blendMode(SUBTRACT);
      noStroke();
    }
    
    void draw(){
      fill(1, ALPHA_VAL);
      rect(0, 0, width, height);
      fill(150, 0, 250);//change the color for different results
      ellipse(mouseX, mouseY, 50, 50);
    }
    
  • Also see the code in reference for lerp()

  • Look at PVector to make an ArrayList of type PVector that holds both x and y

  • edited January 2017

    @kevo1414 -- See also this previous discussion of a sketch that left traces of previous ball positions behind:

  • jeremydouglass idea is indeed very good

    @kevo1414 here is your sketch with PVector

    ArrayList<PVector> positions = new ArrayList();
    
    void setup() {
      size(640, 360);
    
      positions.add( new PVector ( width / 2, height / 2) );
    }
    
    void draw() {
      background(0, 0, 255);
      ball();
    }
    
    void mousePressed() {
      positions.add(  new PVector ( mouseX, mouseY )  );
    }
    
    void ball() {
    
      int ballSize = 8;
      connectingBallLine();
    
      // Balls parameters
      strokeWeight(1);
      stroke(0);
      fill(255);
    
      for ( int i = 0; i < positions.size(); i++) {
        PVector pv1 = positions.get(i);
    
        ellipse( pv1.x, pv1.y, ballSize, ballSize);
    
        // ellipse( (int) xPositions.get(xPositions.size()-1), (int) yPositions.get(xPositions.size()-1), ballSize, ballSize);
      }
    }
    
    void connectingBallLine() {
      for ( int i = 0; i < positions.size()-2; i++) {
    
        PVector pv1 = positions.get(i);
        PVector pv2 = positions.get(i+2);
    
        arrow( pv1.x, pv1.y, pv2.x, pv2.y, 8);
    
        // arrow((int) xPositions.get(xPositions.size()-2), (int) yPositions.get(yPositions.size()-2), (int) xPositions.get(xPositions.size()-1), (int) yPositions.get(yPositions.size()-1), 8);
      }
    }
    
    // Function for creating arrow
    void arrow(float x1, float y1, 
      float x2, float y2, 
      float s) {
    
      strokeWeight(1);
      stroke(0);
      line(x1, y1, x2, y2);
    
      pushMatrix();
      translate(x2, y2);
      float a = atan2(x1-x2, y2-y1); // 70, 360
      rotate(a);
      line(0, 0, -s, -s);
      line(0, 0, s, -s);
      popMatrix();
    }
    
  • So I watched some videos on YT about PVectors. If I understand it correctly, PVector is a class which can store two values. Instead of two variables which stores x and y values, we can store x and y value in one variable. Yes?

    In code above that you posted @Chrisir, we have an arrayList in which we can store only PVectors (line 1). And each time we pressed the mouse button, in arrayList positons goes PVector with two values. xMouse and yMouse.

    If this is true I don't know why ConnectingBallLine() does not work correctly with PVectors.

    How can I use lerp() with PVectors? It is possible do to something like that:

    lerp(pv1, pv2, 0.5);

    ?

  • Yes

    x=lerp(pv1.x,pv2.x, 0.5);

    y=....

  • edited January 2017

    This is with PVectors. If I change code in connectingBallLine() like below, I get someting similiar with no PVectors but on my sketch stays previus ellipses.

    void connectingBallLine() {
      for ( int i = 0; i < positions.size()-1; i++) {
     
        PVector pv1 = positions.get(positions.size()-2);
        PVector pv2 = positions.get(positions.size()-1);
     
        arrow( pv1.x, pv1.y, pv2.x, pv2.y, 8);
      }
    }
    

    I hope you understand what I want to tell you, my english is not perfect so excuse me for this :(

  • lerp is for a smooth transition between pv1 and pv2

    Like for a ball that flies between them

  • edited January 2017

    Ok nevermind about above post. Code below is the same code as the first code in this topic only that we included PVectors

    ArrayList positions = new ArrayList();
    
     
    void setup() {
      size(640, 360);
     
      positions.add( new PVector ( width / 2, height / 2) );
    }
     
    void draw() {
      background(0, 0, 255);
      ball();
      println(positions.size()-1);
    }
     
    void mousePressed() {
      positions.add(  new PVector ( mouseX, mouseY )  );
    }
     
    void ball() {
     
      int ballSize = 8;
      connectingBallLine();
     
      // Balls parameters
      strokeWeight(1);
      stroke(0);
      fill(255);
     
      for ( int i = 0; i < positions.size(); i++) {
        PVector pv1 = positions.get(positions.size()-1);
     
        ellipse( pv1.x, pv1.y, ballSize, ballSize);
     
        // ellipse( (int) xPositions.get(xPositions.size()-1), (int) yPositions.get(xPositions.size()-1), ballSize, ballSize);
      }
    }
     
    void connectingBallLine() {
      for ( int i = 0; i < positions.size()-1; i++) {
     
        PVector pv1 = positions.get(positions.size()-2);
        PVector pv2 = positions.get(positions.size()-1);
     
        arrow( pv1.x, pv1.y, pv2.x, pv2.y, 8);
      }
    }
     
    // Function for creating arrow
    void arrow(float x1, float y1, float x2, float y2, float s) {
     
      strokeWeight(1);
      stroke(0);
      line(x1, y1, x2, y2);
     
      pushMatrix();
      translate(x2, y2);
      float a = atan2(x1-x2, y2-y1); // 70, 360
      rotate(a);
      line(0, 0, -s, -s);
      line(0, 0, s, -s);
      popMatrix();
    }
    
  • What do you need now?

  • edited January 2017

    Transition between balls with lerp() function.

    But I don't know where do I need to put this lerp() function neither how to use it.

    If I use lerp() function in connectingBallLine() function like below (line 41, 42), I got arrow transition and not ball transition that I want. Understood?

    ArrayList positions = new ArrayList();
    
    void setup() {
      size(640, 360);
      positions.add( new PVector ( width / 2, height / 2) );
    }
     
    void draw() {
      background(0, 0, 255);
      ball();
    }
     
    void mousePressed() {
      positions.add(  new PVector ( mouseX, mouseY )  );
    }
     
    void ball() {
     
      int ballSize = 8;
      connectingBallLine();
     
      // Balls parameters
      strokeWeight(1);
      stroke(0);
      fill(255);
     
      for ( int i = 0; i < positions.size(); i++) {
        PVector pv1 = positions.get(positions.size()-1);
        ellipse( pv1.x, pv1.y, ballSize, ballSize);
      }
    }
     
    void connectingBallLine() {
      for ( int i = 0; i < positions.size()-1; i++) {
    
        PVector pv1 = positions.get(positions.size()-2);
        PVector pv2 = positions.get(positions.size()-1);
     
        arrow( pv1.x, pv1.y, pv2.x, pv2.y, 8);
        
        pv1.x = lerp(pv1.x, pv2.x, 0.01);
        pv1.y = lerp(pv1.y, pv2.y, 0.01);
      }
    }
     
    // Function for creating arrow
    void arrow(float x1, float y1, float x2, float y2, float s) {
     
      strokeWeight(1);
      stroke(0);
      line(x1, y1, x2, y2);
     
      pushMatrix();
      translate(x2, y2);
      float a = atan2(x1-x2, y2-y1); // 70, 360
      rotate(a);
      line(0, 0, -s, -s);
      line(0, 0, s, -s);
      popMatrix();
    }
    
  • If I understand it correctly, PVector is a class which can store two values.

    Actually it is 3 float fields: x, y & z. Look up its reference: L-)
    https://Processing.org/reference/PVector.html

  • Yep, I notice that but I did not want to complicate things. :P Thanks

  • I'll take a look

    this doesn't really make sense:

    for ( int i = 0; i < positions.size()-1; i++) {
    
        PVector pv1 = positions.get(positions.size()-2);
        PVector pv2 = positions.get(positions.size()-1);
    

    Don't you want to loop over all entries? So shouldn't you say positions.get(i) instead?

  • homework?

  • Answer ✓
    ArrayList<PVector> positions = new ArrayList();
    float amt;
    int count; 
    
    void setup() {
      size(640, 360);
      positions.add( new PVector ( width / 2, height / 2) );
    }
    
    void draw() {
      background(0, 0, 255);
      ballManagement();
    }
    
    void mousePressed() {
      positions.add(  new PVector ( mouseX, mouseY )  );
    }
    
    void ballManagement() {
    
      int ballSize = 8;
    
      // Balls parameters
      strokeWeight(1);
      stroke(0);
      fill(255);
    
      for ( int i = 0; i < positions.size(); i++) {
        PVector pv1 = positions.get(i);
        ellipse( pv1.x, pv1.y, ballSize, ballSize);
      }
    
      connectingBallLine();
    }
    
    void connectingBallLine() {
      if (positions.size()<2)
        return; 
      PVector pv1 = positions.get(count);
      PVector pv2 = positions.get(count+1);
      float x = lerp(pv1.x, pv2.x, amt/60);
      float y = lerp(pv1.y, pv2.y, amt/60);
    
      fill(255, 2, 2); // red 
      ellipse( x, y, 6, 6);
    
      amt = amt + 0.5;
      if (amt>60) {
        amt=0; 
        count++;
        if (count>positions.size()-2) 
          count=0;
      }
    }
    
  • edited February 2017

    Sorry for late respond, I was in hospital for two days.

    Woow this is amazing stuff. This is what I wanted. Thanks for your big help! I really appreciate your help, I don't know what I would do without you. ^:)^

    ArrayList positions = new ArrayList();
    float amt;
    int count; 
     
    void setup() {
      size(640, 360);
      positions.add( new PVector ( width / 2, height / 2) );
    }
     
    void draw() {
      background(0, 0, 255);
      ballManagement();
    }
     
    void mousePressed() {
      positions.add(  new PVector ( mouseX, mouseY )  );
    }
     
    void ballManagement() {
     
      int ballSize = 8;
     
      // Balls parameters
      strokeWeight(1);
      stroke(0);
      fill(255);
     
      for ( int i = 0; i < positions.size(); i++) {
        PVector pv1 = positions.get(positions.size()-1);
        ellipse( pv1.x, pv1.y, ballSize, ballSize);
      }
     
      connectingBallLine();
    }
     
    void connectingBallLine() {
      if (positions.size()<2)
        return; 
      PVector pv1 = positions.get(positions.size()-2);
      PVector pv2 = positions.get(positions.size()-1);
      float x = lerp(pv1.x, pv2.x, amt/60);
      float y = lerp(pv1.y, pv2.y, amt/60);
     
      strokeWeight(1);
      stroke(0);
      fill(255);
      ellipse( x, y, 8, 8);
     
      amt = amt + 0.5;
      if (amt>60) {
        amt=0; 
        count++;
        if (count>positions.size()-2) 
          count=0;
      }
    }
    

    This is very good but still I try to achive this.

  • But /Lord_of_the_Galaxy

    already showed you how.....?

  • You can also combine his and my idea?

  • What this code from @Lord_of_the_Galaxy do?

    public static final int ALPHA_VAL = 5;//fine-tune yourself for best result
    void setup(){
      size(1280, 720);
      background(0);
      blendMode(SUBTRACT);
      noStroke();
    }
     
    void draw(){
      fill(1, ALPHA_VAL);
      rect(0, 0, width, height);
      fill(150, 0, 250);//change the color for different results
      ellipse(mouseX, mouseY, 50, 50);
    }
    

    Video

  • The ellipses get weaker because of weak background that gets drawn over the images

Sign In or Register to comment.