Pułapka na myszy w SDL

12

Jak mogę uwięzić mysz użytkownika w mojej grze? Nie jest to gra pełnoekranowa, ale chcę, żeby użytkownik nie mógł przeciągnąć myszy poza ekran.

Czy muszę sprawdzić współrzędne myszy i SDL_WarpCursor, aby powiedzieć to w oknie (ręcznie), czy też istnieje sposób automatyczny?

Dziękuję Ci.

David Gomes
źródło
Czy zastanawiałeś się nad ukryciem kursora i wypaczeniem go z powrotem na środek? Następnie po prostu narysuj celownik pośrodku ekranu zamiast kursora OS.
Vaughan Hilts,

Odpowiedzi:

24

Chociaż możesz to zaimplementować za pomocą SDL_WarpCursor (), mam problemy z tą metodą na niektórych platformach. Miałem prawdziwy problem z niektórymi platformami, które niezawodnie wykonywały akcję WarpCursor (), szczególnie gdy wywoływałem ją w każdej ramce.

Pamiętaj też, że na wielu platformach kursor jest obsługiwany z większą częstotliwością niż Twoja aplikacja. Jest to szczególnie ważne, jeśli pracujesz poniżej 60 klatek na sekundę! Więc nawet jeśli platforma z powodzeniem wypacza mysz w każdej ramce gry, kursor może nadal uciec od okna, jeśli odbiera aktualizacje między renderowanymi ramkami.

Prawidłowa metoda pułapki myszy pod SDL to:

SDL_WM_GrabInput( SDL_GRAB_ON );

To mówi SDL, że twoim celem jest przejęcie pełnej kontroli nad myszą + klawiaturą (zobacz dokumentację ), a zatem trzymanie myszy wewnątrz okna bez względu na wszystko. Od tego momentu mysz nie będzie się przesuwać poza okno, bez względu na liczbę klatek na sekundę, i nie powinieneś wywoływać SDL_WarpCursor, chyba że naprawdę zamierzasz gdzieś teleportować kursor, zamiast spamować go w sposób ciągły.

W tym trybie „chwytania” będziesz nadal otrzymywać zdarzenia ruchu myszy, tak jakby mysz nie była ograniczana w oknie. (Jeśli więc kursor znajduje się na prawej krawędzi ekranu, a użytkownik przesuwa mysz dalej w prawo, otrzymasz zdarzenie ruchu myszy pokazujące ruch w prawo, chociaż pozycja kursora się nie zmieni). Jest to bardzo przydatne (na przykład) do obracania kontrolek w grach FPS, w których zależy tylko na względnym ruchu kursora, a nie na jego absolutnej pozycji.

Aktualizacja dla SDL2 - 9 grudnia 2013 r

Ten interfejs został zmieniony dla SDL2. Jeśli używasz SDL 1.2, powyższa odpowiedź jest nadal poprawna. Jednak w SDL2 SDL_WM_GrabInput(SDL_GrabMode)funkcja nie jest już dostępna. Nowym sposobem SDL2 na przechwycenie myszy jest:

SDL_SetRelativeMouseMode(SDL_TRUE);

W przeciwnym razie jest to identyczne z wcześniejszą funkcją - w tym trybie będziesz nadal otrzymywać SDL_MOUSEMOTIONzdarzenia, tak jakby mysz nie była ograniczona w oknie.

Trevor Powell
źródło
1
Uwaga: Zauważyłem, że na niektórych platformach natychmiast otrzymuję fałszywe zdarzenie MouseMotion z bardzo dużym ruchem, natychmiast po włączeniu chwytania myszy. Aby sobie z tym poradzić, mój kod ignoruje pierwsze zdarzenie ruchu myszy otrzymane po włączeniu tego trybu.
Trevor Powell,
To działało idealnie i jest o wiele łatwiejsze niż ręczne. Dziękuję Ci!
David Gomes,
3

Chociaż zaktualizowana odpowiedź Trevora odzwierciedla bieżący stan SDL2, możesz również uwięzić mysz, tworząc ją SDL_Windowza pomocą SDL_WINDOW_INPUT_GRABBEDzestawu. Pamiętaj, że natknąłem się na dziwne problemy w Linuksie (prawdopodobnie z powodu dziwactwa okienkowego X), w których nigdy nie możesz wyjść z okna, dopóki nie zostanie wywołane SDL_QUIT (nawet jeśli inne zdarzenie systemu operacyjnego wykradnie fokus).

Justin Skiles
źródło
Dzięki, SDL_WINDOW_INPUT_GRABBED działa doskonale na moim kodzie SDL2.
Adrian Maire
3

W przypadku SDL2 wydaje się również istnieć funkcja SDL_SetWindowGrab, jeśli chcesz ją włączyć lub wyłączyć.

SDL_SetWindowGrab(SDL_Window* window, SDL_bool grabbed)
Michael Shaffer
źródło
2

Za pomocą SDL Motion Event można wykryć ruch myszy. Następnie możesz wywołać WarpCursor, który nawet po odpaleniu zdarzenia potokuje wartości relX i relY. Możesz także ukryć kursor systemu operacyjnego i narysować celownik lub coś podobnego na środku ekranu. Zapewnia to, że mysz wydaje się zawsze znajdować się w środku dla użytkownika i nadal można odbierać wartości ruchu i tym podobne.

Vaughan Hilts
źródło