I have a sketch that simulates marbles bumping into each other. Each marble has one PVector for ‘location’ and another one for ‘velocity’. location.add(velocity) moves the marble to it’s next location, slowly for small velocities, quickly for larger ones.

I’d like to create a small group of marbles clustering around some random point, with random initial velocities but all pointing straight out/away from the middle of the cluster.

Below are the main pieces pulled out of the rest of the sketch. It just places the marbles but doesn’t move them around, decrease their velocities, etc…

Any help setting the velocities to point outward from ‘r’ would be huge!!

class MovingPoint {
PVector location, velocity;
MovingPoint(float x, float y, float xv, float yv) {
location = new PVector(x, y);
velocity = new PVector(xv, yv);
}
}
MovingPoint [] points;
void setup() {
size(800, 600);
ellipseMode(CENTER);
points = new MovingPoint[10];
for (int i=0; i<10; i++)
points[i] = new MovingPoint(0, 0, 0, 0);
initializePoints();
}
void initializePoints() {
// pick a semi-random point as the center
PVector r = new PVector(random(200, 600), random(200, 400));
for (int i=0; i<10; i++) {
points[i].location.x = r.x + random(-50, 50);
points[i].location.y = r.y + random(-50, 50);
// how to set the velocities pointing out/away from 'r'?
}
}
void draw() {
background(225);
stroke(0);
fill(0);
for (int i=0; i<10; i++)
ellipse(points[i].location.x, points[i].location.y, 10, 10);
}
void mouseClicked() {
initializePoints();
}

tip: how you initialize the point will end up with points forming a square (you will find it if you increase the number of points). If you want a circular distribution, check out random2D, which returns a vector with a random angle and a unit length. Then you can scale the vector with a random value. https://processing.org/reference/PVector_random2D_.html

I ended up using polar coordinates to aim the marbles straight out from the center. Here’s the rework in case it helps anyone else-

class MovingPoint {
PVector location, velocity;
MovingPoint(float x, float y, float xv, float yv) {
location = new PVector(x, y);
velocity = new PVector(xv, yv);
}
}
final int NUM_POINTS = 10;
MovingPoint [] points;
PVector center;
void setup() {
size(800, 600);
ellipseMode(CENTER);
points = new MovingPoint[NUM_POINTS];
center = new PVector();
for (int i=0; i<NUM_POINTS; i++)
points[i] = new MovingPoint(0, 0, 0, 0);
initializePoints();
}
void initializePoints() {
float radius = 50; // radius from center to marbles
float degrees = 270; // top
float dx = 360.0 / NUM_POINTS;
// pick a semi-random point as the center
center = new PVector(random(200, 600), random(200, 400));
for (int i=0; i< NUM_POINTS; i++, degrees+=dx) {
float x = center.x + radius * cos(radians(degrees));
float y = center.y + radius * sin(radians(degrees));
points[i].location.x = x;
points[i].location.y = y;
// calculate the point twice as far out as this one (going straight out)
// ... and set the velocity equal to the difference
// (so one "location.add(velocity)" moves this marble twice as far out)
points[i].velocity.x = (center.x + radius * 2 * cos(radians(degrees))) - x;
points[i].velocity.y = (center.y + radius * 2 * sin(radians(degrees))) - y;
}
}
void draw() {
if (millis() < 1000)
((java.awt.Canvas) surface.getNative()).requestFocus();
background(225);
stroke(255, 0, 50);
fill(255, 0, 50);
ellipse(center.x, center.y, 5, 5);
stroke(0);
fill(0);
for (int i=0; i<NUM_POINTS; i++) {
MovingPoint p = points[i];
ellipse(p.location.x, p.location.y, 10, 10);
// add one pass at the velocity to see where the marble is headed
line(p.location.x, p.location.y, p.location.x + p.velocity.x, p.location.y + p.velocity.y);
}
}
void mouseClicked() {
initializePoints();
}

but either way works The repulsion force (this case velocity) is a difference between the two points (where the force is applied - where the center is) so actually the position of PVector center doesn’t affect the velocity and only the offset (this case cos/sin * radius or in the previous case random(-50,50)) matters.