7.2 The laws of motion

As well as being parallel, physics is homogeneous. We implement the principle of homogeneity by making sure to derive all of our classes from a base class that has the necessary laws built into it. We give the base class a move(dt) method that encapsulates the laws of motion. And we ensure homogeneity by making move(dt) non-virtual so that the child classes can't override it.

What are the laws of physical motion that we need to use? Ordinarily we discuss motion in terms of a scalar mass quantity and four vector quantities: position, velocity, acceleration, and force. (Keep in mind that when we say, for instance, that velocity is a vector, we mean that velocity is a scalar speed times a unit direction vector.) The laws relating these are quite simple, where the d/dt operator is the derivative operator.


If we suppose we are working in two or in three dimensions, then each line is really two or three scalar equations ? for in a vector equation the corresponding components must match.

In our simulations, we want to think of the force as the given, and the position as the thing that we figure out. So we actually want to turn all of these equations around. It's clear how to turn the first equation around, but how do we 'turn around' an equation of the form rate = d/dt quantity? We do it in the following way.


Taking a derivative is the same as evaluating the ratio of differentials.


We can think of the differential dt as a normal number.


The dquantity is the change in quantity from its old to its new value.


We get this by moving the terms of the equation. Now drop the new and old to write a line that looks like computer code.


Think of the left side as the new value and right side as old value.

Now we can 'turn around' our three motion equations and come up with this.

  1. acceleration = force/mass

  2. velocity = velocity + dt x acceleration

  3. position = position + dt x velocity

These are the equations we're going to use for the simulation of physics that we'll use in our Pop Framework. What characterizes this set of equations is that if you specify an object's mass, a force that acts on the object, a timestep dt, and an initial position, velocity and acceleration, equations (1), (2), and (3) will generate fresh values for position, velocity and acceleration.

In discussing simulations, by the way, it's a common practice to blur the line between the infinitesimal dt of a mathematical derivative and a dt that is instead thought of as very small real-number change. The fascinating subject of numerical analysis goes into the details of exactly when and how this can be done in a reasonable way so as to yield stable and accurate simulation equations. Suffice to say that what we're doing here is reasonably Kosher. [More precisely, we're doing 'Euler integration' of the motion path; for greater accuracy one can do 'Runge-Kutte integration' of the motion path. A good algorithm for Runge-Kutte can be found in the classic work Numerical Recipes in C, by W. Press, S. Teukolsky, W. Vetterling and B. Flamery (Cambridge University Press, 1992). Numerical Recipes in C can also be accessed for free online at www.nr.com]

Regarding the critters in the Pop Framework, let's mention how we compute their mass. The critters have a Real _mass field as well as a _density, and a _radius. The critter's internal mutators and accessor ensure that _mass is always the _density times the cube of the _radius. Making mass proportional to size gives behaviors that look more 'physical,' or realistic. The default _density is simply 1.0, but if we want a critter to be more resistant to the action of forces we set its density to a higher value. You can read more about this point in Chapter 8: Critters.

Both physics and computers like to do the same thing over and over. Physics works by continually reapplying the laws of motion to every object in the world. Our simulation will work by applying our three equations over and over.

We can state this a bit differently. It's common these days to speak of physics as a dynamical system. A dynamical system has some state and a transform operator that maps each state to a new state. In the case of motion, the state might be a triple consisting of


and the transform would be specified by giving a mass and a force and three equations above. When we investigate (or play with!) a dynamical system we like to drop 'test particles' into it and watch what happens to them. This means that we specify a starting state_0 and watch how it evolves under successive applications of the transform operator. That is, we look at sequences like this.


That's essentially what we're doing when we run instances of the Pop program and repeatedly apply the cGame::step, which first calls an update loop and then a move loop. The step method as a whole is our transform.

Regarding our three equations for position, velocity, and acceleration, how do we divide these up between the 'update' and the 'move' phases? Changing the acceleration is more of an update thing because we are going to take into account the possibility of changes to an object's motion due to object?object collisions, possible forces among objects (including flight and pursuit), and possible user input. So we put the first equation into an update method and put the second two into a move method.

So we might imagine our physics objects as having methods like this.

    acceleration = force/mass; 
    /* Possibly make additional changes to acceleration and/or 
        velocity due to collisions, 
    object-to-object forces, or user input. */ 

    velocity = velocity + dt * acceleration; 
    position = position + dt * velocity; 

Our cCritter::update will use a dt argument in case the critter needs to do something to itself relating to the timestep; an example might be changing its size, as in a balloon leaking air. We feed a CPopView *pview into the update so that the critter can possibly 'sniff' at the graphical world of the CPopView to find out the pixel colors of some locations, perhaps reversing its velocity direction when approaching certain colors. In the examples given in this book, neither the dt nor the pview arguments are used by our critter update methods. But you will need to use these arguments for some of the exercises.

We'll say more about exactly how we represent our forces in the rest of this chapter.

    Part I: Software Engineering and Computer Games
    Part II: Software Engineering and Computer Games Reference