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 + -
显示快捷键?