mirror of
https://github.com/nature-of-code/noc-book-2
synced 2024-11-17 07:49:05 +01:00
Notion - Update docs
This commit is contained in:
parent
ba5c08a09d
commit
b94abff7d4
1 changed files with 150 additions and 0 deletions
150
src/chapter-content/Chapter 2. Forces .html
Normal file
150
src/chapter-content/Chapter 2. Forces .html
Normal file
|
@ -0,0 +1,150 @@
|
|||
<blockquote data-type="epigraph">
|
||||
“Don’t underestimate the Force.” </blockquote> <a data-type="indexterm">
|
||||
forces </a> <p>
|
||||
In the final example of Chapter 1, I demonstrated how to calculate a dynamic acceleration based on a vector pointing from a circle on the canvas to the mouse position. The resulting motion resembles a magnetic attraction between shape and mouse, as if some <i>force </i> was pulling the circle in towards the mouse. In this chapter I will detail the concept of a force and its relationship to acceleration. The goal, by the end of this chapter, is to build a simple physics engine and understand how objects move around a canvas by responding to a variety of environmental forces. </p> <h2>
|
||||
2.1 Forces and Newton’s Laws of Motion </h2> <a data-type="indexterm">
|
||||
forces / Newton's laws of motion </a> <a data-type="indexterm">
|
||||
Newton / Isaac </a> <p>
|
||||
Before I examine the practical realities of simulating forces and building a basic physics engine 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,” the term “force” can be used to mean a variety of things. It can indicate a powerful intensity, as in “They pushed the boulder with great force” or “They spoke forcefully.” The definition of <i><b>force </b> </i> that I care about is more formal and comes from Sir Isaac Newton’s laws of motion: </p> <a data-type="indexterm">
|
||||
forces / defined </a> <p>
|
||||
<span class="highlight">
|
||||
A force is a vector that causes an object with mass to accelerate. </span> </p> <p>
|
||||
The good news is that you hopefully recognize the first part of the definition: <i>a force is a vector </i> . Thank goodness you just spent a whole chapter learning what a vector is and how to program with vectors! </p> <p>
|
||||
Let’s define Newton’s three laws of motion in relation to the concept of a force. </p> <h3>
|
||||
Newton’s First Law </h3> <a data-type="indexterm">
|
||||
Newton's first law </a> <p>
|
||||
Newton’s first law is commonly stated as: </p> <p>
|
||||
<span class="highlight">
|
||||
An object at rest stays at rest and an object in motion stays in motion. </span> </p> <p>
|
||||
However, this is missing an important element related to forces. I could expand the definition by stating: </p> <p>
|
||||
<span class="highlight">
|
||||
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. </span> </p> <a data-type="indexterm">
|
||||
Aristotle </a> <p>
|
||||
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? </p> <a data-type="indexterm">
|
||||
equilibrium </a> <a data-type="indexterm">
|
||||
forces / equilibrium </a> <a data-type="indexterm">
|
||||
forces / terminal velocity </a> <a data-type="indexterm">
|
||||
terminal velocity </a> <p>
|
||||
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 <i><b>equilibrium </b> </i> . The falling ball will reach a terminal velocity (that stays constant) once the force of air resistance equals the force of gravity. </p> <figure>
|
||||
<img
|
||||
alt="Figure 2.1: The pendulum doesn't move because all the forces cancel each other out (add up to a net force of zero). "
|
||||
src="chapter02/ch02_01.png" />
|
||||
<figcaption>
|
||||
Figure 2.1: The pendulum doesn't move because all the forces cancel each other out (add up to a net force of zero).
|
||||
</figcaption> </figure> <p>
|
||||
Considering a p5.js canvas, I could restate Newton’s first law as follows: </p> <a data-type="indexterm">
|
||||
Newton's first law / PVector class and </a> <a data-type="indexterm">
|
||||
PVector class (Processing) / Newton's first law and </a> <p>
|
||||
<span class="highlight">
|
||||
An object’s velocity vector will remain constant if it is in a state of equilibrium. </span> </p> <p>
|
||||
Skipping Newton’s second law (arguably the most important law for the purposes of this book) for a moment, let’s move on to the third law. </p> <a data-type="indexterm">
|
||||
Newton's third law </a> <h3>
|
||||
Newton’s Third Law </h3> <p>
|
||||
This law is often stated as: </p> <p>
|
||||
<span class="highlight">
|
||||
For every action there is an equal and opposite reaction. </span> </p> <p>
|
||||
This law frequently causes 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 <i>actively </i> decide to push you back. But this is not the action and reaction referred to in Newton’s third law. </p> <p>
|
||||
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.” </p> <p>
|
||||
A better way of stating the law might be: </p> <p>
|
||||
<span class="highlight">
|
||||
Forces always occur in pairs. The two forces are of equal strength, but in opposite directions. </span> </p> <p>
|
||||
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). </p> <p>
|
||||
Consider 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. </p> <p>
|
||||
And if you are wearing roller skates when you push on that truck? </p> <figure>
|
||||
<img
|
||||
alt="Figure 2.2"
|
||||
src="chapter02/ch02_02.png" />
|
||||
<figcaption>
|
||||
Figure 2.2
|
||||
</figcaption> </figure> <p>
|
||||
You’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 I’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. </p> <h3>
|
||||
Newton’s Third Law (as seen through the eyes of p5.js) </h3> <a data-type="indexterm">
|
||||
Newton's third law / PVector class and </a> <a data-type="indexterm">
|
||||
PVector class (Processing) / Newton's third law and </a> <p>
|
||||
<span class="highlight">
|
||||
If you calculate a p5.Vector </span> </p> <p>
|
||||
You’ll soon see that in the world of coding simulation, it’s often not necessary to stay true to the above. Sometimes, such as in the case of <a href=#chapter02_example6>gravitational attraction between bodies </a> , I’ll want to model equal and opposite forces in my example code. Other times, such as a scenario where I‘ll say, “Hey, there’s some wind in the environment,” I’m not going to bother to model the force that a body exerts back on the air. In fact, I’m not going to bother modeling the air at all! Remember, this examples in this book are taking inspiration from the physics of the natural world for the purposes of creativity and interactivity and do not require perfect precision. </p> <h2>
|
||||
2.2 Forces and p5.js—Newton’s Second Law as a Function </h2> <a data-type="indexterm">
|
||||
acceleration / Newton's second law </a> <a data-type="indexterm">
|
||||
natural phenomena / Newton's second law / modeling </a> <a data-type="indexterm">
|
||||
Newton's second law </a> <p>
|
||||
Now it‘s time for most important law for you, the p5.js coder. </p> <h3>
|
||||
Newton’s Second Law </h3> <p>
|
||||
This law is stated as: </p> <p>
|
||||
<span class="highlight">
|
||||
Force equals mass times acceleration. </span> </p> <p>
|
||||
Or: </p> <div data-type="equation">
|
||||
\vec{F} = M \times \vec{A} </div> <p>
|
||||
Why is this the most important law for this book? Well, let’s write it a different way. </p> <div data-type="equation">
|
||||
\vec{A} = \vec{F} / M </div> <p>
|
||||
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. </p> <a data-type="indexterm">
|
||||
density </a> <a data-type="indexterm">
|
||||
mass / weight vs. </a> <a data-type="indexterm">
|
||||
weight / mass vs. </a> <div data-type="note">
|
||||
<h6> Weight vs. Mass </h6><ul>
|
||||
<li>
|
||||
The <i><b>mass </b> </i> of an object is a measure of the amount of matter in the object (measured in kilograms). </li> </ul> <ul>
|
||||
<li>
|
||||
<i><b>Weight </b> </i> , 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 (<code>w = m * g </code> ). Weight is measured in newtons. </li> </ul> <ul>
|
||||
<li>
|
||||
<i><b>Density </b> </i> is defined as the amount of mass per unit of volume (grams per cubic centimeter, for example). </li> </ul> <p>
|
||||
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. </p> </div> <p>
|
||||
Now, in the world of p5.js, what is mass anyway? Aren’t we dealing with pixels? To start in a simpler place, let’s say that in a pretend pixel world, all objects have a mass equal to 1. <code>F / 1 = F </code> . And so: </p> <div data-type="equation">
|
||||
\vec{A} = \vec{F} </div> <p>
|
||||
The acceleration of an object is equal to force. This is great news. After all, in Chapter 1 I described acceleration as the key to controlling the movement of objects on a canvas. <code>position </code> changes according to <code>velocity </code> , and <code>velocity </code> according to <code>acceleration </code> . Acceleration was where it all began. Now you can see that <i>force </i> is truly where it all begins. </p> <p>
|
||||
Let’s take the <code>Mover </code> class, with position, velocity, and acceleration. </p> <pre data-code-language="javascript" data-type="programlisting" class="codesplit">
|
||||
class Mover {
|
||||
constructor(){
|
||||
this.position = createVector();
|
||||
this.velocity = createVector();
|
||||
this.acceleration = createVector();
|
||||
}
|
||||
} </pre> <p>
|
||||
Now the goal is to be able to add forces to this object, with code something like: </p> <pre data-code-language="javascript" data-type="programlisting" class="codesplit">
|
||||
mover.applyForce(wind); </pre> <p>
|
||||
or: </p> <pre data-code-language="javascript" data-type="programlisting" class="codesplit">
|
||||
mover.applyForce(gravity); </pre> <p>
|
||||
where wind and gravity are <code>p5.Vector </code> objects. According to Newton’s second law, I could implement this function as follows. </p> <pre data-code-language="javascript" data-type="programlisting" class="codesplit">
|
||||
applyForce(force) {
|
||||
//{!1} Newton's second law at its simplest.
|
||||
this.acceleration = force;
|
||||
} </pre> <h2>
|
||||
2.3 Force Accumulation </h2> <a data-type="indexterm">
|
||||
forces / accumulation of </a> <p>
|
||||
This looks pretty good. After all, <i>acceleration = force </i> is a literal translation of Newton’s second law (in a world without mass). Nevertheless, there’s a pretty big problem here which I’ll quickly encounter when I return to my original goal: creating object that responds to wind and gravity forces. </p> <pre data-code-language="javascript" data-type="programlisting" class="codesplit">
|
||||
mover.applyForce(wind);
|
||||
mover.applyForce(gravity);
|
||||
mover.update(); </pre> <p>
|
||||
OK, I’ll <i>be </i> the computer for a moment. First, I call <code>applyForce() </code> with wind. And so the <code>Mover </code> object’s acceleration is now assigned the vector <code>wind </code> . Second, I call <code>applyForce() </code> with gravity. Now the <code>Mover </code> object’s acceleration is set to the gravity vector. Finally, I call <code>update() </code> . What happens in <code>update() </code> ? Acceleration is added to velocity. </p> <pre data-code-language="javascript" data-type="programlisting" class="codesplit">
|
||||
this.velocity.add(this.acceleration); </pre> <p>
|
||||
If you run this code, you will not see error in the console, but zoinks! There’s a major problem. What is the value of acceleration when it is added to velocity? It is equal to the gravity vector. Wind has been left out! Anytime <code>applyForce() </code> is called, acceleration is overwritten. How can I handle more than one force? </p> <a data-type="indexterm">
|
||||
force accumulation </a> <p>
|
||||
The answer lies in the full definition of Newton’s second law itself which I now to confess to having simplified. Here’s a more accurate way to put it: </p> <p>
|
||||
<span class="highlight">
|
||||
Net Force equals mass times acceleration. </span> </p> <p>
|
||||
Or, acceleration is equal to the <i>sum of all forces </i> divided by mass. This makes perfect sense. After all, as you saw in Newton’s first law, if all the forces add up to zero, an object experiences an equilibrium state (i.e. no acceleration). This can be implemented through a process known as <i><b>force accumulation </b> </i> — adding all of the forces together. At any given moment, there might be 1, 2, 6, 12, or 303 forces. As long as the object knows how to accumulate them, it doesn’t matter how many forces act on it. </p> <pre data-code-language="javascript" data-type="programlisting" class="codesplit">
|
||||
applyForce(force) {
|
||||
//{!1} Newton's second law, but with force accumulation. I now add each force to acceleration, one at a time.
|
||||
this.acceleration.add(force);
|
||||
} </pre> <p>
|
||||
Now, I’m not finished just yet. Force accumulation has one more piece. Since I’m adding all the forces together at any given moment, I have to make sure that I clear acceleration (i.e. set it to zero) before each time <code>update() </code> is called. Consider a wind force for a moment. Sometimes wind is very strong, sometimes it’s weak, and sometimes there’s no wind at all. For example, you might write code that creates a gust of wind, say, when the user holds down the mouse. </p> <pre data-code-language="javascript" data-type="programlisting" class="codesplit">
|
||||
if (mouseIsPressed) {
|
||||
let wind = createVector(0.5, 0);
|
||||
mover.applyForce(wind);
|
||||
} </pre> <a data-type="indexterm">
|
||||
acceleration / force accumulation and </a> <p>
|
||||
When the user releases the mouse, the wind should stop, and according to Newton’s first law, the object continues moving at a constant velocity. However, if I forgot 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! Acceleration, in a time-based physics simulation, has no memory; it is calculated based on the environmental forces present at any given moment (frame) in time. This is different than, say, position, which must remember its previous location in order to move properly to the next. </p> <p>
|
||||
One way to implement clearing the acceleration for each frame is to multiply the vector by 0 at the end of <code>update() </code> . </p> <pre data-code-language="javascript" data-type="programlisting" class="codesplit">
|
||||
update() {
|
||||
this.velocity.add(this.acceleration);
|
||||
this.position.add(this.velocity);
|
||||
// Clearing acceleration after it's been applied
|
||||
this.acceleration.mult(0);
|
||||
} </pre> <div data-type="exercise">
|
||||
<h6> Exercise 2.1 </h6><p>
|
||||
Using forces, simulate a helium-filled balloon floating upward and bouncing off the top of a window. Can you add a wind force that changes over time, perhaps according to Perlin noise? </p> </div> <h2>
|
||||
2.4 Dealing with Mass </h2> <a data-type="indexterm">
|
||||
mass / modeling </a> <a data-type="indexterm">
|
||||
natural phenomena / mass / modeling </a> <p>
|
||||
OK. I’ve got one small (but fundamental) addition to make before integrating forces into the <code>Mover </code> class. After all, Newton’s second law is really \vec{F} = M \times \vec{A}, not \vec{F} = \vec{A}. Incorporating mass is as easy as adding an instance variable to the class, but I need to spend a little more time here because of another impending complication. </p> <p>
|
||||
First I’ll add mass. </p>
|
Loading…
Reference in a new issue