Main content
Computer programming
Course: Computer programming > Unit 5
Lesson 5: Forces- Newton's laws of motion
- Challenge: Floating balloon
- Motion of many objects
- Challenge: Wall balls
- Modeling gravity and friction
- Challenge: Speed bumps
- Air and fluid resistance
- Challenge: Sinking logs
- Gravitational attraction
- Challenge: Artwork generator
- Mutual attraction
- Challenge: Mutual repulsion
- Project: Creature comforts and critter jitters
© 2023 Khan AcademyTerms of usePrivacy PolicyCookie Notice
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
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.
Want to join the conversation?
- Oh my god, I solved this challenge by typing one character!(9 votes)
- Set the gravity constant to something less than 0!(1 vote)
- Hello! Can anyone help guide me in the right direction as to what I should be looking for to fill in these blanks:
Mover.prototype.calculateAttraction = function(m) {
____;
var strength = ____;
____;
};
? I'm pretty sure I got the force.mult(-1*strength); part right, but I don't know where to look to fill in these blanks from the hint! Thanks :).(3 votes)- You need to put a minus sign before the G (well, as we are dealing with vectors, putting a minus changes the direction, putting a minus before G changes the answer for the force from positive to negative, from attraction to repulsion)(5 votes)
- why in the line 30 ( Mover.prototype.calculateAttraction = function(m,i) {) the function is accepting two parameters ? i see the m used inside the function, but i not see the i being used :/(5 votes)
- Is it important the order in the methods, when creating the object? I mean at the beggining of the code, not at the
draw function
. I've realized the.display
is usually after the.applyForce
and theupdate
methods.(2 votes)- The order of methods and properties do not matter.(2 votes)
- Is it possible for an object to be attracted to another object (like in the gravity examples) when it is within a certain distance, but when it is outside of that distance, it moves randomly (like in the walker examples)?
I've tried using PVector.sub to calculate the distance but I'm not sure where I would put the if function...
for example:
if (within certain distance) {
calculate attraction}
else {
move randomly}
here is my actual code that I tried putting within the draw function:
(I know the problem is in this part because both the attraction and random movement work when used individually)
for (var i = 0; i < movers.length; i++) {
var force = attractor.calculateAttraction(movers[i]);
if (force<100) {
movers[i].applyForce(force);
} else {
movers[i].update();
}
movers[i].checkEdges();
movers[i].display();
}
any tips?
thanks(3 votes) - In this last example on mutual attraction there are three loops, one outside the draw function and two inside. I'm getting lost following the logic. Could someone give me an explanation foor each.
Thank you.(1 vote)- First, you make a bunch of Movers. 5 of them in fact.
You want to make them only once, otherwise you'll end up with thousands. :P So you do that outside the draw function.
Then, each Mover is attracted to each other mover.
You could draw a table:
Where there's an o, the two movers attract each other.| 0 1 2 3 4
--+--------------
0 | x o o o o
1 | o x o o o
2 | o o x o o
3 | o o o x o
4 | o o o o x
So for each Mover in in the left column, you find the attraction for each Mover in the upper row: two nested for loops.(4 votes)
- Just put a minus sign before the 1 and after the = on line 1(2 votes)
- What differentiates ==! and ===?(1 vote)
===
checks whether two things are equal.!==
checks whether two things are not equal.(3 votes)
- Hiii, how can i erase some of my spin-offs, i tried to find something like that and there's nothing(1 vote)
- Please go to your profile. You'll find your programs there.
When you open one, you'll see some buttons under the program's display, so below the code and canvas. One of the buttons is "Delete".(3 votes)
- In the next challenge, why is it so easy? It is not making me follow the Hints, and all I did was multiply the force by -1 and I passed. Is that what I was supposed to do?(2 votes)