3

I am trying to figure out the best way to work with user input in OpenGL games for Windows. I have four options on my mind:

(1) Just peek messages for the game window inside main messages loop, which contains also rendering, like this:

while (running) {
    while (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE)) {
        DispatchMessage(&msg);
    }
    render();
    SwapBuffers(hDC);
}

//...

LRESULT CALLBACK windowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    //do something with messages
}

This is the method used in most OpenGL tutorials. The big problem of this method is in FPS dependency.

(2) Use SetWindowsHookEx in a separate thread with WH_KEYBOARD_LL / WH_MOUSE_LL:

HHOOK hhK = SetWindowsHookEx(WH_KEYBOARD_LL, 
    [](int nCode, WPARAM wParam, LPARAM lParam)->LRESULT {
        KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *) lParam;
        //handle keyboard
        return CallNextHookEx(0, nCode, wParam, lParam);
}
, GetModuleHandle(NULL), NULL);

HHOOK hhM = SetWindowsHookEx(WH_MOUSE_LL, 
    [](int nCode, WPARAM wParam, LPARAM lParam)->LRESULT {
        MSLLHOOKSTRUCT *pkbhs = (MSLLHOOKSTRUCT *) lParam;
        //handle mouse
        return CallNextHookEx(0, nCode, wParam, lParam);
}
, GetModuleHandle(NULL), NULL);

//We don't event have to create a window
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

This method allows me to peek any number of messages per second, but it seems too artificial to me + it hooks the whole user input in the system, which doesn't seem right to me either.

(3) Same as (2), but using WH_KEYBOARD / WH_MOUSE. Requires a separate .dll, which seems an overhead.

(4) Use DirectInput. Didn't try it, but from what I saw in documentation and tutorials, may be the best way + we could easily capture input also from a gamepad.

The problem is that I'm trying to build OpenGL game, while DirectInput is a part of DirectX.


So, my question is - which way is the correct way to work with user input? Or maybe there are methods I missed?

Cruel_Crow
  • 359
  • 3
  • 15
  • 1
    http://gamedev.stackexchange.com/questions/15502/what-should-i-use-to-handle-input/15512#15512 – Alex K. May 02 '14 at 19:11
  • They are talking about cross-platform libraries, which I do not want to use, and telling that "you will have to go to the operating system API to collect input" - that exactly what I'm trying to do.. – Cruel_Crow May 02 '14 at 19:20
  • 1
    First decide what kind of game you're making. Fighting games may ***poll*** the input at a fixed frequency higher than the display is refreshed, but in other types of games you can afford to handle input as a series of ***events*** in an event loop/message pump and only deal with changes to input at the beginning of each frame. – Andon M. Coleman May 02 '14 at 19:30
  • @AndonM.Coleman Basicly, I want a fully FPS independent input. – Cruel_Crow May 02 '14 at 19:33
  • Then you either need to draw in a separate thread from your input event handler, or poll your input in a separate thread. But you cannot achieve that property when drawing is allowed to cause variability in the rate at which your input is sampled (e.g. `SwapBuffers (...)` causes blocking for an unpredictable amount of time). You will not miss any input events using the event approach along side a variable framerate in a single thread, but you also will not know exactly when the event occurred. – Andon M. Coleman May 02 '14 at 19:35
  • @AndonM.Coleman Thank you for the detailed explanation, but my question was not about that. The question was more about **how** do I capture messages in a separate thread. – Cruel_Crow May 02 '14 at 19:44
  • I don't see why you would need that? Since the message pump is tied to the thread that owns a window, you would be better off handling drawing in its own thread. There is no requirement that the message pump and active GL context belong to the same thread, but there is a requirement that `PeekMessage (...)` be called from the thread where the window was created. – Andon M. Coleman May 02 '14 at 19:54
  • @AndonM.Coleman Say, my game is running slow (15 FPS) and I want to be able to capture at least 20 input actions per second (mouse moves, key presses). It may be critical if we are talking about a game like Starcraft. – Cruel_Crow May 02 '14 at 20:13
  • Well, in that case it is even less important to draw in a separate thread. Like I already told you, in a message pump based system, you do not lose events, you only lose information about when exactly they occurred if your frame takes an exceptionally long time. – Andon M. Coleman May 02 '14 at 20:20
  • @Cruel_Crow I understand that you have stated that you would prefer not having to use an external library but I would like to suggest [OIS Input](http://sourceforge.net/projects/wgois/) if you do come to the conclusion that you need such a library. – Alex Zywicki Jul 05 '14 at 16:57

0 Answers0