微软多动画理解

来源:互联网 发布:js隐藏与显示 编辑:程序博客网 时间:2024/05/20 16:11

不同的动作衔接的时候进行动画平滑过渡。通过m_bIdle和bCanMove控制动作的平滑过渡,SetMoveKey()是移动动画平滑过渡,SetIdleKey()是闲置动画平滑过渡

void CTiny::SetMoveKey()
{
    DWORD dwNewTrack = ( m_dwCurrentTrack == 0 ? 1 : 0 );
    LPD3DXANIMATIONCONTROLLER pAC;
    LPD3DXANIMATIONSET pAS;
    m_pAI->GetAnimController( &pAC );


    if( m_fSpeed == m_fSpeedWalk )
        pAC->GetAnimationSet( m_dwAnimIdxWalk, &pAS );
    else
        pAC->GetAnimationSet( m_dwAnimIdxJog, &pAS );


    pAC->SetTrackAnimationSet( dwNewTrack, pAS );
    pAS->Release();


    pAC->UnkeyAllTrackEvents( m_dwCurrentTrack );
    pAC->UnkeyAllTrackEvents( dwNewTrack );


    pAC->KeyTrackEnable( m_dwCurrentTrack, FALSE, m_dTimeCurrent + MOVE_TRANSITION_TIME );
    pAC->KeyTrackSpeed( m_dwCurrentTrack, 0.0f, m_dTimeCurrent, MOVE_TRANSITION_TIME, D3DXTRANSITION_LINEAR );
    pAC->KeyTrackWeight( m_dwCurrentTrack, 0.0f, m_dTimeCurrent, MOVE_TRANSITION_TIME, D3DXTRANSITION_LINEAR );
    pAC->SetTrackEnable( dwNewTrack, TRUE );
    pAC->KeyTrackSpeed( dwNewTrack, 1.0f, m_dTimeCurrent, MOVE_TRANSITION_TIME, D3DXTRANSITION_LINEAR );
    pAC->KeyTrackWeight( dwNewTrack, 1.0f, m_dTimeCurrent, MOVE_TRANSITION_TIME, D3DXTRANSITION_LINEAR );
    m_dwCurrentTrack = dwNewTrack;

    pAC->Release();
}


void CTiny::SetIdleKey( bool bResetPosition )
{
    DWORD dwNewTrack = ( m_dwCurrentTrack == 0 ? 1 : 0 );
    LPD3DXANIMATIONCONTROLLER pAC;
    LPD3DXANIMATIONSET pAS;
    m_pAI->GetAnimController( &pAC );


    pAC->GetAnimationSet( m_dwAnimIdxLoiter, &pAS );
    pAC->SetTrackAnimationSet( dwNewTrack, pAS );
    pAS->Release();


    pAC->UnkeyAllTrackEvents( m_dwCurrentTrack );
    pAC->UnkeyAllTrackEvents( dwNewTrack );


    pAC->KeyTrackEnable( m_dwCurrentTrack, FALSE, m_dTimeCurrent + IDLE_TRANSITION_TIME );
    pAC->KeyTrackSpeed( m_dwCurrentTrack, 0.0f, m_dTimeCurrent, IDLE_TRANSITION_TIME, D3DXTRANSITION_LINEAR );
    pAC->KeyTrackWeight( m_dwCurrentTrack, 0.0f, m_dTimeCurrent, IDLE_TRANSITION_TIME, D3DXTRANSITION_LINEAR );
    pAC->SetTrackEnable( dwNewTrack, TRUE );
    pAC->KeyTrackSpeed( dwNewTrack, 1.0f, m_dTimeCurrent, IDLE_TRANSITION_TIME, D3DXTRANSITION_LINEAR );
    pAC->KeyTrackWeight( dwNewTrack, 1.0f, m_dTimeCurrent, IDLE_TRANSITION_TIME, D3DXTRANSITION_LINEAR );
    if( bResetPosition )
        pAC->SetTrackPosition( dwNewTrack, 0.0 );


    m_dwCurrentTrack = dwNewTrack;


    pAC->Release();
}

SmoothLotier()是闲置时候进行的闲置动画的平滑过渡

void CTiny::SmoothLoiter()
{
    LPD3DXANIMATIONCONTROLLER pAC;
    LPD3DXANIMATIONSET pASTrack, pASLoiter;
    m_pAI->GetAnimController( &pAC );


    // check if we're loitering
    pAC->GetTrackAnimationSet( m_dwCurrentTrack, &pASTrack );
    pAC->GetAnimationSet( m_dwAnimIdxLoiter, &pASLoiter );
    if( pASTrack && pASTrack == pASLoiter )
    {
        D3DXTRACK_DESC td;
        pAC->GetTrackDesc( m_dwCurrentTrack, &td );
        if( td.Position > pASTrack->GetPeriod() - IDLE_TRANSITION_TIME )  // come within the change delta of the end
            SetIdleKey( true );
    }


    SAFE_RELEASE( pASTrack );
    SAFE_RELEASE( pASLoiter );
    SAFE_RELEASE( pAC );
}


应用代码为

void CTiny::Animate( double dTimeDelta )
{
    // adjust position and facing based on movement mode
    if( m_bUserControl )
        AnimateUserControl( dTimeDelta );  // user-controlled
    else if( m_bIdle )
        AnimateIdle( dTimeDelta );         // idling - not turning toward
    else
        AnimateMoving( dTimeDelta );       // moving or waiting - turning toward


    // loop the loiter animation back on itself to avoid the end-to-end jerk
    SmoothLoiter();


    D3DXMATRIX mxWorld, mx;


    // compute world matrix based on pos/face
    D3DXMatrixRotationY( &mxWorld, -m_fFacing );
    D3DXMatrixTranslation( &mx, m_vPos.x, m_vPos.y, m_vPos.z );
    D3DXMatrixMultiply( &mxWorld, &mxWorld, &mx );
    D3DXMatrixMultiply( &mxWorld, &m_mxOrientation, &mxWorld );
    m_pAI->SetWorldTransform( &mxWorld );
}


void CTiny::AnimateUserControl( double dTimeDelta )
{
    // use keyboard controls to make Tiny move


    bool bCanMove;


    if( GetKeyState( 'V' ) < 0 )
    {
        m_bUserControl = false;
        SetSeekingState();
        return;
    }


    if( GetKeyState( 'W' ) < 0 )
    {
        bCanMove = true;


        if( GetAsyncKeyState( VK_SHIFT ) < 0 )
        {
            if( m_fSpeed == m_fSpeedWalk )
            {
                m_fSpeed = m_fSpeedJog;
                m_bIdle = true;  // Set idle to true so that we can reset the movement animation below
            }
        }
        else
        {
            if( m_fSpeed == m_fSpeedJog )
            {
                m_fSpeed = m_fSpeedWalk;
                m_bIdle = true;  // Set idle to true so that we can reset the movement animation below
            }
        }


        D3DXVECTOR3 vMovePos;
        GetFacing( &vMovePos );
        D3DXVec3Scale( &vMovePos, &vMovePos, float( m_fSpeed * GetSpeedScale() * dTimeDelta ) );
        D3DXVec3Add( &vMovePos, &vMovePos, &m_vPos );


        // is our step ahead going to take us out of bounds?
        if( IsOutOfBounds( &vMovePos ) )
            bCanMove = false;


        // are we stepping on someone else?
        if( IsBlockedByCharacter( &vMovePos ) )
            bCanMove = false;


        if( bCanMove )
            m_vPos = vMovePos;
    }
    else
        bCanMove = false;




    if( m_bIdle && bCanMove )
    {
        SetMoveKey();
        m_bIdle = false;
    }


    if( !m_bIdle && !bCanMove )
    {
        SetIdleKey( true );
        m_bIdle = true;
    }


    // turn
    if( GetKeyState( 'A' ) < 0 )
        m_fFacing = float( m_fFacing + m_fSpeedTurn * dTimeDelta );


    if( GetKeyState( 'D' ) < 0 )
        m_fFacing = float( m_fFacing - m_fSpeedTurn * dTimeDelta );
}

原创粉丝点击