Вопрос по клавишам

Тема в разделе "Программирование / Скриптинг", создана пользователем iamdss, 1 июл 2015.

  1. iamdss

    iamdss

    Сообщения:
    117
    Симпатии:
    0
    Всем доброго дня. Помогите с информацией, пожалуйста. Я определяю нажатия клавиш в OnPlayerRunCmd примерно так:

    Код:
    if ((buttons & IN_JUMP && buttons & IN_USE) || (buttons & IN_JUMP && buttons & IN_DUCK))
    Внутри этого условия я дополнительно проверяю статус клавиш WASD:

    Код:
    if(buttons & IN_FORWARD)
    {
    	ClientEyeAngle[0] = -40.0;
    } else
    if(buttons & IN_BACK)
    {
    	ClientEyeAngle[0] = -140.0;
    } else
    if(buttons & IN_MOVELEFT)
    {
    	ClientEyeAngle[0] = -40.0;
    	ClientEyeAngle[1] -= 270.0;
    } else
    if(buttons & IN_MOVERIGHT)
    {
    	ClientEyeAngle[0] = -40.0;
    	ClientEyeAngle[1] -= 90.0;
    } else
    {
    	ClientEyeAngle[0] = -90.0;
    }
    Но мне надо знать, когда нажаты не только клавиши по отдельности, но и вместе, например, W + D. У меня же нажатия ловятся раздельно, то есть, если нажаты W + D, то в один вызов OnPlayerRunCmd приходит W, а в следующий - D. Это нормально? Или я неправильно получаю клавиши:

    Код:
    if ((buttons & IN_FORWARD) && (buttons & IN_MOVERIGHT))
    {
        // Вот сюда я никогда не попадаю
    }
    Во-вторых, не могли бы вы объяснить мне, что есть что из этого ряда операторов:

    Код:
    |, &, ^, ~, <<, >>
    & - я так понял, логическое "и", а остальные?
     
  2. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.994
    Симпатии:
    2.990
    & побитовое и
    | побитовое или
    >> и << побитовые сдвиги вправо и влево
    ^ Побитное исключающее ИЛИ
    ~ Побитное отрицание


    По поводу проблемы - сохраняй нажатые кнопки в переменную и в следующем фрейме смотри что было нажато ранее.
     
    iamdss нравится это.
  3. iamdss

    iamdss

    Сообщения:
    117
    Симпатии:
    0
    Понял. Спасибо.
     
  4. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.994
    Симпатии:
    2.990
    iamdss, еще есть вариант.

    OnPlayerRunCmd вызывается когда игрок выполняет какие-то действия. Поэтому при нажатии клавиш OnPlayerRunCmd выполняется для каждой отдельно. Поэтому пробуй проверять не buttons который в OnPlayerRunCmd, а GetClientButtons(client).
     
    iamdss нравится это.
  5. iamdss

    iamdss

    Сообщения:
    117
    Симпатии:
    0
    Нет, не совсем понял. Если в этот коллбек приходит нажатие только одной клавиши, то как я определю поднятие клавиши? Приведу пример:

    Код:
    // Нажатие
    if (buttons & IN_FORWARD)
    
    // Отпускание
    if (buttons ~ IN_FORWARD)
    Получается, если в коллбек приходит только одна клавиша, то в каждый момент времени я буду фиксировать, что нажата одна клавиша, а другие отпущены. То есть, я и так и эдак получу ложную информацию. Скорее всего, я не прав, поправьте.

    Добавлено через 1 минуту
    О, спасибо. Это меняет дело. Думаю, это наиболее подходящий вариант. Теперь точно нет вопросов =)

    Добавлено через 2 минуты
    Кстати, чем компилируете плагины и в чём пишете? Я в Notepad++, но хотелось бы в MS студии, если можно...
     
    Последнее редактирование: 1 июл 2015
  6. R1KO

    R1KO Супер-модератор

    Сообщения:
    5.994
    Симпатии:
    2.990
    iamdss нравится это.
  7. Reiko1231

    Reiko1231 AlexTheRegent

    Сообщения:
    237
    Симпатии:
    569
    Код для всех клавиш выполняется в одном вызове, для этого в него и передается параметр buttons, чтобы не вызывать каждый примерно каждый OnGameFrame для каждого игрока GetClientButtons(). Так как тогда в каждом плагине придется получать одну и ту же информацию из одной и той же функции. Поэтому для оптимизации её вызывают принудительно, но зато один раз для всех вызовов.
    Код:
    public OnGameFrame()
    {
    	PrintToServer("OnGameFrame");
    }
    
    public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:angles[3], &weapon, &subtype, &cmdnum, &tickcount, &seed, mouse[2])
    {
    	PrintToServer("OnPlayerRunCmd");
    	
    	if ( buttons & IN_FORWARD && buttons & IN_DUCK) {
    		PrintToServer("IN_FORWARD && IN_DUCK");
    	}
    }
    [​IMG]
    Ну или я неправильно понял, что спрашивается.

    По коду, могу предположить, что нужно 8 проверок - лево, право, вперед, назад, а затем их возможные комбинации лево+вперед, лево+назад и так далее.
    С другой стороны, опять же, не зная задачи, можно предположить, что движение лево-право будет некий угол альфа, а вперед-назад - бета, тогда итоговый угол поворота игрока можно будет записать как тригонометрическую функцию, но над ней надо будет подумать (если вообще её можно написать, так как нужно знать задачу). Тогда нужно будет произвести всего 2-4 проверки (если игрок движется вперед, то очевидно, что назад он идти не может, а если не движется вперед, то надо проверить, а не движется ли он назад. Аналогично 1-2 проверки на лево-право) и в зависимости от их истинности менять альфа, бету (увеличивать или присваивать), а затем для каждого vecAngles[] получать итоговое значение. Хотя не факт, что данный способ будет быстрее в выполнении, потому что 8 проверок скорее всего быстрее, чем 2-4 проверки + нахождение синуса и косинуса.
     
    Серый™ и iamdss нравится это.
  8. iamdss

    iamdss

    Сообщения:
    117
    Симпатии:
    0
    Ребят, всё получилось, всё замечательно. Люто плюсую. Тема исчерпана.