Я использую 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 по умолчанию. Я видел в некоторых играх, что они предоставляют опцию для аппаратной мыши, а в других (я думаю) это уже по умолчанию. Может ли кто-нибудь дать некоторое представление о том, как этого добиться.
источник
Mouse.GetState()
сломан. Вы уверены, что положение мыши находится в том же кадре, что и при рисовании? Также помните, что для курсора Windows включено ускорение / замедление, поэтому он выглядит более отзывчивым. Если вы хотите приблизиться к оборудованию, вы должны нажать DirectInput, который даст вам дельты движения вместо абсолютных положений мыши. Но я верю, чтоMouse.GetState()
это все еще правильный способ сделать это в XNA.Mouse.GetState()
не сломан, и до тех пор, покаIsFixedTimeStep == true
люди не должны видеть задержку, если не сравнивать непосредственно с видимыми окнами мыши. Однако, установив для IsFixedTimeStep значение false при более низкой частоте кадров, он становится видимым для всех. О непосредственном вводе я считал, что возможность (в крайнем случае).Ответы:
То, что вы видите, не является входным лагом.
Чтобы получить положение курсора в Windows, вы можете использовать
WM_MOUSEMOVE
илиGetCursorPos
. Они оба обеспечивают положение курсора после того, как Windows его обработала, применяя такие вещи, как ускорение. Это позиция курсора, которую использует Windows, в том числе для рисования. И почти всегда то, что вы хотите использовать тоже.Это то, что использует XNA . В частности
GetCursorPos
( MSDN ). Это означает, что при вызовеMouse.GetState
вы получаете истинную позицию курсора в том виде, в каком она видится в Windows - с практически нулевой задержкой.Теперь вы можете использовать
WM_INPUT
(или DirectInput, хотя это не рекомендуется). Это дает вам необработанные данные указателя. Это происходит до того, как Windows может применить такие вещи, как ускорение, и обычно это не то, что вам нужно.То, что вы видите, это выходной лаг.
Это из-за « аппаратного курсора ». Это небольшой спрайт, который отображается над экраном графическим процессором в самом конце конвейера. И я имею в виду конец . Он идет после буфера кадра - он вставляется в поток данных при отправке изображения на монитор. Причина, по которой он реагирует так быстро, заключается в том, что его положение задается путем прямой установки регистров GPU. Там нет ожидания вокруг в трубопроводе вообще.
С другой стороны, ваша игра должна проходить через конвейер GPU. Это добавляет множество задержек само по себе. Наиболее проблематичным из них для вас является двойная буферизация - которую (я почти уверен) вы не можете отключить в XNA 4. Вы не рисуете непосредственно в буфер кадра - вы рисуете в буфер. Который представлен каждые ~ 16 мс (при 60FPS). Это означает, что вы просматриваете минимум 16 мс между получением результата
Mouse.GetState
получения чего-либо на основе этого результата на экране. Наверное, дольше. Конечно, намного медленнее, чем аппаратный курсор.Итак, каковы решения?
Одним из них является использование
SetCursor
( MSDN ), чтобы изменить изображение, отображаемое аппаратным курсором, на изображение, которое лучше подходит для вашей игры (или просто жить с курсором Windows).А другой (гораздо проще) просто принять отставание и
Game.IsMouseVisible = false
скрыть относительное отставание. Показать свой собственный курсор в игре. Это будет на 16 мс медленнее, чем скрытый курсор Windows - но кого это волнует? Геймеры привыкли к этому. И 16 мс почти визуально незаметны (поэтому мы делаем рендеринг с частотой 60 кадров в секунду).источник