Shiffman, Chapter 2

Forces

Newton's laws give us the rules. Forces — gravity, wind, friction, drag — give our objects a reason to move.

Prerequisites: Chapter 1 (Vectors). We'll use everything from there.
10
Chapters
3
Simulations
10
Quizzes

Chapter 0: Why Forces?

At the end of Chapter 1, we had a ball accelerating toward the mouse. It looked like something was pulling it. But we never said what that something was. We just picked an acceleration vector and ran with it.

In the real world, acceleration doesn't just appear. It comes from forces: gravity pulling you down, wind pushing you sideways, friction slowing your shoes on the ground, a spring yanking a door shut.

The big shift: In Chapter 1, we controlled acceleration directly. From now on, we'll control forces, and let Newton's second law compute the acceleration for us. Forces are the cause; acceleration is the effect.

By the end of this chapter, you'll be able to throw multiple forces at an object — gravity, wind, friction, drag — and watch them combine into realistic motion. The same two-line motion algorithm from Chapter 1 still applies. The only thing that changes is where the acceleration comes from.

Chapter 1Chapter 2
We invent accelerationForces produce acceleration
One acceleration per frameMany forces accumulate
All objects respond the sameMass makes objects respond differently
What is the fundamental difference between Chapter 1 and Chapter 2?

Chapter 1: Newton's Laws

Isaac Newton gave us three laws of motion. Together, they explain why things move (or don't).

Newton's First Law: 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.

Before Newton, people followed Aristotle's idea: things stop unless something keeps pushing them. Newton flipped it: things keep going unless something stops them. A hockey puck on frictionless ice would slide forever. It's forces (friction, air resistance) that slow things down.

In code, this means: if no forces act on an object, its velocity stays constant. We don't need to "keep pushing" it each frame.

Newton's Third Law: For every action, there is an equal and opposite reaction. Forces always come in pairs.

Push against a wall. The wall pushes back on you with equal force. Push a friend on roller skates — they slide backward, but you might too (depending on mass and friction). The forces are equal; the outcomes depend on each object's properties.

In our simulations, we won't always model both sides of a force pair. When we apply "wind" to a ball, we won't bother modeling the force the ball exerts back on the air. We're inspired by physics, not slaves to it.

According to Newton's first law, what happens to an object with no forces acting on it?

Chapter 2: F = ma

Newton's second law is the star of this chapter. It's usually written as:

F = m × a

But for us programmers, the more useful form is:

a = F / m

Acceleration is directly proportional to force and inversely proportional to mass. Push harder, you accelerate more. Be heavier, you accelerate less. This single equation turns any force vector into an acceleration vector.

Why this matters: In Chapter 1, acceleration was our starting point. Now we go one level deeper: force is the starting point. Force divided by mass gives acceleration. Acceleration changes velocity. Velocity changes location. It's the same chain, just longer.
Force
Applied by environment (gravity, wind...)
↓ a = F / m
Acceleration
Changes velocity each frame
Velocity → Location
Same as Chapter 1

For simplicity, let's start with mass = 1. Then a = F / 1 = F. The acceleration is the force. This is a perfectly fine starting point, and it's what we'll use until we introduce mass in a few chapters.

pseudocode
function applyForce(force):
  acceleration = force   # mass = 1, so a = F
If an object has mass 2 and a force of (6, 4) is applied, what is the acceleration?

Chapter 3: Force Accumulation

Here's a problem. Say we want gravity and wind to act on our ball. If applyForce() just sets acceleration to the force, the second call overwrites the first:

pseudocode
applyForce(wind)     # acceleration = wind
applyForce(gravity)  # acceleration = gravity (wind is lost!)

The fix is force accumulation: we add each force to acceleration instead of replacing it.

a = ΣF / m

The net force is the sum of all forces. Divide by mass and you get acceleration.

pseudocode
function applyForce(force):
  acceleration = acceleration + force  # accumulate!
Critical detail: We must reset acceleration to zero at the start of each frame (or at the end of update()). Acceleration has no memory — it's recalculated from scratch every frame based on whatever forces are present right now. Velocity remembers. Acceleration doesn't.
pseudocode
function update():
  velocity = velocity + acceleration
  location = location + velocity
  acceleration = (0, 0)  # clear for next frame

Now we can throw as many forces as we want — 1, 5, 100 — and they'll all combine naturally. Gravity pulling down? Wind pushing right? Friction slowing you? They all add up into one net acceleration.

Why must we clear acceleration at the end of each frame?

Chapter 4: Gravity & Wind

Let's apply two of the simplest forces: gravity (a constant downward pull) and wind (a horizontal push).

Gravity is easy to model. Near Earth's surface, every object experiences the same gravitational acceleration: about 9.8 m/s2 downward. In pixel-land, we'll use a much smaller number:

gravity = (0, 0.1)

Wind is equally simple — a constant horizontal force:

wind = (0.05, 0)

Each frame, we apply both forces, then update:

pseudocode
each frame:
  mover.applyForce(gravity)
  mover.applyForce(wind)
  mover.update()
  mover.display()
  mover.checkEdges()
Watch what happens: The ball doesn't fall straight down and it doesn't fly straight right. It curves — a parabolic arc, just like a ball thrown at an angle in real life. The gravity pulls it down while the wind pushes it right. That's force accumulation in action.

Edge-checking is also simple: if the ball hits the bottom, reverse its y-velocity (bounce). If it hits a side, reverse its x-velocity. Multiply by a damping factor (like 0.9) for energy loss on each bounce.

If gravity is (0, 0.1) and wind is (0.05, 0), what is the net force on the object?

Chapter 5: Mass

Time to bring mass into the picture. Newton's second law is F = ma, which means a = F/m. A heavier object accelerates less from the same force.

pseudocode
function applyForce(force):
  f = force / mass             # a = F / m
  acceleration = acceleration + f
Important subtlety: We divide a copy of the force by mass, not the original. If we modified the original force vector, every subsequent object receiving that same force would get the wrong value. Always copy first, then divide.

Now imagine two balls — one with mass 1 and another with mass 10 — both experiencing the same gravity force. The light ball accelerates 10 times faster than the heavy one. Add in a wind force and watch how differently they move.

PropertyLight ball (m=1)Heavy ball (m=5)
Gravity force(0, 0.1)(0, 0.1)
Acceleration from gravity(0, 0.1)(0, 0.02)
Wind force(0.05, 0)(0.05, 0)
Acceleration from wind(0.05, 0)(0.01, 0)
Wait, don't all objects fall at the same rate? In real life, yes — because gravitational force itself is proportional to mass (F = mg). The mass cancels out: a = mg/m = g. But in our simplified sim, we're applying the same force vector to all objects, so heavier ones do fall slower. If you want realistic gravity, scale the force by mass: gravity = (0, 0.1 * mass).
An object with mass 4 receives a force of (8, 0). What is its acceleration?

Chapter 6: Friction

So far our forces have been push-forward forces. But some forces resist motion. Friction is the most common one: it acts in the opposite direction of an object's velocity and slows it down.

The formula for kinetic friction is:

friction = −μ × N × v̂

Let's break this apart:

SymbolMeaningIn our sim
μCoefficient of friction (how rough the surface is)A constant, e.g. 0.01
NNormal force (how hard the surface pushes back)We'll simplify to 1
Unit velocity vector (direction of motion)velocity.normalize()
Opposite directionMultiply by -1
pseudocode
function computeFriction(mover):
  friction = mover.velocity.copy()
  friction.normalize()       # direction of motion
  friction.mult(-1)          # reverse it
  friction.mult(mu)          # scale by coefficient
  return friction
The effect: Friction doesn't make objects stop instantly. It just applies a small force opposite to their motion each frame. Over time, this saps kinetic energy and the object decelerates to a halt — exactly what you see when a ball rolls across a carpet.
In which direction does friction act?

Chapter 7: Drag

When an object moves through a fluid (air, water), it experiences drag — a resistive force that increases with speed. The faster you move, the harder the fluid pushes back.

Fdrag = −½ ρ v2 A Cd

That's the full equation. We'll simplify it for our simulation by rolling the density, area, and drag coefficient into one constant c:

Fdrag = −c × |v|2 × v̂

The key difference from friction: drag is proportional to the square of velocity. Going twice as fast means four times the drag. This is why terminal velocity exists — at some speed, drag equals gravity and acceleration stops.

pseudocode
function computeDrag(mover, c):
  speed = mover.velocity.mag()
  dragMag = c * speed * speed  # proportional to v^2
  drag = mover.velocity.copy()
  drag.normalize()
  drag.mult(-1)
  drag.mult(dragMag)
  return drag
Friction vs drag: Friction has a constant magnitude (μN). Drag's magnitude grows with speed squared. At low speeds, drag is barely noticeable. At high speeds, it dominates. This is why skydivers reach terminal velocity and bullets slow down quickly.
If you double the speed of an object, how does the drag force change?

Chapter 8: Forces Playground

Everything comes together here. Below, multiple balls with different masses fall under gravity, experience wind (click and hold to apply wind), and encounter friction along the ground. Watch how mass changes everything.

Forces on Multiple Objects

Click/tap and hold to apply a rightward wind force. Balls have different masses (size = mass). Friction acts along the bottom. Watch heavier balls resist wind more.

Click to apply wind
What to notice: When you apply wind, the small balls fly to the right much faster than the big ones. That's F = ma in action: same force, different mass, different acceleration. Along the ground, friction slows them all, but the light balls bounce higher because they had more velocity when they hit.
Why do smaller balls accelerate more than larger balls when the same wind force is applied?

Chapter 9: Summary

Forces are the bridge between "things that move" and "things that move believably." Here's what we built:

ConceptFormulaKey Insight
Newton's 2nd Lawa = F / mForce divided by mass gives acceleration
Force Accumulationa = ΣF / mSum all forces, then divide by mass
Gravity(0, g)Constant downward force
Friction−μ N v̂Opposes motion, constant magnitude
Drag−c |v|2Opposes motion, grows with speed squared
The pattern: applyForce(f) adds f/mass to acceleration. update() adds acceleration to velocity, velocity to location, then clears acceleration. This is the engine for everything in the rest of the book.

What we covered:

• Newton's three laws
• F = ma and its rearrangement
• Force accumulation
• Gravity and wind
• Mass and its effect
• Friction (constant resistance)
• Drag (velocity-dependent resistance)

What comes next:

Chapter 3: Oscillation. We'll add angles, trigonometry, and periodic motion to our toolkit. Think pendulums, springs, and wave patterns — forces that pull objects back toward equilibrium.

What three things must you do each frame to properly simulate forces?