If you're seeing this message, it means we're having trouble loading external resources for Khan Academy.

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

In the final example of the last section, we saw how we could calculate a dynamic acceleration based on a vector pointing from a circle on the screen to the mouse location. The resulting motion resembled a magnetic attraction between circle and mouse, as if some force were pulling the circle in towards the mouse. In this section, we will formalize our understanding of the concept of a force and its relationship to acceleration. Our goal, by the end of this, is to understand how to make multiple objects move around the screen and respond to a variety of environmental forces.

Before we begin examining the practical realities of simulating forces in code, let’s take a conceptual look at what it means to be a force in the real world. Just like the word “vector,” “force” is often used to mean a variety of things. It can indicate a powerful intensity, as in “She pushed the boulder with great force” or “He spoke forcefully.” The definition of force that we care about is much more formal and comes from Isaac Newton’s laws of motion:

A force is a vector that causes an object with mass to accelerate.

The good news here is that we recognize the first part of the definition: a force is a vector. Thank goodness we just spent a whole section learning what a vector is and how to program with PVectors!

Let’s look at Newton's three laws of motion in relation to the concept of a force.

Newton’s First Law

Newton’s first law is commonly stated as:

An object at rest stays at rest and an object in motion stays in motion.

However, this is missing an important element related to forces. We could expand it by stating:

An object at rest stays at rest and an object in motion stays in motion at a constant speed and direction unless acted upon by an unbalanced force.

By the time Newton came along, the prevailing theory of motion—formulated by Aristotle—was nearly two thousand years old. It stated that if an object is moving, some sort of force is required to keep it moving. Unless that moving thing is being pushed or pulled, it will simply slow down or stop. Right?

This, of course, is not true. In the absence of any forces, no force is required to keep an object moving. An object (such as a ball) tossed in the earth’s atmosphere slows down because of air resistance (a force). An object’s velocity will only remain constant in the absence of any forces or if the forces that act on it cancel each other out, i.e. the net force adds up to zero. This is often referred to as equilibrium. The falling ball will reach a terminal velocity (that stays constant) once the force of air resistance equals the force of gravity.

Diagram of two people blowing on pendulumThe pendulum doesn't move because all the forces cancel each other out (add up to a net force of zero)

In our ProcessingJS world, we could restate Newton’s first law as follows:

An object’s PVector velocity will remain constant if it is in a state of equilibrium.

Skipping Newton’s second law (arguably the most important law for our purposes) for a moment, let’s move on to the third law.

Newton’s Third Law

This law is often stated as:

For every action there is an equal and opposite reaction.

This law frequently causes some confusion in the way that it is stated. For one, it sounds like one force causes another. Yes, if you push someone, that someone may actively decide to push you back. But this is not the action and reaction we are talking about with Newton’s third law.

Let’s say you push against a wall. The wall doesn’t actively decide to push back on you. There is no “origin” force. Your push simply includes both forces, referred to as an “action/reaction pair.”

A better way of stating the law might be:

Forces always occur in pairs. The two forces are of equal strength, but in opposite directions.

Now, this still causes confusion because it sounds like these forces would always cancel each other out. This is not the case. Remember, the forces act on different objects. And just because the two forces are equal, it doesn’t mean that the movements are equal (or that the objects will stop moving).

Try pushing on a stationary truck. Although the truck is far more powerful than you, unlike a moving one, a stationary truck will never overpower you and send you flying backwards. The force you exert on it is equal and opposite to the force exerted on your hands. The outcome depends on a variety of other factors. If the truck is a small truck on an icy downhill, you’ll probably be able to get it to move. On the other hand, if it’s a very large truck on a dirt road and you push hard enough (maybe even take a running start), you could injure your hand.

What if you pushed a truck while wearing roller skates?

A man pushing a truck while wearing roller skatesYou’ll accelerate away from the truck, sliding along the road while the truck stays put. Why do you slide but not the truck? For one, the truck has a much larger mass (which we’ll get into with Newton’s second law). There are other forces at work too, namely the friction of the truck’s tires and your roller skates against the road.

Let's re-state Newton's third law for our ProcessingJS world:

If we calculate a PVector f that is a force of object A on object B, we must also apply the force—PVector.mult(f,-1);—that B exerts on object A.

We’ll see that in the world of ProcessingJS programming, we don’t always have to stay true to the above. Sometimes, such as in the case of see gravitational attraction between bodies, we’ll want to model equal and opposite forces. Other times, such as when we’re simply saying, “Hey, there’s some wind in the environment,” we’re not going to bother to model the force that a body exerts back on the air. In fact, we’re not modeling the air at all! Remember, we are simply taking inspiration from the physics of the natural world, not simulating everything with perfect precision.

Newton's Second Law

And here we are at the most important law for the ProcessingJS programmer.

This law is traditionally stated as:

Force equals mass times acceleration.

Or:

\vec{F} = M\vec{A}

Why is this the most important law for us? Well, let’s write it a different way.

\vec{A} = \vec{F}/M

Acceleration is directly proportional to force and inversely proportional to mass. This means that if you get pushed, the harder you are pushed, the faster you’ll move (accelerate). The bigger you are, the slower you’ll move.

Weight vs. Mass

The mass of an object is a measure of the amount of matter in the object (measured in kilograms).

Weight, though often mistaken for mass, is technically the force of gravity on an object. From Newton’s second law, we can calculate it as mass times the acceleration of gravity (w = m * g). Weight is measured in newtons.

Density is defined as the amount of mass per unit of volume (grams per cubic centimeter, for example).

Note that an object that has a mass of one kilogram on earth would have a mass of one kilogram on the moon. However, it would weigh only one-sixth as much.

Now, in the world of ProcessingJS, what is mass anyway? Aren’t we dealing with pixels? To start in a simpler place, let’s say that in our pretend pixel world, all of our objects have a mass equal to 1. F/1 = F. And so:

\vec{A} = \vec{F}

The acceleration of an object is equal to force. This is great news. After all, we saw in the Vectors section that acceleration was the key to controlling the movement of our objects on screen. Location is adjusted by velocity, and velocity by acceleration. Acceleration was where it all began. Now we learn that force is truly where it all begins.

Let's use what we've learnt to build on our Mover object, which currently has location, velocity, and acceleration. Now our goal is to be able to add forces to this object, perhaps saying:

mover.applyForce(wind);

or:

mover.applyForce(gravity);

where wind and gravity are PVectors. According to Newton’s second law, we could implement this function as follows:

Mover.prototype.applyForce = function(force) {
    this.acceleration = force;
};

Force Accumulation

This looks pretty good. After all, acceleration = force is a literal translation of Newton’s second law (without mass). Nevertheless, there’s a pretty big problem here. Let’s return to what we are trying to accomplish: creating a moving object on the screen that responds to wind and gravity.

mover.applyForce(wind);
mover.applyForce(gravity);
mover.update();
mover.display();

Ok, let’s be the computer for a moment. First, we call applyForce() with wind. And so the Mover object’s acceleration is now assigned the PVector wind. Second, we call applyForce() with gravity. Now the Mover object’s acceleration is set to the gravity PVector. Third, we call update(). What happens in update()? Acceleration is added to velocity.

velocity.add(acceleration);

We’re not going to see any error in our program, but zoinks! We’ve got a major problem. What is the value of acceleration when it is added to velocity? It is equal to the gravity force. Wind has been left out! If we call applyForce() more than once, it overrides each previous call. How are we going to handle more than one force?

The truth of the matter here is that we started with a simplified statement of Newton’s second law. Here’s a more accurate way to put it:

Net Force equals mass times acceleration.

Or, acceleration is equal to the sum of all forces divided by mass. This makes perfect sense. After all, as we saw in Newton’s first law, if all the forces add up to zero, an object experiences an equilibrium state (i.e. no acceleration). Our implementation of this is through a process known as force accumulation. It’s actually very simple; all we need to do is add all of the forces together. At any given moment, there might be 1, 2, 6, 12, or 303 forces. As long as our object knows how to accumulate them, it doesn’t matter how many forces act on it.

Let's modify the applyForce() method so that we add each new force to acceleration, accumulating them:

Mover.prototype.applyForce = function(force) {
    this.acceleration.add(force);
};

Now, we’re not finished just yet. Force accumulation has one more piece. Since we’re adding all the forces together at any given moment, we have to make sure that we clear acceleration (i.e. set it to zero) before each time update() is called. Let’s think about wind for a moment. Sometimes the wind is very strong, sometimes it’s weak, and sometimes there’s no wind at all. At any given moment, there might be a huge gust of wind, say, when the user holds down the mouse

if (mousePressed) {
  var wind = new PVector(0.5, 0);
  mover.applyForce(wind);
}

When the user releases the mouse, the wind will stop, and according to Newton’s first law, the object will continue to move at a constant velocity. However, if we had forgotten to reset acceleration to zero, the gust of wind would still be in effect. Even worse, it would add onto itself from the previous frame, since we are accumulating forces! Acceleration, in our simulation, has no memory; it is simply calculated based on the environmental forces present at a moment in time. This is different than, say, location, which must remember where the object was in the previous frame in order to move properly to the next.

The easiest way to implement clearing the acceleration for each frame is to multiply the PVector by 0 at the end of update().

Mover.prototype.update = function() {
    this.velocity.add(this.acceleration);
    this.location.add(this.velocity);
    this.acceleration.mult(0);
};

Dealing with Mass

OK. We’ve got one tiny little addition to make before we are done with integrating forces into our Mover class and are ready to look at examples. After all, Newton’s second law is really \vec{F} = M\vec{A}, not \vec{A} = \vec{F}. Incorporating mass is as easy as adding a property to our object, but we need to spend a little more time here because a slight complication will emerge.

 

Units of Measurement

Now that we are introducing mass, it’s important to make a quick note about units of measurement. In the real world, things are measured in specific units. We say that two objects are 3 meters apart, the baseball is moving at a rate of 90 miles per hour, or this bowling ball has a mass of 6 kilograms. As we’ll see later in this course, sometimes we will want to take real-world units into consideration. However, in this section, we’re going to ignore them for the most part. Our units of measurement are in pixels (“These two circles are 100 pixels apart”) and frames of animation (“This circle is moving at a rate of 2 pixels per frame”). In the case of mass, there isn’t any unit of measurement for us to use. We’re just going to make something up. In this example, we’re arbitrarily picking the number 10. There is no unit of measurement, though you might enjoy inventing a unit of your own, like “1 moog” or “1 yurkle.” It should also be noted that, for demonstration purposes, we’ll tie mass to pixels (drawing, say, a circle with a radius of 10). This will allow us to visualize the mass of an object. In the real world, however, size does not definitely indicate mass. A small metal ball could have a much higher mass than a large balloon due to its higher density.

Mass is a scalar (float), not a vector, as it’s just one number describing the amount of matter in an object. We could be fancy about things and compute the area of a shape as its mass, but it’s simpler to begin by saying, “Hey, the mass of this object is…um, I dunno…how about 1?”

var Mover = function() {
    this.mass = 1;
    this.position = new PVector(random(width), random(height));
    this.velocity = new PVector(0, 0);
    this.acceleration = new PVector(0, 0);
};

This isn’t so great since things only become interesting once we have objects with varying mass, but it’ll get us started. Where does mass come in? We use it while applying Newton’s second law to our object.

Mover.prototype.applyForce = function(force) {
  force.div(this.mass);
  this.acceleration.add(force);
};

Yet again, even though our code looks quite reasonable, we have a fairly major problem here. Consider the following scenario with two Mover objects, both being blown away by a wind force.

var m1 = new Mover();
var m2 = new Mover();
 
var wind = new PVector(1, 0);
 
m1.applyForce(wind);
m2.applyForce(wind);

Again, let’s be the computer. Object m1 receives the wind force—(1,0)—divides it by mass (10), and adds it to acceleration.

m1 equals wind force: (1,0)
Divided by mass of 10: (0.1,0)

OK. Moving on to object m2. It also receives the wind force—(1,0). Wait. Hold on a second. What is the value of the wind force? Taking a closer look, the wind force is actually now (0.1,0)!! Do you remember this little tidbit about working with objects? When you pass an object (in this case a PVector) into a function, you are passing a reference to that object. It’s not a copy! So if a function makes a change to that object (which, in this case, it does by dividing by mass) then that object is permanently changed! But we don’t want m2 to receive a force divided by the mass of object m1. We want it to receive that force in its original state—(1,0). And so we must protect ourselves and make a copy of the PVector f before dividing it by mass. Fortunately, the PVector object has a convenient method for making a copy—get(). get() returns a new PVector object with the same data. And so we can revise applyForce() as follows:

Mover.prototype.applyForce = function(force) {
    var f = force.get();
    f.div(this.mass);
    this.acceleration.add(f);
};

Alternatively, we could re-write the method using the static version of div(), using what we learnt about static functions from the previous section:

Mover.prototype.applyForce = function(force) {
  var f = PVector.div(force, this.mass);
  this.acceleration.add(f);
};

The important thing is to find a way to *not* affect that original force vector, so that it can be applied to multiple Mover objects.

Creating Forces

We know what a force is (a vector), and we know how to apply a force to an object (divide it by mass and add it to the object’s acceleration vector). What are we missing? Well, we have yet to figure out how we get a force in the first place. Where do forces come from?

Throughout this section, we'll look at two methods for creating forces in our ProcessingJS world:

  • Make up a force! After all, you are the programmer, the creator of your world. There’s no reason why you can’t just make up a force and apply it.
  • Model a force! Yes, forces exist in the real world. And physics textbooks often contain formulas for these forces. We can take these formulas, translate them into source code, and model real-world forces in ProcessingJS.

The easiest way to make up a force is to just pick a number. Let’s start with the idea of simulating wind. How about a wind force that points to the right and is fairly weak? Assuming a Mover object m, our code would look like:

var wind = new PVector(0.01, 0);
  m.applyForce(wind);

The result isn’t terribly interesting, but it is a good place to start. We create a PVector object, initialize it, and pass it into an object (which in turn will apply it to its own acceleration). If we wanted to have two forces, perhaps wind and gravity (a bit stronger, pointing down), we might write the following:

var wind = new PVector(0.01, 0);
var gravity = new PVector(0, 0.1);
m.applyForce(wind);
m.applyForce(gravity);

Now we have two forces, pointing in different directions with different magnitudes, both applied to object m. We’re beginning to get somewhere. We’ve now built a world for our objects in ProcessingJS, an environment to which they can actually respond.

Here's what our program looks like, when we put that all together:

Woo! We've covered a lot, but now we can do so much. Keep going - learn to use the force!


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.