enemy.cpp
来自「一个symbian 冒险游戏代码」· C++ 代码 · 共 1,167 行 · 第 1/4 页
CPP
1,167 行
int attackLimit = aggressionFactor;
if ( attackLimit < 2 ) attackLimit = 2;
int attackHitLimit = cowardnessFactor;
if ( attackHitLimit < 2 ) attackHitLimit = 2;
int damageLimit = ( ( Fixf(200) - m_cowardness ) * Fixf(0.25) ).toInt();
if ( damageLimit < 5 ) damageLimit = 5;
if ( m_attackCounter >= attackLimit )
{
// attacked several times => back up
m_attackCounter = 0;
m_backUpTime = m_cowardness * Fixf(0.15) + Fixf(0.35);
m_waitTime = Fixf(0);
}
else if ( m_attackHitCounter >= attackHitLimit )
{
// attacked successfully several times => back up and wait
m_attackHitCounter = 0;
m_backUpTime = m_cowardness * Fixf(0.15) + Fixf(0.5);
m_waitTime = m_cowardness * Fixf(0.25) + Fixf(0.5);
}
else if ( m_hitpoints.toInt() < ( m_hitPointMarker - damageLimit ) )
{
// suffered considerable damage => back up and wait
m_hitPointMarker = m_hitpoints.toInt();
m_backUpTime = m_cowardness * Fixf(0.25) + Fixf(1);
m_waitTime = m_cowardness * Fixf(0.5) + Fixf(0.35);
}
else
{
// attack target
m_attackTime -= dt;
if ( m_attackTime <= Fixf(0) )
{
// actual attack
attack();
// set delay
m_attackTime = ( Fixf(150) - m_aggression ) * Fixf(0.005);
if ( m_attackTime < Fixf(0) ) m_attackTime = Fixf(0);
}
else
{
// attack delay
if ( animEnded() ) stand();
}
}
//-------
}
//-------
}
}
// flee?
if ( m_hitpoints <= m_cowardness )
{
setBehavior( BEHAVIOR_FLEE );
}
// target dead?
if ( target->isDead() )
{
setBehavior( BEHAVIOR_PATROL );
}
}
void Enemy::behaviorFlee( Fix dt )
{
MapObject* target = m_map->player();
FixVec2 dirv = target->position() - position();
// update direction
m_dirChangeTime -= dt;
if ( m_dirChangeTime < Fixf(0) )
{
Dir dir = getATanAsDir( -dirv );
setDirection( dir );
m_dirChangeTime = Fixf(1);
}
if ( isInterruptable() )
{
if ( m_collisionCount > 5 )
{
stand();
}
else
{
run();
}
}
if ( ( m_state == BODY_IDLE ) && ( m_hitpoints.toInt() < m_hitPointMarker ) )
{
// is idling and has suffered damage since started fleeing => desperate struggle
m_cowardness = m_hitpoints - Fixf(5);
if ( m_cowardness < Fixf(0) ) m_cowardness = Fixf(0);
setBehavior( BEHAVIOR_COMBAT );
}
}
void Enemy::draw( Surface& dst )
{
const bool halfResolution = GameApp::get()->isHalfResolution();
int refX, refY;
const Surface& anim = bodyAnim( &refX, &refY );
if ( anim.mirror() ) refX = -refX;
int hpx = position().x.toInt();
int hpy = position().y.toInt();
int x0 = position().x.toInt() - refX;
int y0 = position().y.toInt() - refY;
if ( halfResolution )
{
x0 >>= 1;
y0 >>= 1;
hpx >>= 1;
hpy >>= 1;
}
x0 += anim.mirror() ? ( -anim.offsetX() - anim.frameWidth() ) : anim.offsetX();
y0 += anim.offsetY();
Surface sf = anim.clipFrame( anim.getFrame(m_time) );
dst.blt( x0, y0, sf, Surface::BLEND_ALPHA1B );
//dst.blt( x0, y0, sf, Surface::BLEND_ALPHA );
//Hit point indicator
if ( m_hitpoints > Fixf(0) )
{
int barCurrent = m_hitpoints.toInt();
int barHalfWidth = m_maxHitPoints.toInt() >> 1;
int barHeight = 8;
if ( halfResolution )
{
barCurrent >>= 1;
barHalfWidth >>= 1;
barHeight >>= 1;
}
const int full = barHalfWidth + barHalfWidth;
const int shift = barHalfWidth;
dst.fill( hpx - shift, hpy, barCurrent, barHeight, 0x8FF0, Surface::BLEND_ALPHA );
dst.fill( hpx + barCurrent - shift, hpy, full - barCurrent, barHeight, 0x8000, Surface::BLEND_ALPHA );
}
m_isDrawn = true;
}
FixVec2 Enemy::center() const
{
return position() - FixVec2( Fix(0), Fix::fromInt(32) );
}
Surface& Enemy::bodyAnim( int* refX, int* refY )
{
GameApp* app = GameApp::get();
int dir = direction();
assert( m_state >= 0 && m_state < BODY_COUNT );
assert( dir >= 0 && dir < DIR_COUNT );
int animation = m_animationSwitchBoard[ m_state ];
if ( refX ) *refX = app->enemyAnimRefPoints[m_type][animation][dir][0];
if ( refY ) *refY = app->enemyAnimRefPoints[m_type][animation][dir][1];
Surface* a = &app->enemyAnims[m_type][animation][dir];
assert( a->frames() > 0 );
return *a;
}
const Surface& Enemy::bodyAnim( int* refX, int* refY ) const
{
return const_cast<Enemy*>(this)->bodyAnim( refX, refY );
}
void Enemy::setType( EnemyType type )
{
m_type = type;
}
void Enemy::setState( BodyState state, bool endTime )
{
if ( state != m_state && m_state != BODY_DEAD )
{
switch ( m_type )
{
case ENEMY_GHOUL:
switch ( state )
{
case BODY_HIT:
break;
case BODY_DEATH:
GameApp::get()->playSound( "enemy_die", SoundContext::CHANNEL_OTHER );
break;
default:
break;
}
break;
case ENEMY_OGRE:
switch ( state )
{
case BODY_HIT:
break;
case BODY_DEATH:
GameApp::get()->playSound( "enemy_die", SoundContext::CHANNEL_OTHER );
break;
default:
break;
}
break;
case ENEMY_HELLBEAST:
switch ( state )
{
case BODY_HIT:
break;
case BODY_DEATH:
GameApp::get()->playSound( "enemy_die", SoundContext::CHANNEL_OTHER );
break;
default:
break;
}
break;
}
m_state = state;
if ( state == BODY_DEAD )
{
setBehavior( BEHAVIOR_DISABLED );
}
if ( !endTime )
{
m_time = Fix(0);
}
else
{
Surface& s = bodyAnim( NULL, NULL );
m_time = s.endTime();
}
}
}
void Enemy::run()
{
setState( BODY_RUN );
Surface& s = bodyAnim( NULL, NULL );
s.setReversed( false );
}
void Enemy::run( Dir dir )
{
setDirection( dir );
setState( BODY_RUN );
}
void Enemy::stand()
{
setState( BODY_IDLE );
}
void Enemy::hit()
{
setState( BODY_HIT );
}
void Enemy::die()
{
m_hitpoints = Fixf(0);
setState( BODY_DEATH );
}
void Enemy::attack()
{
setState( BODY_ATTACK );
}
void Enemy::backUp()
{
setState( BODY_BACKUP );
Surface& s = bodyAnim( NULL, NULL );
s.setReversed( true );
}
void Enemy::wait()
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?