Tracking ball task with smooth curve

Hi there,

I have a very simply tracking task in which people track a ball with their mouse. Currently the ball bounces off the edges of the screen, however I would like it to follow along a smooth curve (basically so that accuracy is not impeded by the bounce movement. Any help would be much appreciated!

This is the tracking task:

PrintWriter out;

void setup() {
  fullScreen();
 //size(640, 360);
  noStroke();
  frameRate(30);
  fill(0,0,400);
  ellipseMode(RADIUS);
  // Set the starting position of the shape
  xpos = width/2;
  ypos = height/2;
     out = createWriter("M:\\Tracking_Taskworking\\accuracy.csv");
   
}
int rad = 12;        // Width of the shape
//float xpos, ypos;    // Starting position of shape    
float xpos, ypos;    // Starting position of shape    

float xspeed = 3;  // Speed of the shape
float yspeed = 3;  // Speed of the shape

int xdirection = 1;  // Left or Right
int ydirection = 1;  // Top to Bottom
double dist; //distance between cursor and moving target

void draw() 
{
      background(1);
      // Update the position of the shape
  xpos = xpos + ( xspeed * xdirection );
  ypos = ypos + ( yspeed * ydirection );
  
  // Test to see if the shape exceeds the boundaries of the screen
  // If it does, reverse its direction by multiplying by -1
  if (xpos > width-rad || xpos < rad) {
    xdirection *= -1;
  }
  if (ypos > height-rad || ypos < rad) {
    ydirection *= -1;
  }

  // Draw the shape
  ellipse(xpos, ypos, rad, rad);

// Calculate distance between cursor and moving target
dist = (Math.sqrt((xpos-mouseX)*(xpos-mouseX) + ((ypos-mouseY)*(ypos-mouseY))));

      out.println((int)dist+","+(int)millis());
    out.flush();
    
}

What about something like this:

PVector target;
movingCircle mc;
int margin;
float minDist, spawnDist;

void setup() {
  
  size(800, 600);
  background(20);

  mc = new movingCircle();
  target = new PVector(50, height / 2);
  margin = 50; 
  minDist = width / 2;
  spawnDist = 40;
}


void draw() {
  background(20);
  
  if (dist(target.x, target.y, mc.getPos().x, mc.getPos().y) < spawnDist) {
    spawnTarget();
  }

  fill(200);
  noStroke();
  ellipse(target.x, target.y, 5, 5);

  mc.moveToward(target);
  mc.show();
}

void spawnTarget() {
  PVector newTarget;
  newTarget = getRandomVector();
  while (dist(newTarget.x, newTarget.y, target.x, target.y) < minDist) {
    newTarget = getRandomVector();
  }
  target = newTarget.copy();
}

PVector getRandomVector() {
  return new PVector(random(margin, width - margin), random(margin, height - margin));
}
  

void mouseClicked() {
}

class movingCircle {
  private int size;
  private PVector pos, dir;
  private float speed;
  private color col;
  private float rotSpeed; // Between 0 and 1

  public movingCircle() {
    size = 30;
    pos = new PVector((int)(width / 2), (int)(height / 2));
    dir = new PVector(1, 0);
    dir.normalize();
    speed = 3;
    col = color(200, 20, 20);
    rotSpeed = 0.02;
  }

  public PVector getPos() {
    return pos;
  }

  public void moveToward(PVector target) {
    PVector targetDir = target.copy().sub(pos);
    float angleToTarget = PVector.angleBetween(dir, targetDir);
    float angleStep = angleToTarget * rotSpeed;
    int turnDir;

    if (PVector.angleBetween(dir.copy().rotate(angleToTarget), targetDir) < PVector.angleBetween(dir.copy().rotate(-angleToTarget), targetDir)) {
      turnDir = 1;
    } else {
      turnDir = -1;
    }

    dir.rotate(turnDir * angleStep);

    move();
  }

  private void move() {
    pos.add(dir.copy().mult(speed));
  }

  public void show() {
    noStroke();
    fill(col);
    ellipse(pos.x, pos.y, size, size);
  }
}

The basic idea is to spawn a target that the circle need to eat. Of course it is not perfect since I see at least 2 flaws:

  • Sometimes it changes the direction of rotation a bit too harshly
  • Sometimes the ball still goes out of the screen

But it should be a nice start =)

1 Like

And please read the guideline here: Guidelines—Tips on Asking Questions

It is explained how to properly format your code. You can still do it by editing your previous post.

1 Like

Hi there,

thanks very much for your help! I will certainly use some of the ideas in there. Plus thanks for the link to the guidelines! :slight_smile: have amended!

Cheers

If you have defined your motion path as a curve then you can use bezierPoint or curvePoint to evaluate a position on the path over time. Is the target following a curved or segmented path, and should the speed of the motion target be constant over time, or can its rate of speed change?

Check out the bundled Processing PDE examples “MovingOnCurves” and, if you need a continuous fixed speed, “ArcLengthParametization.”