Tricks of the Windows Game Programming Gurus:Making Silicon Think with Artificial Intelligence

All ITKnowledge Source Code Search Tips Advanced Search |

| Tricks of the Windows Game Programming Gurus by Andre LaMothe Sams, Macmillan Computer Publishing ISBN: 0672313618 Pub Date: 09/27/99

Search this book:

Previous | Table of Contents | Next

There are other choices—0.5 or 0.9—whatever. It’s even possible to compute the exact overflow and then shrink the vector by that amount, if perfection’s your goal.

I know we haven’t hit vector math yet, and yet I’ve been using the terminology in this example, so I thought I would give an example of some tracking code that uses this algorithm, ripped right out of a real game. This code makes these little mines track the player. Look at how the real code performs all the previous steps in a real example:

    // mine tracking algorithm

    // compute vector toward player

    float vx = player_x - mines[index].varsI[INDEX_WORLD_X];

    float vy = player_y - mines[index].varsI[INDEX_WORLD_Y];

    // normalize vector (sorta :)

    float length = Fast_Distance_2D(vx,vy);

    // only track if reasonable close

    if (length < MIN_MINE_TRACKING_DIST)

       {

       vx=MINE_TRACKING_RATE*vx/length;

       vy=MINE_TRACKING_RATE*vy/length;

       // add velocity vector to current velocity

       mines[index].xv+=vx;

       mines[index].yv+=vy;

       // add a little noise

       if ((rand()%10)==1)

          {

          vx = RAND_RANGE(-1,1);

          vy = RAND_RANGE(-1,1);

          mines[index].xv+=vx;

          mines[index].yv+=vy;

          } // end if

       // test velocity vector of mines

      length = Fast_Distance_2D(mines[index].xv, mines[index].yv);

       // test for velocity overflow and slow

       if (length > MAX_MINE_VELOCITY)

          {

          // slow down

          mines[index].xv*=0.75;

          mines[index].yv*=0.75;

          } // end if

       } // end if

    else

       {

       // add a random velocity component

       if ((rand()%30)==1)

          {

          vx = RAND_RANGE(-2,2);

          vy = RAND_RANGE(-2,2);

          // add velocity vector to current velocity

          mines[index].xv+=vx;

          mines[index].yv+=vy;

          // test velocity vector of mines

          length = Fast_Distance_2D(mines[index].xv, mines[index].yv);

          // test for velocity overflow and slow

          if (length > MAX_MINE_VELOCITY)

             {

             // slow down

             mines[index].xv*=0.75;

             mines[index].yv*=0.75;

             } // end if

          } // end if

     } // end else

Although it’s obvious that this code was hijacked from a `for` loop or something that processed a number of mines, that’s irrelevant. It’s a good example of a clean implementation of the algorithm, but it also has some areas I want to bring to your attention. For example, there’s a section of the code that tests if the mine is within a certain distance of the player. If not, the mine doesn’t track the player but has its trajectory slightly modified with some random noise. In addition, even when the mine tracks the player, I add some random noise to the result. This adds more realism to the tracking. In space, water, air, or whatever, there are going to be changes in gravity, density, and so forth that would slightly alter the physics. Thus, adding the noise makes things more realistic.

For an example of this trajectory tracking algorithm, check out `DEMO12_3.CPP|EXE` on the CD. It allows you to move a little ship around in a scrolling universe. Within this universe are mines that follow you by using the previous algorithm. The controls are

Arrow Keys | Controls ship
Ctrl | Fires ship’s weapons
+/- | Changes the tracking rate
H | Toggles huds
S | Toggles scanner

Notice how decreasing the tracking rate makes the tracking object look like it’s on ice.

> TIP: Because I’m using GDI to draw text, the text printing slows the game down tremendously. I wanted you to see this. In a real game, you would make your own font engine to draw text.

This is a good example of a small game, so there’s a lot to learn. Study it well.

#### Anti-Tracking: Evasion Algorithms

Starting to get little quantum disturbances in your brain—that is, ideas? Good! The next AI technique is to enable creatures in the game to get away from you. Remember how the ghosts in Pac-Man fled when you ate the powerups? Making an evasion AI do the same thing is simple. In fact, you already have the code! The previous tracking code is the exact opposite of what you want; just take the code and flip the equalities around. Presto! You’ll have an evasion algorithm. Here’s the code after the inversions:

    // given: player is at player_x, player_y

    // and game creature is at

    // monster_x, monster_y

    // first test x-axis

    if (player_x < monster_x)

       monster_x++;

    if (player_x > monster_x)

       monster_x--;

    // now y -axis

    if (player_y < monster_y)

       monster_y++;

> Note: If you have a heartbeat, you should have noticed that there is no conditional for equal to (`==`). This is because I don’t want the object to move in this case. I want it to sit on the player. If you want, you can make the `==` case do something else.

    if (player_y > monster_y)

       monster_y--;

Now you can create a fairly impressive AI system with just random motion, chasing, and evasion. In fact, you have enough to make a Pac-Man brain. Not much, but good enough to sell 100 million or so copies, so that’s not too bad! To check out evasion in action, run `DEMO12_4.CPP|EXE` on the CD. It’s basically the same as `DEMO12_2.CPP`, but with the evasion AI instead of the tracking AI. Now let’s move on to patterns.

### Patterns and Basic Control Scripting

Algorithmic and deterministic algorithms are great, but sometimes you need to make a game object follow a sequence of steps, or a script of sorts. For example, when you start your car, there is a specific sequence of steps that you perform:

  1. Get the keys out of your pocket.
  2. Put the key in the door.
  3. Open the door.
  4. Get in the car.
  5. Close the door.
  6. Put the key in the ignition.
  7. Turn the key.
  8. Start the car.

The point is that there’s a sequence of steps that you don’t think much about. You just replay them every time. Of course, if something goes wrong, you might change your sequence, like pressing the gas pedal or jump-starting the car because you left the lights on last night. Patterns are an important part of intelligent behavior, and even humans, the epitome of intelligent life on this planet (yeah, right), use them.

Previous | Table of Contents | Next

Copyright © Macmillan Computer Publishing, Inc.

Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.