Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
70 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

Contents
 Introduction
 Character Image
 Files

 Checking for
 Movement

 Collision Detection
 Animation
 NPCs and Random
 Movement

 Ordering Characters

 Printable version
 Discuss this article
 in the forums



The Series
 Beginning Windows
 Programming

 Using Resources
 in Win32 Programs

 Tracking Your
 Window/Using GDI

 Introduction
 to DirectX

 Palettes and Pixels
 in DirectDraw

 Bitmapped Graphics
 in DirectDraw

 Developing the
 Game Structure

 Basic Tile Engines
 Adding Characters
 Tips and Tricks

NPCs and Random Movement

In a really well-done game, NPCs will probably be doing something suitable to who they are. Old men and women won't move around much, kids will run through the town playing, and thieves will quickly walk away whenever they notice anyone paying too much attention. But to do all that, we either need to hard-code a bunch of behavior for each NPC type (which is not a good idea), or use a script (which we don't know how to do yet). So for now, let's start off our NPCs by implementing the simplest form of behavior that's found in lots of old RPGs -- random movement.

The nice part about implementing NPCs is that we can use a lot of the same code that we used for setting up the player. Our function that checks whether or not a character can move to a certain position can be used for NPCs, and the code we just wrote for actually plotting characters can also be used for NPCs, with one minor change. We'd just have to stick it in a function that takes one argument: the y-value to use for the source RECT. Hence we will have multiple character images loaded onto a single surface, and specify which character to use via this parameter.

So what's left to do? First we'll need to set up some sort of system that determines random movements for the NPC. The simplest way to do it is just to choose a random number, and if it falls in a certain range, or is divisible by a certain number, then the character should move, so we pick a random direction and that's it! The code would look something like this:

// choose a random number
int nDir;
int nRand = rand();

// move if 128 divides nRand (bits 0-6 used) and NPC is still
if (((nRand & 0x0000007F) == 0) && (move.xMove == 0) && (move.yMove == 0))
{
  // use bit 7 to determine positive (south, east) or negative (north, west) movement
  nDir = ((nRand & 0x00000080) >> 6) - 1;

  // use bit 8 to determine horizontal or vertical movement
  if ((nRand & 0x00000100) == 0)
  {
    // move vertically
    if (MoveOK(move.xTile, move.yTile + nDir))
    {
      move.yMove = nDir;
      move.yTile += nDir;
      move.yOffset -= (nDir << 5);  // remember, this is multiplication by 32
      move.nFace = ((nDir == 1) ? 0 : 3);
    }
  }
  else
  {
    // move horizontally
    if (MoveOK(move.xTile + nDir, move.yTile))
    {
      move.xMove = nDir;
      move.xTile += nDir;
      move.xOffset -= (nDir << 5);
      move.nFace = ((nDir == 1) ? 6 : 9);
    }
  }
}

All right, I'm using some pretty odd-looking code in there to people who don't use bitwise operations a lot, so I'll clear it up a little. The bitwise AND operator & can be used to extract bits from a number. That's what I'm doing here -- essentially extracting three random numbers from one. In the case of nDir, I mask out a single bit: bit 7. So the result of the & operation is either 2^7 * 1 = 128 or 2^7 * 0 = 0. Shifting by six places is equivalent to dividing by 64, so the result is now either 2 or 0. Then I subtract one to get either 1 or -1. Cool, hey? You can do it more straightforwardly if you want; I use bitwise operators and shifts a lot so that looks pretty natural to me, but do what works for you.

Anyway, this is all it takes to get NPCs moving around, and we already said that we could use our player drawing function to draw NPCs as well. So we're finished, right? Well, not quite.





Next : Ordering Characters