Estou usando C # e tentando obter a posição do mouse de hardware. A primeira coisa que tentei foi a simples funcionalidade XNA, simples de usar
Vector2 position = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);
Depois disso, eu também faço o desenho do mouse e, comparando com o mouse de hardware do Windows, esse novo mouse com coordenadas fornecidas pelo xna está "relaxando". Com isso, quero dizer, que está atrasado em alguns quadros. Por exemplo, se o jogo estiver rodando a 600 fps, a maldição será responsiva, mas a 60 fps o atraso do mouse do software não será mais aceitável. Por isso, tentei usar o que eu pensava ser um mouse de hardware,
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetCursorPos(out POINT lpPoint);
mas o resultado foi exatamente o mesmo. Também tentei obter o cursor de formulário do Windows, e esse também era um beco sem saída, mas com o mesmo atraso. Brincando com a funcionalidade xna:
GraphicsDeviceManager.SynchronizeWithVerticalRetrace = true/false
Game.IsFixedTimeStep = true/fale
alterou o tempo de atraso por razões um tanto óbvias, mas a linha inferior é que, independentemente disso, ainda estava atrás do mouse padrão do Windows. Eu já vi em alguns jogos, eles fornecem opção para mouse acelerado por hardware, e em outros (acho) já é por padrão. Alguém pode dar alguma pista sobre como conseguir isso.
fonte
Mouse.GetState()
está quebrado. Você tem certeza de que está posicionando o mouse no mesmo quadro que o desenha? Lembre-se também de que o cursor do Windows tem a aceleração / desaceleração ativada, para que ele se sinta mais responsivo. Se você quiser se aproximar do hardware, pressione DirectInput, que fornecerá deltas de movimento em vez de posições absolutas do mouse. Mas acredito queMouse.GetState()
ainda é a maneira correta de fazer isso no XNA.Mouse.GetState()
não está quebrado e desde que asIsFixedTimeStep == true
pessoas não consigam ver atraso, a menos que comparadas diretamente com o mouse visível do Windows. No entanto, definir IsFixedTimeStep como false na taxa de quadros inferior torna-se visível para todos. Sobre a entrada direta, considerei uma possibilidade (último recurso).Respostas:
O que você está vendo não é atraso de entrada.
Para obter a posição do cursor no Windows, você pode usar
WM_MOUSEMOVE
ouGetCursorPos
. Ambos fornecem a posição do cursor depois que o Windows o processou, aplicando coisas como aceleração. Esta é a posição do cursor que o Windows usa, inclusive para desenhar. E quase sempre o que você deseja usar também.É isso que o XNA usa . Especificamente
GetCursorPos
( MSDN ). Isso significa que, quando você ligaMouse.GetState
, está obtendo a verdadeira posição do cursor como o Windows vê - com praticamente zero atraso.Agora, você pode usar
WM_INPUT
(ou DirectInput, embora isso seja preterido). Isso fornece os dados brutos do ponteiro. Isso ocorre antes que o Windows possa aplicar coisas como aceleração e geralmente não é o que você deseja.O que você está vendo é atraso na saída.
Isso ocorre por causa do " cursor de hardware ". Este é um pequeno sprite que é atraída sobre a tela pela GPU no mesmo fim de seu pipeline. E eu quero dizer o fim . Ele vem após o buffer de quadro - é inserido no fluxo de dados à medida que a imagem está sendo enviada ao monitor. A razão pela qual ele reage tão rapidamente é porque sua posição é definida configurando diretamente os registros da GPU. Não há nenhuma espera no pipeline.
Seu jogo, por outro lado, precisa passar pelo pipeline da GPU. Isso adiciona muitos atrasos por conta própria. O mais problemático para você é o buffer duplo - o qual (tenho certeza) não pode ser desativado no XNA 4. Você não desenha diretamente no buffer do quadro - você desenha no buffer traseiro. Que é apresentado a cada ~ 16ms (a 60FPS). Isso significa que você está olhando no mínimo cerca de 16ms entre receber o resultado de
Mouse.GetState
obter algo com base nesse resultado na tela. Provavelmente mais. Certamente muito mais lento que o cursor do hardware.Então, quais são as soluções?
Uma é usar
SetCursor
( MSDN ) para alterar a imagem exibida pelo cursor do hardware, para uma imagem que melhor se adapte ao seu jogo (ou simplesmente viva com o cursor do Windows).E o outro (muito mais fácil) é apenas aceitar o atraso e definir
Game.IsMouseVisible = false
para ocultar o atraso relativo. Exiba seu próprio cursor no jogo. Será 16ms mais lento que o cursor oculto do Windows - mas quem se importa? Os jogadores estão acostumados a isso. E 16ms é quase visualmente imperceptível de qualquer maneira (é por isso que renderizamos as coisas a 60FPS).fonte