If you're seeing this message, it means we're having trouble loading external resources on our website.

If you're behind a web filter, please make sure that the domains *.kastatic.org and *.kasandbox.org are unblocked.

# Mutual attraction

Hopefully, you found it helpful that we started with a simple scenario—one object attracts another object—and moved on to one object attracts many objects. However, it’s likely that you are going to find yourself in a slightly more complex situation: many objects attract each other. In other words, every object in a given system attracts every other object in that system (except for itself).
We’ve really done almost all of the work for this already. Let’s consider a program with an array of `Mover` objects:
``````var movers = [];

for (var i = 0; i < 5; i++) {
movers[i] = new Mover(
random(0.1, 2),
random(width),
random(height));
}

draw = function() {
background(255, 255, 255);
for (var i = 0; i < movers.length; i++) {
movers[i].update();
movers[i].display();
}
};``````
The `draw()` function is where we need to work some magic. Currently, we’re saying: “for every mover i, update and display yourself.” Now what we need to say is: “for every mover i, be attracted to every other mover j, and update and display yourself.”
``````for (var i = 0; i < movers.length; i++) {
// For every Mover, check every Mover!
for (var j = 0; j < movers.length; j++) {
var force = movers[j].calculateAttraction(movers[i]);
movers[i].applyForce(force);
}
}

for (var i = 0; i < movers.length; i++) {
movers[i].update();
movers[i].display();
}``````
Notice that we made an entirely new `for` loop above the update-and-display loop. That's because we want to make sure that we calculate all the attraction forces before updating each mover. If we accidentally updated each mover in that first `for` loop, then we'd be affecting the calculation of the attraction forces after, and they wouldn't be accurate.
Our code won't work yet, because we need each `Mover` to have a `calculateAttraction()` method. In the previous example, we had an `Attractor` object with a method named `calculateAttraction()`. Now, since we have movers attracting movers, we can copy that method into the `Mover` object:
``````Mover.prototype.calculateAttraction = function(m) {
var force = PVector.sub(this.position, m.position);
var distance = force.mag();
distance = constrain(distance, 5.0, 25.0);
force.normalize();

var strength = (G * this.mass * m.mass) / (distance * distance);
force.mult(strength);
return force;
};``````
Of course, there’s one small problem. When we are looking at every mover i and every mover j, are we OK with the times that i equals j? For example, should mover #3 attract mover #3? The answer, of course, is no. If there are five objects, we only want mover #3 to attract 0, 1, 2, and 4, skipping itself. We do, however, want to calculate and apply both the force from mover #3 on mover #1, and mover #1 on mover #3. The calculated forces will be the same for the pair, but the resulting acceleration will be different, depending on the mass of each mover. Our attraction table should look like:
0 ⇢ 1, 2, 3, 4
1 ⇢ 0, 2, 3, 4
2 ⇢ 0, 1, 3, 4
3 ⇢ 0, 1, 2, 4
And so, we finish this example by modifying our for loop so that the inner loop avoids movers attracting themselves:
``````for (var i = 0; i < movers.length; i++) {
for (var j = 0; j < movers.length; j++) {
if (i !== j) {
var force = movers[j].calculateAttraction(movers[i]);
movers[i].applyForce(force);
}
}
}``````
Let's see it all together now:

This "Natural Simulations" course is a derivative of "The Nature of Code" by Daniel Shiffman, used under a Creative Commons Attribution-NonCommercial 3.0 Unported License.