Previous Section  < Day Day Up >  Next Section

Work and Kinetic Energy

Before we can delve into the energy-based model, we must define a couple new quantities. Two of them are work and kinetic energy. We all use the term work in our everyday language, so I'm sure you have a sense of what it means. Be careful, though: In physics, work has a very precise definition. Work is equal to force times displacement.

Work

W = FDx

where

Dx = displacement

and

F = force in the direction of displacement.


If work is defined as force times displacement, this means that the object must move for work to be done. This might contradict your current perception of work. For example, if you push against a brick wall until you work up a sweat, you might think you've worked really hard. However, a physicist will tell you that you've done no work at all, because the brick wall hasn't moved.

Another important aspect of this definition is that the force must be in the same direction as the displacement. It can be a negative force, but it must be in the same direction as the displacement. You might have noticed that force and displacement are both vector quantities, so the only way you can multiply them together is if their directions are the same.

For example, suppose your game character must pull a wagon filled with treasure, as shown in Figure 12.1. He'll probably pull the handle at an angle, but the wagon will roll horizontally across the ground. What that means in terms of work is that you need to use the horizontal component of the force, not the total force, to calculate the work.

Figure 12.1. Pulling a wagon at an angle.

graphics/12fig01.gif

Before looking at examples, it's important to discuss a few quick facts about vectors. Chapter 4, "Vector Operations," detailed several operations that may need to be calculated in order to process some vector operations. This chapter will require several of those methods including the dot product, normalization, and scalar multiplication. Standing with the emphasis on readability over robustness, the code in this chapter is centered around a vector definition that looks like this:


2D vector



    typedef struct

    { 

     float x; 

     float y;

    } vector2D;



3D vector



    typedef struct

     {

      float x;

      float y;

      float z;

     } vector3D;

These vectors are used from here on out for the sake of simplicity and so that the mathematics can be emphasized. If you prefer an earlier or different implementation, feel free to substitute it in the examples. The vector library that is provided with the sample source code contains all the details needed for operations that are not explicitly defined within this chapter.

One last detail concerning work is the issue of units. If you haven't discovered this already, metric units are always the easiest to work with in physics simulation. If you choose to keep everything metric for consistency, the force is measured in Newtons, and the displacement is measured in meters, which means that the work is measured in Newton-meters (N*m). This unit has been renamed the joule (J), so 1J = 1N*m. If you insist on using British units, work is measured in foot-pounds (ft*lbs).

Joule (J)

1J = 1N*m


Example 12.1: Calculating Work

Suppose the player in your game must push a secret stone wall at least 2 meters to gain access to a bonus level. If the player's character can push with a horizontal force of 1500N and a kinetic frictional force of 50N is working against him, how much work total will it take to move the wall out of the way?

Solution

Let's start with the definition of work, W = FDx. The net force in this case is 1500N – 50N = 1450N, and the displacement is 2m.

W = FDx

= 1450N(2m)

= 2900N*m

= 2900J

Programming the calculation for work is fairly straightforward. Here is a function that returns the amount of work done given a force, a friction force, and a displacement:


float calculateWork(float force, float friction, float displacement)

     {

         //calculate the difference of the forces.

         float netForce = force-friction;



   //multiply by displacement

         float temp = displacement*netForce;

         return temp;

      }

This function will return a float value of the work in Joules. Always make sure to double check your units when setting up calculations. Refer to Chapter 6, "Transformations," for more information on unit calculations.

NOTE

Both units N*m and J are equally acceptable, so use whichever one you like better.


Example 12.2: Calculating Work with Angled Force

Let's go back to the wagon example. If your character pulls the wagon with a force of 1600N@60° and the kinetic friction is 25N, how much work will it take to pull the wagon 5m?

Solution
  1. Notice that the force of the character pulling the wagon is at an angle, and the displacement is horizontal. This means that you can use only the horizontal component of that force:

    FCx = FC(cosq)

    = 1600N(cos60°)

    = 1600N(0.5)

    = 800N

  2. Now you can find the net force:

    Fnet = FCxFf

    = 800N – 25N

    = 775N

  3. Finally, all you need is the definition of work:

    W = Fnet Dx

    = 775N(5m)

    = 3875N*m

    = 3875J

Angled forces may frequently be calculated depending on how a game models physics.

Here is a function that will return the amount of work done considering an angled force:


float calculateAngledWork(vector2D vect, float friction,float displacement)

      {

          float temp;

          //don't forget to convert to rads....

          temp = cos(DegreesToRads(vect.y));



          //calculate the horizontal force;

          float horizForce = vect.x*temp;



          float work = calculateWork(horizForce,friction, displacement);

          return work;

      }

Here we see the first usage of our 2Dvector type. Using the quick conversion macros from Chapter 6, we get the cosine of the angled force, and then continue on to calculate the horizontal force. The final amount of work is determined when we reuse the work function that was listed in Example 12.1.

Example 12.3: Calculating Work with Force and Displacement at Different Angles

Suppose you're coding a top-down game where the object being moved is free to move in both the x and y directions. A net force of 2000N@60° is applied to the object, but due to constraints, the object moves 3m@30°. How much work is done to move the object?

Solution
  1. The challenge here is that the two vectors are at different angles. First, break both vector quantities into components so that you can work with them more easily:

    F = 2000N@60° = [2000(cos60°) 2000(sin60°)] = [1000 1732]

    Dr = 3m@30° = [3(cos30°) 3(sin30°)] = [2.6 1.5]

  2. Now you need to find the component of the force that is in the same direction as the displacement. You can use the dot product for this. Remember that the dot product of the force and the normalized displacement vector produce the length of the projection. That projection times the normalized displacement reveals the component of the force in the direction of the motion:

    graphics/12inl01.gif = [2.6/3 1.5/3] = [0.866 0.5]

    |Fr| = F • graphics/12inl02.gif = [1000 1732]•[0.866 0.5] = 1732

    Fr = |Fr|* graphics/12inl03.gif = 1732[0.866 0.5] = [1500 866] = 1732N@30°

  3. Now that both the force and displacement are in the same direction (30), you can multiply their magnitudes together. All you need is the definition of work:

    W = Fr Dr

    = 1732N(3m)

    = 5196N*m

    = 5196J

Programming code to illustrate this example begins to work with some of the more complex calculations that were defined in Chapter 4. This code follows along with the explanation provided in the previous example:


float calculateAngledWorkFromVector(vector2D initial, vector2D change)

     {

          vector2D force, displacement,displacementNormal, temp;

          float projectionLength, work;



          //change vectors from Polar to Cartesian. 

          force = polarToCartesian(initial);

          displacement = polarToCartesian(change);



          //Normalize the displacementNormal

          displacementNormal = normalizeVector(displacement);



          //the length of the project is the dot product of the

          force against the displacement normal.

          projectionLength = dotProduct(force,displacementNormal);



          //Let's see what that length is.

          cout<<"Projection Length "<< projectionLength<<"\n";



          //multiply projection times normalized displacement Vector

          temp = scalarMultiply(projectionLength,displacementNormal);



          //Get back to Polar coordinates to calculate work. Don't 

          forget about radians.

          temp = cartesianToPolar(temp);



          //Finally, our work is calculated.

          work = temp.x * change.x;

          return work;



     }

This function does take some work. The first step is to convert from polar coordinates to Cartesian so that we can process our force and displacement vector components properly.

The next step is to determine the displacement Normal. This is done through the use of the normalizeVector() function. We then use the dotProduct() function to determine the projection length. Now that the projection length is known, we multiply it by the displacementNormal and get the final vector that we can use to calculate work.

This function admittedly takes a bit of reading to understand fully. You can take a look at the sample documentation and see this function in action. Here are quick reminders of the calculation of vector normals and the dot product:


vector3D normalizeVector(vector3D vect)

    {

        float mag,square;

        vector3D temp;

        square = squareVector(vect);

        mag = sqrt(square);



        temp.x = vect.x/mag;

        temp.y = vect.y/mag;

        temp.z = vect.y/mag;

        return temp;

    }

Remember that the normal calculates the magnitude of the vector and then divides each element in the vector by that amount resulting in the normal of the original vector.


float dotProduct(vector3D a, vector3D b)

     {

         vector3D temp;

         float scalar;

         temp.x = a.x*b.x;

         temp.y = a.y*b.y;

         temp.z = a.z*b.z;

         scalar = sumVector(temp);

         return scalar;

     }

The dot product multiplies the two vectors resulting in a vector that is summed. Remember that the dot product returns a scalar value. If you have forgotten either of these functions, refresh your memory with a quick trip back to Chapter 4.

NOTE

Remember that work is a scalar quantity, so as soon as the force and displacement are in the same direction, you can ignore it and simply multiply the magnitudes.


The second quantity we need to define is kinetic energy. Kinetic energy is the amount of energy an object has because it is moving. Therefore, the faster it's moving, the more kinetic energy it has. In that respect, it's very similar to momentum, which is mass times velocity.

The definition of kinetic energy is one-half of the mass times the speed squared, ½mv2.

Kinetic Energy

KE = ½mv 2

where m = mass and v = speed.


Notice that the definition is based on speed rather than velocity. (Remember that speed is the scalar version of velocity, so it's the velocity minus its direction.)

Because kinetic energy is also a scalar quantity, the direction doesn't matter. Just as speed changes on an instantaneous basis, so does kinetic energy. Any time the speed changes, the kinetic energy changes also, so quite often you'll find that we designate initial and final kinetic energy over a period of time, just as we did with velocity in earlier chapters.

Also, this is another place where metric units are much easier to work with. If the speed is measured in m/s and the mass is measured in kg, the kinetic energy can also be measured in joules:

kg(m/s)2 = kg(m2/s2) = (kg*m/s)*m = N*m = J

Example 12.4: Calculating Kinetic Energy

Suppose you have a device that can clock the speed of a baseball as it crosses the plate, and it registers 90mi/hr for a particular pitch. If the baseball has a mass of 145g, how much kinetic energy does it have at that instant?

Solution
  1. The first thing you need to do is convert all the units. The speed must be measured in m/s, and the mass must be in kg:

    graphics/12equ01.gif


    145g = 0.145kg

  2. Now you can plug these values into the definition of kinetic energy:

    KE = ½mv2 = ½(0.145kg)(40.225m/s)2 = 117.3J

Programming this calculation is fairly straightforward. Here is a function that will calculate kinetic energy given a mass in kilograms and a speed in meters per second:


float calculateKineticEnergy(float mass, float speed)

     {

          float KE;

          KE = (mass/2)*(pow(speed,2));

          return KE;

     }

Now that we've defined both work and kinetic energy, we're ready to use a new theorem that describes a direct relationship between the two. Not surprisingly, it's called the work-energy theorem. This theorem states that the net or total work done on an object is equal to the change in its kinetic energy.

Work-Energy Theorem

W = DKE = KEfKEi

or

graphics/12equ11.gif


where the force and displacement are in the same direction, and v is speed.


This theorem basically says that if work is done on an object (a force moves it a certain distance), the object either speeds up or slows down. Conceptually, this sounds exactly like Newton's Second Law (and it is), but this version can be used to track the object's final speed after any given displacement. Let's use an example to show how this might be the easier version to work with in a gaming example.

Example 12.5: Work-Energy Theorem

Suppose you're programming a baseball game, and the shortstop needs to throw the ball to the first baseman. It takes some work for him to get the ball moving. If he can produce a force of 400N for a distance of 0.75m (from behind his head to the point where he lets go of the ball), and the baseball has a mass of 145g, what speed should the ball have when he lets go?

Solution

This is a great opportunity to use the work-energy theorem:

W = DKE = KEfKEi

graphics/12inl04.gif

400N(0.75m) = ½(0.145kg)(vf)2 – 0

300J = 0.0725kg(vf)2

graphics/12inl05.gif

64.33m/s = vf

The basis for the work energy theorem provides the foundation for all the conservation theorems presented later. Each of them needs to be organized for fairly specific purposes inside a game. This function will tell us the final speed using the work energy theorem:


float calculateWorkEnergy(float force, float mass, 

                         float displacement, float velocityInitial)

     {

       float work,vFinal;

       work = calculateWork(force,displacement);

       vFinal = work/((mass/2) - calculateKE(mass, velocityInitial));

       velocityFinal = sqrt(Final);

       return vFinal;

     }

This function does quite a bit of calculation to determine the final speed of the object. First, it calculates the work done by the force and displacement. Then the value for work is plugged directly into the function to determine the final velocity. The right side terms come straight out of the work energy theorem. Once those have resolved, the square root is taken and returned as the final speed of the object. Very cool.

In game programming, finding the final speed is more helpful than finding the acceleration, so you might find this theorem quite useful. Remember that there is always more than one way to approach a physics model. You could have just as easily used Newton's Second Law and the five equations of motion, but that would probably require more steps. As a game programmer, always look for the most optimized formula for your particular scenario. In some cases, the work-energy theorem might hit the spot.

Self-Assessment

1.

A tugboat exerts a constant force of 5500N to pull a ship through the harbor. If the tugboat pulls the ship 5km, how much work is done?

2.

If the main character in your game has to push a cart 5 meters down the road, and he pushes with a force of 30N at a –60° angle, how much work is being done?

3.

If the cart described in question 2 starts from rest and has a mass of 50kg, how fast will it be going at the end of the 5 meters?

4.

What is the kinetic energy of a 3000-kg car moving at 55mi/hr?

5.

A 2-g bullet leaves the barrel of a gun going 300m/s. What is its kinetic energy?

6.

If the length of the barrel of the gun described in question 5 is 50cm, find the average force exerted on the bullet to move it the length of the barrel.


    Previous Section  < Day Day Up >  Next Section