Trap mouse in SDL


12

Come posso intrappolare il mouse dell'utente all'interno del mio gioco? Non è un gioco a schermo intero, ma lo voglio in modo che l'utente non possa trascinare il mouse all'esterno dello schermo.

Devo controllare le coordinate del mouse e SDL_WarpCursor per farlo dire all'interno della finestra (manualmente), oppure esiste un modo automatico?

Grazie.


Hai mai pensato di nascondere il cursore e riportarlo al centro? Quindi, disegna il mirino al centro dello schermo al posto del cursore del sistema operativo.
Vaughan Hilts,

Risposte:


24

Mentre puoi implementarlo usando SDL_WarpCursor (), ho riscontrato problemi con quel metodo su alcune piattaforme. Ho avuto problemi reali con alcune piattaforme che non eseguivano in modo affidabile l'azione WarpCursor (), in particolare quando la chiamavo ogni frame.

Inoltre, ricorda che su molte piattaforme, il cursore viene gestito con una frequenza superiore rispetto alla tua app. Questo è particolarmente vero se corri sotto i 60 fps! Quindi, anche se la piattaforma deforma con successo il mouse su ogni frame del gioco, il cursore potrebbe comunque allontanarsi dalla finestra se riceve aggiornamenti tra i frame renderizzati.

Il metodo corretto per intrappolare il mouse in SDL è:

SDL_WM_GrabInput( SDL_GRAB_ON );

Questo dice a SDL che la tua intenzione è quella di ottenere il pieno controllo del mouse + tastiera (vedi la documentazione ), e quindi mantenere il mouse all'interno della finestra, non importa quale. Da questo punto in poi, il mouse non si sposterà fuori dalla finestra, indipendentemente dalla frequenza dei fotogrammi, e non dovresti chiamare SDL_WarpCursor, tranne se hai davvero intenzione di teletrasportare il cursore da qualche parte, anziché spammarlo continuamente.

In questa modalità di "acquisizione", continuerai a ricevere eventi di movimento del mouse come se il mouse non fosse vincolato all'interno della finestra. (Quindi se il cursore si trova sul bordo destro dello schermo e l'utente sposta il mouse più a destra, riceverai un evento di movimento del mouse che mostra il movimento a destra, sebbene la posizione del cursore non cambierà). Questo è davvero utile per (ad esempio) girare i controlli per i giochi FPS, dove ti preoccupi solo del movimento relativo del cursore, non della sua posizione assoluta.

Aggiornamento per SDL2 - 9 dicembre 2013

Questa interfaccia è stata modificata per SDL2. Se stai usando SDL1.2, la risposta sopra è ancora corretta. Tuttavia, in SDL2 la SDL_WM_GrabInput(SDL_GrabMode)funzione non è più disponibile. Il nuovo modo di SDL2 per catturare il mouse è:

SDL_SetRelativeMouseMode(SDL_TRUE);

Altrimenti, questo è identico alla funzione precedente: in questa modalità continuerai a ricevere SDL_MOUSEMOTIONeventi come se il mouse non fosse vincolato all'interno della finestra.


1
Avvertenza: ho notato che su alcune piattaforme, ricevo immediatamente un evento MouseMotion spurio con un movimento molto grande, immediatamente dopo aver acceso il mouse grabbing. Per far ciò, il mio codice ignora il primo evento di movimento del mouse ricevuto dopo aver attivato questa modalità.
Trevor Powell,

Funzionava perfettamente ed è molto più semplice del modo manuale. Grazie!
David Gomes,

3

Mentre la risposta aggiornata di Trevor riflette lo stato corrente di SDL2, puoi anche intercettare il mouse creando il tuo SDL_Windowcon il SDL_WINDOW_INPUT_GRABBEDset. Ricorda che ho riscontrato alcuni strani problemi su Linux (presumibilmente a causa di alcune stranezze di X windowing) in cui non puoi mai uscire dalla finestra a meno che non venga chiamato SDL_QUIT (anche se un altro evento del sistema operativo ruba l'attenzione).


Grazie, SDL_WINDOW_INPUT_GRABBED funziona perfettamente sul mio codice SDL2.
Adrian Maire,


2

È possibile utilizzare SDL Motion Event per rilevare quando il mouse si sposta. Quindi, puoi chiamare WarpCursor all'interno anche dopo aver lanciato un evento per reindirizzare i valori relX e relY. Puoi anche nascondere il cursore del tuo sistema operativo e disegnare un mirino o qualcosa di simile al centro dello schermo. Questo assicura che il mouse sembri essere sempre nel mezzo per l'utente e che tu possa ancora ricevere valori per il movimento e simili.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.