Previous Section  < Day Day Up >  Next Section

Collision with a Stationary Object

The simplest type of collision to model is one in which a moving object collides with a fixed stationary object, such as a billiard ball hitting the bumper. The bumper doesn't move, so you only need to model the resulting motion of one object, the ball. This type of scenario can be modeled using vector reflection, which refers to the motion of the moving object—in this case, the ball. An interesting symmetry exists: The angle that the ball comes in at must equal the angle at which it leaves. In other words, the angle of incidence (incoming) must equal the angle of reflection (outgoing), as shown in Figure 13.1.

Figure 13.1. Vector reflection.

graphics/13fig01.gif

This process is very simple to program if the wall is perfectly horizontal or perfectly vertical. Likewise, if the stationary object is in an axis-aligned bounding box, which means that the sides of the box are perfectly horizontal and vertical, the vector reflection is simple to model. We'll tackle the non-axis-aligned case next. For now, let's go back to the billiard ball about to hit the bumper. Hopefully, after working through Chapter 10, "Motion in Two and Three Dimensions," you're tracking the ball's velocity with a vector in component form: ball velocity = [vx vy]. If the bumper is vertical, all you have to do is reverse the horizontal component of the velocity when the ball hits, as shown in Figure 13.2.

Figure 13.2. Vector reflection with a vertical wall.

graphics/13fig02.gif

Similarly, if the wall is horizontal, all you have to do is reverse the direction of the vertical component of the ball's velocity when it hits.

Axis-Aligned Vector Reflection

If the stationary boundary is vertical, vf = [–vix viy] and

if the stationary boundary is horizontal, vf = [vix –viy]

for incoming velocity vi = [vix viy].


Example 13.1: Axis-Aligned and Non-Axis-Aligned Vector Reflection

Suppose you're coding a simple Pong game, and you want to model the collision of the ball with the paddle. If the ball is approaching the paddle with an incoming velocity of [40 75] when it hits, what should its resulting velocity be?

Solution

In Pong, the ball goes back and forth across the screen, so when it hits the paddle, it collides with the vertical edge. That means you must reverse the horizontal component of the velocity and leave the vertical component the same. Therefore, the final velocity vector must be [–40 75].

Now that we've discussed axis-aligned vector reflection, let's tackle non-axis-aligned. What if the stationary object is oriented in such a way that its edges are no longer parallel to the x- and y-axes? The angle of incidence must still equal the angle of reflection, but now it's more complicated than just reversing one component. Let's start with two dimensions and then extend the process to 3D.

Typically when you approach this scenario, you know the moving object's incoming velocity vector (vi), you know the boundary line of the stationary object it is about to bounce off of (B), and you're looking for the new resulting velocity vector (vf). This is shown in Figure 13.3.

Figure 13.3. Non-axis-aligned vector reflection.

graphics/13fig03.gif

To implement this form of reflection in code, we can use this function:


vector2D axisAlignedCollision(vector2D vect, char b)

     {

       vector2D temp = vect;



        if(b == 'v')

            temp.x = temp.x*= -1;

        else if(b =='h')

            temp.y = temp.y*= -1;



       return temp;

     }

This particular function requires that we know if the user is making a horizontal or vertical reflection. Normally, you don't ask the player to give this information. The key here would be to nest the guts of this reflection inside a collision algorithm. Remember that collision detection is only half the process. As the game designer and developer, you have to determine what the outcome is going to be.

The first thing you need to find is the normal (N) to the line of the stationary object. Chapter 1, "Points and Lines," discussed perpendicular lines. It said that slopes are negative reciprocals of each other. So if the slope of the boundary line (B) is Dy/Dx, the slope of the normal (N) must be –Dx/Dy. In vector form, that's the same as saying B = [Dx Dy]; therefore, N = [Dy –Dx]. Then you need to normalize N so that it has a length of 1. Chapter 4, "Vector Operations," discussed normalizing. It said that to normalize a vector, you must divide it by its own magnitude. In Figure 13.4, normalized N is written as N'.

Figure 13.4. The normal to the boundary line.

graphics/13fig04.gif

The next step is to find the projection (P) of –vi onto the normal (N').

NOTE

Note that you need to reverse vi before taking the dot product because it's facing the wrong way with respect to P.


Back in Chapter 4, you found that the dot product gives you the magnitude of the projection, so the magnitude of P = –vi • N'.

To get P to point in the same direction as the normal, you must multiply the magnitude of P by the normal, so the vector P = (–vi • N') * N', as shown in Figure 13.5.

Figure 13.5. Projection added.

graphics/13fig05.gif

Now to find vf, all you need is a bit of geometry. Figure 13.6 adds a new vector, V. Look at how vectors vi and P are lined up tip-to-tail (see Chapter 4). This means that V = vi + P.

Figure 13.6. A new vector v added.

graphics/13fig06.gif

Look at Figure 13.6; you see that P + V = vf. Now just substitute the previous line for V:

If V = vi + P and

P + V = vf then

vf = P + (vi + P)

This brings you to the final line you are looking for:

vf = 2 * P + vi

Non-Axis-Aligned Vector Reflection

vf = 2 * P + vi

where vi = the incoming velocity and P = the projection of –vi onto the normal of the boundary line.


Example 13.2: Non-Axis-Aligned 2D Vector Reflection

Suppose you're coding a modified Pong game that has additional objects on the screen, and you want to model the collision of the ball with one of these obstacles. Suppose you have already determined that a collision is about to happen in the next frame. The obstacle's closest boundary goes from the point (50,25) to the point (200,250). If the ball is approaching the obstacle with an incoming velocity of [50 10] when it hits, what should its resulting velocity be?

Solution
  1. Find a vector to describe the boundary line:

    B = [Dx Dy]

    = [200 250] – [50 25]

    = [150 225]

  2. Find the normal (or perpendicular) vector:

    N = [Dy –Dx]

    = [225 –150]

  3. Normalize N:

    graphics/13equ01.gif


    N = [225 –150]

    graphics/13equ02.gif


  4. Find P by calculating the length of the projection and multiplying that by N':

    P = (–vi • N') * N'

    = ([–50 –10] • [0.832 –0.555]) * N'

    = (–36.05) * N'

    = (–36.05) * [0.832 –0.555]

    [–30 20]

  5. The final step is to calculate the final velocity:

    vf = 2 * P + vi

    = 2 * [–30 20] + [50 10]

    = [–60 40] + [50 10]

    = [–10 50]

Let's look at how we can turn this big calculation into a function that will properly calculate non-axis aligned reflections for a 2D object:


vector2D nonAxisAlignedCollision(vector2D a, vector2D b)

    {

      vector2D temp,temp2,temp3,length,reflection;

      float projection;



      temp = normalizeVector(a);



      //reverse the vector.

      temp2 = scalarMultiply(-1,b);



      //find the project length using the dot product.

      projection = dotProduct(temp2,temp);

      length = scalarMultiply(projection,temp);



      //the reflection is going to be twice the length.

      reflection = scalarMultiply(2,length);



      //sum them all together making sure the reflection is inverted.

      temp3 = sumVectors(scalarMultiply(-1,reflection),temp2);



      //tada!!

      return temp3;

    }

This function follows right along with the solution to the previous example. First, we normalize the vector that describes the boundary. Then we determine the projection length by reversing the colliding object's vector and calculating the dot product. Multiply the projection with the boundary normal. We then determine the length component of the reflection by multiplying the projection by the boundary normal. The reflection is determined to be twice the size of the length. Sum all the vectors with the reversed object vector, and we have a non-axis aligned reflection.

You might be wondering how to extend this to 3D. If you know the incoming velocity and the 3D plane about to be hit, you can calculate the final velocity using the same vector operations. The only slight difference is that in 3D the object bounces off a plane rather than a 2D line. Two vectors define the plane, so the normal vector can be found using the cross-product of those two vectors, as discussed in Chapter 4. Let's look at a 3D example.

Example 13.3: Non-Axis-Aligned 3D Vector Reflection

Now suppose you're coding a modified 3D Pong game that has additional objects on the screen, and you want to model the collision of the ball with one of these obstacles. Suppose you have already determined that a collision is about to happen in the next frame. The obstacle's closest boundary is a plane defined by the vectors [200 250 –300] and [50 200 –25]. If the ball is approaching the obstacle with an incoming velocity of [100 –50 –50] when it hits, what should its resulting velocity be?

Solution
  1. Find the surface normal, as you did in Chapter 4:

    N = [200 250 –300] * [50 200 –25]

    = [(250 * –25) – (–300 * 200) (–300 * 50) – (200 * –25) (200 * 200) – (250 * 50)]

    = [(–6250 + 60000) (–15000 + 5000) (40000 – 12500)]

    = [53750 –10000 27500]

    graphics/13equ03.gif


  2. Find P by calculating the length of the projection and multiplying that by N':

    P = (–vi • N') * N'

    = ([–100 50 50] • [0.8783 –0.1634 0.4494]) * N'

    = (–73.53) * N'

    = (–73.53) * [0.8783 –0.1634 0.4494]

    [–64.5814 12.0148 –33.0444]

  3. The last step is to calculate the final velocity:

    vf = 2 * P + vi

    = 2*[–64.5814 12.0148 –33.0444] + [100 –50 –50]

    = [–129.1628 24.0296 –66.0888] + [100 –50 –50]

    = [–29.1628 –25.9704 –116.0888]

This calculation is almost identical to the non-axis aligned 2D reflection. The major changes are the implementation of the 3D vector:


vector3D nonAxisAlignColl(vector3D a, vector3D b,vector3D velocity)

{

  vector3D temp,normal, velocityTemp,velocityFinal,length, reflection;



       velocityTemp = scalarMultiply(-1,velocity);



        float projection;

        temp = crossProduct(a,b);



        //get the surface normal

        normal = normalizeVector(temp);



        //calculate the projection.

        projection = dotProduct(velocityTemp,normal);



        //Take the length of the projection against the normal.

        length = scalarMultiply(projection,normal);



        //Lets obtain the final vector.

        reflection = scalarMultiply(2,length);

        velocityFinal = sumVectors(reflection,velocity);

        return velocityFinal;

    }

If you need to refer back to the function definition for the dotProduct, normalizeVector, or scalarMultiply methods, take a look at the last chapter or check out the source code for this chapter.

Now that we've discussed the motion of a moving object bouncing off a fixed object, we can move on to two moving objects. The rest of this chapter examines how two objects interact when one object is still when it gets hit and when both objects are moving when they collide.

Self-Assessment

1.

Suppose you're coding a 2D pool game with a top-down view. If the sides of the table are parallel to the x- and y-axes, and one of the balls has an incoming velocity of [–30 50] when it hits the bumper at the top of the screen, what should its resulting velocity be?

2.

Suppose you're coding a 2D pool game where the camera can rotate around the table. If the bumper that the cue ball is about to hit goes from (40,150) to (240,300), and the ball is approaching it with an incoming velocity of [80 20], what should the ball's resulting velocity be?

3.

Suppose you're coding a full 3D pool game where the camera can be oriented any way the player wants. If the bumper is now the plane defined by vectors [30 100 –50] and [200 –50 –25], and the cue ball has an incoming velocity of [20 –10 –50] when it hits, what should its resulting velocity be?


    Previous Section  < Day Day Up >  Next Section