Easing mouse strokes

edited June 2016 in Questions about Code

Hello. I've created an easing function that allows mouse cursor to behave elastically. But the problem is, I can't get anything drawn on the canvas. The elastic string line (green) should appear when mouse is clicked and should disappear once mouse is released; but to achieve that I set 'background' to a certain color, which doesn't allow me to draw (draw through continuous lines like this) on the canvas. All I want is to draw shapes not with my mouse coordinates but with the scattering point of the line (the orange dot), which will make the strokes less jagged. Here's the code I'm working with:

Spring2D s1;

float gravity = 0;
float mass = 4.0;

void setup() {
  frameRate(60);
  size(640, 360);
  fill(255, 126);
  // Inputs: x, y, mass, gravity
  s1 = new Spring2D(0.0, width/2, mass, gravity);
  }

void draw() {
  s1.display(mouseX, mouseY);
  s1.update(mouseX, mouseY);
  }

class Spring2D {
  float vx, vy; // The x- and y-axis velocities
  float x, y; // The x- and y-coordinates
  float gravity;
  float mass;
  float radius = 10;
  float stiffness = 0.7;
  float damping = 0.5;

  Spring2D(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; 
  }

  void display(float nx, float ny) {
   if (mousePressed == true) {

    background(0);

    stroke(40, 255, 150);
    line(x, y, nx, ny);


    noStroke();
    fill(255, 130, 40);
    ellipse(x, y, 5, 5);

  } else  {
   background(0);
   }
  }
}

Thanks.

Tagged:

Answers

  • this is surely not ideal, but it is an idea, maybe it could lead to something better. You can erase the old green lines by drawing over them with a black line. The problem is that the black lines will be drawn over parts of the orange line, especially when the mouse is moving quickly.

    Spring2D s1;
    
    float gravity = 0;
    float mass = 4.0;
    
    void setup() {
      frameRate(60);
      size(640, 360);
      fill(255, 126);
      // Inputs: x, y, mass, gravity
      s1 = new Spring2D(0.0, width/2, mass, gravity);
      background(0);
      }
    
    void draw() {
      s1.update(mouseX, mouseY);
      s1.display(mouseX, mouseY);
    
      }
    
    class Spring2D {
      float vx, vy; // The x- and y-axis velocities
      float x, y;   // The x- and y-coordinates
      float px, py; // the previous x- and y- coordinates
      float gravity;
      float mass;
      float radius = 10;
      float stiffness = 0.7;
      float damping = 0.5;
    
      Spring2D(float xpos, float ypos, float m, float g) {
        x = xpos;
        y = ypos;
        px = xpos;
        py = ypos;
        mass = m;
        gravity = g;
      }
    
      void update(float targetX, float targetY) {
        px = x;
        py = y;
        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; 
      }
    
      void display(float nx, float ny) {
       if (mousePressed == true) {
    
        stroke(0);
        strokeWeight(3);
    
        line(px, py, pmouseX, pmouseY);
    
        stroke(255, 130, 40);
        line(px, py, x, y);
    
        stroke(40, 255, 150);
        strokeWeight(1);
        line(x, y, nx, ny);
    
    
        noStroke();
        fill(255, 130, 40);
        ellipse(x, y, 3, 3);
    
      } else  {
      // background(0);
       }
      }
    }
    
  • Yeah, thanks. If black lines wasn't drawn on the orange one, it would be perfect. ^^

  • Is it that hard guys?

  • Solved?

  • No Chrisir, still looking for the solution.

  • Answer ✓
    Spring2D s1;
    
    float gravity = 0;
    float mass = 4.0;
    
    ArrayList<PVector> memory = new ArrayList(); 
    
    void setup() {
    
      size(640, 360);
      frameRate(60);
      fill(255, 126);
      // Inputs: x, y, mass, gravity
      s1 = new Spring2D(0.0, width/2, mass, gravity);
    }
    
    void draw() {
      background(0);
    
      s1.display(mouseX, mouseY);
      s1.update(mouseX, mouseY);
    
      // ellipses
      //for (PVector pv : memory) {
      //  fill(255, 130, 40); // orange
      //  fill(255, 0, 0); // red
      //  ellipse(pv.x, pv.y, 2, 2);
      //}
    
      // lines 
      for (int i = 0; i<memory.size()-2; i++) {
        //fill(255, 130, 40); // orange
        PVector pv1=memory.get(i);
        PVector pv2=memory.get(i+1);
        stroke(255, 0, 0); // red
        line(pv1.x, pv1.y, 
          pv2.x, pv2.y);
        noStroke();
      }
    }
    
    class Spring2D {
      float vx, vy; // The x- and y-axis velocities
      float x, y; // The x- and y-coordinates
      float gravity;
      float mass;
      float radius = 10;
      float stiffness = 0.7;
      float damping = 0.5;
    
      Spring2D(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;
      }
    
      void display(float nx, float ny) {
        if (mousePressed == true) {
    
          background(0);
    
          stroke(40, 255, 150);
          line(x, y, nx, ny);
    
    
          noStroke();
          fill(255, 130, 40);
          ellipse(x, y, 5, 5);
          store(x, y);
        } else {
          //background(0);
        }
      }
    }
    
    void store (float x, float y) {
      memory.add(new PVector(x, y));
    }
    // 
    
  • Oh Chrisir, that's awesome, exactly what I want. Thank you so much.

    The only little thing is that when mouse is released and and clicked somewhere else, it connects the line. And likewise; the first stroke, when mouse is clicked on a point and stay still it draws a short line towards the mouse cursor. ^^ Can you fix that too?

  • I can't . I don't see how

  • Thanks :)

  • edited July 2016

    Just kidding

    Its dead easy

    I just don't have time

  • Ah ok, then I'll play a bit with it. But still open to your edit ^^

  • edited July 2016 Answer ✓

    first in line 90 check if one of the values is different from the previous

    line 20&21 at end of draw() better

    for the line - that's true. you could

    • make an ArrayList segments of our current ArrayList with PVector (solution A) OR

    • make a class with PVector & a flag hasNextLine or so (solution B)

  • following solution B above :

    Spring2D s1;
    
    float gravity = 0;
    float mass = 4.0;
    
    ArrayList<Point2D> memory = new ArrayList(); 
    
    void setup() {
    
      size(640, 360);
      frameRate(60);
      fill(255, 126);
    
      // Inputs: x, y, mass, gravity
      s1 = new Spring2D(0.0, width/2, mass, gravity);
    }
    
    void draw() {
    
      background(0);
    
    
      // ellipses
      //for (PVector pv : memory) {
      //  fill(255, 130, 40); // orange
      //  fill(255, 0, 0); // red
      //  ellipse(pv.x, pv.y, 2, 2);
      //}
    
      // lines 
      stroke(255, 0, 0); // red
      for (int i = 0; i<memory.size()-2; i++) {
        //fill(255, 130, 40); // orange
        if (memory.get(i).hasLineToNext) {
          PVector pv1=memory.get(i).p1;
          PVector pv2=memory.get(i+1).p1;
    
          line(pv1.x, pv1.y, 
            pv2.x, pv2.y);
        }
      }//for
      noStroke();
    
      s1.display(mouseX, mouseY);
      s1.update(mouseX, mouseY);
    } // draw 
    
    // ---------------------------------------------------------
    
    void store (float x, float y) {
      int sizeArrayList = memory.size()-1;
    
      if (sizeArrayList>=0) {
        PVector p1 = memory.get(sizeArrayList).p1; 
    
        if (p1.x!=x || p1.y!=y)
          memory.add(new Point2D(x, y));
      } // if
      else {
        // first point gets stored always 
        memory.add(new Point2D(x, y));
      } // else 
    
      println( memory.size());
    }
    
    void mouseReleased() {
      // break the line !!!
    
      // the last element is set as not having a line after it 
      int sizeArrayList = memory.size()-1;
      memory.get(sizeArrayList).hasLineToNext=false;
    }
    
    // ===================================================
    
    class Spring2D {
      float vx, vy; // The x- and y-axis velocities
      float x, y; // The x- and y-coordinates
      float gravity;
      float mass;
      float radius = 10;
      float stiffness = 0.7;
      float damping = 0.5;
    
      Spring2D(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;
      }
    
      void display(float nx, float ny) {
        if (mousePressed) {
    
          //   background(0);
    
          stroke(40, 255, 150);
          line(x, y, nx, ny);
    
    
          noStroke();
          fill(255, 130, 40);
          ellipse(x, y, 5, 5);
          store(nx, ny);
        } else {
          //background(0);
        }
      }
    }
    
    // ==============================================
    
    class Point2D {
    
      // later all those points are connected to lines 
    
      // position of the point
      PVector p1;
    
      // this indicates whether the line is interrupted (see mouseReleased()) 
      boolean hasLineToNext=true;  // default
    
      // constructor
      Point2D(float x_, float y_) {
    
        p1=new PVector(x_, y_);
      }// constructor
      //
    }// class
    // 
    
  • Have you tried this code? This weirdly draws by mouse co-ordinates and not by the orange line.

  • edited July 2016 Answer ✓

    Ah, ok

    Line 117

    replace nx, ny

    with x,y

  • Aww marry me!

Sign In or Register to comment.