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

iamdss

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

C-подобный:
if ((buttons & IN_JUMP && buttons & IN_USE) || (buttons & IN_JUMP && buttons & IN_DUCK))

Внутри этого условия я дополнительно проверяю статус клавиш WASD:

C-подобный:
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. Это нормально? Или я неправильно получаю клавиши:

C-подобный:
if ((buttons & IN_FORWARD) && (buttons & IN_MOVERIGHT))
{
    // Вот сюда я никогда не попадаю
}

Во-вторых, не могли бы вы объяснить мне, что есть что из этого ряда операторов:

C-подобный:
|, &, ^, ~, <<, >>

& - я так понял, логическое "и", а остальные?
 

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #2
& побитовое и
| побитовое или
>> и << побитовые сдвиги вправо и влево
^ Побитное исключающее ИЛИ
~ Побитное отрицание


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

R1KO

fuck society
Сообщения
9,457
Реакции
7,786
  • Команда форума
  • #4
iamdss, еще есть вариант.

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

iamdss

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

C-подобный:
// Нажатие
if (buttons & IN_FORWARD)

// Отпускание
if (buttons ~ IN_FORWARD)

Получается, если в коллбек приходит только одна клавиша, то в каждый момент времени я буду фиксировать, что нажата одна клавиша, а другие отпущены. То есть, я и так и эдак получу ложную информацию. Скорее всего, я не прав, поправьте.

Добавлено через 1 минуту
iamdss, еще есть вариант.

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

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

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

Reiko1231

AlexTheRegent
Сообщения
508
Реакции
1,336
Код для всех клавиш выполняется в одном вызове, для этого в него и передается параметр buttons, чтобы не вызывать каждый примерно каждый OnGameFrame для каждого игрока GetClientButtons(). Так как тогда в каждом плагине придется получать одну и ту же информацию из одной и той же функции. Поэтому для оптимизации её вызывают принудительно, но зато один раз для всех вызовов.
buttons Copyback buffer containing the current commands (as bitflags - see entity_prop_stocks.inc).
C-подобный:
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");
	}
}
Ну или я неправильно понял, что спрашивается.

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

iamdss

Участник
Сообщения
126
Реакции
12
Ребят, всё получилось, всё замечательно. Люто плюсую. Тема исчерпана.
 
Сверху Снизу