player.cpp
来自「一个symbian 冒险游戏代码」· C++ 代码 · 共 1,095 行 · 第 1/3 页
CPP
1,095 行
case BODY_WALK:
break;
case BODY_DEATH:
GameApp::get()->playSound( "hero_die", SoundContext::CHANNEL_OTHER );
break;
case BODY_ATTACK:
switch ( m_currentWeapon )
{
case WEAPON_SWORD: GameApp::get()->playSound( "hero_attack", SoundContext::CHANNEL_OTHER ); break;
case WEAPON_SPEAR: GameApp::get()->playSound( "hero_attack", SoundContext::CHANNEL_OTHER ); break;
case WEAPON_SHOTGUN: GameApp::get()->playSound( "hero_shotgun", SoundContext::CHANNEL_OTHER ); break;
default: GameApp::get()->playSound( "hero_attack", SoundContext::CHANNEL_OTHER ); break;
}
break;
case BODY_TAKE_WEAPON:
break;
default:
break;
}
m_state = state;
setVirtualState( (BodyState) virtualState );
if ( !endTime )
{
m_time = Fix(0);
}
else
{
Surface& s = bodyAnim( NULL, NULL );
m_time = s.endTime();
}
}
}
void Player::setVirtualState( BodyState virtualState )
{
if ( virtualState != m_virtualState )
{
m_virtualState = virtualState;
m_time = Fixf(0);
}
}
void Player::clearVirtualState()
{
m_virtualState = BODY_NONE;
m_time = Fixf(0);
}
void Player::walk( Dir dir )
{
if ( m_hitpoints <= Fixf(0) ) return;
setDirection( dir );
if ( m_hitpoints > maxHitPoints()*Fixf(0.25) )
setState( BODY_WALK );
else
setState( BODY_WALK_WOUNDED );
}
void Player::stand()
{
setState( BODY_IDLE );
}
void Player::hit()
{
}
void Player::die( MapObject* killer )
{
m_killer = killer;
m_hitpoints = Fixf(0);
setState( BODY_DEATH );
}
void Player::attack()
{
setState( (BodyState) BODY_ATTACK );
}
void Player::cheat()
{
m_hitpoints = m_maxHitPoints;
}
void Player::drink()
{
setState( BODY_DRINK );
}
void Player::changeWeapon()
{
int newWeapon;
for ( int i = 1; i < WEAPON_COUNT; i++ )
{
newWeapon = ( m_currentWeapon + i ) % WEAPON_COUNT;
assert( newWeapon < WEAPON_COUNT );
if ( hasItem( (char*) WEAPON_NAMES[ newWeapon ] ) )
{
m_nextWeapon = newWeapon;
setState( BODY_TAKE_WEAPON );
break;
}
}
}
void Player::updateWalk( Fix dt, bool wounded )
{
if ( m_time < Fixf(0.2) ) return;
Fix speed = getModifiedSpeed();
if ( wounded )
{
// wounded => loss of speed
speed *= Fixf(0.75);
}
speed *= ( Fixf(1) - getWeaponSlowdownFactor() );
if ( speed < Fixf(10) ) speed = Fixf(10);
FixVec2 dir = directionVector();
FixVec2 delta = dir * ( dt* speed );
delta.y *= m_map->blockDimensionsRatio();
Surface& s = bodyAnim( NULL, NULL );
s.setReversed( false );
s.setFrameRateModifier( Fix( speed.v >> 7 ) ); // speed 128 => frame rate modifier 1.0 => 100% frame rate
if ( !m_map->testPointCollision( m_pos, delta, dir ) )
{
setPosition( position() + delta );
}
else
{
restorePosition();
}
}
void Player::updateAttack( Fix dt, Fix skill, Fix damage, Fix range, Fix anglecos )
{
const Surface& s = bodyAnim( NULL, NULL );
Fix damagetime = s.endTime()*Fixf(0.5);
if ( m_time > damagetime && m_time <= damagetime+dt )
{
tryAttack( skill, damage, range, anglecos );
}
if ( m_time > ( s.endTime() + getWeaponDelay() ) )
{
stand();
}
}
void Player::updateDeath( Fix /*dt*/ )
{
if ( animEnded() )
{
setState( BODY_DEAD, true );
}
}
void Player::updateDrink( Fix /*dt*/ )
{
if ( animEnded() )
stand();
}
void Player::tryAttack( Fix skill, Fix damage, Fix range, Fix anglecos )
{
MapObject* objlist[4];
FixVec2 pos = position();
int objs = getObjects( pos, range, anglecos, objlist, sizeof(objlist) / sizeof(objlist[0]) );
for ( int i = 0 ; i < objs ; ++i )
if ( isSkillSuccess(skill) )
{
objlist[i]->damage( damage, this );
}
else
{
objlist[i]->disturb( this );
}
}
Fix Player::getModifiedSpeed()
{
if ( m_speedModifyTime > Fixf(0) )
{
Fix speed = m_speed;
speed += m_speedModifier * speed;
if ( speed < Fixf(0) ) speed = Fixf(0);
return speed;
}
else
{
m_speedModifyTime = Fixf(0);
return m_speed;
}
}
bool Player::animEnded() const
{
const Surface& s = bodyAnim( NULL, NULL );
return m_time > s.endTime();
}
bool Player::isInterruptable()
{
return m_state != BODY_ATTACK &&
m_state != BODY_DRINK &&
m_state != BODY_DEATH &&
m_state != BODY_DEAD &&
m_state != BODY_TAKE_WEAPON &&
m_state != BODY_PUT_WEAPON &&
m_virtualState != BODY_TAKE_WEAPON &&
m_virtualState != BODY_PUT_WEAPON;
}
bool Player::isInState( const char* statename )
{
int state = -1;
for ( int i = 0; i < 2; i++ )
{
// first pass: check virtual state
// second pass: check state
state = ( i == 0 ) ? m_virtualState : m_state;
if ( state == BODY_IDLE )
{
if ( strcmp( statename, "IDLE" ) == 0 ) return true;
}
else if ( state == BODY_WALK )
{
if ( strcmp( statename, "WALK" ) == 0 ) return true;
}
else if ( state == BODY_WALK_WOUNDED )
{
if ( strcmp( statename, "WALK_WOUNDED" ) == 0 ) return true;
}
else if ( state == BODY_ATTACK )
{
if ( strcmp( statename, "ATTACK" ) == 0 ) return true;
}
else if ( state == BODY_DRINK )
{
if ( strcmp( statename, "DRINK" ) == 0 ) return true;
}
else if ( state == BODY_DEATH )
{
if ( strcmp( statename, "DEATH" ) == 0 ) return true;
}
else if ( state == BODY_DEAD )
{
if ( strcmp( statename, "DEAD" ) == 0 ) return true;
}
else if ( state == BODY_TAKE_WEAPON )
{
if ( strcmp( statename, "TAKE_WEAPON" ) == 0 ) return true;
}
else if ( state == BODY_PUT_WEAPON )
{
if ( strcmp( statename, "PUT_WEAPON" ) == 0 ) return true;
}
else if ( state == BODY_STILL )
{
if ( strcmp( statename, "STILL" ) == 0 ) return true;
}
if ( ( state == BODY_TAKE_WEAPON ) || ( state == BODY_PUT_WEAPON ) )
{
if ( strcmp( statename, "CHANGE_WEAPON" ) == 0 ) return true;
}
if ( m_weaponInHand )
{
if ( strcmp( statename, "WEAPON_IN_HAND" ) == 0 ) return true;
}
}
return false;
}
void Player::setState( const char* statename )
{
if ( strcmp( statename, "DRINK" ) == 0 )
{
drink();
}
else if ( strcmp( statename, "IDLE" ) == 0 )
{
stand();
}
else
{
throwError( Exception( Format("Invalid character state: {0}", statename) ) );
}
}
FixVec2 Player::blockRenderPositionReference() const
{
return m_map->pixelToBlock( FixVec2( m_pos.x, m_pos.y ) );
}
FixVec2 Player::blockRenderPositionExtreme() const
{
bool lowerHalf, oddBlock;
FixVec2 lowRightPoint = renderPositionLow( SIDE_RIGHT );
FixVec2 block = m_map->pixelToBlock( lowRightPoint, 0, &lowerHalf, &oddBlock );
if ( lowerHalf )
{
// point located on the lower half of the block: need to check left
FixVec2 left = m_map->pixelToBlock( renderPositionLow( SIDE_LEFT ) );
if ( ( left.x != block.x ) || ( left.y != block.y ) )
{
// exceeding the boundary of the block located below and on the left, which is a latter block:
// need to change the rendering position there to maintain correct drawing order
block.y += Fix::fromInt( 1 );
if ( !oddBlock ) block.x -= Fix::fromInt( 1 );
}
}
return block;
}
FixVec2 Player::renderPositionLow( int side ) const
{
const bool halfResolution = GameApp::get()->isHalfResolution();
const int xSign = ( side < 0 ) ? -1 : ( side > 0 ) ? 1 : 0;
int refX, refY;
const Surface& anim = bodyAnim( &refX, &refY );
if ( anim.mirror() ) refX = -refX;
const int frameHalfWidth = anim.frameWidth() >> 1;
const int frameHeight = anim.frameHeight();
int x0 = position().x.toInt() - refX;
int y0 = position().y.toInt() - refY;
int shiftX = anim.mirror() ? ( -anim.offsetX() - anim.frameWidth() ) : anim.offsetX();
int shiftY = anim.offsetY();
shiftX += frameHalfWidth;
x0 += shiftX;
y0 += shiftY;
if ( halfResolution )
{
x0 += shiftX;
y0 += shiftY;
}
int x1 = x0 + frameHalfWidth * xSign;
int y1 = y0 + frameHeight;
if ( halfResolution )
{
x1 += frameHalfWidth * xSign;
y1 += frameHeight;
}
return FixVec2( Fix::fromInt(x1), Fix::fromInt(y1) );
}
// End of File
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?