Как я могу подключить аналоговый джойстик контроллера к мыши

Итак, я пытаюсь использовать аналоговый джойстик на геймпаде для перемещения курсора мыши на рабочем столе. Проблема в том, что мне нужно получить ту же плавность, что и в Попытке 2, но без использования абсолютного положения мыши. Курсор необходимо переместить относительно его текущей позиции. Причина этого в том, что многие приложения (в основном видеоигры) также устанавливают абсолютную позицию мыши. Это заставляет приложение и попытку 2 бороться друг с другом за контроль над мышью.

Попытка 1 (относительная)

// keep updating the controller state and mouse position
while (true)
{
    // getState returns a 2d float vector with normalized values from [-1, 1]
    // The cursor is being set relative to its current position here.
    SetCursorPosition(GetCursorPosition() + analogStick->getState());
}

Это решение работает, но страдает от проблемы с округлением, поскольку GetCursorPosition и SetCursorPosition основаны на целых числах. В результате небольшие движения не регистрируются, потому что меньшие аналоговые движения всегда будут усечены. Наглядно говоря, небольшие движения аналогового джойстика будут перемещать мышь только по оси X или Y, даже если вы попытаетесь сделать диагональное движение.

Попытка 2 (абсолютная)

vec2 mouseTargetPosition = GetCursorPosition(); // global cursor position
while (true)
{
    mouseTargetPosition += leftStick->getState();
    vec2 newPosition = lerp(GetCursorPos(), mouseTargetPosition, 0.8f);
    SetCursorPos(round(newPosition.x), round(newPosition.y));
}

Это решение отлично работает, мышь реагирует на малейшие движения и движется очень естественно в результате интерполяции накопленных аналоговых движений. Но он устанавливает мышь в абсолютное положение (mouseTargetPosition), что делает это решение нарушающим условия сделки.


person Watercycle    schedule 21.12.2015    source источник


Ответы (1)


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

vec2 mouseTargetPos, mouseCurrentPos, change;
while (true)
{
    // Their actual position doesn't matter so much as how the 'current' vector approaches
    // the 'target vector'
    mouseTargetPos += primary->state;
    mouseCurrentPos = util::lerp(mouseCurrentPos, mouseTargetPos, 0.75f);
    change = mouseTargetPos - mouseCurrentPos;

    // movement was too small to be recognized, so we accumulate it
    if (fabs(change.x) < 0.5f) accumulator.x += change.x;
    if (fabs(change.y) < 0.5f) accumulator.y += change.y;

    // If the value is too small to be recognized ( < 0.5 ) then the position will remain the same
    SetCursorPos(GetCursorPos() + change);
    SetCursorPos(GetCursorPos() + accumulator);

    // once the accumulator has been used, reset it for the next accumulation.
    if (fabs(accumulator.x) >= 0.5f) accumulator.x = 0;
    if (fabs(accumulator.y) >= 0.5f) accumulator.y = 0;

}
person Watercycle    schedule 29.12.2015