Placeholder Image

Subtitles section Play video

  • [BELL RINGS]

  • Hello and welcome to chapter two of the Nature of Code, forces.

  • So I want to start with this discussion

  • by talking about Newton's laws of motion.

  • So by no means is anything I'm going

  • to do be a really accurate, robust physics simulation.

  • But at a minimum, I want to examine

  • what the basic laws of motion are, the basic principles

  • behind how things move, and just make sure

  • that the code I'm writing fits with that for the most part.

  • So let's start with those laws of motion.

  • Law number one.

  • This is how it is often referred to most informally--

  • an object at rest stays at rest.

  • However, a more accurate statement of this

  • might be, 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.

  • So that's a bit of a mouthful of stuff,

  • but let's unpack that for a moment.

  • Let's think about this in the context of our P5 canvas

  • and the object being a circle that I'm

  • drawing on that canvas.

  • If this circle is going to obey Newton's first law,

  • if it's not moving, there's no reason for it to start moving,

  • or if it is moving at a particular velocity vector,

  • there's no reason for that velocity vector

  • to ever change unless acted upon by a force.

  • The definition that I offered over here

  • uses the term unbalanced force.

  • So something that's very important about this concept

  • of staying at rest or staying at a constant velocity

  • is that it's not just whether the force is there or not,

  • but whether the net force, the sum

  • of all the forces in the environments,

  • add up to something non-zero.

  • For example, with my marker here, there's

  • a force of gravity pulling it down, presumably

  • towards the center of the earth, but there's also

  • some other forces that I'm applying to it to keep it up,

  • that are pushing it up.

  • And so if I try my best to balance the force--

  • balance the force-- then it won't move at all.

  • This diagram is another example of this.

  • So all of these forces balance themselves out,

  • and this object is at a state of equilibrium,

  • meaning it won't start moving, or if it

  • were, its velocity would remain constant.

  • And the reason I'm harping on this

  • so much is I really want to make sure

  • when I go to write the next bits of code

  • that I'm going to write, that the simulation obeys this law.

  • But in order for it to obey this law in the first place,

  • I have got to understand--

  • I'm using the term force all over the place.

  • It's really important that I think I take a moment now

  • to define what I mean by force.

  • A force is a vector that causes an object with mass

  • to accelerate.

  • That is the technical definition that I

  • am going to use for force.

  • Here's the good news.

  • Vector-- check.

  • We've got that.

  • I just did a whole section of videos about what is a vector,

  • so we can understand force as a vector.

  • Here's more good news for you.

  • Accelerate-- check.

  • I just did a video tutorial about how to apply acceleration

  • in a P5 sketch.

  • So if we can create a vector and somehow

  • have that vector affect the object's acceleration,

  • then we are implementing a force.

  • And if the way that we implement the force in our code

  • obeys this law, then we are golden.

  • One thing here-- mass is not something

  • that I have discussed, or used, or implemented

  • as a property of any of the things I've done so far.

  • So let's put a question mark there and return to that.

  • Which leads me to Newton's second law,

  • F equals M times A, or Force equals Mass times Acceleration.

  • I can also describe this law as a restatement

  • of the definition of force.

  • Force is a vector that causes an object with mass to accelerate.

  • We're turning back to the code for a moment.

  • I have these two lines of code--

  • vel.add(this.acc), pos.add(this.vel).

  • And in this example, everything starts with acceleration.

  • I'm calculating an acceleration based

  • on a vector that points from the object moving

  • to the mouse itself.

  • So if everything starts with acceleration,

  • maybe I need to rethink the way that I'm

  • describing this formula.

  • And a different way that I could consider it is acceleration

  • equals force divided by mass.

  • The idea being that if I introduce some force--

  • like let's say there is a wind force

  • with a magnitude and direction that I want

  • to put into this environment.

  • If I have that force, I could take that force, divide it

  • by this object's mass, and that would become the object's

  • acceleration, which would then affect its velocity, which

  • would then affect its position.

  • And this is the technique, the strategy by which everything

  • I do is going to be built upon.

  • I'm really ready to start implementing this in code.

  • But before I do so, there's a few things I want to address.

  • One is you might hear, when looking

  • at how physics engines are built, the term integration.

  • And this is actually one way of doing integration.

  • This specific way is referred to as Euler integration.

  • Why is it called integration?

  • I'm getting into the weeds here into the math aspect of this,

  • but it is important, and I think this will help you

  • as you move forward and do more of this stuff

  • when you see the lingo popping up here and there.

  • In calculus, there's the concept of a derivative.

  • And you might typically see this as written as like dx

  • over dt, the change in x with the change in time.

  • This is actually what velocity is doing.

  • Velocity is dx dt.

  • If x is position, velocity is the change

  • in position over time.

  • Acceleration is the change in velocity over time.

  • So velocity can be thought of as the derivative of position,

  • and acceleration can be thought of as the derivative

  • of velocity.

  • But I'm not going in that direction.

  • I'm not starting with position, and then

  • figuring out what's the velocity,

  • and then figuring out what's the acceleration.

  • I'm going in the other way.

  • I'm starting with what's the acceleration,

  • and then changing the velocity, and then taking the velocity

  • and changing the position.

  • So the other direction of doing the derivative

  • is integration, the integral.

  • So that's why this process is tied to calculus

  • and the concept of integration.

  • The big difference here is that calculus,

  • being the study, in a way, of infinitesimally small time

  • steps, these time steps are quite large.

  • This algorithm is just being applied 30 times per second.

  • But as I move my arm back and forth,

  • are you seeing this animation at 30 frames per second?

  • Maybe because you're watching a video, which

  • is then recording me and playing it back at 30 frames a second.

  • But the actual physical time space that I'm in

  • is very continuous.

  • The time step is infinitesimally small.

  • And if I were doing an accurate calculation of a physics

  • simulation, I would need to take that under consideration.

  • Instead, I'm using a technique called Euler integration, which

  • allows me to have fixed time steps, which are rather large,

  • and it's wildly inaccurate.

  • And I'll maybe back circle back to this

  • as I look in future videos about other integration techniques.

  • There's Berlet physics, and there's

  • Runge Kutta integration.

  • I probably didn't say that correctly.

  • And so maybe I could circle back when

  • we look at other physics libraries that

  • might have slightly more robust methodologies

  • underneath the hood.

  • But the reason why I like this methodology is, number one,

  • it works just fine.

  • I just want my particles to spiral around the screen

  • in pretty ways.

  • And two, it's really fast and really easy to implement.

  • So it has its advantages in terms

  • of the kinds of examples and demonstrations

  • that I want to show you.

  • Also, I know there's so much more to this.

  • Before you start typing your comments in the chat about

  • the theory of relativity, and space-time continuum,

  • and Planck time, and also "Plonk" time--

  • I don't even know how to say it--

  • my goal here is not to go in-depth

  • into the physics of this, and I'm

  • glad to include in this video's description

  • other resources that do, but to take

  • these ideas, these core classic concepts,

  • and then work out a way to implement them in code.

  • I should also mention there is Newton's third law, which

  • is often stated as, for every action,

  • there is an equal and opposite reaction.

  • That's a little bit misleading, and I've written

  • some thoughts about that here.

  • Another way of stating that law is,

  • forces always occur in pairs.

  • The two forces are of equal strength

  • but in opposite directions.

  • So to be honest, this law is not so meaningful to me right now.

  • Trust me, it's kind of important.

  • But in terms of the simulation that I want to start with,

  • I am not going to bother to simulate

  • every possible reaction and opposite

  • interaction of every force within the system.

  • But this will come up again, and I will look at this law

  • when, in a future video as part of this section,

  • I look at gravitational attraction

  • and how two bodies both attract each other,

  • and those forces are of equal strength

  • but in the opposite direction.

  • To get started implementing Newton's second law in code,

  • I want to build off of the example

  • that I finished with in the previous section on vectors.

  • So here, I have this mover object.

  • It starts at a position 200, 200,

  • and two functions are called, update() and show().

  • So if I run it, the acceleration is

  • being calculated as a vector pointing towards the mouse.

  • You could think of it as a force,

  • a gravitational attraction force pulling into the mouse.

  • It's not really that.

  • Of course, it's not really that.

  • It's just some pixels on a screen.

  • But I'm not even using the formula

  • for gravitational attraction.

  • So I'm going to circle back to that

  • and make some changes to this kind of idea later.

  • But right now, what I want to do is change the way the internals

  • of the mover object works because right now,

  • the acceleration is being calculated right here

  • in update(), and I don't want to do that.

  • Instead, I want to write a function that's

  • basically Newton's second law.

  • So I want to write a function--

  • I'm going to change its name in a moment--

  • that implements this particular law.

  • The law, again, is force equals mass times acceleration.

  • But I've rewritten it to acceleration equals

  • force divided by mass.

  • Guess what?

  • Let's just pretend for a moment that the world we live in,

  • the world that I'm programming in, there's no concept of mass.

  • In fact, everything in this entire universe

  • has a mass of 1.

  • So in that case, going back to this law of force

  • equals mass, which is 1, 1 times acceleration

  • is really just same as force equals acceleration

  • or acceleration equals force.

  • So these are the same concepts.

  • Meaning, I could just say this.acc = force.

  • There we go.

  • This is the simplified version of Newton's second law in code.

  • I'm going to change the name to applyForce(),

  • the idea being that what I want to do is take a force that

  • exists in the environment, not something calculated from

  • within the object.

  • That's going to be important later in some

  • of the other videos I'll do.

  • But right now, imagine a wind force

  • external to the object, or a gravitational pull

  • maybe pulling it down along the y-axis external to the object.

  • For example, let gravity equal createVector(0, 1).

  • I'm making a vector that points down,

  • and then I want to say mover.applyForce(gravity).

  • Let's run this code.

  • Remember, this is the applyForce() function.

  • It sets the acceleration equal to the force,

  • and then that acceleration is added to velocity

  • and that velocity is added to position.

  • Ooh.

  • [BUZZER]

  • I forgot that I'm programming in a class, and in a class,

  • I don't use the keyword function to define an instance method

  • of that class, I just say applyForce().

  • Ugh.

  • There we go.

  • Look at that.

  • There's that force of gravity pulling it down.

  • This sketch is a little bit sad because the ball falls

  • and it never comes back.

  • So just for the purpose of demonstration,

  • I'm going to add an artificial constraint

  • to this particular sketch, where what

  • I'm going to do is I'm going to look at this bottom edge,

  • and if this circle reaches the bottom edge,

  • I'm going to take its velocity and reverse it.

  • Really, if I were doing a physics simulation,

  • I would think about this as an object with a different mass,

  • and what kind of forces are happening

  • when it hits that object.

  • But I'm going to just bypass all of that with a quick shortcut.

  • I can come back and look at that a little later, maybe.

  • But I'm going to bypass that with a quick shortcut

  • of just inverting the velocity.

  • And I'm going to do that by adding a function called edges

  • to keep track of when the object hits an edge.

  • So this is really your classic bouncing ball code,

  • and I have another video that goes through this algorithm

  • more specifically.

  • But what I'm looking for is anytime that y position

  • is at the bottom of the canvas or below--

  • because testing if it's equal to height

  • is not going to do me any good.

  • If it's not precisely equal, it could easily move past--

  • then I'm going to shove it back up to height

  • because if it goes too far and it turns around,

  • it could get stuck.

  • So I'm going to make sure even if it goes past height,

  • I set its position to height and then reverse its velocity.

  • And let's take a look.

  • Ooh, that didn't work.

  • Why didn't it work?

  • It's one thing to write a function.

  • It's another thing to call it.

  • So let's say mover.edges().

  • And there we are.

  • So now this gravitational force is pulling the object down

  • and it's bouncing up or down.

  • Why is it going off to the right a little bit?

  • It's going off to the right because I gave it

  • an initial random velocity.

  • Interestingly, you notice how it's

  • slowing down and eventually kind of losing its bounce

  • and stopping?

  • In a weird sort of way, that's what I wanted to do.

  • That feels realistic.

  • But I can't see in the code why it's doing that because really,

  • I'm reversing its velocity.

  • There's nothing causing it.

  • It should go all the way back up to the top,

  • and then all the way back down there, then all the way

  • back up to the top.

  • And this, I think, is because of this Euler integration.

  • I'm not looking at continuous time.

  • And there's a lot of inaccuracies here.

  • Not to mention the fact that I'm violating

  • all of the principles of time and space

  • by just resetting its position back to the height

  • if it got below the height, so it's

  • losing some time where it might regain its velocity moving back

  • up.

  • So there's all sorts of goofy stuff going on here.

  • And these are the kinds of things

  • that as a programmer, working with this

  • in a creative context, ultimately,

  • I'm going to need to do massaging and tweaking

  • things to get it to feel right, whatever

  • the types of application it is that I'm wanting to create.

  • But right now, I just want to test if Newton's second law is

  • at play.

  • And I'm going to test that by doing this.

  • Only if the mouse is pressed, apply this force of gravity,

  • meaning the net force is currently 0

  • so the object is at rest.

  • Now I am going to apply the force.

  • I'm going to let go.

  • Oh.

  • [FAKE SOBS]

  • [BELL DINGS]

  • I'm applying gravity, but when I let go,

  • I think the gravity should stop being applied because I'm

  • no longer pressing the mouse.

  • But the gravity still seems to be there.

  • Why is that?

  • Well, there's a flaw in the way that I programmed this.

  • The flaw is that I'm setting the acceleration equal to force.

  • If the force goes away, I don't set the acceleration back to 0,

  • but I should.

  • So one of the strange things about this Euler integration

  • and algorithm is that while velocity and position are

  • accumulating over time, acceleration

  • is just a function, a calculation based on,

  • at any given moment in time, what

  • are the forces in the environment?

  • So at any given time, we should start

  • with an acceleration of 0.

  • And there only is an acceleration

  • if there is a non-0 force.

  • So there's a variety of ways that I could handle this.

  • I'm going to just, I think, for simplicity, say this.acc.set(0,

  • 0).

  • So this is me just clearing the force out

  • at the end of every animation cycle.

  • So now, let's see if Newton's second law--

  • sorry, first law-- is really at play, and the second one.

  • Oops.

  • Cannot read properties set of undefined because I

  • haven't given acceleration of value until I've applied

  • the force, so this is just a flaw in how I've written

  • the constructor.

  • I also need to say, initialize a starting acceleration of 0.

  • Now here we go.

  • The object is staying at rest.

  • There's no force.

  • I click the mouse.

  • Whoop.

  • I let go of the mouse and it just flew off.

  • Let's make the gravity less strong.

  • I'm going to change this to 0.1.

  • I'm holding down the mouse.

  • There's gravity.

  • I let go.

  • The gravity is gone.

  • The object keeps its constant velocity

  • because there's no force acting on it.

  • Let's try also now adding a second force

  • into the environment.

  • So there's one force pointing straight down called gravity.

  • Let's add another force called wind and point it to the right.

  • Let's get rid of the if (mouseIsPressed).

  • I'll come back to that in a little bit.

  • So now I've got gravity pointing down

  • and wind pointing to the right.

  • Of course, I could have just made one force

  • with this as the x component and this as the y component.

  • But I'm demonstrating an idea that as you start

  • to build these kinds of simulations,

  • there might be a variety of forces that are at play or not

  • at play, based on any number of factors,

  • and you can now separate those out into different vectors

  • and individually apply them to your object.

  • Let's run this sketch and see what happens.

  • Wait a second.

  • This I anticipated-- this error.

  • Why is gravity not being applied?

  • I only see wind.

  • Let's change the order here.

  • Let's put wind--

  • I don't know.

  • Let's move the code around a little bit.

  • Let's declare wind and gravity there, but now

  • apply them like this.

  • I don't know.

  • Is that going to do anything?

  • Wait.

  • Now, only gravity is being applied, but not the wind.

  • Go back into the mover.

  • What's wrong?

  • this.acc = force.

  • So stepping through the code, mover.applyForce(wind).

  • this.acc = wind.

  • move.applyForce(gravity).

  • this.acc = gravity.

  • I just overwrote the wind.

  • The wind is ignored because I'd take gravity and put it

  • into acceleration.

  • As I was diagramming this and describing it,

  • I think a couple of times, I used this term net force,

  • or the sum of all forces, or this idea

  • of force accumulation.

  • Meaning the object's acceleration

  • is a result of the sum of all of the forces in its environment

  • at any given time.

  • Wind and gravity both act on the object,

  • and both get added into the acceleration.

  • So this applyForce() function shouldn't actually set

  • acceleration equal to force, but rather it should call add.

  • this.acc.add(force).

  • I can call applyForce() as many times as I want and add up all

  • the forces into the acceleration.

  • There we go.

  • The visual result of that isn't super interesting.

  • Let's make it a little more interesting by saying--

  • and I'll make the gravity a little stronger.

  • So now the wind will only be applied if I click the mouse,

  • but gravity will always be applied.

  • Let's see if this works.

  • There's the ball bouncing.

  • And now I'm going to click the mouse and the wind-- oh.

  • Let's add some more edges.

  • So now I've added a check for the right and left edges,

  • and make sure the x slides back onto the edge,

  • and the velocity is reversed.

  • We have probably more elegant, and efficient, and shorter way

  • to write this, but I'm just putting it in there

  • to get it to work.

  • Let's see how the forces are going.

  • Gravity.

  • And now I'm going to click the mouse, and wind is happening.

  • You can see that.

  • The wind is pushing it in that direction.

  • But let's let go of the mouse and now the wind

  • is no longer there and it's bouncing back and forth.

  • The x velocity is constant now because there's no x component

  • to the net force.

  • But I could add the wind back in and we can see now it's

  • pushing it to the side.

  • I could also just increase the relative strength

  • of these forces, just to see what that looks like.

  • And we can see that here.

  • And we see I already have a pretty interesting

  • and dynamic simulation going.

  • This is a small detail and not super important,

  • in terms of what I'm doing, but it

  • would be nice to actually have the ball reverse

  • its course when the edge of the circle

  • hits the edge of the canvas, rather

  • than the center of the circle.

  • So in that sense, I could add another variable for r

  • to keep track of the object's radius.

  • So I'm going to say this.r = 16, and then draw the ellipsis,

  • this.r * 2, and then use this.r to determine where the edge is.

  • Let me have it move a little slower so this is hopefully

  • a little more visible.

  • Ooh.

  • Whoa.

  • I forgot something.

  • I've got to set it back to this.r.

  • There we go.

  • So that's a little bit more realistic in terms

  • of where it's actually bouncing in terms of hitting the edge.

  • So this is a good stopping point for this example,

  • I think there's of twists you could do on this.

  • First of all, I've just hardcoded numbers here

  • for wind and gravity.

  • There might be other ways you think about calculating those.

  • For example, you could actually pull from a weather API

  • and get the actual wind and have that affect this object.

  • Or you could use Perlin noise.

  • Maybe these vectors are changing over time

  • for some other reason, or there's more than two forces.

  • So many ways you could go in this direction,

  • but this is a bit of a foundation,

  • upon which you could build a simple interactive simulation.

  • There's a couple of different things

  • that I want to do with this example, which

  • I'll do in separate videos.

  • Number one is there's no concept of mass here.

  • So what would it mean if I added to the mover object

  • a mass property, and how would I use that mass value

  • and actually bring that back into the true Newton's

  • second law, force equals mass times acceleration?

  • So I want to bring back mass.

  • Bring back mass.

  • Then I also want to investigate other forces

  • that I can look up a real-world formula for

  • and see if I can implement those.

  • And the first one I'll do is friction.

  • For example, there's this thing happening

  • where the ball comes to a resting point,

  • but then it just rolls back and forth.

  • Could I simulate the friction of it against the edge

  • and have it slow down and reach a stopping point?

  • So the next video, I'll start with math, and then I'll

  • look at friction, and keep going from there,

  • finishing up with looking at the real formula

  • for gravitational attraction and how

  • I might implement that in code.

  • So maybe I'll see you, maybe I won't, and go on with your day.

  • May the force be with you.

  • I said it.

  • I said it.

  • I said it.

  • Goodbye.

  • [MUSIC PLAYING]

[BELL RINGS]

Subtitles and vocabulary

Click the word to look it up Click the word to find further inforamtion about it