Ловушка мыши в SDL

12

Как я могу поймать мышь пользователя в мою игру? Это не полноэкранная игра, но я хочу, чтобы пользователь не мог перетаскивать мышь за пределы экрана.

Нужно ли проверять координаты мыши и SDL_WarpCursor, чтобы это говорилось внутри окна (вручную), или есть автоматический способ?

Спасибо.

Дэвид Гомес
источник
Рассматривали ли вы скрыть курсор и переместить его обратно в центр? Затем просто нарисуйте перекрестие в центре экрана вместо курсора ОС.
Вон Хилтс

Ответы:

24

Хотя вы можете реализовать это с помощью SDL_WarpCursor (), у меня возникли проблемы с этим методом на некоторых платформах. У меня были реальные проблемы с некоторыми платформами, которые ненадежно выполняли действие WarpCursor (), особенно когда я вызывал его каждый кадр.

Также помните, что на многих платформах курсор обрабатывается с большей частотой, чем ваше приложение. Это особенно верно, если вы работаете ниже 60 кадров в секунду! Таким образом, даже если платформа успешно деформирует мышь на каждом кадре вашей игры, курсор все равно может покинуть ваше окно, если он получает обновления между вашими визуализированными кадрами.

Правильный метод отлова мыши под SDL:

SDL_WM_GrabInput( SDL_GRAB_ON );

Это говорит SDL, что вы намерены фактически получить полный контроль над мышью + клавиатурой (см. Документацию ) и, следовательно, держать мышь внутри окна, несмотря ни на что. С этого момента мышь не будет перемещаться за пределы окна, независимо от частоты кадров, и вам не следует вызывать SDL_WarpCursor, за исключением случаев, когда вы действительно намерены телепортировать курсор куда-то, а не спамить его непрерывно.

Находясь в этом режиме «захвата», вы продолжите получать события движения мыши, как будто мышь не была ограничена внутри окна. (Таким образом, если курсор находится на правом краю экрана, и пользователь перемещает свою мышь дальше вправо, вы получите событие движения мыши, показывающее движение вправо, хотя положение курсора не изменится). Это действительно полезно для (например) поворота элементов управления в играх FPS, где вас интересует только относительное движение курсора, а не его абсолютное положение.

Обновление для SDL2 - 9 декабря 2013 г.

Этот интерфейс был изменен для SDL2. Если вы используете SDL1.2, ответ выше по-прежнему правильный. Однако в SDL2 эта SDL_WM_GrabInput(SDL_GrabMode)функция больше не доступна. Новый способ захвата мыши в SDL2:

SDL_SetRelativeMouseMode(SDL_TRUE);

В противном случае это идентично предыдущей функции - в этом режиме вы продолжите получать SDL_MOUSEMOTIONсобытия, как будто мышь не была ограничена внутри окна.

Тревор Пауэлл
источник
1
Предупреждение: я заметил, что на некоторых платформах я сразу же получаю ложное событие MouseMotion с очень большим движением сразу после включения захвата мыши. Чтобы справиться с этим, мой код игнорирует первое событие движения мыши, полученное после включения этого режима.
Тревор Пауэлл
Это сработало отлично, и это намного проще, чем ручным способом. Спасибо!
Дэвид Гомес
3

Хотя обновленный ответ Тревора действительно отражает текущее состояние SDL2, вы можете также ловить мышь, создав SDL_Windowс SDL_WINDOW_INPUT_GRABBEDнабором. Имейте в виду, что я столкнулся с некоторыми странными проблемами в Linux (вероятно, из-за некоторой причуды окон X), когда вы никогда не сможете выйти из окна, пока не будет вызван SDL_QUIT (даже если другое событие ОС уводит фокус).

Джастин Скилс
источник
Спасибо вам, SDL_WINDOW_INPUT_GRABBED отлично работают над моим кодом SDL2.
Адриан Мэр
3

Для SDL2, кажется, также есть функция SDL_SetWindowGrab, если вы хотите включить и отключить ее.

SDL_SetWindowGrab(SDL_Window* window, SDL_bool grabbed)
Майкл Шаффер
источник
2

Вы можете использовать SDL Motion Event, чтобы определить, когда движется мышь. Затем вы можете вызывать WarpCursor внутри, даже после запуска события для передачи значений relX и relY. Вы также можете скрыть курсор вашей ОС и нарисовать перекрестие или что-то подобное в центре экрана. Это гарантирует, что мышь, кажется, всегда находится посередине для пользователя, и вы все равно можете получать значения для движения и тому подобное.

Вон Хилтс
источник