Миша на пастці в SDL


12

Як я можу потрапити в пастку миші користувача всередині своєї гри? Це не повноекранна гра, але я хочу, щоб користувач не міг перетягнути мишу за межі екрана.

Чи потрібно перевіряти координати миші та SDL_WarpCursor, щоб це було сказано всередині вікна (вручну), чи існує автоматичний шлях?

Дякую.


Ви думали про те, щоб сховати курсор і повернути його до центру? Потім просто намалюйте перехрестя в центрі екрану замість курсору ОС.
Vaughan Hilts

Відповіді:


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
Caveat: Я помітив, що на деяких платформах я одразу після включення захоплення миші отримую помилкову подію MouseMotion з дуже великим рухом. Щоб впоратися з цим, у мене код ігнорує першу подію руху миші, отриману після ввімкнення цього режиму.
Тревор Пауелл

Це спрацювало чудово, і це набагато простіше, ніж ручний спосіб. Дякую!
Девід Гомес

3

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


Дякую, SDL_WINDOW_INPUT_GRABBED прекрасно працює над моїм кодом SDL2.
Адріан Мейр


2

Ви можете використовувати подію руху SDL, щоб виявити, коли миша рухається. Потім ви можете зателефонувати WarpCursor всередину, що навіть після запуску події передає значення relX та relY. Ви також можете приховати курсор ОС і намалювати перехрестя або щось подібне в центрі екрана. Це гарантує, що миша, здається, завжди знаходиться в середині для користувача, і ви все одно можете отримувати значення для руху тощо.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.