Używam C # i próbuję uzyskać pozycję myszy sprzętowej. Pierwszą rzeczą, którą wypróbowałem, była prosta funkcjonalność XNA, która jest prosta w użyciu
Vector2 position = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);
Następnie wykonuję również rysowanie myszy i w porównaniu z myszą sprzętową systemu Windows, ta nowa mysz z współrzędnymi podanymi przez xna „zwalnia”. Rozumiem przez to, że jest opóźniony o kilka klatek. Na przykład, jeśli gra działa z prędkością 600 kl./s, klątwa będzie reagować, ale przy 60 kl./s opóźnienie myszy programowej nie jest już dopuszczalne. Dlatego próbowałem użyć myszy, która moim zdaniem była sprzętową,
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetCursorPos(out POINT lpPoint);
ale wynik był dokładnie taki sam. Próbowałem też uzyskać kursor Windows, i to był ślepy zaułek - działał, ale z tym samym opóźnieniem. Mieszanie z funkcjonalnością xna:
GraphicsDeviceManager.SynchronizeWithVerticalRetrace = true/false
Game.IsFixedTimeStep = true/fale
zmienił czas opóźnienia z dość oczywistych powodów, ale sedno jest takie, że niezależnie od tego, że nadal był za domyślną myszą Windows. Widziałem w niektórych grach, że zapewniają one opcję dla myszy z akceleracją sprzętową, aw innych (tak myślę) jest już domyślnie. Czy ktoś może dać jakieś wskazówki, jak to osiągnąć.
źródło
Mouse.GetState()
jest zepsuty. Czy na pewno ustawiasz pozycję myszy w tej samej ramce podczas jej rysowania? Pamiętaj również, że kursor Windows ma włączone przyspieszanie / zwalnianie, więc jest bardziej responsywny. Jeśli chcesz zbliżyć się do sprzętu, powinieneś nacisnąć DirectInput, co da ci deltę ruchu zamiast absolutnej pozycji myszy. Ale uważam, żeMouse.GetState()
nadal jest to właściwy sposób na zrobienie tego w XNA.Mouse.GetState()
nie jest zepsuty i tak długo, jakIsFixedTimeStep == true
ludzie nie powinni widzieć opóźnienia, chyba że są porównywane bezpośrednio z myszą z widocznymi oknami. Jednak ustawienie IsFixedTimeStep na wartość false przy niższej liczbie klatek na sekundę staje się widoczne dla wszystkich. O bezpośrednim wejściu uznałem, że jest to możliwość (w ostateczności).Odpowiedzi:
To, co widzisz, nie jest opóźnieniem wejściowym.
Aby uzyskać pozycję kursora w systemie Windows, możesz użyć
WM_MOUSEMOVE
lubGetCursorPos
. Oba zapewniają pozycję kursora po przetworzeniu go przez system Windows, stosując takie rzeczy, jak przyspieszenie. Jest to pozycja kursora używana przez system Windows, w tym do rysowania. I prawie zawsze to, czego chcesz użyć.Tego używa XNA . W szczególności
GetCursorPos
( MSDN ). Oznacza to, że kiedy dzwoniszMouse.GetState
, otrzymujesz prawdziwą pozycję kursora, tak jak widzi ją Windows - z praktycznie zerowym opóźnieniem.Teraz możesz użyć
WM_INPUT
(lub DirectInput, choć jest to przestarzałe). To daje surowe dane wskaźnika. Dzieje się tak, zanim system Windows może zastosować takie przyspieszenie, i zwykle nie jest tym, czego chcesz.To, co widzisz, to opóźnienie wyjściowe.
Wynika to z „ kursora sprzętowego ”. Jest to mały duszek, który jest przeciągany przez ekran przez GPU na samym końcu jego potoku. I mam na myśli koniec . Pojawia się za buforem ramki - zostaje wstawiony do strumienia danych, gdy obraz jest wysyłany do monitora. Powodem, dla którego tak szybko reaguje, jest ustawienie pozycji przez bezpośrednie ustawienie rejestrów GPU. W planach nie ma w ogóle czekania.
Z drugiej strony twoja gra musi przejść przez procesor GPU. Daje to wiele opóźnień. Najbardziej problematycznym z nich jest podwójne buforowanie - czego (jestem prawie pewien) nie można wyłączyć w XNA 4. Nie rysujesz bezpośrednio do bufora ramki - przyciągasz do bufora backbuffera. Co jest prezentowane co ~ 16ms (przy 60 FPS). Oznacza to, że patrzysz na minimum 16 ms między otrzymaniem wyniku
Mouse.GetState
otrzymania czegoś na podstawie tego wyniku na ekranie. Prawdopodobnie dłużej. Z pewnością znacznie wolniej niż kursor sprzętowy.Więc jakie są rozwiązania?
Jednym z nich jest użycie
SetCursor
( MSDN ) do zmiany obrazu wyświetlanego przez kursor sprzętowy, aby był obrazem, który lepiej pasuje do twojej gry (lub po prostu kursor Windows).Drugim (o wiele łatwiejszym) jest po prostu zaakceptowanie opóźnienia i ustawienie
Game.IsMouseVisible = false
ukrywania względnego opóźnienia. Wyświetl własny kursor w grze. Będzie o 16 ms wolniejszy niż ukryty kursor Windows - ale kogo to obchodzi? Gracze są do tego przyzwyczajeni. A 16ms jest prawie niewidoczna wizualnie (dlatego renderujemy rzeczy w 60 FPS).źródło