Должен ли я использовать DirectInput или цикл сообщений Windows? - PullRequest
14 голосов
/ 30 января 2010

Я работаю над C ++ DirectX 2D-игрой, и мне нужен ввод с клавиатуры и мыши.
Википедия говорит:

Microsoft рекомендует, чтобы новые приложения использовали цикл сообщений Windows для ввода с клавиатуры и мыши вместо DirectInput

Так как мне его использовать?
У меня есть класс GameScreen, который заботится о рисовании и обновлении (игровая логика), я вызываю методы Draw и Update в цикле сообщений Windows.

Спасибо

Ответы [ 7 ]

14 голосов
/ 30 января 2010

Поскольку вам достаточно запустить насос сообщений, чтобы иметь окно, вы также можете использовать этот насос для обработки ввода с клавиатуры и мыши. От вас зависит, будете ли вы передавать события клавиатуры на дочернее окно, вы можете обрабатывать их в насосе, если хотите.

Ваш типичный насос сообщений выглядит так:

while (GetMessage(&msg, NULL, 0, 0))
{
    if (WM_QUIT == msg.message)
       break;
    TranslateMessage(&msg); // post a WM_CHAR message if this is a WM_KEYDOWN
    DispatchMessage(&msg);  // this sends messages to the msg.hwnd
}

Для игры ваш насос может выглядеть примерно так

while (true)
{
   if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD))
   {
      bool fHandled = false;
      if (msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST)
         fHandled = MyHandleMouseEvent(&msg);
      else if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST)
         fHandled = MyHandleKeyEvent(&msg);
      else if (WM_QUIT == msg.message)
         break;

      if ( ! fHandled)
      {
         TranslateMessage(&msg);
         DispatchMessage(&msg);
      }
   }
   else
   {
       // if there are no more messages to handle right now, do some
       // game slice processing.
       //
   }
}

Конечно, ваш реальный насос, вероятно, будет даже более сложным, чем, возможно, с MsgWaitForMultipleObjects, так что вы можете периодически просыпаться, даже если нет сообщений для обработки, но сразу же, когда есть сообщения.

5 голосов
/ 30 января 2010

DirectInput устарел по уважительным причинам. Насколько я знаю, он создает дополнительный поток и просто запрашивает интерфейс Windows * Raw Input . Для лучшей производительности я бы использовал Raw Input напрямую.

Если производительность не является проблемой для вас (и я полагаю, что это относится к 2D-игре на текущем оборудовании), следуйте советам Microsoft и используйте оконные сообщения, как описано Джоном Кноллером.

3 голосов
/ 18 февраля 2010

К вашему сведению: ответ Ре Джона Кнеллера ... упрощенный насос сообщений выглядит следующим образом:

while (GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

Тест WM_QUIT, который он включил, НИКОГДА не может быть верным, потому что GetMessage возвращает ноль при получении WM_QUIT. Однако для проверки WM_QUIT в цикле PeekMessage требуется , поскольку PeekMessage возвращает значение true / false независимо от того, было возвращено сообщение или нет. Поскольку GetMessage блокируется до тех пор, пока не будет возвращено сообщение, оно может иметь другое возвращаемое значение.

1 голос
/ 30 января 2010

Да, сообщение MSDN правильно. Используя сообщения Windows, вы можете использовать поддержку мультиязычности (для любой клавиатуры, которую может использовать пользователь) / личные настройки пользователя (правая кнопка мыши вместо левой) и т. Д., Которые вы должны отменить, чтобы использовать DirectInput / XInput , Используйте только те 2 для поддержки геймпада / джойстика. В остальном просто используйте сообщения Windows.

За подробностями я согласен с ответом Джона Кнеллера.

1 голос
/ 30 января 2010

Если в игре есть одно окно, то, насколько я могу судить, различие - дело вкуса. Тем не менее, если у вас есть (или вы планируете иметь, или не можете решительно исключить возможность наличия в будущем) несколько окон, то обмен сообщениями по окнам может стать утомительным.

Проблема в том, что по умолчанию сообщения клавиатуры / мыши направляются только в окно, находящееся в данный момент в фокусе, и обычно в играх вы хотите иметь возможность переключать фокус (на высокопроизводительный обзор, врагов на радаре и т. Д.) И по-прежнему поддерживать интерактивность. Простое решение было бы для каждого модуля, который требует ввода с клавиатуры / мыши, чтобы запросить его напрямую, а не полагаться на пересылку сообщений - следовательно, DirectInput.

Конечно, я не могу много сказать о вашем конкретном сценарии - только мой 2с.

0 голосов
/ 27 августа 2015

Используйте только использование directinput при особых обстоятельствах

Хорошая особенность цикла сообщений Windows, используемого с getmessage, заключается в том, что он использует 0% использования процессора. Если вы делаете непроцессорные задачи, такие как ожидание ключа от пользователя, сбор данных от пользователя, таких как в базе данных или налоговой программе, или даже в текстовом редакторе, имеет смысл просто использовать сообщение Windows с getmessage. Для всех вышеперечисленных программ датой является процесс, когда пользователь нажимает клавишу.

Все, что необходимо для обработки ключей в цикле сообщений Windows, - это переключение этой программы. Мышь даже не должна находиться в окне.

Особые обстоятельства - использование directinput

Если вам нужно: 1) Знайте, когда клавиша нажата и отпущена. Вы также можете не захотеть, чтобы повторяющиеся клавиши распознавались как нажатия клавиш.
2) Обработка клавиш в фоновом режиме при переключении на другую программу.

Если что-то из перечисленного верно, то использовать directinput.

Если вы просто собираете данные от пользователя, вам нужно будет использовать команду sleep, чтобы приостановить выполнение программы. Вы хотите, чтобы программа имела 0% использования процессора в диспетчере задач, если программа просто сидит в ожидании ключей от пользователя.

Используйте функцию сна, переводя программу в спящий режим до тех пор, пока вы не захотите опросить прямой ввод для клавиш.

Поэтому прямой ввод просто тратит время программирования, если вы выполняете простую обычную задачу по сбору ключей от пользователя, как вы можете видеть.

0 голосов
/ 30 января 2010

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

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

...