Вам хотелось, когда нибудь сделать удары ногой, рукой и использовать их в виде комбо, например по нажатию 2 раза какой-то кнопки за определённое время вызвать ту или иную функцию? Вот и решил я наваять какой, никакой код :D
// m_iState: 0 = Нет нажатия
// 1 = Нажато 1 раз
// 2 = Нажато дважды
// 3 = Готово к использованию
struct TapData_s
{
// Конструктор
TapData_s()
{
m_nKey = 0; m_iState = 0;
m_flPressTime1 = gpGlobals->curtime;
m_flPressTime2 = gpGlobals->curtime+1;
m_flDelayBetweenPressesMin = 0;
m_flDelayBetweenPressesMax = 0;
}
public:
int m_iState;
int m_nKey;
float m_flPressTime1;
float m_flPressTime2;
float m_flDelayBetweenPressesMin;
float m_flDelayBetweenPressesMax;
};
class CTapHandler
{
public:
CTapHandler(){ m_vTapDataList.RemoveAll(); }
void AddKeyToTrackList( const int &nKey, const float &flTimeToPressTwiceMin, const float &flTimeToPressTwiceMax )
{
bool noMatches = true; // Lolmen : Проверка на наличие такой клавиши в списке
for ( int i = m_vTapDataList.Count() - 1; i >= 0; i-- )
{
TapData_s *pCurTap = m_vTapDataList.Element( i );
if ( pCurTap && pCurTap->m_nKey == nKey )
{
noMatches = false;
}
}
if ( noMatches != false )
{
TapData_s *pNewTap = new TapData_s;
if ( pNewTap )
{
pNewTap->m_nKey = nKey;
pNewTap->m_flDelayBetweenPressesMin = flTimeToPressTwiceMin;
pNewTap->m_flDelayBetweenPressesMax = flTimeToPressTwiceMax;
m_vTapDataList.AddToTail( pNewTap );
}
}
}
void HandleKeysTaps( const CBasePlayer *pPlayer )
{
for ( int i = m_vTapDataList.Count() - 1; i >= 0; i-- )
{
TapData_s *pCurTap = m_vTapDataList.Element( i );
if ( pCurTap && pPlayer )
{
switch( pCurTap->m_iState )
{
case 0:
{ // Lolmen : Первое нажатие игроком
if ( pPlayer->m_afButtonPressed & pCurTap->m_nKey )
{
pCurTap->m_iState = 1;
pCurTap->m_flPressTime1 = gpGlobals->curtime;
}
}
break;
case 1:
{ // Lolmen : Второе нажатие игроком
if ( pPlayer->m_afButtonPressed & pCurTap->m_nKey )
{
pCurTap->m_iState = 2;
pCurTap->m_flPressTime2 = gpGlobals->curtime;
}
}
break;
case 2:
{
float dt = pCurTap->m_flPressTime2 - pCurTap->m_flPressTime1;
// Lolmen : Больше наше dt или равно минимальному времени нажатия,
// или же, меньше, а может и равно максимальному времени?
if ( dt >= pCurTap->m_flDelayBetweenPressesMin && dt <= pCurTap->m_flDelayBetweenPressesMax )
{
pCurTap->m_iState = 3;
}
else
{ // Lolmen : Если не прокатило сбрасываем статус на начало
pCurTap->m_iState = 1;
pCurTap->m_flPressTime1 = gpGlobals->curtime;
}
}
break;
default:
{ // Lolmen : На следующем кадре опять сбрасываем статус, если достигнут результ
if ( pCurTap->m_iState >= 3 )
{
pCurTap->m_iState = 1;
pCurTap->m_flPressTime1 = gpGlobals->curtime;
}
}
break;
}
}
}
}
void Update( void )
{ // Lolmen : Покадровый обновитель
CBasePlayer *pPlayer = UTIL_GetLocalPlayer();
if ( pPlayer != NULL )
{
HandleKeysTaps( pPlayer );
}
}
// Эта функция вернёт true только 1 раз за кадр
bool KeyPressedTwice( const int &nKey )
{
bool ret = false;
for ( int i = m_vTapDataList.Count() - 1; i >= 0; i-- )
{
TapData_s *pCurTap = m_vTapDataList.Element( i );
if ( pCurTap )
{
if ( pCurTap->m_nKey == nKey && pCurTap->m_iState >= 3 )
{
ret = true;
break;
}
}
else
{
continue;
}
}
return ret;
}
private:
CUtlVector< TapData_s* > m_vTapDataList;
};
Это был класс для определения функциональности, как его применять?
// Lolmen : Создадим где-то главный экземпляр:
CTapHandler gpTapHandler;
// NOTE: в других файлах используем ссылку на главный экз "extern CTapHandler gpTapHandler;"
Теперь давайте попробуем использовать наш экземпляр например в оружии SMG1
В конструктор добавим такое :
CWeaponSMG1::CWeaponSMG1()
{
// какойто инициализирующий код тут
// Lolmen : наш отлавливатель
gpTapHandler.AddKeyToTrackList( IN_FORWARD, 0.1f, 0.3f );
gpTapHandler.AddKeyToTrackList( IN_SPEED, 0.015f, 0.5f );
// Lolmen : Примечаение : ( Кнопка, минимальное время, максимальное время ) за которое мона нажать 2жды
}
Так, мы определили, за какими кнопками нужно установить наблюдение, теперь будем это использовать :
CWeaponSMG1::ItemPostFrame( )
{
// Lolmen: Разместим где-то покадровую обновлялку
gpTapHandler.Update();
// Какой-то SMG'шный код тут :
// Lolmen: Теперь смотрим были-ли нажаты 2жды след кнопки :
if ( gpTapHandler.KeyPressedTwice( IN_FORWARD ) )
{
// Вызываем какой-то метот тут:
}
if ( gpTapHandler.KeyPressedTwice( IN_SPEED ) )
{
// Делаем что-то еще
}
}
P.S Если будут проблемы, обращаемся в форум.