C # / XNA отримують апаратне положення миші


10

Я використовую C # і намагаюся отримати апаратне положення миші. Перше, що я спробував, це простий функціонал XNA, який простий у використанні

Vector2 position = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);

Після цього я також малюю мишу, і порівнюючи з апаратною мишею Windows, ця нова миша з наданими xna координатами "відхиляється". Я маю на увазі, що це відстає від кількох кадрів. Наприклад, якщо гра працює на 600 кадрів в секунду, прокляття буде чуйною, але затримка миші при 60 кадрів в секунду вже не прийнятна. Тому я спробував використовувати те, що я вважав апаратною мишкою,

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetCursorPos(out POINT lpPoint);

але результат був точно таким же. Я також спробував отримати курсор форми Windows, і це було також тупиком - працював, але з такою ж затримкою. Заплутатися з функцією xna:

GraphicsDeviceManager.SynchronizeWithVerticalRetrace = true/false
Game.IsFixedTimeStep = true/fale

змінив час затримки з дещо очевидних причин, але суть полягає в тому, що незалежно від того, що він все ще був за мишею Windows за замовчуванням. У деяких іграх я бачив, що вони пропонують опцію для апаратної миші, а в інших (я думаю) це вже за замовчуванням. Хто-небудь може дати певну думку про те, як цього досягти.


2
Я не думаю, що Mouse.GetState()це порушено. Ви впевнені, що положення миші отримуєте в тому ж кадрі, що і малюєте? Також пам’ятайте, що курсор Windows увімкнено прискорення / уповільнення, тому він почуває себе більш чуйним. Якщо ви хочете наблизитись до обладнання, вам слід натиснути DirectInput, який дасть вам дельти руху замість абсолютних позицій миші. Але я вважаю, що Mouse.GetState()це все-таки правильний спосіб зробити це в XNA.
Піжама Panda

Ні, Mouse.GetState()не порушено, і поки IsFixedTimeStep == trueлюди не мають змоги побачити затримку, якщо не порівнювати безпосередньо з видимою мишею Windows. Однак встановлення IsFixedTimeStep на значення false у нижньому кадрі стає видимим для всіх. Щодо прямого введення я вважав, що можливість (остання можливість).
Сандер

Не впевнений, що це те, що ви хочете, але що стосується зміни спрайту курсора, поки він знаходиться у вашому вікні, а потім зробити його завжди видимим?
Вільям Маріагер

Саме цим я і займаюся, річ у тому, що я не хочу лише показувати це, але також знати точне положення миші. Але те, що я отримую, трохи відстає від того, що має бути.
Сандер

Відповіді:


17

Те, що ви бачите, це не відставання.

Для отримання положення курсору в Windows ви можете використовувати WM_MOUSEMOVEабо GetCursorPos. Вони обидва забезпечують положення курсору після того, як Windows обробила його, застосувавши такі речі, як прискорення. Це положення курсору, яке використовує Windows, в тому числі для малювання. І майже завжди те, що ви також хочете використовувати.

Це те, що використовує XNA . Зокрема GetCursorPos( MSDN ). Це означає, що під час дзвінка Mouse.GetStateви отримуєте справжнє положення курсору так, як це бачить Windows - з практично нульовою затримкою.

Тепер ви можете використовувати WM_INPUT(або DirectInput, хоча це застаріло). Це дає вам необроблені дані вказівника. Це ще до того, як Windows може застосувати такі речі, як прискорення, і зазвичай це не те, що потрібно.

Те, що ви бачите, це відставання у виході.

Це через " апаратний курсор ". Це невеликий спрайт, який отримує над екраном GPU в самому кінці свого конвеєра. І я маю на увазі кінець . Це відбувається після буфера кадру - він вставляється в потік даних під час надсилання зображення на монітор. Причина, на яку вона реагує так швидко, полягає в тому, що її положення встановлюється безпосередньо шляхом встановлення регістрів GPU. У трубопроводі взагалі немає очікування.

З іншого боку, ваша гра повинна пройти через конвеєр GPU. Це додає багато затримок самостійно. Найбільш проблематичним з них для вас є подвійне буферизація - яке (я майже впевнений) ви не можете вимкнути в XNA 4. Ви не малюєте безпосередньо до буфера кадру - малюєте до резервного буфера. Що презентується кожні ~ 16 мс (при 60 FPS). Це означає, що ви шукаєте як мінімум приблизно 16 мс між отриманням результату Mouse.GetStateотримання чогось на основі цього результату на екрані. Напевно, довше. Звичайно набагато повільніше, ніж апаратний курсор.

То які рішення?

Перше - використовувати SetCursor( MSDN ) для зміни зображення, яке відображається апаратним курсором, для отримання зображення, яке найкраще відповідає вашій грі (або просто жити з курсором Windows).

А інше (набагато простіше) - просто прийняти відставання і налаштувати Game.IsMouseVisible = falseприховати відносне відставання. Показуйте власний курсор у грі. Це буде на 16 м повільніше, ніж прихований курсор Windows - але кого це хвилює? Геймери звикли до цього. І 16 мс в будь-якому випадку майже візуально непомітні (саме тому ми рендеруємо речі зі швидкістю 60 кадрів в секунду).


Дякую за детальне пояснення цього питання. Швидше за все, я просто дотримуюся миші XNA. Збираюся трохи зачекати, перш ніж приймати, якщо хтось матиме додаткове рішення для цього.
Сандер

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