High-Definition マウスの移動を活用する

標準のコンピューターマウスは400ドット/インチ (DPI) でデータを返しますが、高解像度のマウスでは 800 DPI 以上のデータが生成されます。 これにより、標準のマウスの場合よりも、高解像度のマウスからの入力がはるかに正確になります。 ただし、標準の WM MOUSEMOVE メッセージを使用して高定義データを取得することはできません _ 。 一般に、ゲームは高解像度のマウスデバイスの恩恵を受けますが、WM の MOUSEMOVE を使用してマウスデータを取得するゲームは、フィルター処理されて _ いないマウスの完全な解決にはアクセスできません。

多くの企業が、Microsoft や Logitech などの高精細なマウスデバイスを製造しています。 高解像度のマウスデバイスが広く普及しているため、これらのデバイスによって生成される情報を最適に使用する方法を開発者が理解しておくことが重要です。 この記事では、ゲームでの高精細マウス入力のパフォーマンスを最適化する最良の方法に焦点を当てています。これは、shooter のようなものです。

マウス移動データの取得

マウスデータを取得するには、次の3つの主要な方法があります。

各方法には、データの使用方法に応じて、長所と短所があります。

WM の _ MOUSEMOVE

マウス移動データを読み取る最も簡単な方法は、WM MOUSEMOVE メッセージを使用することです _ 。 次に、WM MOUSEMOVE メッセージからマウス移動データを読み取る方法の例を示し _ ます。

case WM_MOUSEMOVE:
{
    int xPosAbsolute = GET_X_PARAM(lParam); 
    int yPosAbsolute = GET_Y_PARAM(lParam);
    // ...
    break;
}

WM MOUSEMOVE からのデータの主な欠点 _ は、画面の解像度に制限されていることです。 つまり、マウスを少し動かしても、ポインターが次のピクセルに移動するのは不十分であるため、WM _ MOUSEMOVE メッセージは生成されません。 このため、このメソッドを使用してマウスの移動を読み取ると、高度な定義の入力の利点が得られます。

ただし、WM MOUSEMOVE の利点は、 _ Windows がポインターの加速度 (ballistics とも呼ばれます) を生のマウスデータに適用することです。これにより、マウスポインターが顧客の期待どおりに動作するようになります。 これにより _ _ 、ユーザーに対してより自然な動作が発生するため、wm はポインターコントロール (wm INPUT または DirectInput 経由) の優先オプションとして機能するようになります。 WM の _ MOUSEMOVE はマウスポインターを移動するのに最適ですが、高い定義の有効桁数が失われるため、最初の人のカメラを移動するのには適していません。

WM mousemove の詳細について _ は、「 wm _ mousemove」を参照してください。

WM _ 入力

マウスデータを取得する2番目の方法は、WM 入力メッセージを読み取ることです _ 。 Wm _ 入力メッセージの処理は、wm MOUSEMOVE メッセージを処理するよりも複雑です _ が、wm _ 入力メッセージは、ヒューマンインターフェイスデバイス (HID) スタックから直接読み取られ、高解像度の結果を反映しています。

WM 入力メッセージからマウス移動データを読み取るには、 _ 最初にデバイスを登録する必要があります。次のコードは、この例を示しています。

// you can #include <hidusage.h> for these defines
#ifndef HID_USAGE_PAGE_GENERIC
#define HID_USAGE_PAGE_GENERIC         ((USHORT) 0x01)
#endif
#ifndef HID_USAGE_GENERIC_MOUSE
#define HID_USAGE_GENERIC_MOUSE        ((USHORT) 0x02)
#endif

RAWINPUTDEVICE Rid[1];
Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC; 
Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE; 
Rid[0].dwFlags = RIDEV_INPUTSINK;   
Rid[0].hwndTarget = hWnd;
RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]));

次のコードは、 _ アプリケーションの WinProc ハンドラーでの WM 入力メッセージを処理します。

case WM_INPUT: 
{
    UINT dwSize = sizeof(RAWINPUT);
    static BYTE lpb[sizeof(RAWINPUT)];

    GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER));

    RAWINPUT* raw = (RAWINPUT*)lpb;

    if (raw->header.dwType == RIM_TYPEMOUSE) 
    {
        int xPosRelative = raw->data.mouse.lLastX;
        int yPosRelative = raw->data.mouse.lLastY;
    } 
    break;
}

WM 入力を使用する利点 _ は、ゲームができるだけ低いレベルでマウスから生データを受け取ることです。

欠点は、WM _ 入力にデータに ballistics が適用されていないことです。そのため、このデータでカーソルを操作する場合は、カーソルを Windows のように動作させるために余分な作業が必要になります。 ポインター ballistics の適用の詳細については、「 pointer ballistics for Windows XP」を参照してください。

WM 入力の詳細について _ は、「 生の入力について」を参照してください。

DirectInput

DirectInput は、システム上の入力デバイスを抽象化する API 呼び出しのセットです。 内部的には、DirectInput は、WM 入力データを読み取るために2番目のスレッドを作成 _ します。 DirectInput api を使用すると、wm 入力を直接読み取るよりもオーバーヘッドが増加し _ ます。 DirectInput は、DirectInput ジョイスティックからデータを読み取る場合にのみ役立ちます。ただし、Windows に対してのみ Xbox 360 コントローラーをサポートする必要がある場合は、代わりにXInputを使用してください。 全体的に、DirectInput を使用すると、マウスやキーボードデバイスからデータを読み取るときに利点はありません。このようなシナリオでは、DirectInput を使用しないことをお勧めします。

前に説明したメソッドに、次のコードに示されている DirectInputの使用の複雑さを比較します。 DirectInput マウスを作成するには、次の一連の呼び出しが必要です。

LPDIRECTINPUT8 pDI;
LPDIRECTINPUTDEVICE8 pMouse;

hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&pDI, NULL);
if(FAILED(hr))
    return hr;

hr = pDI->CreateDevice(GUID_SysMouse, &pMouse, NULL);
if(FAILED(hr))
    return hr;

hr = pMouse->SetDataFormat(&c_dfDIMouse2);
if(FAILED(hr))
    return hr;

hr = pMouse->SetCooperativeLevel(hWnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
if(FAILED(hr))
    return hr;

if(!bImmediate)
{
    DIPROPDWORD dipdw;
    dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
    dipdw.diph.dwObj        = 0;
    dipdw.diph.dwHow        = DIPH_DEVICE;
    dipdw.dwData            = 16; // Arbitrary buffer size

    if(FAILED(hr = pMouse->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)))
        return hr;
}

pMouse->Acquire();

次に、DirectInput マウスデバイスを各フレームで読み取ることができます。

DIMOUSESTATE2 dims2; 
ZeroMemory(&dims2, sizeof(dims2));

hr = pMouse->GetDeviceState(sizeof(DIMOUSESTATE2), &dims2);
if(FAILED(hr)) 
{
    hr = pMouse->Acquire();
    while(hr == DIERR_INPUTLOST) 
        hr = pMouse->Acquire();

    return S_OK; 
}

int xPosRelative = dims2.lX;
int yPosRelative = dims2.lY;

まとめ

全体的には、高度なマウス移動データを受信する最良の方法は、WM _ 入力です。 ユーザーがマウスポインターを移動するだけの場合は、 _ ballistics ポインターを実行する必要がないように、WM MOUSEMOVE を使用することを検討してください。 マウスが高解像度のマウスでない場合でも、これらのウィンドウメッセージはどちらも正常に機能します。 高度な定義をサポートすることにより、Windows のゲームでより正確な制御をユーザーに提供できます。