18.3 Sniffing a trail

Suppose you want to program a car-racing game in which you look down at a track from above and use the controls to steer your car along the track. Lining the track with lots of little walls is an option, but in this section we'll talk about a different approach. The idea here is to lay down a trail that your critter can move along.

The cCritter::update method takes a CPopView *pactiveview argument. The reason we have this argument is so that the update can feed the pactiveview into the method COLORREF cCritter::sniff(const cVector &snifflocation, CPopView *pactive view). The sniff return value tells you the color of the pixel of the onscreen view corresponding to a given location.

The way to use sniff would be to make the track that you want your critter to stay on be some one particular color, say cColorStyle::CN_WHITE. And then, in that critter's update code, you could have it look ahead and see if it was about to move off the track, and if so, look for a better direction to move in.

A good strategy in looking for a better direction would be to successively try turning left or right by greater and greater amounts. Here's an untested example of how you might do it.

#define LOOKAHEAD 1.1 /* Maybe 1.1 is not the best value to use, 
    maybe should depend on speed. */ 
#define SNIFFTURNSTEP PI/90.0 /* Radians for 2 degrees. Can make 
    larger if this runs too slow. */ 

cCritterSnifferCar::update(cPopView *pactiveview, Real dt) 
    COLORREF sniffcolor = sniff(_position + LOOKAHEAD * radius() * 
        tangent(), pactiveview); 
        //sniffcolor is the color of a pixel a just a bit ahead of me. 
    COLORREF whitecolor = cColorStyle::CN_WHITE; 
    if (sniffcolor == cColorStyle::CN_WHITE || //all clear ahead 
        sniffcolor == -1) 
            /* The "-1" color means your pixel is offscreen or not 
                in clipping region */ 
    //Else you try to turn till you see a good spot. 
    Real sign = 1.0; 
    Real angle = SNIFFTURNSTEP; 
    cVector originaltan = tangent(); 
    int whilecount = 0; /* Never go into a while loop without making 
        sure you get out! */ 
    while(sniffcolor != cColorStyle::CN_WHITE) /* Waggle back and 
        forth till you see a good spot */ 
        yaw(sign * angle); 
        sniffcolor = sniff(_position + LOOKAHEAD * radius() * 
            tangent(), pactiveview); 
        angle += SNIFFTURNSTEP; 
        sign *= -1.0; 
        if (++whilecount > 90) //Fuhgeddaboutit and bail 

All this said, sniffing pixels may not the best method to use to follow a trail. It won't work well if you switch to the OpenGL 3D view, although you could perhaps handle this by sniffing a 2D map of the world that you keep in a cMemoryDC instead of sniffing the screen.

In André LaMothe, Tricks of the Windows Game Programming Gurus (Sams, 2001), you will find a more robust trail-following technique called waypoint pathfinding.

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