相對滑鼠移動和 CoreWindow

在遊戲中,滑鼠是許多玩家熟悉的常用控制選項,對很多遊戲類型也是必要裝置,包括第一和第三人稱角度射擊,以及即時策略遊戲。 在本文中,我們將討論相對滑鼠控制項的實作,這不會使用系統游標,也不會傳回絕對螢幕座標;而是追蹤滑鼠移動之間的像素差異。

有些應用程式 (例如遊戲) 更常以滑鼠作為輸入裝置。 例如,3D 模組工具使用滑鼠時,可能會模擬虛擬軌跡球來定位 3D 物件;或者遊戲使用滑鼠時,會透過滑鼠的視角控制項,變更檢視相機的方向。

在這些案例中,應用程式需要相對滑鼠資料。 相對滑鼠值代表滑鼠自最後一格畫面以來移動的距離,而非視窗或畫面內的絕對 x-y 座標值。 此外,應用程式通常會隱藏滑鼠游標,因為對於操作 3D 物件或場景來說,游標相對於螢幕座標的位置並不相關。

當使用者採取動作,將應用程式移至相對 3D 物件/場景的操作模式,應用程式必須:

  • 忽略預設的滑鼠處理。
  • 啟用相對滑鼠處理。
  • 將滑鼠游標設為 null 指標 (nullptr),即可隱藏滑鼠游標。

當使用者採取動作,將應用程式移出相對 3D 物件/場景的操作模式,應用程式必須:

  • 啟用預設/絕對滑鼠處理。
  • 關閉相對滑鼠處理。
  • 將滑鼠游標設為非 null 值 (使游標可見)。

注意
如果使用此模式,絕對滑鼠游標位置會保留在進入無游標相對模式時。 游標會重新出現在先前啟用相對滑鼠移動模式時,所在的同一個螢幕座標位置。

處理相對滑鼠移動

若要存取相對滑鼠差異值,請註冊 MouseDevice::MouseMoved 事件 (如這裡所示)。



// register handler for relative mouse movement events
Windows::Devices::Input::MouseDevice::GetForCurrentView()->MouseMoved +=
        ref new TypedEventHandler<MouseDevice^, MouseEventArgs^>(this, &MoveLookController::OnMouseMoved);




void MoveLookController::OnMouseMoved(
    _In_ Windows::Devices::Input::MouseDevice^ mouseDevice,
    _In_ Windows::Devices::Input::MouseEventArgs^ args
    )
{
    float2 pointerDelta;
    pointerDelta.x = static_cast<float>(args->MouseDelta.X);
    pointerDelta.y = static_cast<float>(args->MouseDelta.Y);

    float2 rotationDelta;
    rotationDelta = pointerDelta * ROTATION_GAIN;	// scale for control sensitivity

    // update our orientation based on the command
    m_pitch -= rotationDelta.y;						// mouse y increases down, but pitch increases up
    m_yaw   -= rotationDelta.x;						// yaw defined as CCW around y-axis

    // limit pitch to straight up or straight down
    float limit = (float)(M_PI/2) - 0.01f;
    m_pitch = (float) __max( -limit, m_pitch );
    m_pitch = (float) __min( +limit, m_pitch );

    // keep longitude in useful range by wrapping
    if ( m_yaw >  M_PI )
        m_yaw -= (float)M_PI*2;
    else if ( m_yaw < -M_PI )
        m_yaw += (float)M_PI*2;
}

此程式碼範例中的事件處理常式 OnMouseMoved 會根據滑鼠移動轉譯檢視。 滑鼠指標的位置會以 MouseEventArgs 物件形式傳遞至處理常式。

當應用程式變更為處理相對滑鼠移動值時,請略過處理來自 CoreWindow::PointerMoved 事件的絕對滑鼠資料。 不過,只有當 CoreWindow::PointerMoved 事件是產生自滑鼠輸入 (而非觸控輸入),才能略過此輸入。 將 CoreWindow::PointerCursor 設為 nullptr 即可隱藏游標。

回到絕對滑鼠移動

一旦應用程式結束 3D 物件或場景操作模式,且不再使用相對滑鼠移動 (例如返回功能表畫面時),則回到正常的絕對滑鼠移動處理方式。 此時請停止讀取相對滑鼠資料、重新開始處理標準滑鼠 (和指標) 事件,並將 CoreWindow::PointerCursor 設為非 null 值。

注意
當應用程式處於 3D 物件/場景操作模式 (處理相對滑鼠移動且滑鼠為關閉狀態),滑鼠將無法叫用 Edge UI,例如:快速鍵、上一頁堆疊或應用程式列。 因此,請務必提供一個能結束此特定模式的機制,例如常用的 Esc 鍵。