smooth friction until velocity gets very close to zero, then jerky for the last couple of pixels

edited March 2018 in Questions about Code

This sketch moves the marbles when you hit the space bar. They decelerate smoothly until almost stopped, but then jiggle just enough to bother the programmer. It's only a couple of unstable pixels at the very end, but not the nice fluid deceleration you'd like to see (and show to your friends). Any suggestions greatly appreciated!

import java.util.ArrayList;

ArrayList list = new ArrayList();
float radius = 35;
float maxVelocity = 10;

void setup() {
  size(800, 600);
  smooth();
  for (int i = 0; i< 15; i++)
    list.add(new Marble());
}

void draw() {
  if (millis() < 1000)
    ((java.awt.Canvas) surface.getNative()).requestFocus();
  background(200);
  for (Marble m : list)
    m.draw();
}

void keyPressed() {
  for (Marble m : list)
    m.velocity.set(random(-maxVelocity, maxVelocity), random(-maxVelocity, maxVelocity));
}

class Marble {
  PVector location, velocity;

  public Marble() {
    location = new PVector(random(width*0.1, width*0.9), random(height*0.1, height*0.9));
    velocity = new PVector(random(-maxVelocity, maxVelocity), random(-maxVelocity, maxVelocity));
  }

  void draw() {
    ellipse(location.x, location.y, radius * 2, radius * 2);
    checkEdgeCollision();
    location.add(velocity);
    velocity.mult(0.975);
  }

  public void checkEdgeCollision() {
    if ((location.x > width - radius) || (location.x < radius)) 
      velocity.x *= -1;
    if ((location.y > height - radius) || (location.y < radius)) 
      velocity.y *= -1;
    if (location.x > width - radius) 
      location.x = width - radius;
    else if (location.x < radius) 
      location.x = radius;
    if (location.y > height - radius) 
      location.y = height - radius;
    else if (location.y < radius) 
      location.y = radius;
  }
}

Answers

  • Answer ✓

    Try another renderer.

    The default renderer, istr, works only with integer positions.

  • Maybe easing is the way to go....

    Kf

    float posx=100;
    float vel=3.0;
    float acc=-0.2;
    float easyingFactor=0.20;  //80%
    
    void setup() {
      size(400, 600);
      fill(255);
      noStroke();
    }
    
    void draw() {
      background(80);
      posx=posx+vel;
      vel=lerp(vel, vel+acc, easyingFactor);
      ellipse(posx, 100, 50, 50);
      if (vel<0) {
        acc=vel=0;
      }
    }
    
    void mouseReleased() {
      posx=random(0, width/2);
      vel=random(2,5);;
      acc=-random(0.1,0.5);
    }
    
  • Thanks a ton Koogs! Looks great in P2D!

    Breadcrumb trail for NetBeans users: To get size(800, 600, P2D) running in NetBeans I added all the OpenGL jars from <Processing's install folder>\core\library to the build path (had formerly only needed core.jar, now includes jogl* and gluegen-rt*). Also had a funky glitch with mousePressed and mouseDragged. With P2D, mouse down on my touch screen was generating mousePressed and one mouseDragged. Unfortunately, the mouseDragged made it look like the mouse had drug a few hundred pixels (distance between mouseX,mouseY and pmouseX,pmouseY). Added a hack to ignore the first mouseDragged(), and everything's neat, tidy, and fluid. Thanks again!

  • Great alternative kfrajer! Very clean and straightforward. Thank you too!

Sign In or Register to comment.