13.4 ''damage'' and ''draw''

When a bullet hits a critter, it gets damaged. We have a cCritter method for this.

int cCritter::damage(int hitstrength) 
        /* If we have our shield on, or were just hit, then don't 
            allow a hit. */ 
    if ( _shieldflag || recentlyDamaged() ) 
        return 0; 
    _lasthit_age = _age; /* Save age for use by the recentlyDamaged() 
        accessor. */ 
    _health -= hitstrength; 
    if (_health <= 0) 
        _health = 0; //Do not allow negative health. 
        die(); /* Make a delete_me service request, possibly make 
            noise or more. */ 
        return _value; //The reward for killing this critter. 
    return 0; //Not killed yet. 

As you can see, damage does nothing if _shieldflag is on, or if you've been recently hit. By default _shieldflag is FALSE, and normally only the cCritterArmedPlayer sets the _shieldflag to TRUE. (This is done by the user making the Player | Shield menu selection.) I might mention here that commercial game designers almost always include a flag like _shieldflag to make their player invulnerable so that they can test out game scenarios without having to worry about the player getting killed. Many released games still have a secret 'cheat' switch for turning on your player's _shieldflag. The colorful expression 'God mode' is often used for this state of player invulnerability.

Also note that a critter won't sustain damage if it was recentlyDamaged(). This inline cCritter method is defined in critter.h as BOOL recentlyDamaged(){return (_age ? _lasthit_age) < cCritter::SAFEWAIT;}. The default size of SAFEWAIT is 0.3 second. The reason we use the recentlyDamaged() check is that it's not good if a critter can get damaged rapidly twice in a row. You don't want your player, for instance, to lose three health points simply from bumbling around near an enemy for a fraction of a second. And if you shoot a fusillade of bullets at an enemy, it's more reasonable to only let two nearby bullets manage to inflict one hit of damage.

In general, a single call to cCritter::damage can kill a critter, since the default _health is only 1. But the player usually starts higher.

The cCritter::damage is often overridden to make a sound as well. We could also override it to move the player critter to the center of the screen, as is done in some computer games.

In the Spacewar game, we start each cCritterAsteroid object's health out at 2, and we override cCritterAsteroid::damage to split a health-two critter into two smaller health-one critters.

As we mentioned above, we use the recentlyDamaged() method to prevent a critter from being damaged too rapidly twice in a row. It's useful to display this 'temporarily unavailable for damage' state. We do this with a line in cCritter::draw in critter.cpp. The DF_WIREFRAME flag causes polygons to be drawn unfilled, but it has no effect on bitmaps.

void cCritter::draw(cGraphics *pgraphics, int drawflags) 
    if (recentlyDamaged()) 
        drawflags |= CPopView::DF_WIREFRAME; 
            /* Draw yourself as a "shadow of yourself" if dead or 
                recently damaged. */ 
    //More code... 

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