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...
}
|