Over the Shoulder View:ru

From Valve Developer Community
Jump to: navigation, search
English
заплечная камера в игре

Шаг 1 - Поставить вид от третьего лица по дефолту.

Найдите и откройте in_camera.cpp, он должен находиться в client.dll файлах. Теперь найдите каждый случай использования sv_cheats, и удалите или закомментируйте все эти строки. Найдите последнюю функцию, и в самом конце вы должны увидеть что-то подобное void CInput::Init_Camera( void ) В этой функции добавьте m_fCameraInThirdPerson = true; Должно получиться вот так:

void CInput::Init_Camera( void )
{
   m_CameraIsOrthographic = false;
   m_fCameraInThirdPerson = true;
}

Данные действия установили вид от третьего лица стандартно, не требуя никаких телодвижений от игрока.

Шаг 2 - Создаём вид из-за плеча.

В этом шаге мы внесём необходимые изменения, для того чтобы сделать камеру с видом из-за плеча. Найдите и откройте clientmode_shared.cpp. Он также находиться в client.dll файлах. Теперь найдите функцию void ClientModeShared::OverrideView( CViewSetup *pSetup ). Замените всё внутри функции на:

C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if(!pPlayer)
       return;

pPlayer->OverrideView( pSetup );

if( ::input->CAM_IsThirdPerson() )
{
   Vector camForward, camRight, camUp;
     
          AngleVectors( pPlayer->EyeAngles(), &camForward, &camRight, &camUp );
     
   trace_t tr, tr2;
   Vector vecStart, vecStop, vecDirection, vecSetDirection;   
   static float camCurrentY;   
   static float camCurrentX=16.0f;   
   float camDelta=0.5f;
   vecStart=pSetup->origin;

   AngleVectors(pPlayer->EyeAngles(), &vecDirection);   
      
   vecSetDirection.Init(0,0,1.0f);
   vecDirection=vecDirection.Cross(vecSetDirection);
   vecStop = vecStart + vecDirection*52.0f;

   UTIL_TraceLine( vecStart, vecStop, MASK_ALL, pPlayer, COLLISION_GROUP_NONE, &tr );
      
   if (tr.fraction == 1) //достаточно ли мы далеки чтобы не задеть стену камерой
   {
    if(camCurrentX < 16.0f)
     camCurrentX +=camDelta;
    if(camCurrentX >16.0f)
     camCurrentX=16.0f;
    VectorMA( pSetup->origin, camCurrentX, camRight, pSetup->origin); //установка правильного смещения
    VectorMA( pSetup->origin, 16.0f, camUp, pSetup->origin);
     vecStart=tr.endpos;
   }
   else   
   {   
       
    vecStop = vecStart + vecDirection * -52.0f;
       
    UTIL_TraceLine( vecStart, vecStop, MASK_ALL, pPlayer, COLLISION_GROUP_NONE, &tr );
         
    if (tr.fraction == 1)   
    {   
     if(camCurrentX > -16.0f)
      camCurrentX -=camDelta;
     if(camCurrentX < -16.0f)
      camCurrentX=-16.0f;
     VectorMA( pSetup->origin, camCurrentX, camRight, pSetup->origin);
     VectorMA( pSetup->origin, 16.0f, camUp, pSetup->origin);
     vecStart=tr.endpos;
    }
    else   
    {   
     VectorMA( pSetup->origin, 0.0f, camRight, pSetup->origin);   
     AngleVectors(pPlayer->EyeAngles(), &vecDirection);   
     vecSetDirection.Init(1.0f,0,0);
     vecDirection=vecDirection.Cross(vecSetDirection);
     vecStop = vecStart +vecDirection*32.0f;
       
     UTIL_TraceLine( vecStart, vecStop, MASK_ALL, pPlayer, COLLISION_GROUP_NONE, &tr);

     if(tr.fraction == 1)
     {
      VectorMA( pSetup->origin, 32.0f, camUp, pSetup->origin);
      vecStart=tr.endpos;
     }
     else   
       //Добавьте код, чтобы сделать игрока прозрачным, таким образом игрок может видеть лучше (?)
     {
      VectorMA( pSetup->origin, 0.0f, camUp, pSetup->origin);
     }
    }

   }
       
   AngleVectors(pPlayer->EyeAngles(), &vecDirection);   
   vecStop = vecStart + vecDirection * -96;
   UTIL_TraceLine( vecStart, vecStop, MASK_ALL, pPlayer, COLLISION_GROUP_NONE, &tr );
     
   vecStart=pSetup->origin;
     
   vecStop = vecStart+vecDirection*-96;
   UTIL_TraceLine( vecStart, vecStop, MASK_ALL, pPlayer, COLLISION_GROUP_NONE, &tr );
        
   if(tr.fraction != 1)
   {
    camCurrentY = -96 * tr.fraction + 10.0f;
   }
   else
          {
    camCurrentY=-96.0f;
    VectorMA( pSetup->origin, camCurrentY, camForward, pSetup->origin);
   }
}

Это создаст вид из-за плеча, который стандартно будет стоять из-за правого плеча. Это конечно не идеальный код, но для начала создания какого-нибудь интересного мода может и подойти. Если не будет пространства справа, то произойдёт проверка и если пространство есть, то установиться x и z -16/+16 а затем проверяется расстояние позади. Если нет пространства слева, или справа, z устанавливается +32 и x 0. Это поместит камеру выше головы модели игрока, таким образом игрок всё ещё сможет видеть. Если будет недостаточно пространства выше, то камера будет помещена на уровне глаз. Все эти проверки нужны для корректного вида камеры, например если вы ползёте в вентиляционных трубах или того хуже, в канализации

Шаг 3 - Исправляем маленький баг

Существует маленький баг, который нужно исправить, если его не исправить, то анимация вашего персонажа при повороте камеры по сторонам, будет глючить. Найдите и откройте c_sdk_player.cpp. Найдите функцию void C_SDKPlayer::UpdateClientSideAnimation() и замените содержимое на:

if ( this == C_SDKPlayer::GetLocalSDKPlayer() )
   m_PlayerAnimState->Update( EyeAngles()[YAW], EyeAngles()[PITCH] );
else
   m_PlayerAnimState->Update( m_angEyeAngles[YAW], EyeAngles()[PITCH] );

BaseClass::UpdateClientSideAnimation();

Теперь анимация должна быть корректной. Для игр на движке HL2MP нужно сделать немного другое. Найдите и откройте файл hl2mp_player.cpp. Найдите функцию void CHL2MP_Player::PostThink( void ) и замените содержимое на:

BaseClass::PostThink();
     
if ( GetFlags() & FL_DUCKING )
{
   SetCollisionBounds( VEC_CROUCH_TRACE_MIN, VEC_CROUCH_TRACE_MAX );
}

m_PlayerAnimState.Update();

QAngle angles = GetLocalAngles();

CBasePlayer *pPlayer = dynamic_cast<CBasePlayer*>(this);
if ( pPlayer )
{
   angles[PITCH] = EyeAngles()[PITCH];
   angles[YAW] = EyeAngles()[YAW];
}
else
{
   angles[PITCH] = EyeAngles()[PITCH];
   angles[YAW] = m_angEyeAngles[YAW];
}

SetLocalAngles( angles );

Теперь глюков быть не должно.

Шаг 4 - Саморегулирующийся прицел.

Найдите и откройте hud_crosshair.cpp. Он находиться в client.dll файлах. Теперь найдите функцию void CHudCrosshair::Paint( void ). Замените содержимое функции на:

if ( !m_pCrosshair )
   return;

if ( !IsCurrentViewAccessAllowed() )
   return;   

C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
Vector vecStart, vecStop, vecDirection, vecCrossPos;
trace_t tr;
     
AngleVectors(pPlayer->EyeAngles(), &vecDirection);

vecStart= pPlayer->EyePosition();
vecStop = vecStart + vecDirection * MAX_TRACE_LENGTH;
     
UTIL_TraceLine( vecStart, vecStop, MASK_ALL, pPlayer , COLLISION_GROUP_NONE, &tr );
     
     
ScreenTransform(tr.endpos, vecCrossPos);

m_pCrosshair->DrawSelf( 0.5f*ScreenWidth()+0.5f*ScreenWidth()*vecCrossPos[0]-0.5f*m_pCrosshair->Width(),   
     0.5f*ScreenHeight()+(0.5f*ScreenHeight()*-vecCrossPos[1])-0.5f*m_pCrosshair->Height(),
     m_clrCrosshair );

Так как вид уже из-за плеча, координаты прицела должны поменяться вот это собственно мы и изменяем.