Spostamento relativo del mouse e CoreWindow

Nei giochi, il mouse è un'opzione di controllo comune che risulta familiare a molti giocatori, ed è altrettanto essenziale per molti generi di giochi, tra cui gli sparatutto in prima e terza persona, e i giochi di strategia in tempo reale. Qui discuteremo dell'implementazione dei controlli del mouse relativi, che non utilizzano il cursore di sistema e non restituiscono le coordinate assolute dello schermo, ma che invece tengono traccia del delta dei pixel tra i movimenti del mouse.

Alcune app, quali ad esempio i giochi, utilizzano il mouse come dispositivo di input più generale. Ad esempio, un modeler 3D potrebbe utilizzare l'input del mouse per orientare un oggetto 3D simulando una trackball virtuale; oppure un gioco potrebbe utilizzare il mouse per modificare la direzione della telecamera di visualizzazione tramite controlli "mouse-look".

In tali scenari, l'app richiede i dati relativi del mouse. I valori relativi del mouse rappresentano la distanza di spostamento del mouse dall'ultimo frame, anziché i valori assoluti delle coordinate x-y all'interno di una finestra o di uno schermo. Inoltre, le app spesso nascondono il cursore del mouse perché la posizione del cursore rispetto alle coordinate dello schermo non è rilevante quando si manipola un oggetto o una scena 3D.

Quando l'utente esegue un'azione che sposta l'app in una modalità di manipolazione dell'oggetto/scena 3D relativa, l'app deve:

  • Ignorare la gestione predefinita del mouse.
  • Abilitare la gestione relativa del mouse.
  • Nascondere il cursore del mouse impostandolo su un puntatore Null (nullptr).

Quando l'utente esegue un'azione che sposta l'app all'esterno di una modalità di manipolazione dell'oggetto/scena 3D relativa, l'app deve:

  • Abilitare la gestione predefinita/assoluta del mouse.
  • Disattivare la gestione relativa del mouse.
  • Impostare il cursore del mouse su un valore non Null (che lo rende visibile).

Nota
Con questo modello, la posizione del cursore assoluto del mouse viene mantenuta quando si immette la modalità relativa senza cursore. Il cursore viene nuovamente visualizzato nella stessa posizione della coordinata dello schermo precedente per abilitare la modalità di spostamento del mouse relativa.

Gestione dello spostamento relativo del mouse

Per accedere ai valori differenziali relativi del mouse, eseguire la registrazione per l'evento MouseDevice::MouseMoved, come illustrato di seguito.



// 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;
}

Il gestore eventi in questo esempio di codice OnMouseMoved esegue il rendering della visualizzazione in base ai movimenti del mouse. La posizione del puntatore del mouse viene passata al gestore come oggetto MouseEventArgs.

Ignorare l'elaborazione dei dati assoluti del mouse dall'evento CoreWindow::PointerMoved quando l'app cambia per gestire i valori di spostamento relativi del mouse. Tuttavia, ignorare questo input solo se l'evento CoreWindow::PointerMoved si è verificato come risultato dell'input del mouse (anziché dell'input di tocco). Il cursore viene nascosto impostando CoreWindow::PointerCursor su nullptr.

Ritorno al movimento assoluto del mouse

Quando l'app esce dalla modalità di manipolazione oggetto o scena 3D e non utilizza più lo spostamento relativo del mouse (ad esempio quando torna a una schermata di menu), tornare alla normale elaborazione dello spostamento assoluto del mouse. In questo momento, interrompere la lettura dei dati relativi del mouse, riavviare l'elaborazione degli eventi standard del mouse (e del puntatore) e impostare CoreWindow::PointerCursor su un valore diverso da Null.

Nota
Quando l'app si trova nella modalità di manipolazione oggetto/scena 3D (elaborazione dei movimenti relativi del mouse con il cursore disattivato), il mouse non può richiamare elementi dell'interfaccia utente perimetrali, quali ad esempio charms, back stack o barra delle app. Pertanto, è importante fornire un meccanismo per uscire da questa particolare modalità, quale ad esempio il tasto Esc di uso comune.