player.cpp

来自「一个symbian 冒险游戏代码」· C++ 代码 · 共 1,095 行 · 第 1/3 页

CPP
1,095
字号
	app->setPlayerAnimationReferencePoint( ANIM_CHANGEWEAPON_SPEAR, DIR_135, 20, 78 );
	
	//Change weapon, shotgun
	app->playerAnims[ANIM_CHANGEWEAPON_SHOTGUN][DIR_0].loadCustom( expandPath("data/anims/hero/hero_changew_shotgun_e.nan"), resampler, halfRes );
	app->playerAnims[ANIM_CHANGEWEAPON_SHOTGUN][DIR_315].loadCustom( expandPath("data/anims/hero/hero_changew_shotgun_se.nan"), resampler, halfRes );
	app->playerAnims[ANIM_CHANGEWEAPON_SHOTGUN][DIR_270].loadCustom( expandPath("data/anims/hero/hero_changew_shotgun_s.nan"), resampler, halfRes );
	app->playerAnims[ANIM_CHANGEWEAPON_SHOTGUN][DIR_90].loadCustom( expandPath("data/anims/hero/hero_changew_shotgun_n.nan"), resampler, halfRes );
	app->playerAnims[ANIM_CHANGEWEAPON_SHOTGUN][DIR_45].loadCustom( expandPath("data/anims/hero/hero_changew_shotgun_ne.nan"), resampler, halfRes );
	app->playerAnims[ANIM_CHANGEWEAPON_SHOTGUN][DIR_135] = Surface( app->playerAnims[ANIM_CHANGEWEAPON_SHOTGUN][DIR_45], Surface::FLAG_MIRROR );
	app->playerAnims[ANIM_CHANGEWEAPON_SHOTGUN][DIR_180] = Surface( app->playerAnims[ANIM_CHANGEWEAPON_SHOTGUN][DIR_0], Surface::FLAG_MIRROR );
	app->playerAnims[ANIM_CHANGEWEAPON_SHOTGUN][DIR_225] = Surface( app->playerAnims[ANIM_CHANGEWEAPON_SHOTGUN][DIR_315], Surface::FLAG_MIRROR );
	app->setPlayerAnimationReferencePoint( ANIM_CHANGEWEAPON_SHOTGUN, DIR_0, 17, 78 );
	app->setPlayerAnimationReferencePoint( ANIM_CHANGEWEAPON_SHOTGUN, DIR_315, 22, 78 );
	app->setPlayerAnimationReferencePoint( ANIM_CHANGEWEAPON_SHOTGUN, DIR_270, 24, 78 );
	app->setPlayerAnimationReferencePoint( ANIM_CHANGEWEAPON_SHOTGUN, DIR_90, 24, 78 );
	app->setPlayerAnimationReferencePoint( ANIM_CHANGEWEAPON_SHOTGUN, DIR_45, 20, 78 );
	app->setPlayerAnimationReferencePoint( ANIM_CHANGEWEAPON_SHOTGUN, DIR_225, 22, 78 );
	app->setPlayerAnimationReferencePoint( ANIM_CHANGEWEAPON_SHOTGUN, DIR_180, 17, 78 );
	app->setPlayerAnimationReferencePoint( ANIM_CHANGEWEAPON_SHOTGUN, DIR_135, 20, 78 );
	
	for ( int k = 0 ; k < DIR_COUNT ; ++k )
	{
		app->playerAnims[ANIM_ATTACK_SWORD][k].setEndBehaviorStop();
		app->playerAnims[ANIM_ATTACK_SPEAR][k].setEndBehaviorStop();
		app->playerAnims[ANIM_ATTACK_SHOTGUN][k].setEndBehaviorStop();
		app->playerAnims[ANIM_DRINK][k].setEndBehaviorStop();
		app->playerAnims[ANIM_DEATH][k].setEndBehaviorStop();
		app->playerAnims[ANIM_CHANGEWEAPON_SWORD][k].setEndBehaviorStop();
		app->playerAnims[ANIM_CHANGEWEAPON_SPEAR][k].setEndBehaviorStop();
		app->playerAnims[ANIM_CHANGEWEAPON_SHOTGUN][k].setEndBehaviorStop();
	}
}

void Player::deinitStatic()
{
	GameApp* app = GameApp::get();

	for ( int i = 0 ; i < Player::BODY_COUNT ; ++i )
	{
		app->playerAnims[i][MapObject::DIR_0].destroy();
		app->playerAnims[i][MapObject::DIR_45].destroy();
		app->playerAnims[i][MapObject::DIR_90].destroy();
		app->playerAnims[i][MapObject::DIR_270].destroy();
		app->playerAnims[i][MapObject::DIR_315].destroy();
	}
}

void Player::update( Fix dt )
{
	const Fix idleThresholdTime = Fixf(1.5);

	m_time += dt;
	if ( m_time < Fixf(0) ) m_time = Fixf(0);
	if ( m_time > Fixf(32000) ) m_time -= Fixf(32000);

	m_speedModifyTime -= dt;
	if ( m_speedModifyTime <= Fixf(0) )
	{
		m_speedModifyTime = Fixf(0);
		m_speedModifier = Fixf(0);
	}

	switch ( state() )
	{
	case BODY_IDLE:
		if ( m_virtualState == BODY_STILL )
		{
			if ( m_time > idleThresholdTime )
			{
				if ( m_weaponInHand )
				{
					setVirtualState( BODY_PUT_WEAPON );
					Surface& s = bodyAnim( NULL, NULL );
					s.setReversed( false );
				}
				else
				{
					clearVirtualState();
				}
			}
		}
		if ( m_virtualState == BODY_PUT_WEAPON )
		{
			if ( animEnded() )
			{
				clearVirtualState();
				m_weaponInHand = false;
			}
		}
		break;

	case BODY_WALK_WOUNDED:
	case BODY_WALK:
		if ( m_virtualState == BODY_TAKE_WEAPON )
		{
			if ( animEnded() )
			{
				clearVirtualState();
				m_weaponInHand = true;
			}
		}
		if ( m_virtualState != BODY_TAKE_WEAPON )
		{
			if ( !m_weaponInHand )
			{
				setVirtualState( BODY_TAKE_WEAPON );
				Surface& s = bodyAnim( NULL, NULL );
				s.setReversed( true );
			}
			else
			{
				updateWalk( dt, ( m_state == BODY_WALK_WOUNDED ) );
			}
		}
		break;

	case BODY_ATTACK:
		updateAttack( dt, getWeaponSkill(), getWeaponDamage(), getWeaponRange(), getWeaponAngle() );
		break;

	case BODY_DRINK:
		if ( m_virtualState == BODY_PUT_WEAPON )
		{
			if ( animEnded() )
			{
				clearVirtualState();
				m_weaponInHand = false;
			}
		}
		if ( m_virtualState != BODY_PUT_WEAPON )
		{
			if ( m_weaponInHand )
			{
				setVirtualState( BODY_PUT_WEAPON );
				Surface& s = bodyAnim( NULL, NULL );
				s.setReversed( false );
			}
			else
			{
				updateDrink( dt );
			}
		}
		break;

	case BODY_DEATH:
		updateDeath( dt );
		break;

	case BODY_TAKE_WEAPON:
		if ( m_virtualState == BODY_PUT_WEAPON )
		{
			if ( animEnded() )
			{
				clearVirtualState();
				m_weaponInHand = false;
			}
		}
		if ( m_virtualState != BODY_PUT_WEAPON )
		{
			if ( m_weaponInHand )
			{
				setVirtualState( BODY_PUT_WEAPON );
				Surface& s = bodyAnim( NULL, NULL );
				s.setReversed( false );
			}
			else
			{
				if ( m_nextWeapon >= 0 )
				{
					assert( m_nextWeapon < WEAPON_COUNT );
					m_currentWeapon = m_nextWeapon;
					m_nextWeapon = -1;
					Surface& s = bodyAnim( NULL, NULL );
					s.setReversed( true );
				}
				if ( animEnded() )
				{
					setState( BODY_WALK );
					m_weaponInHand = true;
				}
			}
		}
		break;

	case BODY_COUNT:
		assert( false );
		break;

	default:
		break;
	}
}

Fix Player::getWeaponSkill()
{
	return m_weaponSkills[ m_currentWeapon ];
}

Fix Player::getWeaponDamage()
{
	return m_weaponDamages[ m_currentWeapon ];
}

Fix Player::getWeaponRange()
{
	return m_weaponRanges[ m_currentWeapon ];
}

Fix Player::getWeaponAngle()
{
	return m_weaponAngles[ m_currentWeapon ];
}

Fix Player::getWeaponDelay()
{
	return m_weaponDelays[ m_currentWeapon ];
}

Fix Player::getWeaponSlowdownFactor()
{
	return m_weaponSlowdownFactors[ m_currentWeapon ];
}

void Player::setWeapon( char* name, Fix skill, Fix damage, Fix range, Fix angle, Fix delay, Fix slowdownFactor )
{
	int weapon = -1;
	for ( int i = 0; i < WEAPON_COUNT; i++ )
	{
		if ( strcmp( name, WEAPON_NAMES[ i ] ) == 0 )
		{
			weapon = i;
			break;
		}
	}

	if ( ( weapon >= 0 ) && ( weapon < WEAPON_COUNT ) )
	{
		m_weaponSkills[weapon] = skill;
		m_weaponDamages[weapon] = damage;
		m_weaponRanges[weapon] = range;
		m_weaponAngles[weapon] = angle;
		m_weaponDelays[weapon] = delay;
		m_weaponSlowdownFactors[weapon] = slowdownFactor;
	}
}

void Player::draw( Surface& dst )
{
	const bool halfResolution = GameApp::get()->isHalfResolution();
	int refX, refY;
	const Surface& anim = bodyAnim( &refX, &refY );
	m_previousAnim = (Surface*) &anim;
	m_previousRefX = refX;
	m_previousRefY = refY;
	if ( anim.mirror() ) refX = -refX;
	int x0 = position().x.toInt() - refX;
	int y0 = position().y.toInt() - refY;
	if ( halfResolution )
	{
		x0 >>= 1;
		y0 >>= 1;
	}
	x0 += anim.mirror() ? ( -anim.offsetX() - anim.frameWidth() ) : anim.offsetX();
	y0 += anim.offsetY();
	
	Surface sf = anim.clipFrame( anim.getFrame( !m_freezeAnim ? m_time : Fixf(0) ) );
	dst.blt( x0, y0, sf, Surface::BLEND_ALPHA1B );
	//dst.blt( x0, y0, sf, Surface::BLEND_ALPHA );

	m_isDrawn = true;
}

void Player::damage( Fix hp, MapObject* enemy )
{
	GameApp::get()->playSound( "hero_get_hit", SoundContext::CHANNEL_OTHER );

	m_hitpoints -= hp;

	// 75% speed loss, duration 2 seconds
	if ( m_speedModifier >= Fixf(-0.75) )
	{
		m_speedModifier = Fixf(-0.75);
		m_speedModifyTime = Fixf(2);
	}

	if ( m_hitpoints.v <= 0 )
		die( enemy );
	else
		hit();
}

void Player::disturb( MapObject* /*enemy*/ )
{
	// 50% speed loss, duration 1.5 seconds
	if ( m_speedModifier >= Fixf(-0.5) )
	{
		m_speedModifier = Fixf(-0.5);
		m_speedModifyTime = Fixf(1.5);
	}
}

FixVec2	Player::center() const
{
	return position() - FixVec2( Fix(0), Fix::fromInt(32) );
}

Surface& Player::bodyAnim( int* refX, int* refY )
{
	GameApp* app = GameApp::get();
	int dir = direction();
	int state = ( m_virtualState == BODY_NONE ) ? m_state : m_virtualState;
	assert( m_state >= 0 && m_state < BODY_COUNT );
	assert( dir >= 0 && dir < DIR_COUNT );

	int animation = m_animationSwitchBoard[ state ];
	if ( ( animation & ANIM_WEAPON_DEPENDENT ) != 0 )
	{
		int weapon = m_currentWeapon;
		animation =	( ( weapon >= 0 ) && ( weapon <= WEAPON_COUNT ) ) ?
					( animation & ~ANIM_WEAPON_DEPENDENT ) + weapon :
					ANIM_DEFAULT;
	}
	assert( ( animation >= ANIM_NONE ) && ( animation < ANIM_COUNT ) );
	if ( ( animation == ANIM_NONE ) && !m_previousAnim ) animation = ANIM_DEFAULT;
	m_freezeAnim = false;

	Surface* a = 0;
	int rX = 0;
	int rY = 0;
	if ( animation != ANIM_NONE )
	{
		rX = app->playerAnimRefPoints[animation][dir][0];
		rY = app->playerAnimRefPoints[animation][dir][1];
		a = &app->playerAnims[animation][dir];
	}
	else
	{
		assert( m_previousAnim );
		rX = m_previousRefX;
		rY = m_previousRefY;
		a = m_previousAnim;
		m_freezeAnim = true;
	}
	if ( refX ) *refX = rX;
	if ( refY ) *refY = rY;
	assert( a->frames() > 0 );
	return *a;
}

const Surface& Player::bodyAnim( int* refX, int* refY ) const
{
	return const_cast<Player*>(this)->bodyAnim( refX, refY );
}

void Player::setState( BodyState state, bool endTime )
{
	if ( state != m_state && m_state != BODY_DEAD )
	{
		int virtualState = BODY_NONE;

		switch ( state )
		{
		case BODY_IDLE:
			virtualState = BODY_STILL;
			break;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?